feat: add official Codex skill and harden task execution
Install and update artemis-use with task diagnostics and plugin guidance. Preserve cross-device file receipts, review canonical reports, guard stage transitions and reduce small history summaries. Improve exploration lifecycle, request recovery and browser live connections.
This commit is contained in:
1 parent
2328a4df0c
commit
e1ea099592
128 files changed
+4944
-700
No files matched your search
@@ -254,18 +254,28 @@ def _mark_liveness_failure(trace_id: str, status_data: dict[str, Any]) -> None:
|
||||
@mcp.tool()
|
||||
def mobile_manage_task(
|
||||
action: str,
|
||||
trace_id: str,
|
||||
trace_id: str = "",
|
||||
instruction: str | None = None,
|
||||
release_loop: bool = False,
|
||||
request_id: str | None = None,
|
||||
review_status: str | None = None,
|
||||
review_reason: str = "",
|
||||
user_confirmed: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""Manages the lifecycle and retrieves the status of a background mobile automation task.
|
||||
|
||||
This is your primary diagnostic and control tool for tasks started by
|
||||
`mobile_run_task` or the web workspace. You MUST use it to poll the task status when your
|
||||
1-minute fallback timer triggers (as required by `mobile_run_task`). You
|
||||
can also steer a subagent that is stuck or off-track, or abort a task.
|
||||
`mobile_run_task` or the web workspace. Poll with reasonable intervals while
|
||||
following a running task; use request diagnostics for unexplained waits.
|
||||
You can also steer a runner that is stuck or off-track, or stop a task.
|
||||
|
||||
### Actions
|
||||
- lookup: Resolve a submission by request_id without starting or resubmitting it.
|
||||
- deletion_preview / delete: Show affected session IDs, then delete only when
|
||||
the user requested it (user_confirmed=true). Active tasks cannot be deleted.
|
||||
An exploration deletes its conversation runs, preserving independent reruns.
|
||||
- review: Record ONLY the user's explicitly stated passed/failed decision with
|
||||
review_reason and user_confirmed=true. Never label the agent's verdict as human.
|
||||
- **'status'**: Returns `trace_id`, `status` ('running'/'pausing'/'task_paused'/
|
||||
'resuming'/'completed'/'failed'/'cancelled'/'interrupted'), `device_serial` (which phone owns this task in multi-device
|
||||
setups), `task_desc`, `model`, `elapsed_seconds`, a `test_summary` (when
|
||||
@@ -311,6 +321,31 @@ def mobile_manage_task(
|
||||
that authorizes the subagent to complete continuous monitoring
|
||||
loops and finish the task gracefully.
|
||||
"""
|
||||
from mcp_server.tools.automation import _id, _request
|
||||
import asyncio
|
||||
|
||||
if action == "lookup":
|
||||
from mcp_server.task_requests import lookup
|
||||
|
||||
return lookup(_id(request_id))
|
||||
_id(trace_id)
|
||||
if action in {"deletion_preview", "delete", "review"}:
|
||||
if action != "deletion_preview" and not user_confirmed:
|
||||
raise ValueError("此动作需要用户明确要求;AI 自行判断不能记作人工复验")
|
||||
if action == "deletion_preview":
|
||||
return asyncio.run(_request("GET", f"/api/sessions/{trace_id}/deletion-preview"))
|
||||
if action == "delete":
|
||||
return asyncio.run(_request("POST", f"/api/sessions/{trace_id}/delete"))
|
||||
if review_status not in {"passed", "failed"}:
|
||||
raise ValueError("review_status 必须为 passed 或 failed")
|
||||
result = asyncio.run(
|
||||
_request(
|
||||
"PUT",
|
||||
f"/api/automation/reports/{trace_id}/review",
|
||||
json={"status": review_status, "reason": review_reason},
|
||||
)
|
||||
)
|
||||
return {"trace_id": trace_id, "test_result": result.get("test_result")}
|
||||
status_data = trace_store.read_status(trace_id) or _web_session_status(trace_id)
|
||||
if not status_data:
|
||||
return {
|
||||
@@ -438,6 +473,15 @@ def mobile_manage_task(
|
||||
test_result = resolve_case_result(None, current_status, response.get("error") or "")
|
||||
response["test_result"] = test_result.model_dump() if test_result else None
|
||||
|
||||
from apps.admin_console.services.case_review import reviewed_result
|
||||
from apps.admin_console.services.automation_store import AutomationStore
|
||||
from pathlib import Path
|
||||
|
||||
review_store = AutomationStore(Path(db_path))
|
||||
response["test_result"] = reviewed_result(
|
||||
trace_id, response.get("test_result"), review_store
|
||||
)
|
||||
|
||||
if current_status in ("running", "pending", "task_paused", "resuming") and is_alive:
|
||||
progress: dict[str, Any] = {}
|
||||
|
||||
@@ -472,12 +516,13 @@ def mobile_manage_task(
|
||||
conn2.row_factory = sqlite3.Row
|
||||
cur2 = conn2.cursor()
|
||||
cur2.execute(
|
||||
"SELECT count(*) as cnt FROM traces WHERE session_id = ? AND type = 'llm_call'",
|
||||
"SELECT coalesce(max(step_number),0) as cnt FROM steps WHERE session_id = ?",
|
||||
(session_id,),
|
||||
)
|
||||
row_cnt = cur2.fetchone()
|
||||
if row_cnt:
|
||||
progress["current_turn"] = row_cnt["cnt"]
|
||||
progress["current_step"] = row_cnt["cnt"]
|
||||
|
||||
cur2.execute(
|
||||
"SELECT payload FROM traces WHERE session_id = ? AND type in ('raw_thinking', 'llm_call') "
|
||||
|
||||
Reference in new issue
Block a user