add ui, refactor agent, fix pipeline

This commit is contained in:
2026-06-04 20:01:44 +03:00
parent 7e6d3a906b
commit bb895612a0
10 changed files with 898 additions and 81 deletions
+7 -19
View File
@@ -1,12 +1,10 @@
"""Создание агентов: главный оркестратор, исполнитель ДЗ, агент пересдачи."""
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, FilesystemBackend, LocalShellBackend
from deepagents.backends import LocalShellBackend
from src.agent.constants import (
AGENT_WORKSPACE_DIR,
AGENTS_MD_VFS_PATH,
BUNDLED_SKILLS_DIR,
SKILLS_VFS_MOUNT,
ensure_agents_md_file,
)
from src.agent.gitea_tools import GITEA_TOOLS
@@ -19,7 +17,7 @@ from src.agent.prompts import (
rework_instructions,
)
from src.agent.subagents import subagent_specs_without_tools
from src.agent.tools import GIT_TOOLS, WEB_TOOLS
from src.agent.tools import GIT_TOOLS
# ---------------------------------------------------------------------------
# Инициализация
@@ -36,29 +34,19 @@ print(f"=== Загружено: journal={len(_journal_tools)}, gitea={len(GITEA_
# Бэкенды (виртуальная файловая система агента)
# ---------------------------------------------------------------------------
_workspace_backend = LocalShellBackend(
_composite_backend = LocalShellBackend(
root_dir=str(AGENT_WORKSPACE_DIR),
virtual_mode=True,
inherit_env=True,
)
_skills_backend = FilesystemBackend(
root_dir=str(BUNDLED_SKILLS_DIR),
virtual_mode=True,
)
_composite_backend = CompositeBackend(
default=_workspace_backend,
routes={SKILLS_VFS_MOUNT: _skills_backend},
)
# ---------------------------------------------------------------------------
# Наборы инструментов
# ---------------------------------------------------------------------------
_homework_tools = [*GIT_TOOLS, *GITEA_TOOLS, *WEB_TOOLS, *_journal_tools]
_web_tools = WEB_TOOLS
_homework_tools = [*GIT_TOOLS, *GITEA_TOOLS, *_journal_tools]
_subagent_tool_map = {
"web_search": _web_tools,
"homework_doing": _homework_tools,
"journal_bh_tasks_submissions": _journal_tools,
}
@@ -71,13 +59,11 @@ _BUILTIN = {
_gitea_names = {t.name for t in GITEA_TOOLS}
_journal_names = {t.name for t in _journal_tools}
_git_names = {t.name for t in GIT_TOOLS}
_web_names = {t.name for t in WEB_TOOLS}
_main_tool_names = _BUILTIN | _gitea_names
_subagent_tool_names: dict[str, set[str]] = {
"web_search": _BUILTIN | _web_names,
"homework_doing": _BUILTIN | _gitea_names | _journal_names | _git_names | _web_names,
"homework_doing": _BUILTIN | _gitea_names | _journal_names | _git_names,
"journal_bh_tasks_submissions": _BUILTIN | _journal_names,
}
@@ -92,6 +78,8 @@ def _make_subagent_middleware(name: str) -> list:
return mw
# ---------------------------------------------------------------------------
# Субагенты с инструментами и middleware
# ---------------------------------------------------------------------------
-2
View File
@@ -4,11 +4,9 @@ from pathlib import Path
PACKAGE_DIR = Path(__file__).resolve().parent
AGENT_WORKSPACE_DIR = PACKAGE_DIR / "agent_workspace"
BUNDLED_SKILLS_DIR = PACKAGE_DIR / "skills"
AGENTS_MD_FILENAME = "AGENTS.md"
AGENTS_MD_VFS_PATH = "/AGENTS.md"
SKILLS_VFS_MOUNT = "/skills/"
# ID курса KFU-26-1 на platform.brojs.ru
COURSE_ID = "698b49da77cb6d4d2e43ce78"
+6 -6
View File
@@ -183,8 +183,8 @@ def _fix_prompt(task: TaskInfo, repo_name: str, v: dict) -> str:
MAX_RETRIES = 2
RATE_LIMIT_RETRIES = 5 # сколько раз повторять при 429
RATE_LIMIT_PAUSE = 90 # секунд ожидания перед повтором
TASK_PAUSE = 15 # пауза между заданиями (снижает давление на rate limit)
RATE_LIMIT_PAUSE = 10 # секунд ожидания перед повтором
TASK_PAUSE = 10 # пауза между заданиями (снижает давление на rate limit)
def _is_rate_limit(exc) -> bool:
@@ -251,7 +251,7 @@ async def fetch_tasks(state: PipelineState) -> dict:
if hasattr(e, "exceptions"):
full += " ".join(repr(sub) for sub in e.exceptions)
if "429" in full and attempt < 5:
wait = 90 * attempt
wait = 10 * attempt
print(f"[pipeline] fetch_tasks: rate limit, жду {wait}с (попытка {attempt}/5)...")
await asyncio.sleep(wait)
else:
@@ -314,8 +314,8 @@ async def _force_submit(task_id: str, repo_url: str) -> None:
if hasattr(e, "exceptions"):
full += " ".join(repr(sub) for sub in e.exceptions)
if "429" in full and attempt < 5:
print(f"[pipeline] [AUTO] Rate limit, жду 70с...")
await asyncio.sleep(70)
print(f"[pipeline] [AUTO] Rate limit, жду 10с...")
await asyncio.sleep(10)
else:
print(f"[pipeline] [AUTO] Ошибка при сдаче: {full[:200]}")
return
@@ -346,7 +346,7 @@ async def process_one_task(state: PipelineState) -> dict:
f"4. В requirements.txt включай ТОЛЬКО пакеты из стека задания — не добавляй ничего лишнего.\n\n"
f"ВАЖНО: в конце обязательно вызови task_submit(taskId='{task_id}', confirmSubmit=True)!"
)
agent_to_use = homework_direct_agent
agent_to_use = rework_agent
else:
prompt = (
f"Выполни задание.\n\n"
@@ -128,7 +128,7 @@ class ValidateJournalWorkflowMiddleware(AgentMiddleware[AgentState[Any], Any]):
return ToolMessage(
content=(
f"Ошибка rate limit (429) от Journal API при вызове {tool_name}.\n"
"Подожди ~60 секунд и повтори этот же вызов."
"Подожди ~10 секунд и повтори этот же вызов."
),
tool_call_id=request.tool_call["id"],
name=tool_name,
-10
View File
@@ -3,19 +3,9 @@ from src.agent.llm import llm
from src.agent.prompts import (
homework_doing_instructions,
journal_tasks_submissions_instructions,
research_instructions,
)
subagent_specs_without_tools: list[dict] = [
{
"name": "web_search",
"description": (
"Ищет информацию в интернете, находит URL и открывает страницы, "
"чтобы извлекать факты только из реально прочитанного контента"
),
"model": llm,
"system_prompt": research_instructions,
},
{
"name": "homework_doing",
"description": (