Commit 296e49e
galgame_plugin: prompt 英文化 + install 路由解耦 + choice_advisor fast loop 修复 (Project-N-E-K-O#1133)
* Add galgame plugin implementation
* Wire galgame plugin into host runtime
* Add galgame plugin regression coverage
* Fix diagnose push lint entrypoint
* PluginUIFrame 通过 iframe 加载插件 UI 页面,原 frame-ancestors 'none'
会指示浏览器拒绝任何 iframe 嵌入,导致 UI 空白。
改为 'self' 允许同源嵌入。
* _resolve_install_task_payload (line 220) 现在先校验 task_id,非法值直接 400,不会再进 load_install_task_state()。
_install_stream_response (line 355) 在返回 StreamingResponse 前先调用 _resolve_install_task_payload(),不存在的 task 会干净地返回 404,不会启动后才炸 SSE
* 实现哀鸿选项 OCR 空间区域过滤
- 新增 AIHONG_CHOICES_REGION_PRESET,定义哀鸿选项检测区域为画面高度 20%-60%
- 新增 OCR box 空间过滤逻辑,仅将中间区域文本送入 menu_stage 选项识别
- 为 source_height 增加降级推导:source_size、window_rect、boxes 最大 bottom、1080
- 调整 choices_shown bounds 匹配,使用过滤后的 choice boxes,减少标题栏、HUD、对白污染
- 补充哀鸿选项区域过滤与全屏 OCR 污染回归测试
验证:
- py_compile passed
- test_galgame_ocr_reader.py -k "aihong_choice_region or aihong_menu_stage_filters": 2 passed
- test_galgame_ocr_reader.py -k "aihong_menu": 9 passed
* 新增 AIHONG_CHOICES_REGION_PRESET,把哀鸿选项识别区域设为画面高度 20% - 60%。
- 新增 OCR boxes 空间过滤函数,只保留中间区域文本参与选项识别。
- 改造哀鸿 menu_stage 识别入口,避免标题栏、HUD、底部对白混入纯文字选项判断。
- 选项 bounds 匹配改用过滤后的 boxes。
- 补充 2 个针对性单测,并确认 aihong_menu 相关测试通过。
* Delete CODE/md/galgame-memory-reader-restart-loop-ocr-fallback-2026-05-04.md
清理文档
* Delete docs/plugins/galgame_agent_context_push_chain_review.md
清理文档
* Delete ocr_debug_capture.png
* 清理 galgame 插件对 core/task_executor 的专用代码污染
- 将 galgame scene_summary 的上下文提示模板下沉到 galgame 插件侧预组装
- 删除 brain/task_executor.py 中 galgame 专用关键词命令路由
- 删除 main_logic/core.py 中 galgame 专用 callback 判断、prefix strip 和 instruction builder
- galgame 控制命令改为走现有通用 UserPlugin LLM 评估路径
- 更新回归测试,断言 galgame 命令通过通用插件评估而不是硬编码路由
验证:
- py_compile passed
- test_agent_rewrite_regression.py 相关用例:3 passed
- test_proactive_sm_integration.py:10 passed
- test_galgame_bridge.py scene_summary 相关用例:2 passed
main_routers/agent_router.py
- openclaw availability timeout: 4.5s -> 4.0s
* plugin desc enum 截断格式化:把 "..." 移进 [] 内并附剩余数量
原渲染对超过 12 个 enum 值的字段是 `enum=[a|b|c]...`,孤零零的 "..."
贴在 ] 外面,LLM 容易把可见 12 个值误读为完整白名单,把用户实际想要
的(被截断掉的)合法值替换成最相近的可见值,或直接拒绝执行。
改成 `enum=[a|b|c|... +N more]`,把省略号放进 [] 内并明确告诉 LLM
"还有 N 个未列出的合法值"。N 来自 len(enum_values) - 12。
≤12 的渲染保持原样不动,原有 test_task_executor_plugin_desc_includes_enum_values
不受影响;新增 test_task_executor_plugin_desc_truncates_long_enum_with_remainder_hint
覆盖截断分支,断言新格式 + 旧的 "]..." 形态不再出现。
验证:
- pytest tests/test_agent_rewrite_regression.py 95 passed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* 解决 codex P1(共享路由聚合层 galgame 污染)+ P2(Open UI 忽略 list_action target/open_in)
P1 — plugin/server/routes/__init__.py:18 + plugin/server/http_app.py:30,172
共享路由聚合层(plugin/server/routes/__init__.py)原本 hardcode
`from plugin.plugins.galgame_plugin.install_routes import ...`,是
commit 0ddcd26 "OCR 区域过滤" 夹带进去的 stealth import,d8e82c00
"清理 galgame 污染" 漏扫这一层。symptom:galgame plugin 任何 import-time
副作用炸(缺 dxcam / tesseract / textractor 可选依赖、非 Windows 环境
等)→ 整个 plugin server 启动 fail,而不是只让 install 端点 404。
修法:
- 共享聚合层 plugin/server/routes/__init__.py 完全不再认识 galgame,
和 mcp_adapter / sts2_autoplay 看齐
- galgame import 移到 plugin/server/http_app.py 的 build_plugin_server_app()
内部,try/except ImportError 兜住;失败时 logger.warning + 跳过 include
- 顶层 builder 仍 hardcode 知道 galgame 是个特殊 case,但已经从"hard
依赖"降级为"optional 依赖"语义;彻底去 hardcode 的方案 B(plugin SDK
自己注册 router)改动跨 plugin loader,留给 follow-up
验证:
- python -c 'build_plugin_server_app()' 正常:86 routes(含 16 galgame)
- 模拟 plugin.plugins.galgame_plugin.install_routes ImportError:
app 仍能 build,70 routes(无 galgame),WARNING 落日志
- pytest plugin/tests/unit/server/ → 135 passed
P2 — frontend/plugin-manager/src/components/plugin/PluginActions.vue:103
backend ui_query_service.py 的 _normalize_list_action 已经在 L460-487
显式 normalize `target` 和 `open_in` 进 list_action 契约,frontend
types/api.ts:51-52 也已经声明这两个字段为可选,但 PR 新加的
handleOpenUi 直接 hardcode `router.push({ path: /plugins/{id}, query:
{ tab: 'ui' } })`,把契约里两个字段全丢了。symptom:plugin 配置
`kind: "ui"` + 外部 URL target / `open_in: "new_tab"` → 按钮静默跳错
地方。
修法:handleOpenUi 按 4 个组合分支:
- 外部 URL (http/https) target × open_in → window.open / location.href
- 内部路由 target × open_in → router.resolve+window.open / router.push
- 无 target → 回退到原 ?tab=ui 默认行为,open_in 仍生效
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* plugin list_action label / confirm_message i18n dict 解析(修 P3 + 老 bug)
CodeRabbit 在 cd051ce 上指出 PluginActions.vue:11 的 `{{ uiAction.label || t(...) }}`
在 label 是 i18n 字典对象时会渲染成 `[object Object]`。
backend `_normalize_plugin_list_action`(plugin/server/application/plugins/
ui_query_service.py L454-487)显式接受 `label` / `confirm_message` 为 string
或 locale-keyed dict(e.g. `{"en-US": "Open UI", "zh-CN": "打开界面"}`),
而 `resolve_i18n_refs`(plugin/sdk/shared/i18n.py L155)只解析 `$i18n` ref,
不会把 locale-keyed 字典拍平,所以 dict 会原样发到 frontend。模板里直接
`{{ value }}` 在 dict 时会渲染成 "[object Object]"。
audit 全 frontend 后发现这是 systemic 老 bug(不只是 PR 引入):
- PluginActions.vue:11 ← PR 引入
- usePluginListContextActions.ts:107 resolveActionLabel ← 老 bug
- usePluginListContextActions.ts:230 confirmIfNeeded ← 老 bug
- PluginList.vue:332 dangerDialog message ← 老 bug
修法:
- 新增 utils/i18nLabel.ts 提供 `resolveLocalizedText(value, locale, fallback)`
helper,按 locale 完整匹配 → 主语言降级 → en-US/en 兜底 → 字典首项 →
fallback 五级解析
- types/api.ts: PluginListAction.label / confirm_message 改为
`LocalizedText = string | Record<string, string>`,contract 与 backend
对齐
- 4 处消费点改用 helper:
- PluginActions.vue: 用 computed `uiActionLabel`
- usePluginListContextActions.ts: resolveActionLabel + confirmIfNeeded
都走 helper,前者 helper 解析空时仍 fallback 到内置 i18n key
- PluginList.vue: dangerDialog 的 :message 用 computed `dangerDialogMessage`
- ResolvedPluginListAction 已在 `& { label: string }` 把 label resolve 为
string,下游 PluginContextMenu / Resolved 消费点不受影响
验证:
- `npm run type-check` (vue-tsc --build) 通过
- 我修改的文件 lint 0 引入新 error(pre-existing `any` 类型 error 全在
未修改区域)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Open UI 按钮 open_in 缺省与 list-action executor convention 对齐
codex 在 08732c1 上指出 handleOpenUi 把缺省 open_in 视为 same-tab
(`action.open_in === 'new_tab'`),但 usePluginListContextActions.ts:366
的 list-action executor 缺省视为 new-tab
(`action.open_in === 'same_tab' ? '_self' : '_blank'`)。
后果:在同一个 plugin manager 里,"Open UI" 按钮和右键菜单 action
对同一个 `kind: "ui"` action(plugin 没显式声明 open_in 时)行为分叉
——一个替换当前页、一个新开 tab,用户体验不一致。
修法:把判断翻成 `action.open_in !== 'same_tab'`,让 undefined → new_tab
与 executor 对齐。plugin 显式设 same_tab 仍然受尊重。
验证:vue-tsc --build 通过。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* handleOpenUi 走 browser navigation + fetchStaticUI 加 stale-response guard
P2-A — PluginActions.vue:143 (codex)
handleOpenUi 在 same_tab + non-HTTP target 时走 router.push(target),但
SPA router(src/router/index.ts)只定义 manager 内部路由(/plugins/:id 等),
plugin server 暴露的 path(如 /plugin/<id>/ui/)会被当 unmatched route,
UI 打不开。
修法:和 usePluginListContextActions.ts:366 的 list-action executor 行为
对齐——`kind === 'ui'` 的 action 永远走 browser navigation
(window.open with _blank/_self),不再按 http vs 内部 path 分两条路径。
仅"无 target → 默认 plugin 详情页 ?tab=ui"这条 fallback 仍走 router.push
(这是真正的 manager 内部路由)。
P2-B — PluginDetail.vue:310 (codex / CodeRabbit 之前 r3183397668 也提过)
fetchStaticUI 没有 stale-response guard,用户快速切换 plugin detail 页
时旧 plugin 的 /ui-info 响应可能在新 plugin 加载后才到,覆盖
hasStaticUI 导致 UI tab 显示状态错位。
修法:照搬 fetchSurfaces 的 pattern——加 currentStaticUiLoadId 模块级
counter,fetchStaticUI 入口 ++loadId + snapshot pluginId,响应到来时
任一不匹配就丢弃。
验证:vue-tsc --build 通过。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* handleOpenUi 跳转前尊重 action.confirm_message
CodeRabbit 在 2c8a90e 上指出 handleOpenUi 没有调用确认守卫,list-action
executor (usePluginListContextActions.ts:executeAction L350) 对
`kind === 'ui'` action 跳转前会先调 confirmIfNeeded 弹确认框,但 Open UI
按钮直接跳过——plugin 给 ui action 配 confirm_message 时两处行为分叉,
按钮绕过了 plugin 自己配的二次确认。
修法:与 confirmIfNeeded (L226-244) 行为对齐——dialog mode 时若解析出
confirm_message 就 ElMessageBox.confirm,用户取消则 return。
hold mode 依赖 host 组件(PluginDangerConfirmDialog)呈现,按钮上下文
不支持,跳过即可(plugin 给 kind: "ui" 配 hold mode 极少见)。
confirm_message 走 resolveLocalizedText(i18nLabel.ts),与之前 P3 一致
处理 string / locale-keyed dict。
验证:vue-tsc --build 通过。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Hongzhi Wen <cartabio.coder1@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent b9c0dc9 commit 296e49e
76 files changed
Lines changed: 73166 additions & 21 deletions
File tree
- brain
- frontend/plugin-manager/src
- components/plugin
- composables
- i18n/locales
- types
- utils
- views
- main_logic
- main_routers
- plugin
- plugins/galgame_plugin
- static
- server
- messaging
- routes
- tests
- fixtures/galgame_plugin
- manual_load/nekoforge.renpy-bridge-demo
- rollback/nekoforge.renpy-bridge-demo
- integration
- unit/plugins
- scripts
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
235 | 235 | | |
236 | 236 | | |
237 | 237 | | |
238 | | - | |
239 | | - | |
| 238 | + | |
240 | 239 | | |
241 | 240 | | |
242 | 241 | | |
| |||
1073 | 1072 | | |
1074 | 1073 | | |
1075 | 1074 | | |
1076 | | - | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
1077 | 1091 | | |
1078 | 1092 | | |
1079 | 1093 | | |
| |||
Lines changed: 98 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
3 | 13 | | |
4 | 14 | | |
5 | 15 | | |
| |||
56 | 66 | | |
57 | 67 | | |
58 | 68 | | |
| 69 | + | |
59 | 70 | | |
60 | | - | |
| 71 | + | |
61 | 72 | | |
62 | 73 | | |
| 74 | + | |
63 | 75 | | |
64 | 76 | | |
65 | 77 | | |
66 | 78 | | |
67 | 79 | | |
68 | 80 | | |
69 | 81 | | |
70 | | - | |
| 82 | + | |
| 83 | + | |
71 | 84 | | |
72 | 85 | | |
73 | 86 | | |
| |||
78 | 91 | | |
79 | 92 | | |
80 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
81 | 176 | | |
82 | 177 | | |
83 | 178 | | |
| |||
170 | 265 | | |
171 | 266 | | |
172 | 267 | | |
| 268 | + | |
173 | 269 | | |
174 | 270 | | |
Lines changed: 5 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| |||
71 | 72 | | |
72 | 73 | | |
73 | 74 | | |
74 | | - | |
| 75 | + | |
75 | 76 | | |
76 | 77 | | |
77 | 78 | | |
| |||
120 | 121 | | |
121 | 122 | | |
122 | 123 | | |
| 124 | + | |
123 | 125 | | |
124 | 126 | | |
125 | 127 | | |
126 | 128 | | |
| 129 | + | |
127 | 130 | | |
128 | 131 | | |
129 | 132 | | |
| |||
168 | 171 | | |
169 | 172 | | |
170 | 173 | | |
| 174 | + | |
171 | 175 | | |
172 | 176 | | |
173 | 177 | | |
| |||
Lines changed: 13 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
37 | | - | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| |||
105 | 106 | | |
106 | 107 | | |
107 | 108 | | |
108 | | - | |
109 | | - | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
110 | 114 | | |
111 | 115 | | |
112 | 116 | | |
| |||
223 | 227 | | |
224 | 228 | | |
225 | 229 | | |
226 | | - | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
227 | 235 | | |
228 | 236 | | |
229 | 237 | | |
230 | | - | |
| 238 | + | |
231 | 239 | | |
232 | 240 | | |
233 | 241 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
0 commit comments