Skip to content

feat: 扩展后端 MCP 应用运行能力 + 加封装服务 + 外部agent测试结果 - #2460

Merged
DoctorReid merged 11 commits into
OneDragon-Anything:mainfrom
ImLaoBJie:mcp-service
Jul 11, 2026
Merged

feat: 扩展后端 MCP 应用运行能力 + 加封装服务 + 外部agent测试结果#2460
DoctorReid merged 11 commits into
OneDragon-Anything:mainfrom
ImLaoBJie:mcp-service

Conversation

@ImLaoBJie

@ImLaoBJie ImLaoBJie commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

新增和修改内容

MCP / HTTP 后端能力

  • 新增应用服务:
    • run_one_dragon(block=False)
    • run_standalone_app(app_id=None, block=False)
    • list_applications
  • 新增 HTTP 对称端点:
    • GET /health
    • GET /game/applications
    • POST /game/run/one-dragon
    • POST /game/run/standalone
  • 保留并兼容上游已有 MCP 能力,应该是无冲突的:
    • open_game(enter=True, block=True)
    • analyze_screen(screenshot=None, save_image=False)
    • click_game
    • input_text
    • screen area 增删改工具

运行状态与运行槽

  • 新增 ApplicationRunSlot (继承RunSlot),用于「一条龙」和 「独立应用 」运行。
  • 保留 RunSlot 作为基础 operation 运行槽。
  • ZzzBackendContext.query_status() / stop() 统一覆盖基础 operation 与应用运行。
  • 应用运行路径复用 run_context.run_application,避免 MCP/HTTP 与 GUI 应用运行逻辑分叉。
  • 启动应用前刷新实例配置和应用缓存,尽量读取 GUI 已保存的 YAML 配置。

MCP prompts 与帮助工具

  • 新增 MCP prompts 模板,方便用户或agent了解:
    • zzz_check_status
    • zzz_run_one_dragon
    • zzz_run_standalone_app
  • 同步提供普通 tool 形式的 usage guide:
    • list_mcp_usage_guides
    • get_mcp_usage_guide

GUI

  • 在「开发工具」中新增「MCP 服务」页面,允许用户通过GU打开MCP服务。
  • 支持本机 MCP server:
    • 探测
    • 启动
    • 停止
    • 重启
    • 复制 MCP 地址
    • 查看当前运行状态
    • 读取 server 日志消息
  • 日志读取做了尾读限制、轮询间隔控制和编码兼容,避免中文乱码和 UI 过度刷新卡顿。

文档

  • 更新 backend README、architecture、entry、MCP、HTTP 文档。
  • 补充 Codex 中 Streamable HTTP MCP server 的配置方式。
  • 说明 GUI 启动、命令行启动、/health 探测和测试仓配合方式。

测试

本地已执行:

uv run ruff check src\zzz_od\backend\backend_context.py
uv run pytest zzz-od-test\test\zzz_od\backend\test_run_slot.py zzz-od-test\test\zzz_od\backend\test_backend_context.py
uv run pytest zzz-od-test\ -m "not requires_secrets"

新界面示意

image

Codex调用结果

image image

Summary by CodeRabbit

  • 新功能
    • 新增本机探测 /health;扩展 HTTP /game/*:应用列表、应用运行(阻塞/非阻塞)、以及自定义 operation 列表/描述/运行;/game/close 未就绪返回 503。
    • 扩展 MCP:列出/描述/执行 operation,并完善运行轮询与停止能力。
    • 开发工具新增本机 MCP 服务管理页(探测、启动/停止/重启、日志与状态展示)。
  • 改进
    • 统一运行调度与状态返回;按需刷新运行配置;减少 HTTP 访问日志噪音。
  • 文档
    • 更新后端入口、架构与 HTTP/MCP/operation 语义说明,并调整相关链接样式。

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

本次改动扩展应用与自定义 operation 运行能力,新增 HTTP/MCP 服务接口、MCP 使用指南和 GUI 本机服务管理页,并同步更新后端文档及测试仓库检出回退流程。

Changes

后端运行与服务能力扩展

Layer / File(s) Summary
运行上下文与缓存
src/one_dragon/base/operation/application/*, src/one_dragon/base/push/push_service.py
增加应用缓存清理、最近运行结果记录和失败结果固化,并统一渠道配置值的字符串化处理。
运行槽、schemas 与 operation 注册
src/zzz_od/backend/backend_context.py, src/zzz_od/backend/schemas.py, src/zzz_od/backend/operation_registry.py
RunSlot 支持应用与 operation 两条路径;新增应用/operation schema、反射扫描、参数校验和描述能力。
HTTP 服务路由
src/zzz_od/backend/http/*, src/zzz_od/backend/entry/server.py, deploy/module_manifest.py
新增 /health、应用运行、operation 查询与运行端点,并接入服务路由及 GUI 所需的服务依赖。
MCP 工具与 Prompt
src/zzz_od/backend/mcp/*
新增应用、operation、运行控制和使用指南工具,并注册对应 MCP prompts。
GUI MCP 服务管理页
src/zzz_od/gui/view/devtools/*
新增本机 MCP 服务的探测、启动、停止、重启、状态轮询和日志展示页面。
后端文档同步
docs/develop/zzz/backend/*.md
更新运行模型、端点、MCP 工具、GUI 管理流程和文档索引。
测试仓库检出回退
.github/workflows/test-check.yml
测试工作流按 fork 同分支、upstream 同分支、upstream main 顺序回退检出测试仓库。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant MCPService
  participant OperationRegistry
  participant ZzzBackendContext
  participant RunSlot
  MCPClient->>MCPService: run_operation(op_id, args, block)
  MCPService->>OperationRegistry: resolve and validate operation
  MCPService->>ZzzBackendContext: submit operation
  ZzzBackendContext->>RunSlot: _start(op_factory)
  RunSlot-->>MCPService: started status or final result
  MCPService-->>MCPClient: structured response
Loading
sequenceDiagram
  participant GUI
  participant McpServiceInterface
  participant McpServiceRunner
  participant ServerProcess
  GUI->>McpServiceInterface: start/stop/restart
  McpServiceInterface->>McpServiceRunner: execute action
  McpServiceRunner->>ServerProcess: launch or terminate process
  McpServiceRunner->>ServerProcess: probe /health
  ServerProcess-->>McpServiceRunner: health response
  McpServiceRunner-->>McpServiceInterface: result and status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题与本次后端 MCP/应用运行扩展和服务封装的主变更一致,主题明确。
Docstring Coverage ✅ Passed Docstring coverage is 95.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/one_dragon/base/operation/application/application_run_context.py (1)

433-449: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

app.execute() 抛异常时未设置 last_application_result,会被下游误判为成功。

except Exception: 分支只记录日志,self.last_application_result 保持在函数开头被清空的 None。而 backend_context.pyApplicationRunSlot._run_application 读取到 result is None 时会走 elif result is None: 分支,将其固化为 OperationResult(success=True, status='应用运行结束')——把真实的执行异常报告为运行成功。

对比 RunSlot._run()(同文件所在改动集)在 except Exception as e: 分支中会显式构造 OperationResult(success=False, status='执行异常'),这里应保持一致语义。

🐛 建议修复:异常路径显式落地失败结果
-        except Exception:
-            log.error("运行应用 {} 失败", app_id, exc_info=True)
+        except Exception as e:
+            log.error("运行应用 {} 失败", app_id, exc_info=True)
+            self.last_application_result = OperationResult(success=False, status=f'执行异常: {e}')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/application/application_run_context.py` around
lines 433 - 449, `application_run_context.py` 中 `app.execute()` 的异常分支没有为
`last_application_result` 赋失败结果,导致下游把异常误判为成功;请在 `run_application` 的 `except
Exception` 分支里为 `self.last_application_result` 显式设置一个失败的
`OperationResult`,并保持与同文件中的 `RunSlot._run()` 异常处理语义一致,确保 `backend_context.py`
读取时不会把 `None` 当作成功结束。
src/zzz_od/backend/backend_context.py (1)

760-805: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

basic_run_slotapp_run_slot 之间的启动互斥检查存在 TOCTOU 竞态,可能同时运行。

start_run 检查 self.app_run_slot.is_running()run_one_dragon/run_standalone_app 检查 self.basic_run_slot.is_running(),但“检查”与“启动”分别持有两个槽各自独立的锁,不是一次原子操作。并发场景下(例如 MCP/HTTP 几乎同时发起 start_runrun_one_dragon),两次检查都可能读到“未运行”,随后两个槽各自成功启动,导致一条龙应用运行与普通 operation 同时抢占游戏控制器,破坏代码里反复强调的“单跑道”设计(如 RunSlot/ApplicationRunSlot 文档所述)。

🔒 建议修复:引入跨槽的启动锁
 class ZzzBackendContext:
     def __init__(self, ctx: ZContext) -> None:
         self._ctx: ZContext = ctx
+        self._start_lock: threading.Lock = threading.Lock()
         self.basic_run_slot: RunSlot = RunSlot(ctx)
         self.run_slot: RunSlot = self.basic_run_slot
         self.app_run_slot: ApplicationRunSlot = ApplicationRunSlot(ctx)

     def start_run(self, source, op_factory):
-        if self.app_run_slot.is_running():
-            return False, None
-        return self.basic_run_slot._start_run(source, op_factory)
+        with self._start_lock:
+            if self.app_run_slot.is_running():
+                return False, None
+            return self.basic_run_slot._start_run(source, op_factory)

     def run_one_dragon(self, source: str):
         self._ensure_ready()
-        if self.basic_run_slot.is_running():
-            return False, None
-        self._refresh_runtime_config()
-        return self.app_run_slot._start_application(...)
+        with self._start_lock:
+            if self.basic_run_slot.is_running():
+                return False, None
+            self._refresh_runtime_config()
+            return self.app_run_slot._start_application(...)

run_standalone_app 同理需要包在同一把 _start_lock 里。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/backend/backend_context.py` around lines 760 - 805, `start_run`,
`run_one_dragon`, and `run_standalone_app` have a TOCTOU race because they check
`basic_run_slot` and `app_run_slot` separately before starting. Fix this by
adding a shared cross-slot start lock or a single atomic arbitration point so
the “is running” check and `_start_run`/`_start_application` launch happen under
the same critical section. Use the existing `RunSlot`/`ApplicationRunSlot` start
path and ensure all three methods coordinate through the same lock to preserve
single-run exclusivity.
🧹 Nitpick comments (3)
src/zzz_od/gui/view/devtools/mcp_service_interface.py (3)

218-222: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

__init__ 不应标注 -> None

McpServiceRunner.__init__McpServiceInterface.__init__ 都添加了 -> None 返回类型标注,这与项目既有约定不一致。

Based on learnings, "follow the established style convention for __init__ methods: do not add a -> None return type annotation to __init__ signatures" was previously flagged in this codebase.

♻️ 建议修改
-    def __init__(self, action: str, port: int, parent: QWidget | None = None) -> None:
+    def __init__(self, action: str, port: int, parent: QWidget | None = None):
-    def __init__(self, ctx: ZContext, parent: QWidget | None = None) -> None:
+    def __init__(self, ctx: ZContext, parent: QWidget | None = None):

Also applies to: 245-261

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/gui/view/devtools/mcp_service_interface.py` around lines 218 -
222, Remove the explicit return type annotation from the affected __init__
methods to match the project’s established style. Update both
McpServiceRunner.__init__ and McpServiceInterface.__init__ so their signatures
do not include -> None, while keeping the existing parameters and initialization
logic unchanged.

Source: Learnings


40-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

端口配置硬编码,未落到 YAML/YamlConfig。

DEFAULT_MCP_PORT 和端口输入框只是页面内的临时状态,每次进入页面都会重置为 23001self.port_card.setValue(str(DEFAULT_MCP_PORT), emit_signal=False)),用户修改后的端口不会被持久化。

As per coding guidelines, "配置改动优先落到 YAML 与对应的 YamlConfig 子类,不要随意散落硬编码配置。" 建议把端口做成一个 YamlConfig 字段,页面读取/写入该配置而不是每次都回退到硬编码默认值。

Also applies to: 277-279

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/gui/view/devtools/mcp_service_interface.py` at line 40, The MCP
port is hardcoded as DEFAULT_MCP_PORT and only stored in the view state, so user
changes are lost when reopening the page. Move the port setting into the
relevant YamlConfig subclass and have the devtools MCP UI read and write that
config instead of resetting via self.port_card.setValue(str(DEFAULT_MCP_PORT),
emit_signal=False); update the persistence flow around the port handling logic
in the MCP service interface so the chosen value survives page refreshes.

Source: Coding guidelines


315-323: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

PlainTextEdit 直接通过 addSettingCard 加入 SettingCardGroup,可能不符合 Fluent 卡片布局预期。

SettingCardGroup.addSettingCard 设计目标是容纳标准 SettingCard(固定高度、带标题/描述),这里塞入一个 setMinimumHeight(180) 的日志文本框,虽然类型上兼容(该方法接受任意 QWidget),但视觉呈现上可能与其余卡片风格不一致。

As per coding guidelines, "GUI 代码优先复用 pyside6-fluent-widgets 与现有项目组件,保持 Fluent Design。" 建议确认实际渲染效果,或考虑用项目里已有的日志/文本展示容器组件包一层,而不是把 PlainTextEdit 直接当作 SettingCard 加入分组。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/gui/view/devtools/mcp_service_interface.py` around lines 315 -
323, The MCP service view currently adds a PlainTextEdit directly into
SettingCardGroup via addSettingCard, which may clash with the expected Fluent
card layout. Update the devtools UI in mcp_service_interface by either wrapping
the log view in an existing project-style container or using a proper
SettingCard-style component, and keep the message_box setup aligned with the
rest of the Fluent design. Verify the rendered appearance still fits the
surrounding SettingCardGroup and content.add_widget structure.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/zzz_od/backend/mcp/service_app.py`:
- Around line 92-97: make_list_applications 直接返回
backend.list_applications(),缺少与同层工具一致的异常兜底;请在 list_applications 里补上 try/except,像
make_run_one_dragon、make_run_standalone_app 一样把 BackendNotReadyError
和其它异常转换为结构化错误结果,而不是让异常直接冒泡到 MCP 框架。优先参考
make_list_applications、make_run_one_dragon 和 make_run_standalone_app
这几个符号来统一处理方式,并保持“无副作用”的正常返回路径不变。

In `@src/zzz_od/gui/view/devtools/mcp_service_interface.py`:
- Around line 333-337: The on_interface_hidden cleanup in
mcp_service_interface.py stops the timers but does not wait for self._runner to
finish, so the worker thread can still be running during page hide or
destruction. Update on_interface_hidden, or the shared teardown path it uses, to
stop the timers and then wait for self._runner to exit, using a timeout if
needed, so the runner is not destroyed while start/restart work is still in
progress.

---

Outside diff comments:
In `@src/one_dragon/base/operation/application/application_run_context.py`:
- Around line 433-449: `application_run_context.py` 中 `app.execute()` 的异常分支没有为
`last_application_result` 赋失败结果,导致下游把异常误判为成功;请在 `run_application` 的 `except
Exception` 分支里为 `self.last_application_result` 显式设置一个失败的
`OperationResult`,并保持与同文件中的 `RunSlot._run()` 异常处理语义一致,确保 `backend_context.py`
读取时不会把 `None` 当作成功结束。

In `@src/zzz_od/backend/backend_context.py`:
- Around line 760-805: `start_run`, `run_one_dragon`, and `run_standalone_app`
have a TOCTOU race because they check `basic_run_slot` and `app_run_slot`
separately before starting. Fix this by adding a shared cross-slot start lock or
a single atomic arbitration point so the “is running” check and
`_start_run`/`_start_application` launch happen under the same critical section.
Use the existing `RunSlot`/`ApplicationRunSlot` start path and ensure all three
methods coordinate through the same lock to preserve single-run exclusivity.

---

Nitpick comments:
In `@src/zzz_od/gui/view/devtools/mcp_service_interface.py`:
- Around line 218-222: Remove the explicit return type annotation from the
affected __init__ methods to match the project’s established style. Update both
McpServiceRunner.__init__ and McpServiceInterface.__init__ so their signatures
do not include -> None, while keeping the existing parameters and initialization
logic unchanged.
- Line 40: The MCP port is hardcoded as DEFAULT_MCP_PORT and only stored in the
view state, so user changes are lost when reopening the page. Move the port
setting into the relevant YamlConfig subclass and have the devtools MCP UI read
and write that config instead of resetting via
self.port_card.setValue(str(DEFAULT_MCP_PORT), emit_signal=False); update the
persistence flow around the port handling logic in the MCP service interface so
the chosen value survives page refreshes.
- Around line 315-323: The MCP service view currently adds a PlainTextEdit
directly into SettingCardGroup via addSettingCard, which may clash with the
expected Fluent card layout. Update the devtools UI in mcp_service_interface by
either wrapping the log view in an existing project-style container or using a
proper SettingCard-style component, and keep the message_box setup aligned with
the rest of the Fluent design. Verify the rendered appearance still fits the
surrounding SettingCardGroup and content.add_widget structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 568a7e67-cf0f-4fa5-985c-c13761cbf999

📥 Commits

Reviewing files that changed from the base of the PR and between 8d018cf and be9b1db.

📒 Files selected for processing (18)
  • docs/develop/zzz/backend/README.md
  • docs/develop/zzz/backend/architecture.md
  • docs/develop/zzz/backend/entry.md
  • docs/develop/zzz/backend/http.md
  • docs/develop/zzz/backend/mcp.md
  • src/one_dragon/base/operation/application/application_factory.py
  • src/one_dragon/base/operation/application/application_run_context.py
  • src/one_dragon/base/push/push_service.py
  • src/zzz_od/backend/backend_context.py
  • src/zzz_od/backend/entry/server.py
  • src/zzz_od/backend/http/routes.py
  • src/zzz_od/backend/http/service_routes.py
  • src/zzz_od/backend/mcp/app.py
  • src/zzz_od/backend/mcp/prompts.py
  • src/zzz_od/backend/mcp/service_app.py
  • src/zzz_od/backend/schemas.py
  • src/zzz_od/gui/view/devtools/app_devtools_interface.py
  • src/zzz_od/gui/view/devtools/mcp_service_interface.py

Comment thread src/zzz_od/backend/mcp/service_app.py Outdated
Comment thread src/zzz_od/gui/view/devtools/mcp_service_interface.py
@DoctorReid DoctorReid self-assigned this Jul 8, 2026
DoctorReid and others added 7 commits July 9, 2026 00:18
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
run_application 的 except 分支此前只 log 不写 last_application_result,
导致 app.execute() 抛异常时该字段保持初始 None,backend 运行槽可能将
异常误判为成功。现将 OperationResult 提为运行时导入,并在 except 分支
固化 success=False 的失败终态。

Task 1 of 后端运行槽合并 + 自定义 operation 运行入口

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
RunSlot 新增 RunType(APPLICATION/OPERATION)枚举与 op_id/run_type 字段;
_start 替代 _start_run(op_factory 与 app_id 互斥、check+submit 同锁原子),
_run 顶层 try/except/finally 固化终态并按 app/op 分派(app 委托 run_application、
op 槽自管 start_running/execute/stop_running),_node_name 统一读
current_op or current_application。ZzzBackendContext.start_run 改调
run_slot._start 并透传 display_name,保证 open_game 路径中间态可跑。
暂不删 ApplicationRunSlot / 不动 query_status/stop(Task 3 收敛)。

Task 2 of 后端运行槽合并 + 自定义 operation 运行入口

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- 删 ApplicationRunSlot 整个类(约 -130 行)及 app_run_slot/basic_run_slot 双字段
- __init__ 只留 self.run_slot: RunSlot = RunSlot(ctx)(无 host)
- 新增 _start_app(source, app_id, group_id):app 路径统一入口,
  refresh_config 作钩子注入槽线程(拒绝路径不刷新,修刷新竞态)
- run_one_dragon/run_standalone_app 改走 _start_app
- start_run 删 app_run_slot.is_running() 守卫(互斥由 _start 锁内原子保证)
- query_status/stop 塌缩为单次 run_slot._query_status()/_stop()(删 6 分支跨槽仲裁)
- list_applications 删 _refresh_runtime_config()(只读路径无副作用)
- 删不再使用的 Application TYPE_CHECKING 导入

Task 3 of backend run-slot 统一设计(spec §4.3/§4.2)

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
…erationInfo/OperationListResult)

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- service_app: list_operations / describe_operation / run_operation 三 tool 工厂
  run_operation 经 resolve_op_class + validate_args 校验后,op_factory 闭包 bake args
  提交 run_slot._start;并发拒绝/校验失败/异常一律返 {started: False, error}
- service_routes: GET /game/operations、GET /game/operations/describe?op_id=、
  POST /game/run/operation?op_id=&block=(args 走 JSON body);业务失败一律 200+body
- app.py: 注册三个新 MCP tool

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
Task 7 文档更新(单槽分派模型落地后的主 spec 同步):
- architecture.md: 删除 ApplicationRunSlot/双槽描述,改为单 RunSlot + app/op 分派
  (app 委托 run_application、op 自管 start_running/execute/stop_running;互斥收进
  _start 锁内;字段 op_id/run_type/app/current_op);新增 operation_registry 小节
- mcp.md: 工具表加 list_operations/describe_operation/run_operation(op_id 格式、
  args 闭包 bake、block),说明 run_operation 是通用 op 运行入口;计数订正为 19
- http.md: 加 GET /game/operations、/game/operations/describe、
  POST /game/run/operation(op_id 走 query、args 走 body、业务失败 200+body)
- entry.md: 新增路由总览表(原有 + 自定义 op 3 端点)
- README.md: mermaid 单槽化 + 已实现列表补自定义 op 运行

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/one_dragon/base/operation/application/application_run_context.py (1)

440-447: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议添加 # noqa: BLE001 以与 backend_context.py 保持一致。

此处的 except Exception 是有意义的异常处理(固化失败终态),Ruff 的 BLE001 警告属于误报。backend_context.py 中相同模式已使用 # noqa: BLE001 抑制,建议此处保持一致。

注:RUF003 对第 444 行中文逗号的警告不予处理,符合路径指令中"不要建议把中文标点符号改为英文"的要求。

🔧 建议的修改
         op_result = app.execute()
         # run_application 的布尔返回值只表示是否成功启动;详细执行结果由这里保留。
         self.last_application_result = op_result
-        except Exception as e:
+        except Exception as e:  # noqa: BLE001
             log.error("运行应用 {} 失败", app_id, exc_info=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/application/application_run_context.py` around
lines 440 - 447, 在应用执行异常处理的 except Exception 语句上添加 # noqa: BLE001,参照
backend_context.py 的相同模式,保留现有的失败终态固化与日志处理逻辑不变。

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/one_dragon/base/operation/application/application_run_context.py`:
- Around line 440-447: 在应用执行异常处理的 except Exception 语句上添加 # noqa: BLE001,参照
backend_context.py 的相同模式,保留现有的失败终态固化与日志处理逻辑不变。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cb9a328b-389c-4f9d-8064-52d28c7f99aa

📥 Commits

Reviewing files that changed from the base of the PR and between 4f5ef68 and 0ac735d.

📒 Files selected for processing (12)
  • docs/develop/zzz/backend/README.md
  • docs/develop/zzz/backend/architecture.md
  • docs/develop/zzz/backend/entry.md
  • docs/develop/zzz/backend/http.md
  • docs/develop/zzz/backend/mcp.md
  • src/one_dragon/base/operation/application/application_run_context.py
  • src/zzz_od/backend/backend_context.py
  • src/zzz_od/backend/http/service_routes.py
  • src/zzz_od/backend/mcp/app.py
  • src/zzz_od/backend/mcp/service_app.py
  • src/zzz_od/backend/operation_registry.py
  • src/zzz_od/backend/schemas.py
✅ Files skipped from review due to trivial changes (2)
  • docs/develop/zzz/backend/README.md
  • docs/develop/zzz/backend/http.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/zzz_od/backend/mcp/app.py
  • docs/develop/zzz/backend/entry.md

…main)

cross-repo PR 贡献者没 fork 测试仓时,原逻辑直接掉到一条龙 main(可能与 PR 代码不匹配)。
新增中间级:一条龙测试仓同名分支(mcp-service),让 maintainer 在主测试仓 push 同名测试即可被 CI 取到;都没有再 main 兜底。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/test-check.yml (1)

34-42: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

三个 checkout 步骤均未设置 persist-credentials: false,存在 GITHUB_TOKEN 泄露风险。

actions/checkout@v5 默认将 GITHUB_TOKEN 持久化到 .git/config。对于 fork 检出步骤(Line 38),贡献者 fork 的测试代码会在 workflow 中执行,恶意测试代码可从 zzz-od-test/.git/config 读取并外泄 token。这是已知的 artipacked 漏洞模式。

建议在所有三个 checkout 步骤的 with 块中添加 persist-credentials: false

🔒️ 建议的修复
       - name: Checkout test repo (fork, same branch)
         id: checkout-test-repo
         uses: actions/checkout@v5
         with:
           repository: ${{ github.event_name == 'pull_request' && (github.event.pull_request.head.repo.full_name && format('{0}/zzz-od-test', github.event.pull_request.head.repo.owner.login) || 'OneDragon-Anything/zzz-od-test') || 'OneDragon-Anything/zzz-od-test' }}
           path: zzz-od-test
           ref: ${{ github.event_name == 'pull_request' && github.head_ref || 'main' }}
           fetch-depth: 1
+          persist-credentials: false
         continue-on-error: true

       - name: Checkout test repo (upstream, same branch)
         id: checkout-test-repo-upstream
         if: steps.checkout-test-repo.outcome == 'failure'
         uses: actions/checkout@v5
         with:
           repository: OneDragon-Anything/zzz-od-test
           path: zzz-od-test
           ref: ${{ github.head_ref || 'main' }}
           fetch-depth: 1
+          persist-credentials: false
         continue-on-error: true

       - name: Checkout test repo (upstream, main)
         id: checkout-test-repo-default
         if: steps.checkout-test-repo-upstream.outcome == 'failure'
         uses: actions/checkout@v5
         with:
           repository: OneDragon-Anything/zzz-od-test
           path: zzz-od-test
           ref: main
           fetch-depth: 1
+          persist-credentials: false

Also applies to: 44-53, 55-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test-check.yml around lines 34 - 42, Update all three
actions/checkout@v5 steps, including “Checkout test repo (fork, same branch)”
and the two additional checkout steps, to set persist-credentials to false
within each with block; preserve their existing repository, path, ref, and
fetch-depth settings.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/workflows/test-check.yml:
- Around line 34-42: Update all three actions/checkout@v5 steps, including
“Checkout test repo (fork, same branch)” and the two additional checkout steps,
to set persist-credentials to false within each with block; preserve their
existing repository, path, ref, and fetch-depth settings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c4bc1278-4972-4b81-99f3-96798dcb6fdb

📥 Commits

Reviewing files that changed from the base of the PR and between 0ac735d and cd42838.

📒 Files selected for processing (1)
  • .github/workflows/test-check.yml

@DoctorReid
DoctorReid merged commit d1e2763 into OneDragon-Anything:main Jul 11, 2026
7 of 8 checks passed
@ImLaoBJie
ImLaoBJie deleted the mcp-service branch July 11, 2026 13:44
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jul 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants