fix: improve cross-device evidence, request diagnostics and prompt efficiency

This commit is contained in:
chenmingxuan committed 2026-10-17 14:55:45 +08:00
1 parent 621f30e437
commit a66803651a
60 files changed
+3097 -160

No files matched your search

+66 -7
View File
@@ -295,7 +295,16 @@ class OperatorNode:
kwargs_to_pass.update(extra_kwargs)
await component(builder, state, self.ctx, **kwargs_to_pass)
return builder.build()
messages = builder.build()
if getattr(state, "structured_decisions", None):
from langchain_core.messages import HumanMessage
# The legacy prompt has no preceding AI tool calls. Deliver the
# same evidence as observations, without orphan function outputs.
for results in self._plugin_result_messages(state.last_execution_result).values():
for result in results:
messages.append(HumanMessage(content=result.content))
return messages
# ------------------------------------------------------------------
# Transcript prompt path (M2, flag agent.memory.transcript.enabled)
@@ -358,6 +367,11 @@ class OperatorNode:
pass
return ledger
def _plugin_result_messages(self, report: Any) -> dict[str, list[BaseMessage]]:
from artemis.plugins.results import plugin_result_messages
return plugin_result_messages(report, self.ctx.data_engine)
async def _build_prompt_transcript(
self,
state: State,
@@ -385,7 +399,15 @@ class OperatorNode:
# 1. S region: rendered exactly once per session.
if not ledger.has_static_prefix:
static_text = render_transcript_static_system(self.prompts, self.ctx, state)
ledger.set_static_prefix([SystemMessage(content=static_text)])
prefix = []
if getattr(self.ctx, "exploration_id", None):
from artemis.exploration.runtime import exploration_prompt
prefix.append(exploration_prompt(self.ctx))
if getattr(self.ctx, "plugins", None):
prefix.append(self.ctx.plugins.prompt())
prefix.append(static_text)
ledger.set_static_prefix([SystemMessage(content="\n".join(prefix))])
# 2. F region cold start: an empty ledger over an existing step record
# trail means the process restarted — freeze the compiled history once.
@@ -423,10 +445,21 @@ class OperatorNode:
ledger.commit_staged(
step_key=getattr(state, "current_step_id", None),
validator_result=validator_result,
tool_results=self._plugin_result_messages(validator_result),
)
# 4. Current tail: observation + plan recitation + injected components.
builder = PromptBuilder()
guidance = None
if getattr(self.ctx, "exploration_id", None):
from artemis.exploration.runtime import exploration_messages
# Guidance belongs at the append-only tail, never before the
# reusable rules/history. Assistant progress does not change it.
guidance = exploration_messages(self.ctx)[1].content
if guidance != getattr(self, "_last_exploration_guidance", None):
builder.add_human_content(guidance)
self._pending_exploration_guidance = guidance
builder.add_human_content(f"# CURRENT OBSERVATION [{ledger.elapsed_label()}]")
components = [
(PlanRecitationPromptComponent(), {}),
@@ -468,6 +501,24 @@ class OperatorNode:
mark_ephemeral(tail, builder.ephemeral_indices)
messages = ledger.render([tail])
# Compaction can remove the original guidance message. Restore the
# exact current instructions once at the new tail, without changing
# the reusable prefix or relying on a lossy history capsule.
if guidance is not None and not any(
guidance
in (
message.content
if isinstance(message.content, str)
else "\n".join(
block.get("text", "") for block in message.content if isinstance(block, dict)
)
)
for message in messages
if isinstance(message, HumanMessage)
):
tail_content.append({"type": "text", "text": guidance})
tail.content = tail_content
self._pending_exploration_guidance = guidance
self._transcript_turn_tail = tail
return messages
@@ -482,6 +533,9 @@ class OperatorNode:
if ledger is not None:
base = next(i for i, message in enumerate(messages) if message is tail)
ledger.stage_turn(messages[base:])
if hasattr(self, "_pending_exploration_guidance"):
self._last_exploration_guidance = self._pending_exploration_guidance
del self._pending_exploration_guidance
except Exception as e:
logger.error(f"Failed to stage transcript turn: {e}")
@@ -547,7 +601,7 @@ class OperatorNode:
t
for t in traced_tools
if not t.name.startswith("plug_")
and t.name not in {"plugin_load", "plugin_read_file"}
and t.name not in {"plugin_load", "plugin_read_file", "plugin_read_result"}
]
traced_tools.extend(plugins.langchain_tools())
bound_llm = active_llm.bind_tools(tools=traced_tools)
@@ -903,6 +957,9 @@ class OperatorNode:
not plan_gate_bounced
and iteration < max_iterations - 1
and len(action_calls) == 1
and not (
plugins and plugins.is_read_only(normalize_name(action_calls[0]["name"]))
)
and not getattr(state, "open_incident", None)
and self._plan_changed_this_turn() is False
):
@@ -1151,14 +1208,16 @@ class OperatorNode:
active_background_tasks=active_background_tasks,
newly_finished_tasks=newly_finished_tasks,
)
if getattr(self.ctx, "plugins", None):
if self._transcript_turn_tail is None and getattr(self.ctx, "plugins", None):
from langchain_core.messages import SystemMessage
messages.insert(0, SystemMessage(content=self.ctx.plugins.prompt()))
if getattr(self.ctx, "exploration_id", None):
if self._transcript_turn_tail is None and getattr(self.ctx, "exploration_id", None):
from artemis.exploration.runtime import exploration_messages
messages[0:0] = exploration_messages(self.ctx)
rules, guidance = exploration_messages(self.ctx)
messages.insert(0, rules)
messages.append(guidance)
# 8. Invoke LLM Loop
new_subagent_calls = []
@@ -1310,7 +1369,7 @@ class OperatorNode:
plugins = get_plugin_runtime(self.ctx)
if plugins and tool_name in plugins.bindings:
return [{"action": tool_name, "args": args}], None
return [{"action": tool_name, "args": args, "tool_call_id": tc["id"]}], None
# Get device resolution fallbacks
width = 1080