- 修复脚本配置文件路径处理问题,避免打包后 ZIP_FILE_PATH 等参数未生效并回退默认值 - 在 chat 模式执行前增加参数归一化和预检,提前检查 ZIP_FILE_PATH、脚本入口和 MCP 配置 - 优化 chat 交互体验,问候语不再触发结构化分析,分析前增加提示,执行中播报每步 action 状态 - 修复 action 失败被误判为 LangGraph 不可用的问题,失败后保留 checkpoint 并给出明确续跑提示 - 补齐 MCP 参数传递,支持向 action 传入 hashCode、nodeUrl、targetIp 等上下文 - 增强全局 action、单 IP action、回滚和日志下载的异常处理与进度回调 - 同步 README、打包 README 和 run.sh 帮助文案,更新打包后 chat 的实际使用说明 - 补充回归测试,覆盖 chat 预检、进度播报、问候处理、MCP 传参与配置路径修复
61 lines
2.6 KiB
Python
61 lines
2.6 KiB
Python
"""按照执行策略把 action 路由到脚本、MCP 或 fake runner。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from .constants import ALLOWED_ACTIONS, HOME_ACTIONS, NODE_ACTIONS
|
||
from .models import AgentState, BackendName, ExecutionStrategy, ActionResult
|
||
|
||
|
||
def build_action_backends(strategy: ExecutionStrategy) -> dict[str, BackendName]:
|
||
"""根据执行策略生成每个 action 对应的后端类型。"""
|
||
if strategy == "fake":
|
||
return {action: "fake" for action in ALLOWED_ACTIONS}
|
||
if strategy == "script_only":
|
||
return {action: "script" for action in ALLOWED_ACTIONS}
|
||
if strategy == "hybrid_node_mcp":
|
||
routes: dict[str, BackendName] = {action: "script" for action in HOME_ACTIONS}
|
||
routes.update({action: "mcp" for action in NODE_ACTIONS})
|
||
return routes
|
||
raise ValueError(f"未知执行策略: {strategy}")
|
||
|
||
|
||
class ActionRouter:
|
||
"""统一的 action 调度器,屏蔽脚本、MCP 和 fake 后端差异。"""
|
||
|
||
def __init__(self, *, script_runner, mcp_runner=None, fake_runner=None) -> None:
|
||
"""保存各类 runner,运行时按 state 中的路由表选择后端。"""
|
||
self.script_runner = script_runner
|
||
self.mcp_runner = mcp_runner
|
||
self.fake_runner = fake_runner
|
||
|
||
def run_action(self, state: AgentState, action: str, **kwargs) -> ActionResult:
|
||
"""执行一个 action,并返回统一的 ActionResult。"""
|
||
backend = state.action_backends.get(action)
|
||
if not backend:
|
||
raise ValueError(f"action 未配置路由: {action}")
|
||
if backend == "script":
|
||
return self.script_runner.run(
|
||
action,
|
||
params=state.params,
|
||
script_entry=state.script_entry,
|
||
config_path=state.config_path,
|
||
trace_file_path=state.trace_file_path,
|
||
**kwargs,
|
||
)
|
||
if backend == "mcp":
|
||
if self.mcp_runner is None:
|
||
raise RuntimeError(f"action 需要 MCP runner: {action}")
|
||
mcp_kwargs = dict(kwargs)
|
||
hash_code = mcp_kwargs.pop("hash_code", None) or state.hash_code
|
||
node_url = mcp_kwargs.pop("node_url", None) or state.node_url
|
||
return self.mcp_runner.run(
|
||
action,
|
||
params=state.params,
|
||
hash_code=hash_code,
|
||
node_url=node_url,
|
||
**mcp_kwargs,
|
||
)
|
||
if self.fake_runner is None:
|
||
raise RuntimeError(f"action 需要 fake runner: {action}")
|
||
return self.fake_runner.run(action, params=state.params, **kwargs)
|