This PR adds a simplified Linear toolkit focused on core functionality: ## What's Included **Tools:** - `get_issue` - Get detailed information about Linear issues - `get_teams` - Get team information and details **Models:** - `DateRange` enum with comprehensive date range support (TODAY, YESTERDAY, THIS_WEEK, LAST_WEEK, THIS_MONTH, LAST_MONTH, THIS_YEAR, LAST_YEAR, LAST_7_DAYS, LAST_30_DAYS) - Timezone-aware datetime handling following Google toolkit patterns ## What's Simplified This toolkit has been streamlined by removing: - Cycles management tools - Projects management tools - Users management tools - Workflows management tools - Corresponding tests and evaluations for removed features ## Quality Assurance - All linting and formatting checks pass - Comprehensive test coverage for included functionality - Follows established patterns from Google toolkit --------- Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>
107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
from typing import Annotated, Any
|
|
|
|
from arcade_tdk import ToolContext, tool
|
|
from arcade_tdk.auth import Linear
|
|
|
|
from arcade_linear.client import LinearClient
|
|
from arcade_linear.utils import (
|
|
add_pagination_info,
|
|
clean_team_data,
|
|
parse_date_string,
|
|
validate_date_format,
|
|
)
|
|
|
|
|
|
@tool(requires_auth=Linear(scopes=["read"]))
|
|
async def get_teams(
|
|
context: ToolContext,
|
|
team_name: Annotated[
|
|
str | None,
|
|
"Filter by team name. Provide specific team name (e.g. 'Frontend', 'Product Web') "
|
|
"or partial name. Use this to find specific teams or check team membership. "
|
|
"Defaults to None (all teams).",
|
|
] = None,
|
|
include_archived: Annotated[
|
|
bool, "Whether to include archived teams in results. Defaults to False."
|
|
] = False,
|
|
created_after: Annotated[
|
|
str | None,
|
|
"Filter teams created after this date. Can be:\n"
|
|
"- Relative date string (e.g. 'last month', 'this week', 'yesterday')\n"
|
|
"- ISO date string (e.g. 'YYYY-MM-DD')\n"
|
|
"Defaults to None (all time).",
|
|
] = None,
|
|
limit: Annotated[
|
|
int, "Maximum number of teams to return. Min 1, max 100. Defaults to 50."
|
|
] = 50,
|
|
end_cursor: Annotated[
|
|
str | None,
|
|
"Cursor for pagination - get teams after this cursor. Use the 'end_cursor' "
|
|
"from previous response. Defaults to None (start from beginning).",
|
|
] = None,
|
|
) -> Annotated[dict[str, Any], "Teams in the workspace with member information"]:
|
|
"""Get Linear teams and team information including team members
|
|
|
|
This tool retrieves team information from your Linear workspace, including team details,
|
|
settings, and member information. Use this tool for team discovery and team membership queries.
|
|
|
|
What this tool provides:
|
|
- Team basic information (name, key, description)
|
|
- Team members and their roles
|
|
- Team settings and configuration
|
|
- Team creation and status information
|
|
- Team hierarchy and relationships
|
|
|
|
This tool is the primary way to get team information.
|
|
"""
|
|
|
|
# Validate inputs
|
|
limit = max(1, min(limit, 100))
|
|
|
|
# Parse and validate date
|
|
created_after_date = None
|
|
if created_after:
|
|
# Validate and parse string (handles DateRange enum strings internally)
|
|
validate_date_format("created_after", created_after)
|
|
created_after_date = parse_date_string(created_after)
|
|
|
|
client = LinearClient(context.get_auth_token_or_empty())
|
|
|
|
# Get teams with filtering
|
|
teams_response = await client.get_teams(
|
|
first=limit,
|
|
after=end_cursor,
|
|
include_archived=include_archived,
|
|
name_filter=team_name,
|
|
)
|
|
|
|
# Apply additional filtering if needed
|
|
teams = teams_response["nodes"]
|
|
|
|
# Filter by creation date if specified
|
|
if created_after_date:
|
|
filtered_teams = []
|
|
for team in teams:
|
|
team_created_at = parse_date_string(team.get("createdAt", ""))
|
|
if team_created_at and team_created_at >= created_after_date:
|
|
filtered_teams.append(team)
|
|
teams = filtered_teams
|
|
|
|
# Clean and format teams
|
|
cleaned_teams = [clean_team_data(team) for team in teams]
|
|
|
|
response = {
|
|
"teams": cleaned_teams,
|
|
"total_count": len(cleaned_teams),
|
|
"filters": {
|
|
"team_name": team_name,
|
|
"include_archived": include_archived,
|
|
"created_after": created_after,
|
|
},
|
|
}
|
|
|
|
# Add pagination info
|
|
if "pageInfo" in teams_response and teams_response["pageInfo"].get("hasNextPage"):
|
|
add_pagination_info(response, teams_response["pageInfo"])
|
|
|
|
return response
|