feat: add plugin runtime and cross-device task orchestration
This commit is contained in:
1 parent
3ee4a5f7a8
commit
6663233ab8
82 files changed
+4147
-124
No files matched your search
@@ -181,6 +181,33 @@ async def _process_action(
|
||||
outcome = _ActionOutcome(action_item=action_item)
|
||||
attempts_log = []
|
||||
|
||||
from artemis.plugins.runtime import get_plugin_runtime
|
||||
from artemis.runtime.task_control import TaskControl
|
||||
|
||||
plugins = get_plugin_runtime(node.ctx)
|
||||
if plugins and action_name in plugins.bindings:
|
||||
operation = plugins.execute(action_name, action_item.get("args", {}), str(uuid.uuid4()))
|
||||
control = getattr(node.ctx, "task_control", None)
|
||||
if isinstance(control, TaskControl):
|
||||
interrupted, result = await control.run_interruptibly(
|
||||
operation,
|
||||
on_pause=getattr(node.ctx, "on_task_pause", None),
|
||||
on_resume=getattr(node.ctx, "on_task_resume", None),
|
||||
)
|
||||
if interrupted:
|
||||
outcome.success = False
|
||||
outcome.error_msg = "插件操作已打断,结果不确定;继续前必须重新观察。"
|
||||
return outcome
|
||||
else:
|
||||
result = await operation
|
||||
outcome.success = result.status == "success"
|
||||
outcome.error_msg = "" if outcome.success else result.text_summary
|
||||
outcome.action_item.update(result.metadata)
|
||||
outcome.action_item["result"] = result.text_summary
|
||||
if result.screenshot_bytes:
|
||||
outcome.post_screenshot_b64 = base64.b64encode(result.screenshot_bytes).decode()
|
||||
return outcome
|
||||
|
||||
validation_passed = True
|
||||
if not burst:
|
||||
# 1. Pre-execution validation (Safety Net)
|
||||
@@ -338,6 +365,8 @@ def _model_facing_action(ctx, action_item: dict) -> dict:
|
||||
The live item carries the controller's pixels; every phrase rendered for
|
||||
a model is normalized first, and the space marker makes that idempotent.
|
||||
"""
|
||||
if action_item.get("plugin_id"):
|
||||
return action_item
|
||||
width = getattr(getattr(ctx, "device", None), "device_width", None) or 1080
|
||||
height = getattr(getattr(ctx, "device", None), "device_height", None) or 2400
|
||||
return normalize_action_dict(action_item, width, height)
|
||||
@@ -419,11 +448,19 @@ async def run_validation_loop(node, state: State) -> dict:
|
||||
execution.append(outcome.action_item)
|
||||
|
||||
post_image_name = None
|
||||
if outcome.post_screenshot_b64:
|
||||
plugin_action = bool(outcome.action_item.get("plugin_id"))
|
||||
mixed_plugin_action = (
|
||||
plugin_action and getattr(ctx, "execution_target", "android") == "mixed"
|
||||
)
|
||||
if outcome.post_screenshot_b64 and not mixed_plugin_action:
|
||||
post_image_name = _absorb_post_screenshot(ctx, state, outcome.post_screenshot_b64)
|
||||
last_screenshot_b64 = outcome.post_screenshot_b64
|
||||
if post_image_name:
|
||||
last_screenshot_name = post_image_name
|
||||
elif mixed_plugin_action:
|
||||
# Keep the Android step observation on its own resource. Plugin
|
||||
# images remain attached to the tool/action trace and its exports.
|
||||
post_image_name = outcome.action_item.get("post_image_name")
|
||||
|
||||
_record_action_end(
|
||||
ctx,
|
||||
|
||||
Reference in new issue
Block a user