feat: pipeline guarantees task submission regardless of LLM tool calling
Added _force_submit() and _is_submitted() helpers. After the agent finishes writing code, the pipeline checks if the task was actually submitted. If not (LLM failed to call tools), the pipeline submits directly via MCP — no LLM involved in the critical submit step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,40 @@ def _is_coding(task: TaskInfo) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _force_submit(task_id: str) -> bool:
|
||||||
|
"""Гарантированно сабмитит задание через MCP напрямую, минуя LLM.
|
||||||
|
|
||||||
|
Вызывается пайплайном после того, как агент написал код в репо.
|
||||||
|
Возвращает True если сабмит прошёл успешно.
|
||||||
|
"""
|
||||||
|
repo_url = f"https://git.brojs.ru/{GITEA_OWNER}/task-{task_id}"
|
||||||
|
update_tool = _get_journal_tool("task_update_answer")
|
||||||
|
submit_tool = _get_journal_tool("task_submit")
|
||||||
|
if not update_tool or not submit_tool:
|
||||||
|
print(f"[pipeline] force_submit: инструменты не найдены")
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
await update_tool.ainvoke({
|
||||||
|
"taskId": task_id,
|
||||||
|
"answerType": "link",
|
||||||
|
"content": repo_url,
|
||||||
|
"commit": {"repoUrl": repo_url, "branch": "main"},
|
||||||
|
})
|
||||||
|
await submit_tool.ainvoke({"taskId": task_id, "confirmSubmit": True})
|
||||||
|
print(f"[pipeline] Задание {task_id[:8]} — сабмит выполнен пайплайном ✓")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[pipeline] force_submit ошибка: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def _is_submitted(task_id: str) -> bool:
|
||||||
|
"""Проверяет, сменился ли статус задания на ready_for_review / done."""
|
||||||
|
data = await _task_json(task_id)
|
||||||
|
status = data.get("status", "")
|
||||||
|
return status in ("ready_for_review", "done")
|
||||||
|
|
||||||
|
|
||||||
async def _task_text(task_id: str) -> str:
|
async def _task_text(task_id: str) -> str:
|
||||||
tool = _get_journal_tool("task_text")
|
tool = _get_journal_tool("task_text")
|
||||||
if not tool:
|
if not tool:
|
||||||
@@ -298,6 +332,12 @@ async def process_one_task(state: PipelineState) -> dict:
|
|||||||
)
|
)
|
||||||
verification = await _verify_repo(repo_name)
|
verification = await _verify_repo(repo_name)
|
||||||
|
|
||||||
|
# Гарантированный сабмит пайплайном — не полагаемся на LLM
|
||||||
|
submitted = await _is_submitted(task_id)
|
||||||
|
if not submitted:
|
||||||
|
print(f"[pipeline] Задание {task_id[:8]} — агент не сабмитил, делаем сами...")
|
||||||
|
await _force_submit(task_id)
|
||||||
|
|
||||||
print(f"[pipeline] Задание {task_id[:8]} — OK (retries={retries})")
|
print(f"[pipeline] Задание {task_id[:8]} — OK (retries={retries})")
|
||||||
results.append({
|
results.append({
|
||||||
"task_id": task_id,
|
"task_id": task_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user