feat: add guided exploration and share user-started MCP backend

This commit is contained in:
chenmingxuan committed 2026-10-16 18:32:46 +08:00
1 parent f86db1ced6
commit ee256ad7ce
144 files changed
+8625 -2075

No files matched your search

+56 -1
View File
@@ -513,6 +513,9 @@ class OperatorNode:
fallback_limit = settings.ARTEMIS_TOOL_FALLBACK_MAX_NO_PROGRESS_ATTEMPTS
active_llm = base_llm
using_tool_fallback = False
exploration_plan_before = (
self._read_task_plan_text() if getattr(self.ctx, "exploration_id", None) else None
)
for iteration in range(max_iterations):
control = getattr(self.ctx, "task_control", None)
@@ -553,6 +556,10 @@ class OperatorNode:
if interrupted:
return None, None, None, False
assert response is not None
if getattr(self.ctx, "exploration_id", None):
from artemis.exploration.runtime import publish_response
publish_response(self.ctx, response)
if isinstance(control, TaskControl) and has_pending_instruction(control.directory):
# The model answered a prompt that predates the user's new direction.
return None, None, None, False
@@ -687,6 +694,12 @@ class OperatorNode:
if other_calls:
results = []
for tc in other_calls:
if (
isinstance(control, TaskControl)
and (control.directory / "pause.request").exists()
):
results.append(("已请求暂停,未执行该工具;恢复后重新观察。", "error"))
continue
tool_name = tc["name"]
logger.info(f"Operator requested tool: {tool_name}")
if tool_name in ["ask_diagnoser", "video_analyzer"]:
@@ -862,7 +875,19 @@ class OperatorNode:
action_calls = []
if isinstance(control, TaskControl) and has_pending_instruction(control.directory):
if isinstance(control, TaskControl) and (
has_pending_instruction(control.directory)
or (control.directory / "pause.request").exists()
):
current_messages.extend(tool_outputs)
for action in action_calls:
current_messages.append(
ToolMessage(
tool_call_id=action["id"],
content="探索已暂停或收到新指导,未执行该操作。",
status="error",
)
)
return None, None, None, False
if action_calls:
@@ -958,6 +983,32 @@ class OperatorNode:
for tm in tool_outputs:
current_messages.append(tm)
if (
getattr(self.ctx, "exploration_id", None)
and other_calls
and not has_terminal_calls
and not other_tool_failed
):
from artemis.exploration.runtime import needs_exploration_turn
plan_after = self._read_task_plan_text()
snapshot = parse_plan(plan_after or "")
if (
plan_after != exploration_plan_before
and snapshot.has_top_level
and snapshot.all_top_level_done
and (
not snapshot.continuous_top_level
or getattr(state, "user_stop_requested", False)
)
and not needs_exploration_turn(self.ctx)
):
# Completing the plan is useful progress. Return to the
# convergence gate and final review instead of demanding
# another device action just to end the operator turn.
logger.info("Exploration plan completed; returning for final review.")
break
if action_calls and not validation_errors:
break
@@ -1103,6 +1154,10 @@ class OperatorNode:
from langchain_core.messages import SystemMessage
messages.insert(0, SystemMessage(content=self.ctx.plugins.prompt()))
if getattr(self.ctx, "exploration_id", None):
from artemis.exploration.runtime import exploration_messages
messages[0:0] = exploration_messages(self.ctx)
# 8. Invoke LLM Loop
new_subagent_calls = []