diff --git a/README.md b/README.md index acb095d..331fda0 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Generated A2APack agent for Tasks API. - Source OpenAPI: https://tasks.a2acloud.io/openapi.json -- Generated operations: 6 +- Generated operations: 12 - Main skill: `auto` The generated code is intentionally editable. Tune prompts, operation diff --git a/agent.py b/agent.py index 2e2bfec..91cb196 100644 --- a/agent.py +++ b/agent.py @@ -27,7 +27,7 @@ from a2a_pack import ( DEFAULT_BASE_URL = "https://tasks.a2acloud.io" -OPERATIONS = json.loads("{\n \"create_task\": {\n \"description\": \"Create Task\",\n \"destructive\": true,\n \"method\": \"POST\",\n \"operation_id\": \"create_task\",\n \"parameters\": [],\n \"path\": \"/api/tasks\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/TaskCreate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"create_task\",\n \"summary\": \"Create Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"delete_task\": {\n \"description\": \"Delete Task\",\n \"destructive\": true,\n \"method\": \"DELETE\",\n \"operation_id\": \"delete_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"delete_task\",\n \"summary\": \"Delete Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"get_task\": {\n \"description\": \"Get Task\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"get_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"get_task\",\n \"summary\": \"Get Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"get_tasks_health\": {\n \"description\": \"Healthz\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"get_tasks_health\",\n \"parameters\": [],\n \"path\": \"/healthz\",\n \"request_body\": null,\n \"security\": null,\n \"skill_name\": \"get_tasks_health\",\n \"summary\": \"Healthz\",\n \"tags\": [\n \"Health\"\n ]\n },\n \"list_tasks\": {\n \"description\": \"List Tasks\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"list_tasks\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"status\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"enum\": [\n \"todo\",\n \"in_progress\",\n \"done\",\n \"canceled\"\n ],\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Status\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"q\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"maxLength\": 120,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Q\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"due_before\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Due Before\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"limit\",\n \"required\": false,\n \"schema\": {\n \"default\": 50,\n \"maximum\": 200,\n \"minimum\": 1,\n \"title\": \"Limit\",\n \"type\": \"integer\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"offset\",\n \"required\": false,\n \"schema\": {\n \"default\": 0,\n \"minimum\": 0,\n \"title\": \"Offset\",\n \"type\": \"integer\"\n }\n }\n ],\n \"path\": \"/api/tasks\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"list_tasks\",\n \"summary\": \"List Tasks\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"update_task\": {\n \"description\": \"Update Task\",\n \"destructive\": true,\n \"method\": \"PATCH\",\n \"operation_id\": \"update_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/TaskUpdate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"update_task\",\n \"summary\": \"Update Task\",\n \"tags\": [\n \"Tasks\"\n ]\n }\n}") +OPERATIONS = json.loads("{\n \"create_epic\": {\n \"description\": \"Create Epic\",\n \"destructive\": true,\n \"method\": \"POST\",\n \"operation_id\": \"create_epic\",\n \"parameters\": [],\n \"path\": \"/api/epics\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/EpicCreate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"create_epic\",\n \"summary\": \"Create Epic\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"create_task\": {\n \"description\": \"Create Task\",\n \"destructive\": true,\n \"method\": \"POST\",\n \"operation_id\": \"create_task\",\n \"parameters\": [],\n \"path\": \"/api/tasks\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/TaskCreate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"create_task\",\n \"summary\": \"Create Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"delete_epic\": {\n \"description\": \"Delete Epic\",\n \"destructive\": true,\n \"method\": \"DELETE\",\n \"operation_id\": \"delete_epic\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"epic_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Epic Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/epics/{epic_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"delete_epic\",\n \"summary\": \"Delete Epic\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"delete_task\": {\n \"description\": \"Delete Task\",\n \"destructive\": true,\n \"method\": \"DELETE\",\n \"operation_id\": \"delete_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"delete_task\",\n \"summary\": \"Delete Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"get_epic\": {\n \"description\": \"Get Epic\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"get_epic\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"epic_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Epic Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/epics/{epic_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"get_epic\",\n \"summary\": \"Get Epic\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"get_task\": {\n \"description\": \"Get Task\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"get_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"get_task\",\n \"summary\": \"Get Task\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"get_tasks_health\": {\n \"description\": \"Healthz\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"get_tasks_health\",\n \"parameters\": [],\n \"path\": \"/healthz\",\n \"request_body\": null,\n \"security\": null,\n \"skill_name\": \"get_tasks_health\",\n \"summary\": \"Healthz\",\n \"tags\": [\n \"Health\"\n ]\n },\n \"list_epic_tasks\": {\n \"description\": \"List Epic Tasks\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"list_epic_tasks\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"epic_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Epic Id\",\n \"type\": \"string\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"status\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"enum\": [\n \"todo\",\n \"in_progress\",\n \"done\",\n \"canceled\"\n ],\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Status\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"q\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"maxLength\": 120,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Q\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"due_before\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Due Before\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"limit\",\n \"required\": false,\n \"schema\": {\n \"default\": 50,\n \"maximum\": 200,\n \"minimum\": 1,\n \"title\": \"Limit\",\n \"type\": \"integer\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"offset\",\n \"required\": false,\n \"schema\": {\n \"default\": 0,\n \"minimum\": 0,\n \"title\": \"Offset\",\n \"type\": \"integer\"\n }\n }\n ],\n \"path\": \"/api/epics/{epic_id}/tasks\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"list_epic_tasks\",\n \"summary\": \"List Epic Tasks\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"list_epics\": {\n \"description\": \"List Epics\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"list_epics\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"status\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"enum\": [\n \"todo\",\n \"in_progress\",\n \"done\",\n \"canceled\"\n ],\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Status\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"q\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"maxLength\": 120,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Q\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"due_before\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Due Before\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"limit\",\n \"required\": false,\n \"schema\": {\n \"default\": 50,\n \"maximum\": 200,\n \"minimum\": 1,\n \"title\": \"Limit\",\n \"type\": \"integer\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"offset\",\n \"required\": false,\n \"schema\": {\n \"default\": 0,\n \"minimum\": 0,\n \"title\": \"Offset\",\n \"type\": \"integer\"\n }\n }\n ],\n \"path\": \"/api/epics\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"list_epics\",\n \"summary\": \"List Epics\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"list_tasks\": {\n \"description\": \"List Tasks\",\n \"destructive\": false,\n \"method\": \"GET\",\n \"operation_id\": \"list_tasks\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"status\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"enum\": [\n \"todo\",\n \"in_progress\",\n \"done\",\n \"canceled\"\n ],\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Status\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"q\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"maxLength\": 120,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Q\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"due_before\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Due Before\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"epic_id\",\n \"required\": false,\n \"schema\": {\n \"anyOf\": [\n {\n \"maxLength\": 36,\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"title\": \"Epic Id\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"limit\",\n \"required\": false,\n \"schema\": {\n \"default\": 50,\n \"maximum\": 200,\n \"minimum\": 1,\n \"title\": \"Limit\",\n \"type\": \"integer\"\n }\n },\n {\n \"description\": \"\",\n \"in\": \"query\",\n \"name\": \"offset\",\n \"required\": false,\n \"schema\": {\n \"default\": 0,\n \"minimum\": 0,\n \"title\": \"Offset\",\n \"type\": \"integer\"\n }\n }\n ],\n \"path\": \"/api/tasks\",\n \"request_body\": null,\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"list_tasks\",\n \"summary\": \"List Tasks\",\n \"tags\": [\n \"Tasks\"\n ]\n },\n \"update_epic\": {\n \"description\": \"Update Epic\",\n \"destructive\": true,\n \"method\": \"PATCH\",\n \"operation_id\": \"update_epic\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"epic_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Epic Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/epics/{epic_id}\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/EpicUpdate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"update_epic\",\n \"summary\": \"Update Epic\",\n \"tags\": [\n \"Epics\"\n ]\n },\n \"update_task\": {\n \"description\": \"Update Task\",\n \"destructive\": true,\n \"method\": \"PATCH\",\n \"operation_id\": \"update_task\",\n \"parameters\": [\n {\n \"description\": \"\",\n \"in\": \"path\",\n \"name\": \"task_id\",\n \"required\": true,\n \"schema\": {\n \"title\": \"Task Id\",\n \"type\": \"string\"\n }\n }\n ],\n \"path\": \"/api/tasks/{task_id}\",\n \"request_body\": {\n \"$ref\": \"#/components/schemas/TaskUpdate\"\n },\n \"security\": [\n {\n \"bearerAuth\": []\n },\n {\n \"apiKeyAuth\": []\n }\n ],\n \"skill_name\": \"update_task\",\n \"summary\": \"Update Task\",\n \"tags\": [\n \"Tasks\"\n ]\n }\n}") ROOT_SECURITY = json.loads("[]") SECURITY_SCHEMES = json.loads("{\n \"apiKeyAuth\": {\n \"description\": \"Use the configured `TASKS_API_KEY` value.\",\n \"in\": \"header\",\n \"name\": \"x-api-key\",\n \"type\": \"apiKey\"\n },\n \"bearerAuth\": {\n \"description\": \"Use `Authorization: Bearer $TASKS_API_KEY`.\",\n \"scheme\": \"bearer\",\n \"type\": \"http\"\n }\n}") SECURITY_FIELDS = json.loads("{\n \"apiKeyAuth\": {\n \"field\": \"X_API_KEY\",\n \"kind\": \"apiKey\",\n \"location\": \"header\",\n \"name\": \"x-api-key\"\n },\n \"bearerAuth\": {\n \"field\": \"BEARERAUTH_TOKEN\",\n \"kind\": \"http\",\n \"scheme\": \"bearer\"\n }\n}") @@ -130,6 +130,120 @@ class TasksApi(A2AAgent): body=body, ) + @skill( + name="list_epics", + description="GET /api/epics - List Epics", + tags=('Epics',), + timeout_seconds=60, + ) + async def list_epics( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "list_epics", + parameters=parameters or {}, + body=body, + ) + + @skill( + name="create_epic", + description="POST /api/epics - Create Epic", + tags=('Epics',), + timeout_seconds=120, + ) + async def create_epic( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "create_epic", + parameters=parameters or {}, + body=body, + ) + + @skill( + name="get_epic", + description="GET /api/epics/{epic_id} - Get Epic", + tags=('Epics',), + timeout_seconds=60, + ) + async def get_epic( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "get_epic", + parameters=parameters or {}, + body=body, + ) + + @skill( + name="update_epic", + description="PATCH /api/epics/{epic_id} - Update Epic", + tags=('Epics',), + timeout_seconds=120, + ) + async def update_epic( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "update_epic", + parameters=parameters or {}, + body=body, + ) + + @skill( + name="delete_epic", + description="DELETE /api/epics/{epic_id} - Delete Epic", + tags=('Epics',), + timeout_seconds=120, + ) + async def delete_epic( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "delete_epic", + parameters=parameters or {}, + body=body, + ) + + @skill( + name="list_epic_tasks", + description="GET /api/epics/{epic_id}/tasks - List Epic Tasks", + tags=('Epics',), + timeout_seconds=60, + ) + async def list_epic_tasks( + self, + ctx: RunContext, + parameters: dict[str, Any] | None = None, + body: Any | None = None, + ) -> dict[str, Any]: + return await self._request( + ctx, + "list_epic_tasks", + parameters=parameters or {}, + body=body, + ) + @skill( name="list_tasks", description="GET /api/tasks - List Tasks", @@ -300,6 +414,15 @@ class TasksApi(A2AAgent): "headers": headers, } if body is not None: + if isinstance(body, (bytes, bytearray)): + body = body.decode("utf-8", errors="replace") + if isinstance(body, str): + stripped = body.strip() + if stripped and stripped[0] in "{[": + try: + body = json.loads(stripped) + except ValueError: + pass request_kwargs["json"] = body async with httpx.AsyncClient(timeout=60.0, follow_redirects=True) as client: response = await client.request( diff --git a/openapi.json b/openapi.json index b68229d..3b21601 100644 --- a/openapi.json +++ b/openapi.json @@ -13,6 +13,269 @@ "title": "DeleteOut", "type": "object" }, + "EpicCreate": { + "properties": { + "description": { + "default": "", + "maxLength": 10000, + "title": "Description", + "type": "string" + }, + "due_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due At" + }, + "labels": { + "items": { + "type": "string" + }, + "maxItems": 20, + "title": "Labels", + "type": "array" + }, + "priority": { + "default": 0, + "maximum": 100.0, + "minimum": -100.0, + "title": "Priority", + "type": "integer" + }, + "status": { + "default": "todo", + "enum": [ + "todo", + "in_progress", + "done", + "canceled" + ], + "title": "Status", + "type": "string" + }, + "title": { + "maxLength": 240, + "minLength": 1, + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "EpicCreate", + "type": "object" + }, + "EpicListOut": { + "properties": { + "epics": { + "items": { + "$ref": "#/components/schemas/EpicOut" + }, + "title": "Epics", + "type": "array" + }, + "limit": { + "title": "Limit", + "type": "integer" + }, + "offset": { + "title": "Offset", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "epics", + "total", + "limit", + "offset" + ], + "title": "EpicListOut", + "type": "object" + }, + "EpicOut": { + "properties": { + "completed_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "due_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due At" + }, + "id": { + "title": "Id", + "type": "string" + }, + "labels": { + "items": { + "type": "string" + }, + "title": "Labels", + "type": "array" + }, + "priority": { + "title": "Priority", + "type": "integer" + }, + "status": { + "enum": [ + "todo", + "in_progress", + "done", + "canceled" + ], + "title": "Status", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + } + }, + "required": [ + "id", + "title", + "description", + "status", + "priority", + "labels", + "due_at", + "completed_at", + "created_at", + "updated_at" + ], + "title": "EpicOut", + "type": "object" + }, + "EpicUpdate": { + "properties": { + "description": { + "anyOf": [ + { + "maxLength": 10000, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "due_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due At" + }, + "labels": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "maxItems": 20, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Labels" + }, + "priority": { + "anyOf": [ + { + "maximum": 100.0, + "minimum": -100.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Priority" + }, + "status": { + "anyOf": [ + { + "enum": [ + "todo", + "in_progress", + "done", + "canceled" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "title": { + "anyOf": [ + { + "maxLength": 240, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + } + }, + "title": "EpicUpdate", + "type": "object" + }, "HTTPValidationError": { "properties": { "detail": { @@ -77,6 +340,18 @@ ], "title": "Due At" }, + "epic_id": { + "anyOf": [ + { + "maxLength": 36, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Epic Id" + }, "labels": { "items": { "type": "string" @@ -182,6 +457,17 @@ ], "title": "Due At" }, + "epic_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Epic Id" + }, "id": { "title": "Id", "type": "string" @@ -225,6 +511,7 @@ "priority", "labels", "due_at", + "epic_id", "completed_at", "created_at", "updated_at" @@ -258,6 +545,18 @@ ], "title": "Due At" }, + "epic_id": { + "anyOf": [ + { + "maxLength": 36, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Epic Id" + }, "labels": { "anyOf": [ { @@ -382,6 +681,460 @@ }, "openapi": "3.1.0", "paths": { + "/api/epics": { + "get": { + "operationId": "listEpics", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "enum": [ + "todo", + "in_progress", + "done", + "canceled" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "q", + "required": false, + "schema": { + "anyOf": [ + { + "maxLength": 120, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Q" + } + }, + { + "in": "query", + "name": "due_before", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Before" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicListOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "List Epics", + "tags": [ + "Epics" + ] + }, + "post": { + "operationId": "createEpic", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "Create Epic", + "tags": [ + "Epics" + ] + } + }, + "/api/epics/{epic_id}": { + "delete": { + "operationId": "deleteEpic", + "parameters": [ + { + "in": "path", + "name": "epic_id", + "required": true, + "schema": { + "title": "Epic Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "Delete Epic", + "tags": [ + "Epics" + ] + }, + "get": { + "operationId": "getEpic", + "parameters": [ + { + "in": "path", + "name": "epic_id", + "required": true, + "schema": { + "title": "Epic Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "Get Epic", + "tags": [ + "Epics" + ] + }, + "patch": { + "operationId": "updateEpic", + "parameters": [ + { + "in": "path", + "name": "epic_id", + "required": true, + "schema": { + "title": "Epic Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EpicOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "Update Epic", + "tags": [ + "Epics" + ] + } + }, + "/api/epics/{epic_id}/tasks": { + "get": { + "operationId": "listEpicTasks", + "parameters": [ + { + "in": "path", + "name": "epic_id", + "required": true, + "schema": { + "title": "Epic Id", + "type": "string" + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "enum": [ + "todo", + "in_progress", + "done", + "canceled" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "in": "query", + "name": "q", + "required": false, + "schema": { + "anyOf": [ + { + "maxLength": 120, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Q" + } + }, + { + "in": "query", + "name": "due_before", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Due Before" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskListOut" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "summary": "List Epic Tasks", + "tags": [ + "Epics" + ] + } + }, "/api/tasks": { "get": { "operationId": "listTasks", @@ -443,6 +1196,23 @@ "title": "Due Before" } }, + { + "in": "query", + "name": "epic_id", + "required": false, + "schema": { + "anyOf": [ + { + "maxLength": 36, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Epic Id" + } + }, { "in": "query", "name": "limit",