Files
crewAI/crewai/tools/linear_tool.py

125 lines
3.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from enum import Enum
from typing import Any, Type
import httpx
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
LINEAR_API_URL = "https://api.linear.app/graphql"
class LinearAction(str, Enum):
MY_ISSUES = "my_issues"
LIST_TEAMS = "list_teams"
LIST_PROJECTS = "list_projects"
class LinearToolInput(BaseModel):
action: LinearAction = Field(
description=(
"Action to perform: "
"'my_issues' — fetch issues assigned to the authenticated user; "
"'list_teams' — list all teams in the workspace; "
"'list_projects' — list all projects in the workspace."
)
)
first: int = Field(
default=25,
ge=1,
le=250,
description="Maximum number of records to return (1250).",
)
_QUERIES: dict[LinearAction, str] = {
LinearAction.MY_ISSUES: """
query MyIssues($first: Int!) {
viewer {
assignedIssues(first: $first, orderBy: updatedAt) {
nodes {
id
identifier
title
state { name }
priority
url
updatedAt
}
}
}
}
""",
LinearAction.LIST_TEAMS: """
query ListTeams($first: Int!) {
teams(first: $first) {
nodes {
id
name
key
description
}
}
}
""",
LinearAction.LIST_PROJECTS: """
query ListProjects($first: Int!) {
projects(first: $first, orderBy: updatedAt) {
nodes {
id
name
description
state
url
updatedAt
}
}
}
""",
}
def _extract(action: LinearAction, data: dict) -> list[dict]:
if action == LinearAction.MY_ISSUES:
return data["viewer"]["assignedIssues"]["nodes"]
if action == LinearAction.LIST_TEAMS:
return data["teams"]["nodes"]
if action == LinearAction.LIST_PROJECTS:
return data["projects"]["nodes"]
return []
class LinearTool(BaseTool):
name: str = "Linear API Tool"
description: str = (
"Interact with the Linear project management API. "
"Supports fetching your assigned issues, listing teams, and listing projects."
)
args_schema: Type[BaseModel] = LinearToolInput
def _run(self, action: LinearAction, first: int = 25) -> Any:
api_key = os.environ.get("LINEAR_API_KEY", "")
if not api_key:
raise EnvironmentError("LINEAR_API_KEY environment variable is not set.")
query = _QUERIES[action]
payload = {"query": query, "variables": {"first": first}}
headers = {
"Authorization": api_key,
"Content-Type": "application/json",
}
response = httpx.post(
LINEAR_API_URL,
json=payload,
headers=headers,
timeout=15,
)
response.raise_for_status()
body = response.json()
if "errors" in body:
raise RuntimeError(f"Linear API errors: {body['errors']}")
return _extract(action, body["data"])