fix: preserve cross-device evidence and render recorded reports

This commit is contained in:
chenmingxuan committed 2026-10-17 16:05:58 +08:00
1 parent a66803651a
commit 1440a1f508
28 files changed
+759 -128

No files matched your search

+19 -8
View File
@@ -276,15 +276,18 @@ class VisualStepSummarizer(StepMemoryService):
"post_ui_elements_text": post_ui_elements_text,
"observation_settled": observation_settled,
}
if receipt_only:
unchanged = bool(pre_img_bytes and post_img_bytes and pre_img_bytes == post_img_bytes)
if receipt_only or unchanged:
from artemis.config.constants import PLUGIN_SUMMARY_TEXT_CHARS
from artemis.plugins.prompt_budget import bounded_result_text
summary = (
f"步骤 {step_number}:只读观察 {action_name};未执行写操作。"
f"步骤 {step_number}:{action_name};重新采集的动作后截图与动作前截图完全相同。"
"只能确认本次画面未变化,不能单凭此判定动作生效、已到页底或测试通过。\n"
if unchanged
else f"步骤 {step_number}:只读观察 {action_name};未执行写操作。"
"以下为工具返回摘录,截图仍在本步骤证据中;不代表视觉验收通过。\n"
+ bounded_result_text(exec_outcome, limit=PLUGIN_SUMMARY_TEXT_CHARS)
)
) + bounded_result_text(exec_outcome, limit=PLUGIN_SUMMARY_TEXT_CHARS)
# Evidence has already been persisted by the caller. As with a
# completed visual summary, do not retain every frame in memory.
payload.update(pre_img_bytes=None, post_img_bytes=None, focus=None)
@@ -295,7 +298,10 @@ class VisualStepSummarizer(StepMemoryService):
if data_engine_step_id is not None and self.ctx.data_engine:
try:
self.ctx.data_engine.update_step_summary(
data_engine_step_id, summary, status="ready", source="tool_receipt"
data_engine_step_id,
summary,
status="ready",
source="unchanged_capture" if unchanged else "tool_receipt",
)
except (OSError, ValueError, sqlite3.Error) as de_err:
logger.debug(f"DataEngine receipt summary update skipped: {de_err}")
@@ -442,7 +448,8 @@ class VisualStepSummarizer(StepMemoryService):
# ACTION section and forbids synthesizing a transition.
dual = bool(pre_bytes) and bool(post_bytes)
template = self._prompt_template if dual else self._single_prompt_template
rendered_prompt = Template(template).render(step_number=step_number)
# The ordinal belongs to the dynamic input, not the cacheable rules.
rendered_prompt = Template(template).render(step_number="N")
phrase = self._action_phrase(action_name, action_args)
lead_lines = [f"Step {step_number} Physical Action: {phrase}"]
# The verbatim arguments are worth a line only when the phrase
@@ -455,7 +462,8 @@ class VisualStepSummarizer(StepMemoryService):
lead_lines.append(
"Observation status: screen still changing; page state is not confirmed."
)
focus = input_data.get("focus")
focus = dict(input_data.get("focus") or {})
goal = focus.pop("goal", "")
if isinstance(focus, dict) and focus:
lead_lines.extend(["", render_focus_block(focus, dual=dual)])
content_blocks: list[dict[str, Any]] = [{"type": "text", "text": "\n".join(lead_lines)}]
@@ -513,7 +521,10 @@ class VisualStepSummarizer(StepMemoryService):
)
messages: list[BaseMessage] = [
SystemMessage(content=rendered_prompt),
SystemMessage(
content=rendered_prompt
+ f"\n\nTask goal (attention context, not observed evidence):\n{goal}"
),
HumanMessage(content=content_blocks),
]