diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8bcde47 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +### 2026-09-19 +1. Created an agent that can accept YouTrack™ task ID, read an issue, create a context for a task (body, comments, image attachments) and decompose it for implementing +2. **[missing]** extract a decomposing because it's manner depends on the task context (i.e. backend-dev, frontend-dev, seller, marketing, ad, design, ...) so an issue_reader agent should listen for not delivered tasks, create a context and delegate a decomposition for specific agent. If there is no agent can create this work - add comment that it cannot be resolved until appropriate agent will be created, assign a task to admin and change status to "To Be Discussed". There should be an agent that has information about all the rest of agents and can provide the information, who can do that task and how (in case of confusing - ask another agents if they can do the task). As this architecture is a very future automatization, it is enough to have just a registry of agents and omit the conversation of issue reader with another agents. \ No newline at end of file diff --git a/agents/backend_dev/BackendDeveloperAgent.py b/agents/issue_reader/IssueReaderAgent.py similarity index 73% rename from agents/backend_dev/BackendDeveloperAgent.py rename to agents/issue_reader/IssueReaderAgent.py index 4ffc82e..3a9aa69 100644 --- a/agents/backend_dev/BackendDeveloperAgent.py +++ b/agents/issue_reader/IssueReaderAgent.py @@ -1,25 +1,22 @@ """ -Backend Developer Agent -This agent specializes in backend development tasks including: -- API development with FastAPI -- Database design and management -- Server-side programming -- System architecture +Issue Decomposing Agent +This agent specializes in development tasks including: +- Web systems architecture """ from typing import Dict, Any import json -from agents.backend_dev.models import TaskPlan -from agents.backend_dev.decomposer import IssueDecomposer -from agents.backend_dev.validator import enforce +from agents.issue_reader.models import TaskPlan +from agents.issue_reader.decomposer import IssueDecomposer +from agents.issue_reader.validator import enforce from common.youtrack_mcp_client import IssueNotFound -class BackendDeveloperAgent: +class IssueReaderAgent: def __init__(self, context_builder, llm): - self.name = "Backend Developer" + self.name = "Issue decomposing agent" self.ctx_builder = context_builder self.decomposer = IssueDecomposer(llm) diff --git a/agents/backend_dev/README.md b/agents/issue_reader/README.md similarity index 100% rename from agents/backend_dev/README.md rename to agents/issue_reader/README.md diff --git a/agents/backend_dev/__init__.py b/agents/issue_reader/__init__.py similarity index 100% rename from agents/backend_dev/__init__.py rename to agents/issue_reader/__init__.py diff --git a/agents/backend_dev/context_builder.py b/agents/issue_reader/context_builder.py similarity index 97% rename from agents/backend_dev/context_builder.py rename to agents/issue_reader/context_builder.py index fa3a1ad..51a5732 100644 --- a/agents/backend_dev/context_builder.py +++ b/agents/issue_reader/context_builder.py @@ -5,8 +5,8 @@ import re import httpx -from agents.backend_dev.models import IssueContext -from agents.backend_dev.project_loader import load_project +from agents.issue_reader.models import IssueContext +from agents.issue_reader.project_loader import load_project from common.as_type import _as_dict, _as_list, _first, _extract_base64 from common.youtrack_mcp_client import IssueNotFound diff --git a/agents/backend_dev/decomposer.py b/agents/issue_reader/decomposer.py similarity index 97% rename from agents/backend_dev/decomposer.py rename to agents/issue_reader/decomposer.py index 81751db..f253dd1 100644 --- a/agents/backend_dev/decomposer.py +++ b/agents/issue_reader/decomposer.py @@ -3,10 +3,10 @@ import json from openai import images -from agents.backend_dev.models import IssueContext, Task, TaskPlan, TaskKind, Atomicity +from agents.issue_reader.models import IssueContext, Task, TaskPlan, TaskKind, Atomicity -SYSTEM_PROMPT = """You are a senior backend engineer. +SYSTEM_PROMPT = """You are a senior engineer. Your job: given a YouTrack issue, its comments, and the project context, produce the SMALLEST possible sequence of tasks to resolve it. diff --git a/agents/backend_dev/models.py b/agents/issue_reader/models.py similarity index 100% rename from agents/backend_dev/models.py rename to agents/issue_reader/models.py diff --git a/agents/backend_dev/project_loader.py b/agents/issue_reader/project_loader.py similarity index 87% rename from agents/backend_dev/project_loader.py rename to agents/issue_reader/project_loader.py index 59e5a61..cb7147d 100644 --- a/agents/backend_dev/project_loader.py +++ b/agents/issue_reader/project_loader.py @@ -1,6 +1,6 @@ from pathlib import Path import yaml -from agents.backend_dev.models import ProjectContext +from agents.issue_reader.models import ProjectContext PROJECTS_DIR = Path(__file__).parent.parent.parent / "projects" diff --git a/agents/backend_dev/validator.py b/agents/issue_reader/validator.py similarity index 93% rename from agents/backend_dev/validator.py rename to agents/issue_reader/validator.py index 64a5b4d..6fa99b7 100644 --- a/agents/backend_dev/validator.py +++ b/agents/issue_reader/validator.py @@ -1,5 +1,5 @@ # validator.py -from agents.backend_dev.models import Task, TaskPlan, Atomicity +from agents.issue_reader.models import Task, TaskPlan, Atomicity MAX_HOURS = 8 VAGUE_VERBS = ("handle", "support", "improve", "refactor", "manage", "deal with") diff --git a/main.py b/main.py index 1beeee2..0ded5eb 100644 --- a/main.py +++ b/main.py @@ -5,8 +5,8 @@ from contextlib import asynccontextmanager import httpx from dotenv import load_dotenv from fastapi import FastAPI, HTTPException -from agents.backend_dev.BackendDeveloperAgent import BackendDeveloperAgent -from agents.backend_dev.context_builder import YouTrackContextBuilder +from agents.issue_reader.IssueReaderAgent import IssueReaderAgent +from agents.issue_reader.context_builder import YouTrackContextBuilder from common.llm_client import LLMClient from common.youtrack_mcp_client import YouTrackMCPClient, IssueNotFound @@ -34,7 +34,7 @@ async def lifespan(app: FastAPI): follow_redirects=True, ) - app.state.backend_agent = BackendDeveloperAgent( + app.state.issue_reader_agent = IssueReaderAgent( YouTrackContextBuilder(mcp, http_for_attachments), LLMClient( base_url=env("LLM_ADDRESS"), @@ -59,18 +59,18 @@ async def say_hello(name: str): return {"message": f"Hello {name}"} -@app.get("/backend") -async def backend_task(task: str): - agent: BackendDeveloperAgent = app.state.backend_agent +@app.get("/decomposing") +async def decomposing_issue(issue: str): + agent: IssueReaderAgent = app.state.issue_reader_agent try: - logger.info(f"Received task: {task}") - plan = await agent.plan_issue(task) + logger.info(f"Received an issue: {issue}") + plan = await agent.plan_issue(issue) logger.info("Task planning successful.") print(agent.render(plan)) return {"plan": plan} except IssueNotFound: - logger.error(f"Issue {task} not found.") - raise HTTPException(status_code=404, detail=f"Issue {task} not found") + logger.error(f"Issue {issue} not found.") + raise HTTPException(status_code=404, detail=f"Issue {issue} not found") except Exception as e: logger.exception("An unexpected error occurred") return {"error": str(e)}