@luchenglong/cli-bridge 0.0.0-stage → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -0
- package/LICENSE +21 -0
- package/MCP-POLICY.md +53 -0
- package/PROVIDER-CONTRACT.md +235 -0
- package/README.en.md +98 -0
- package/README.md +151 -2
- package/assets/indicator-states.svg +62 -0
- package/bin/agy-quota.mjs +223 -0
- package/core/bridge-kit.mjs +549 -0
- package/core/scheduling.mjs +149 -0
- package/docs/ARCHITECTURE.md +117 -0
- package/docs/FALLBACK-AND-INDICATOR.md +93 -0
- package/docs/HANDOVER.md +226 -0
- package/docs/INSTALL.md +118 -0
- package/docs/MCP-POLICY.zh.md +49 -0
- package/docs/MIGRATION.md +43 -0
- package/docs/RELEASE-SOP.md +80 -0
- package/docs/history/agy/CHANGELOG.md +326 -0
- package/docs/history/codebuddy/CHANGELOG.md +668 -0
- package/docs/history/mimo/CHANGELOG.md +346 -0
- package/dynamic/agy.host.js +1237 -0
- package/dynamic/agy.host.template.mjs +140 -0
- package/dynamic/codebuddy.host.js +1787 -0
- package/dynamic/codebuddy.host.template.mjs +162 -0
- package/dynamic/mimo.host.js +1732 -0
- package/dynamic/mimo.host.template.mjs +169 -0
- package/dynamic/opencode.host.js +1443 -0
- package/dynamic/opencode.host.template.mjs +125 -0
- package/home-plugin/cli-bridge-indicator/cordis.patch.yml +31 -0
- package/home-plugin/cli-bridge-indicator/lib/client.js +606 -0
- package/home-plugin/cli-bridge-indicator/lib/index.mjs +420 -0
- package/home-plugin/cli-bridge-indicator/lib/preset-declarations.mjs +137 -0
- package/home-plugin/cli-bridge-indicator/lib/settings.mjs +300 -0
- package/mcp/agy-mcp-server.mjs +6 -0
- package/mcp/cli-bridge-mcp.mjs +185 -0
- package/mcp/codebuddy-mcp-server.mjs +6 -0
- package/mcp/mimo-mcp-server.mjs +6 -0
- package/mcp/providers/agy.mjs +254 -0
- package/mcp/providers/codebuddy.mjs +397 -0
- package/mcp/providers/mimo.mjs +290 -0
- package/mcp/providers/opencode.mjs +236 -0
- package/package.json +89 -4
- package/preset/agy-first/agent.cordis.yml +141 -0
- package/preset/agy-first/cli-bridge.mjs +169 -0
- package/preset/agy-first/plugin-list.mjs +26 -0
- package/preset/agy-first/preset.yml +3 -0
- package/preset/codebuddy-first/agent.cordis.yml +141 -0
- package/preset/codebuddy-first/cli-bridge.mjs +188 -0
- package/preset/codebuddy-first/plugin-list.mjs +20 -0
- package/preset/codebuddy-first/preset.yml +3 -0
- package/preset/mimo-first/agent.cordis.yml +143 -0
- package/preset/mimo-first/cli-bridge.mjs +236 -0
- package/preset/mimo-first/plugin-list.mjs +39 -0
- package/preset/mimo-first/preset.yml +3 -0
- package/preset/opencode-first/agent.cordis.yml +141 -0
- package/preset/opencode-first/cli-bridge.mjs +147 -0
- package/preset/opencode-first/plugin-list.mjs +26 -0
- package/preset/opencode-first/preset.yml +3 -0
- package/preset/standard-base.mjs +102 -0
- package/providers/agy.mjs +398 -0
- package/providers/codebuddy.mjs +926 -0
- package/providers/mimo.mjs +864 -0
- package/providers/opencode.mjs +619 -0
- package/providers/registry.mjs +39 -0
- package/scripts/build.mjs +235 -0
- package/scripts/deploy.mjs +61 -0
- package/scripts/verify.mjs +148 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Changelog — @luchenglong/cli-bridge
|
|
2
|
+
|
|
3
|
+
本项目遵循 [语义化版本](https://semver.org/);版本号同步 `package.json`、Git tag 与
|
|
4
|
+
GitHub Release(`scripts/verify.mjs` 在 CI 与 prepack 双重锁一致)。
|
|
5
|
+
|
|
6
|
+
> **三个旧桥接包(`agy-first-bridge` / `codebuddy-first-bridge` / `mimo-first-bridge`)
|
|
7
|
+
> 的全部历史已逐字并入各自 lineage 文档,本文件只记统一包自身的变更:**
|
|
8
|
+
> - AGY 线:[docs/history/agy/CHANGELOG.md](docs/history/agy/CHANGELOG.md)(终版 1.7.1)
|
|
9
|
+
> - CodeBuddy 线:[docs/history/codebuddy/CHANGELOG.md](docs/history/codebuddy/CHANGELOG.md)(终版 1.6.2)
|
|
10
|
+
> - MiMo 线:[docs/history/mimo/CHANGELOG.md](docs/history/mimo/CHANGELOG.md)(终版 1.2.9)
|
|
11
|
+
|
|
12
|
+
## [0.2.3] - 2026-10-15
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **第四个 provider:OpenCode**(`opencode`)。四形态全量交付:描述符
|
|
16
|
+
`providers/opencode.mjs`、preset `opencode-first`、`dynamic/opencode.host.js`、
|
|
17
|
+
MCP 面 `mcp/providers/opencode.mjs`。工具面 = `opencode_run` /
|
|
18
|
+
`opencode_continue` / `opencode_status` + **opencode_models**(列出本机可用模型)。
|
|
19
|
+
- **opencode_models**:执行 `opencode models` 取模型列表,支持 `freeOnly` /
|
|
20
|
+
`provider` 过滤;**免费模型优先排序**(`-free` 后缀)。CLI 缺失/未登录时明确
|
|
21
|
+
返回 `ok:false` 与可操作错误,**绝不凭空伪造模型列表**。
|
|
22
|
+
- **设置面板可选「用哪个 opencode」与「默认模型」**:三个字段均为可自定义下拉 ——
|
|
23
|
+
`binPath`(下拉列出实测探测到的候选路径)、`defaultModel`(实时调
|
|
24
|
+
`opencode models` 填充)、`defaultAgent`(build / plan)。
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **exe 解析优先级统一**:env `OPENCODE_BIN`/`OPENCODE_CLI` > 桌面版 V2 已知路径
|
|
28
|
+
(`ai.opencode.desktop/cli/<ver>-<arch>/`,版本按 semver 降序)> PATH 查找
|
|
29
|
+
`opencode-cli`。二进制名是 **`opencode-cli`**(V2 桌面版),不做 `opencode.exe`
|
|
30
|
+
兜底 —— V1/V2 不能并存安装,兜底会误命中另一个版本。
|
|
31
|
+
- 单一 id 轴(契约 §3.1)落到测试:keystone 四个测试文件原先硬编码三家 id 列表,
|
|
32
|
+
改为全部从 `PROVIDER_IDS` / `providerMeta()` 派生 —— 以后新增 provider 零改动。
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- **opencode 事件解析的两个真实缺陷**(端到端测试捕获,单元测试当时全绿):
|
|
36
|
+
① 文本在 `part.text` 而非顶层,原实现取 `parsed.text` 恒为 undefined → 响应体为空;
|
|
37
|
+
② 正文(`text` 事件)与统计(`step_finish` 事件的 `cost`/`tokens`)在**不同**事件里,
|
|
38
|
+
且原实现倒序遍历会在读到 `text` 前先命中末尾的 `step_finish` 并返回 → 回填恒空,
|
|
39
|
+
表现为「成功但正文为空」。改为**正向**扫完全流再决策,命中终态事件时回填末段文本。
|
|
40
|
+
- 更正 opencode CLI 事实(按本机实测 v2.0.29 而非文档推断):**不存在 `result` 事件**
|
|
41
|
+
(终止判据是退出码 0/1/130)、`run` 子命令**无 `--prompt`**(`-p` 是 `--password`)、
|
|
42
|
+
V2 **无 `--variant`**(并入 `--model provider/model#variant`)、V2 **无 `--dir`**
|
|
43
|
+
(cwd 靠 spawn 工作目录)。
|
|
44
|
+
|
|
45
|
+
## [0.2.2] - 2026-10-10
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
- **设置面板改横向标签页**(替代 0.2.1 的纵向网格堆叠 —— 页面长度随 provider 数增长的
|
|
49
|
+
问题):一排名字点击切换,同屏只渲染一张卡;「总设置」= 调度卡,其余 = 各 CLI 偏好卡
|
|
50
|
+
(卡头 chip 保留)。tab 上带 启用绿点/灰点 + 优先级 `#n`,顺序跟随优先级;
|
|
51
|
+
`flex-wrap` 使第 4、5 个 CLI 只是多一个 tab,布局零改动。
|
|
52
|
+
- **id 轴后端驱动**:`providerMetas()` 以视图 `scheduling.all` ∪ `providers` 键为权威轴,
|
|
53
|
+
本地 `PROVIDERS` 表降级为 fallback(只补 presetId/label 展示)——新 provider 接入时
|
|
54
|
+
灯 pill、弹窗分区、标签页、调度卡、保存循环全部自动出现,client.js 零改动。
|
|
55
|
+
### Fixed
|
|
56
|
+
- React hook 顺序红线:tab 状态声明置于 `if (!view)` 早期 return 之前(否则 view 加载
|
|
57
|
+
瞬间 hook 数量变化 → 面板崩溃),`client-ui-surface` 静态锁。
|
|
58
|
+
- **首发 npm 的 scoped 包可见性**:`package.json` 补 `publishConfig.access = "public"`。
|
|
59
|
+
此前只有 RELEASE-SOP 要求命令行 `npm publish --access public`;走 GUI/插件通道发布时不带该
|
|
60
|
+
参数,npm 按私有包处理 → `E402 Payment Required`。写入 package.json 后任何发布通道都正确。
|
|
61
|
+
|
|
62
|
+
### 发布(2026-10-14)
|
|
63
|
+
- **首发 npm**:`@luchenglong/cli-bridge@0.2.2`(统一包首次发布;registry 上 `latest=0.2.2`,
|
|
64
|
+
shasum `362d506e`,58 files / 320.1 kB)。npm 首次创建 scoped 包返回 `PUT 202 Accepted`
|
|
65
|
+
("may take a few minutes to become available")—— 属正常,勿重复发布。
|
|
66
|
+
- **旧包已 deprecated**(三条均已在 registry 生效,显示迁移提示):`agy-first-bridge`(终版 1.7.1)、
|
|
67
|
+
`codebuddy-first-bridge`(终版 1.6.2)、`mimo-first-bridge`(终版 1.2.9)。
|
|
68
|
+
|
|
69
|
+
## [0.2.1] - 2026-10-10
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
- **指示灯长期存在**:超过 `PROJECT_TTL_MS`(10 分钟)无活动的项目(`stale:true`)不再
|
|
73
|
+
渲染为常亮 pill(弹窗历史列表保留);服务端半边 —— 顶层聚合 `state/lastStatus/
|
|
74
|
+
fallbackActive` 只认新鲜项目,全陈旧时回落 `idle`(此前一次失败的 ✗AGY 会永久挂灯,
|
|
75
|
+
`indicator-state` 新增 3 条红线锁)。
|
|
76
|
+
### Changed
|
|
77
|
+
- **设置面板卡片模式**:「总设置」区(调度卡:启用数量 + 优先级)与每个 CLI 独立成卡、
|
|
78
|
+
响应式网格排布;CLI 卡头带 启用/未启用 与优先级 `#n` chip(与调度视图同源派生,两处
|
|
79
|
+
永远一致),未启用卡半透明并明确提示「三形态不注册工具、偏好仍保存」。
|
|
80
|
+
- **单一 id 轴贯通 `scripts/build.mjs` 与 `preset-declarations`**(改从 `providers/registry.mjs`
|
|
81
|
+
派生 `PROVIDER_IDS`):新增 provider 只改 registry,调度卡/构建派生物自动跟上
|
|
82
|
+
(PROVIDER-CONTRACT.md §3.1)。版本锁三处 + provider `mcp.version` 同步 0.2.1。
|
|
83
|
+
|
|
84
|
+
## [0.2.0] - 2026-10-10
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
新增「CLI 调度」:让用户选择由智能体调用 CLI 时**启用哪些 CLI(数量)**以及**调用优先级**。
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
- **调度单源 `core/scheduling.mjs`**(纯逻辑、无 import,可同时被宿主 ESM 与动态沙箱文本内联消费):
|
|
91
|
+
`normalizeScheduling` / `resolveScheduling` / `isBridgeEnabled`(门禁 helper)/ `defaultPriority` /
|
|
92
|
+
`describeScheduling`。语义:`enabled` = 勾选启用集合(未启用一面不注册任何工具/政策段/心跳),
|
|
93
|
+
`priority` = 数组顺序即调用建议顺序(首位最高);文件缺失/坏值/无 fs → 全部启用 + 注册表顺序
|
|
94
|
+
(**fail-open**:读不到配置永远不等于关掉所有桥)。
|
|
95
|
+
- **落盘**:统一设置文件新增顶层 `_scheduling` 区(下划线前缀 = 非 provider 区,旧代码逐分区读取
|
|
96
|
+
整区忽略 → 纯增量向后兼容)。`normalizeAll` / `settingsView` / `parseSettingsBody` 三区同步:
|
|
97
|
+
GET 返回 `scheduling:{enabled,priority,order,all,labels}`;POST 整区替换、类型严格(非对象 /
|
|
98
|
+
未知 id → 400)、**缺省 = 保持现值**(provider-only 提交绝不悄悄重置调度)。
|
|
99
|
+
- **四形态贯穿**:① 6 个桥接宿主(3 preset + 3 dynamic 模板)`apply()` 首行门禁 —— 禁用面零注册;
|
|
100
|
+
② 声明制 preset 注册顺序按 priority 排(三个 preset 恒常注册:禁用 ≠ 从目录消失,用户仍可切入排查);
|
|
101
|
+
③ MCP `selectedProviders()` 无钉住时按 `enabled` 过滤、按 `order` 排序(子进程启动读一次,重启刷新);
|
|
102
|
+
本机实际注册的是 `dsh-home\bin\` 下三个自包含旧服务器(不依赖本包),故另附最小只读副本
|
|
103
|
+
`bin\cli-bridge-scheduling.mjs`(物料源 `deploy/legacy-mcp/`),三服务器 `tools/list`/`tools/call`
|
|
104
|
+
现读过滤 —— 面板关掉某面后 MCP 子进程重启即空工具面;语义单源仍是 `core/scheduling.mjs`。
|
|
105
|
+
④ `GET /cli-bridge/status` 每次轮询现读并附 `scheduling` 快照(灯侧即时可见)。
|
|
106
|
+
env `CLI_BRIDGE_PROVIDER`(薄封装钉住单面)优先级最高;宿主形态传 `ignorePin` 不受全局 env 反噬。
|
|
107
|
+
- **构建**:`scripts/build.mjs` 新增 `/*__SCHED__*/` 占位,内联 `core/scheduling.mjs` + 注入
|
|
108
|
+
`SCHED_ALL_IDS` 常量(沙箱禁 import,拿不到 registry);旧模板无该占位则不注入(向后兼容)。
|
|
109
|
+
- **UI**:设置面板顶部「调度 · 启用与优先级」卡 —— 每 CLI 一行(勾选 + 序号徽标 + ↑↓);
|
|
110
|
+
provider 卡片顺序跟随优先级,禁用面仍渲染(不改开关也能修好它的 token/预选);全禁用时红字警告。
|
|
111
|
+
过渡窗口护栏:新 client.js 先于宿主热加载时(旧宿主视图无 `scheduling`),卡片自动禁用交互、
|
|
112
|
+
POST 跳过 `_scheduling`、保存后红字提示「重启 DSH 后重新保存」,绝不假成功。
|
|
113
|
+
- `mcp/cli-bridge-mcp.mjs --check` 报告新增 `scheduling:{source,enabled,order}`,部署后一眼确认生效面。
|
|
114
|
+
|
|
115
|
+
### Notes
|
|
116
|
+
- 提示词连续性红线不受影响:政策段全文仍逐字来自 provider,门禁只做「注册 / 不注册」;
|
|
117
|
+
优先级以**注册与装配顺序**表达(preset 目录序 / MCP tools/list 序 / 提示段落序),不新增文案。
|
|
118
|
+
- 生效时机:preset / 动态形态下次会话装配即读;MCP 子进程需重启才刷新工具面(面板保存提示已说明)。
|
|
119
|
+
|
|
120
|
+
## [0.1.0] - 2026-10-10
|
|
121
|
+
|
|
122
|
+
首个统一版本:`agy-first-bridge`、`codebuddy-first-bridge`、`Xiaomi MiMo-bridge`
|
|
123
|
+
三个插件整合为一个包、一个指示灯、一个 MCP server、一个设置面板。
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
- **统一内核 `core/bridge-kit.mjs`**:状态引擎(项目分桶 / 会话租约 / 累计 runs+tokens)、
|
|
127
|
+
行流解析、NDJSON 半行安全、限流判定(`isLimited` 可被 provider 收窄覆盖)、回退三选一
|
|
128
|
+
编排(`createRunner`:preflight → resolveExe → buildArgv → 瞬时错误静默重试一次 →
|
|
129
|
+
限流弹窗 → fallback/retry/cancel)、MCP 快照载荷(`buildMcpBridgePayload`/
|
|
130
|
+
`normalizeMcpBridge`,文件 `{DSH_HOME}/cli-bridge-mcp-<id>.json`,90s stale)。
|
|
131
|
+
- **Provider 注册表 `providers/registry.mjs` + 冻结契约 `PROVIDER-CONTRACT.md`**:
|
|
132
|
+
agy / codebuddy / mimo 各以一个描述符(buildArgv / parseJson / buildResult /
|
|
133
|
+
foldStreamEvent / resolveBackend / settings / tools / execute / attach …)接入,
|
|
134
|
+
三形态(preset / dynamic 沙箱 / MCP stdio)共享同一 provider 模块,零重复逻辑。
|
|
135
|
+
- **单一状态灯(家级插件 `home-plugin/cli-bridge-indicator/`)**:一个 pill 聚合三家
|
|
136
|
+
(AGY · CB · MIMO 分区弹出面板),每项目实时步骤折叠、悬停当前步骤、点击展开活动面板;
|
|
137
|
+
preset 租约(75s TTL/30s 心跳)+ 宿主枚举(agents.list × composedPreset)双通道判定
|
|
138
|
+
「本会话是否运行在桥接预设下」;旧路由 `/agy-indicator/status`、
|
|
139
|
+
`/codebuddy-indicator/status`、`/mimo-indicator/status` 保持兼容别名。
|
|
140
|
+
- **统一设置面板**:`GET/POST /cli-bridge/settings` + 浏览器内三卡片表单(meta 驱动,
|
|
141
|
+
provider 各自声明 fields/secretKeys);单一文件 `{DSH_HOME}/cli-bridge-settings.json`
|
|
142
|
+
按 provider 分区;token 永不明文回传(掩码 set+尾4位);POST 空=保持、
|
|
143
|
+
`<key>Clear:true`=清除;**旧包设置文件一次性字段级迁移**:codebuddy 扁平
|
|
144
|
+
`codebuddy-bridge-settings.json` 与 mimo `{APPDATA}/mimo-first-bridge/settings.json`
|
|
145
|
+
(backend→preferredBackend、desktopModel)在统一键未写过时自动回退,写过即失效,
|
|
146
|
+
永不写旧文件。
|
|
147
|
+
- **单一 MCP server `mcp/cli-bridge-mcp.mjs`**(bin `cli-bridge-mcp`):一次接入暴露
|
|
148
|
+
全部 provider 工具(agy_run/continue/status/quota、codebuddy_run/continue/status、
|
|
149
|
+
mimo_run/continue/status/settings);`--provider=<id>` 过滤单面;
|
|
150
|
+
`mcp/<id>-mcp-server.mjs`(bin 同名兼容入口)= 带 `--provider=<id>` 的薄封装,
|
|
151
|
+
旧包 MCP 配置只需换路径。
|
|
152
|
+
- **preset 声明制交付(Form-A 自注册)**:`preset-declarations.mjs` 在 indicator 内
|
|
153
|
+
`ctx.inject(['agentPresets'])` 直接 `register(definition)`,任何 DSH 版本可用;
|
|
154
|
+
bundle patch 只含一行 indicator;桥接插件行走裸子路径
|
|
155
|
+
`@luchenglong/cli-bridge/preset-<id>`(历史事故教训:相对路径在 preset baseUrl
|
|
156
|
+
下误解析)。preset id 保持旧值不可变:`cordis-agy` / `codebuddy-first` / `cordis-mimo`。
|
|
157
|
+
- **构建单一源 `scripts/build.mjs`**:`preset/<dir>/plugin-list.mjs` 一份源同时生成
|
|
158
|
+
legacy `agent.cordis.yml` + `preset.yml` 与运行时声明;`dynamic/<id>.host.js` 由
|
|
159
|
+
模板(双占位符 KIT+PROVIDER)内联生成(`stripModuleSyntax`,遇到不支持的模块形态
|
|
160
|
+
大声失败);`--check` 漂移即 CI 红;`--only=<id>` 支持并行开发。
|
|
161
|
+
- **发布红线闸门 `scripts/verify.mjs`**(prepack + CI,9 项):client 注册 id ≡ 包名
|
|
162
|
+
(历史事故 agy 1.6.1 / codebuddy 1.1.8:不一致 = 客户端组合加载失败 = 启动致命屏)、
|
|
163
|
+
bundle 行名、exports 目标存在性、preset 桥接说明符、描述符完整度、
|
|
164
|
+
`dsh.client.platform=web`、plugin-list 单源存在性、版本双锁
|
|
165
|
+
(`package.json` ≡ MCP `SERVER_VERSION` ≡ CHANGELOG 顶部条目)、
|
|
166
|
+
凭据泄漏扫描(fixtures 文件名形态 + 源码内 ≥24 位随机凭据字面量,`fake-*` 白名单)。
|
|
167
|
+
- **CI(`.github/workflows/ci.yml`)**:node 18/20/22 矩阵跑 build → verify → build
|
|
168
|
+
--check → dynamic 宿主 `node --check` → `node --test` → 统一与分 provider MCP
|
|
169
|
+
`--check`。
|
|
170
|
+
- **AGY 额度面板保留**:`GET /agy-indicator/quota`(5 分钟缓存)→ `bin/agy-quota.mjs`
|
|
171
|
+
(脚本定位 = env `CLI_BRIDGE_AGY_QUOTA` > 包内 bin,绝无硬编码用户路径)。
|
|
172
|
+
|
|
173
|
+
### Changed(相对三个旧包)
|
|
174
|
+
- 三包合一:一个 npm 包名(`@luchenglong/cli-bridge`)、一个 git 仓库、一套文档;
|
|
175
|
+
旧包 `deprecated` 后不再维护。
|
|
176
|
+
- 状态灯从三盏 pill 变一盏聚合 pill(悬停/点击面板内按 provider 分区),旧「各自一盏」
|
|
177
|
+
的视觉由分区色标代替;每个项目的活动细节、runs/tokens 统计语义不变。
|
|
178
|
+
- 设置从三个面板/文件统一为一个分区式面板;字段与语义逐字段映射(见上迁移条目)。
|
|
179
|
+
- MCP 从三个 server 变一个(工具名、入参、返回文本语义逐字不变)。
|
|
180
|
+
|
|
181
|
+
### Known limitations(0.1.0,有意省略)
|
|
182
|
+
- codebuddy 设置面板的**促销角标**未随迁(旧 v1.6.1 的 `modelPromotions` 面板装饰);
|
|
183
|
+
模型目录保留「倍率 + 授权」两标与账号实时清单,选模型行为不受影响。
|
|
184
|
+
- 除此之外,三家全部工具语义、状态机、回退弹窗、额度面板(AGY quota)、旧路由/
|
|
185
|
+
旧设置文件/旧 MCP 快照路径兼容均按逐字兼容移植,无已知功能缺口。
|
|
186
|
+
|
|
187
|
+
### Compatibility
|
|
188
|
+
- DSH:`>=0.1.1-rc.2 <0.3.0-0`(本机 0.2.1-alpha.1 验证);无 dsh peer 依赖,
|
|
189
|
+
兼容闸门天然通过。
|
|
190
|
+
- Node ≥ 18(MCP/dynamic/preset 全形态);零运行时依赖。
|
|
191
|
+
- 红线 4:升级包名必须同步改 `client.js` 注册 id(verify + 测试双保险)。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chenglong
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/MCP-POLICY.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# CLI Bridge policy (cli-bridge MCP)
|
|
2
|
+
|
|
3
|
+
中文 | [English](MCP-POLICY.md) — canonical copy; also installed into
|
|
4
|
+
`~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md` on the authoring machine.
|
|
5
|
+
|
|
6
|
+
The local **`agy`** (Google Antigravity), **`codebuddy`** (Tencent CodeBuddy Code,
|
|
7
|
+
four product faces) and **`mimo`** (Xiaomi MiMoCode CLI / MiMo Desktop) agent CLIs
|
|
8
|
+
are available to this host through the MCP server **`cli-bridge`**, exposed as
|
|
9
|
+
`agy_run / agy_continue / agy_status / agy_quota`, `codebuddy_run / codebuddy_continue /
|
|
10
|
+
codebuddy_status` and `mimo_run / mimo_continue / mimo_status / mimo_settings`
|
|
11
|
+
(server-qualified, e.g. `mcp__cli-bridge__agy_run`). Every CLI runs **fully
|
|
12
|
+
non-interactively under host control** — permissions are auto-approved, they never
|
|
13
|
+
prompt, and they can edit files, run builds, and investigate multi-file code.
|
|
14
|
+
|
|
15
|
+
One server exposes all three; run it with `--provider=agy` (or the per-provider
|
|
16
|
+
entry `mcp/<id>-mcp-server.mjs`) to expose a single family and keep the older
|
|
17
|
+
tool-surface configuration byte-compatible.
|
|
18
|
+
|
|
19
|
+
## Priority rule — decision table and context pattern
|
|
20
|
+
|
|
21
|
+
### Tool Selection (identical for all three families)
|
|
22
|
+
- **Single read/glob/grep or short (<30s) command** → Use native host tools.
|
|
23
|
+
- **Implementing, editing, refactoring, debugging, builds, multi-file investigation** → Prefer `<id>_run` first (pick the family your account/quota favors).
|
|
24
|
+
- **Follow-ups on the same topic** → Use `<id>_continue` with `sessionId`/`conversationId` or `latest: true` (conversation context is preserved server-side).
|
|
25
|
+
- **Final build/test verification of the CLI's output** → Use native host tools.
|
|
26
|
+
- **Image/video generation** → Dispatch to `agy_run` without specifying a model.
|
|
27
|
+
|
|
28
|
+
### Context Protocol (one topic = one conversation)
|
|
29
|
+
- **First dispatch on a topic**: include a compact CONTEXT preamble (point to paths, do not paste file contents; the CLI reads the repo itself):
|
|
30
|
+
```
|
|
31
|
+
CONTEXT: 2-6 lines — goal; repo root; key paths; decisions/constraints; current state.
|
|
32
|
+
TASK: the complete instruction.
|
|
33
|
+
```
|
|
34
|
+
- **Follow-ups**: call `<id>_continue` and state only what is new.
|
|
35
|
+
- When the task must not write files yet, call `<id>_run` with `mode: "plan"`.
|
|
36
|
+
- When you delegate to a sub-agent, instruct it to also follow this CLI-first policy.
|
|
37
|
+
- While `<id>_run`/`<id>_continue` is running, call `<id>_status` any time to see the
|
|
38
|
+
live per-project step + recent trail without waiting for completion.
|
|
39
|
+
|
|
40
|
+
## Quota awareness (agy)
|
|
41
|
+
|
|
42
|
+
`agy_quota` reports the Google AI plan pools. The **Gemini 5-hour window** is the
|
|
43
|
+
sole per-task gate (below ~10% remaining the bridge blocks dispatch); an exhausted
|
|
44
|
+
weekly bucket does not abort work — it only means agy is a poor pick for the rest
|
|
45
|
+
of the week. `codebuddy` has no quota API: watch per-project `runs`/`totalTokens`
|
|
46
|
+
via `codebuddy_status`. `mimo_settings` shows the effective backend (CLI vs Desktop).
|
|
47
|
+
|
|
48
|
+
## Fallback — never loop
|
|
49
|
+
|
|
50
|
+
When a CLI is **rate-limited or the network is down**, the tool result text says so
|
|
51
|
+
explicitly. **Do NOT retry in a loop.** Finish the task with your own tools, or ask
|
|
52
|
+
the user whether to fall back to the local model / API config. Never ask the CLI to
|
|
53
|
+
call back into this host.
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# PROVIDER-CONTRACT — CLI Bridge 提供方(Provider)接入契约 v0.1.0(冻结)
|
|
2
|
+
|
|
3
|
+
> 单一事实来源:`core/bridge-kit.mjs`(通用骨架)。每个 CLI 提供方(agy /
|
|
4
|
+
> codebuddy / mimo)只写一个**描述符模块** + 各形态的薄适配层。
|
|
5
|
+
> **禁止**修改 `core/`、`home-plugin/`、`mcp/cli-bridge-mcp.mjs`、`scripts/`、
|
|
6
|
+
> `providers/registry.mjs`、根 `package.json` —— 这些是 keystone,由 Lead 单作者维护。
|
|
7
|
+
> 你的写权限范围见每个 provider 任务卡的 write_scopes。
|
|
8
|
+
|
|
9
|
+
## 0. 命名与硬约束(红线)
|
|
10
|
+
|
|
11
|
+
- provider id(全小写,用于事件通道/设置分区/文件名/工具名):`agy` | `codebuddy` | `mimo`。
|
|
12
|
+
- preset id(保持旧包不变,旧会话头引用):`cordis-agy` | `codebuddy-first` | `cordis-mimo`。
|
|
13
|
+
- 模型工具名(保持旧包不变):`agy_run/agy_continue/agy_status(/agy_quota)`、
|
|
14
|
+
`codebuddy_run/codebuddy_continue/codebuddy_status`、`mimo_run/mimo_continue/mimo_status(/mimo_settings)`。
|
|
15
|
+
- 客户端契约(红线 4):浏览器半注册 id **必须**等于包名 `@luchenglong/cli-bridge`;
|
|
16
|
+
该文件是 keystone(`home-plugin/cli-bridge-indicator/lib/client.js`),provider 作者**不碰**。
|
|
17
|
+
- 动态沙箱形态禁止 `import/require`;派生文件一律由 `node scripts/build.mjs` 生成,
|
|
18
|
+
生成物不要手改(`npm test` 的 build-sync 会锁)。
|
|
19
|
+
|
|
20
|
+
## 1. 描述符模块(每个 provider 一个文件)
|
|
21
|
+
|
|
22
|
+
文件:`providers/<id>.mjs`。ESM,**零外部依赖**:只允许
|
|
23
|
+
`import ... from '../core/bridge-kit.mjs'`(动态构建时该 import 行会被剥离并内联骨架)。
|
|
24
|
+
默认导出工厂:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
export default function defineProvider(deps = {}) { return descriptor }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`deps` 由宿主形态注入(preset 形态:`{ process, env }`;dynamic 形态:`{ env }`(沙箱,
|
|
31
|
+
只有 typeof 守卫可读到的 env 对象);MCP 形态:`{ nodeFs, nodeChild, nodePath, env }`)。
|
|
32
|
+
描述符字段(★=必填):
|
|
33
|
+
|
|
34
|
+
| 字段 | 类型 | 说明 |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| ★ `id` | string | 'agy'/'codebuddy'/'mimo' |
|
|
37
|
+
| ★ `label` | string | UI 短标签:'AGY'/'CB'/'MIMO' |
|
|
38
|
+
| ★ `presetId` | string | 上表 preset id |
|
|
39
|
+
| ★ `defaultBackend` | string\|null | 如 'codebuddy'/'mimocode';agy 无多后端给 null |
|
|
40
|
+
| `defaultMode` | string | 默认 'auto' |
|
|
41
|
+
| `exeName` | string | PATH 兜底可执行名('agy'/'codebuddy'/'mimo') |
|
|
42
|
+
| `binEnvVars` | string[] | 探测用的环境变量名(['AGY_BIN'] 等) |
|
|
43
|
+
| ★ `backends(env)` | fn | 合法后端名数组或 null(单后端) |
|
|
44
|
+
| ★ `normalizeBackend(v)` | fn | 别名归一(非法输入返回 null) |
|
|
45
|
+
| ★ `resolveBackend(args, target, preferred)` | fn | 显式 > 会话归属(target.backend) > 偏好 > default |
|
|
46
|
+
| ★ `buildArgv(exePrefix, args, opts)` | fn | 返回 `{ argv, mode, timeoutSec, env? }`;opts 见 bridge-kit createRunner 调用点 |
|
|
47
|
+
| ★ `parseJson(stdoutText)` | fn | 宽容解析 stream-json,返回末 result 事件对象或 null |
|
|
48
|
+
| ★ `buildResult(parsed, outcome, mode, stderrText, stdoutText, backend)` | fn | 统一结果对象 `{ok,status,response,sessionId,mode,backend,totalTokens,durationSeconds,numTurns,exitCode,stderr,...}` |
|
|
49
|
+
| `foldStreamEvent(ev, project, summarizeArgs, maxArgLen, maxTrail)` | fn | 实时步骤折叠(写 project.current/trail);无 stream-json 的 provider 省略 |
|
|
50
|
+
| `isTransientCliError(res)` | fn→bool | 瞬时错误自动重试一次的判定 |
|
|
51
|
+
| `isLimited(res)` | fn→bool | 可选:覆盖 kit 的限流/网络判定(默认 kit `isLimited`);runner 用 provider 版决定是否弹回退三选一 |
|
|
52
|
+
| `failureHint(res)` | fn→string | 按失败类型给可行动指引(空串=用通用) |
|
|
53
|
+
| `preflight({args,exec,backend,cwd,engine,ctx,o})` | fn | 返回 `{ abort: <结果对象> }` 或 undefined |
|
|
54
|
+
| `execute({args,exec,backend,cwd,built,engine,ctx,o,runSync})` | async fn | **非 spawn 主路径**(mimo 桌面 HTTP 等);与 `delegates` 配合:runner 在 `delegates(backend,args)` 为真(或未定义 delegates)时完全委托,返回值直接交 engine.end;为假则落回通用 pipeline(jobs/瞬时重试/回退弹窗) |
|
|
55
|
+
| `delegates(backend, args)` | fn→bool | 可选:限定 execute 的接管范围(例:mimo 只接管 mimo-desktop,mimocode 走通用 pipeline)。kit 在委托前已 engine.begin(cwd) 并调过 buildArgv——对不 spawn 的后端 buildArgv 可返回空壳 `{argv:[],mode,timeoutSec}` |
|
|
56
|
+
| ★ `unavailableStatus` | string | 找不到可执行时的 status(旧包各自保持:'CODEBUDDY_UNAVAILABLE' 等由你定,注意 isLimited 认 'CLI_UNAVAILABLE',特殊名需自行保证限流判定不受影响) |
|
|
57
|
+
| ★ `tools` | object | `{ run:{name,description,inputSchema}, continue:{...}, status:{...} }` 纯对象 ToolDefinition(不含 execute),preset/dynamic 注册用 |
|
|
58
|
+
| ★ `runToolLogic(args, exec)` | async fn | 三形态共用:`this.runner.coreExecute` 已被工厂注入,见下 |
|
|
59
|
+
| `extraTools` | array | 额外工具 `[{name,description,inputSchema,logic(args,exec)}]`(agy_quota / mimo_settings) |
|
|
60
|
+
| ★ `settings` | object | 设置分区契约,见 §3 |
|
|
61
|
+
| `mcp` | object | MCP 形态扩展,见 §4 |
|
|
62
|
+
|
|
63
|
+
工厂约定:`defineProvider(deps)` 内部按上述字段构造 descriptor,并提供
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
descriptor.attach(hostOpts) → runner // 见下;每个宿主形态调用一次
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`attach(hostOpts)`:`hostOpts = { ctx, subprocess, resolveExe, getCwdFallback, getPreferredBackend?, getSettings?, planActiveFor?, publish }`。
|
|
70
|
+
内部构造 `engine = createStatusEngine({ provider: this, publish })` 与
|
|
71
|
+
`runner = createRunner(Object.assign({}, hostOpts, { provider: this, engine }))`,
|
|
72
|
+
把两者挂到 `this.engine`/`this.runner` 后返回 runner。descriptor 上的
|
|
73
|
+
`runToolLogic/continueToolLogic/statusToolLogic` 直接闭包引用 `this.runner/this.engine`
|
|
74
|
+
(宿主调用前必先 attach;dynamic 形态在 host 里 attach,preset 形态在 apply 里 attach)。
|
|
75
|
+
`continueToolLogic`:把 `args.prompt`(可选)+ sessionId/latest 语义组装成 run 调用。
|
|
76
|
+
(三份占位 stub 已按此形态实现,替换时保持 attach/xxxToolLogic 签名不变。)
|
|
77
|
+
|
|
78
|
+
可选补充字段:
|
|
79
|
+
|
|
80
|
+
| 字段 | 说明 |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `isSuccessStatus(st)` | 灯/聚合层的「成功态」判定(mimo 的 ACCEPTED 就靠它);缺省=仅 SUCCESS |
|
|
83
|
+
|
|
84
|
+
## 2. 事件与状态通道(由 keystone 统一监听,provider 只管发)
|
|
85
|
+
|
|
86
|
+
- preset 形态(Node 模块 `preset/<id>/cli-bridge.mjs`):
|
|
87
|
+
- 状态变化 `ctx.emit('<id>/status', { snapshot })`;snapshot 即 engine.statusSnapshot()(顶层含 `provider` 字段)。
|
|
88
|
+
- 挂载时与每 30s `ctx.emit('<id>/mode', { active: true, sessionId })`(心跳租约,TTL 75s)。
|
|
89
|
+
- dynamic 形态:`ctx.get('cliBridgeCollector').mergeSnapshot('<id>', snapshot)`。
|
|
90
|
+
(旧 `<id>Collector` 服务名在 keystone 里保留别名,向后兼容旧包并存场景。)
|
|
91
|
+
- 家级 HTTP 单一路由:`GET /cli-bridge/status` 返回
|
|
92
|
+
`{ providers: { agy:{state,running,projects,presetActive,presetSessions}, codebuddy:{...}, mimo:{...} }, updatedAt }`。
|
|
93
|
+
- provider 模块**不要**自己注册事件监听/webServer 路由/preset —— 全在 keystone 指示灯与注册表里做。
|
|
94
|
+
|
|
95
|
+
## 3. 设置分区(统一文件 `{dsh-home}/cli-bridge-settings.json`,按 id 分区)
|
|
96
|
+
|
|
97
|
+
`descriptor.settings`:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
{
|
|
101
|
+
keys: string[], // 本分区允许的字符串字段名
|
|
102
|
+
secretKeys?: string[], // 其中属凭据/token 的字段:GET 只回掩码,
|
|
103
|
+
// POST 空值=保持现值,`<key>Clear:true`=显式清除
|
|
104
|
+
defaults(): object, // 默认值
|
|
105
|
+
normalize(raw, env?): object, // 清洗(未知键丢弃)
|
|
106
|
+
meta?(env): object, // 展示元数据(字段标签/选项等)
|
|
107
|
+
diagnose?(settings, env): string // 一行诊断文本(灯面板用)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
读写/落盘/GUI 全在 keystone;provider 只给纯逻辑。旧 codebuddy 的
|
|
112
|
+
preferredBackend/defaultModel/endpointOverride/codebuddyEnToken 归入 `codebuddy` 分区;
|
|
113
|
+
mimo 的 backend/desktopModel 归入 `mimo` 分区;agy 暂无分区字段可给 `{keys:[],defaults:()=>({}),normalize:()=>({})}`。
|
|
114
|
+
**token 永不回传明文**(keystone 负责掩码)。
|
|
115
|
+
|
|
116
|
+
`meta(env)` 的返回直接驱动合并后的设置面板(client.js 按它渲染,不认识任何具体字段名):
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
meta(env) → {
|
|
120
|
+
titleSuffix?: string, // 卡片标题后缀(如 'CodeBuddy')
|
|
121
|
+
fields: [ {
|
|
122
|
+
key: string, // 分区字段名
|
|
123
|
+
label: string, // 中文标签可,面板统一中文
|
|
124
|
+
type: 'text' | 'select', // 缺省 'text'
|
|
125
|
+
options?: [{value,label}], // select 用
|
|
126
|
+
allowCustom?: boolean, // select 允许自定义输入(defaultModel 就是它)
|
|
127
|
+
placeholder?: string,
|
|
128
|
+
note?: string, // 字段下方说明
|
|
129
|
+
secret?: boolean // 凭据字段:必须同时列入 secretKeys
|
|
130
|
+
} ]
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
diagnose(settings, env) 返回一行文本(卡片底部「诊断」区);无诊断给 ''。
|
|
135
|
+
|
|
136
|
+
### 3.1 调度区(顶层 `_scheduling`,非 provider 分区 —— 新增 provider 零改动接入)
|
|
137
|
+
|
|
138
|
+
`{DSH_HOME}/cli-bridge-settings.json` 顶层另有 `_scheduling` 区(下划线前缀 = 非 provider
|
|
139
|
+
命名空间,逐分区读取的旧代码天然忽略):
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
"_scheduling": { "enabled": string[], "priority": string[] }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- `enabled` = 启用集合(集合语义,数组顺序无意义);`priority` = 调用优先级,**数组顺序即优先级**;
|
|
146
|
+
- 生效序 `order = priority ∩ enabled`;缺省 / 文件缺失 / 值坏 → 全量启用(fail-open:读配置
|
|
147
|
+
失败绝不等于关桥);显式 `enabled: []` = 全关(被尊重);非空但全部未知 → 回落全开;
|
|
148
|
+
- 单源逻辑 `core/scheduling.mjs`(`normalizeScheduling / resolveScheduling / isBridgeEnabled /
|
|
149
|
+
describeScheduling`),宿主形态用 `ignorePin`(全局 env `CLI_BRIDGE_PROVIDER` 只是 MCP 进程
|
|
150
|
+
启动参数,不得反噬用户会话里的桥);钉住仅对 MCP 进程最高优先;
|
|
151
|
+
- **provider 作者不需要为此写任何代码**:注册表 `providers/registry.mjs` 的 `PROVIDER_IDS` 是
|
|
152
|
+
唯一 id 轴 —— 新 id 进注册表后,面板调度卡(labels 取 `descriptor.label`、all 取视图
|
|
153
|
+
`scheduling.all`)、四形态门禁(preset/dynamic `isBridgeEnabled(id, PROVIDER_IDS)`、MCP
|
|
154
|
+
`selectedProviders`、status 视图)自动纳入;preset/dynamic 模板/声明一律以 ids 数组传参,
|
|
155
|
+
禁止新增硬编码 id 列表(keystone 测试 `tests/core/scheduling.test.mjs` +
|
|
156
|
+
`tests/keystone/scheduling-gate.test.mjs` 锁语义)。
|
|
157
|
+
|
|
158
|
+
## 4. MCP 形态(`mcp/providers/<id>.mjs`)
|
|
159
|
+
|
|
160
|
+
统一 stdio JSON-RPC 服务器 `mcp/cli-bridge-mcp.mjs`(keystone)聚合三家工具。每个 provider 导出:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
export const meta = { id, label, version } // version 独立跟随本包
|
|
164
|
+
export function tools(env) → [{ name, description, inputSchema }] // 完整列表(含 extra)
|
|
165
|
+
export async function call(name, args, io) → string // 返回纯文本;错误也是文本
|
|
166
|
+
export function check(env) → true | throw // --check 自检
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`io = { fs, path, homeDir, env, log }`。`call` 内部自己起子进程(无 DSH ctx),复用
|
|
170
|
+
描述符的 buildArgv/parseJson/buildResult;**每次状态变化把 engine 快照写
|
|
171
|
+
`{homeDir}/cli-bridge-mcp-<id>.json`**(用 bridge-kit 的 buildMcpBridgePayload + 原子写
|
|
172
|
+
`tmp→rename`)。允许 `import node:*`(MCP 是真 Node 进程)。
|
|
173
|
+
|
|
174
|
+
## 5. 交付文件清单(每个 provider 完全一致,路径冻结)
|
|
175
|
+
|
|
176
|
+
| 文件 | 形态 | 说明 |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `providers/<id>.mjs` | 描述符 | §1;只 import bridge-kit |
|
|
179
|
+
| `preset/<presetDir>/cli-bridge.mjs` | preset host | presetDir:agy→`agy-first`、codebuddy→`codebuddy-first`、mimo→`mimo-first`(package.json exports `./preset-agy|./preset-codebuddy|./preset-mimo` 指向这里)。薄适配:读 `@deepseek-ai/dsh` 注入的 ctx,descriptor.attach() 装配 runner,注册 `descriptor.tools`+extraTools(`ctx.tools.register`,`ctx.effect` 包裹),注册提示段 `ctx.systemPrompt.section({name:'<id>:policy', text})`,心跳 `ctx.emit('<id>/mode')`,状态 `ctx.emit('<id>/status',{snapshot})`;导出 `apply(ctx)`/`name`/`inject` |
|
|
180
|
+
| `preset/<presetDir>/plugin-list.mjs` | preset 组合唯一权威源 | `export const meta={id,name,description,order}` + `export function buildPlugins(deps)`:以 `import { standardPluginRows, bridgeRow } from '../standard-base.mjs'` 为基底(keystone 单源,勿复制官方行),复制 persona 行改 prefix/suffix(如有),末尾 bridgeRow(id, deps.bridgeName)。返回纯数据(`__jsExpr` 占位原样透传,不要自己包函数) |
|
|
181
|
+
| `preset/<presetDir>/agent.cordis.yml` | **生成物·勿手改** | 由 `node scripts/build.mjs` 从同目录 plugin-list.mjs 生成(legacy 目录形态 `preset.yml` 同批生成)。当前 DSH(≥0.1.7-alpha.1,声明制)不读它;仅作 ≤0.1.6 的兜底交付物与 `npm run deploy:local` 拷贝源。桥接行 name 为裸说明符 `@luchenglong/cli-bridge/preset-<id>`(相对路径在注册表 baseUrl 下必然错解——历史事故) |
|
|
182
|
+
| `dynamic/<id>.host.template.mjs` | dynamic 沙箱 | 以旧仓 `dynamic/host.template.mjs`/`dynamic/host.js` 为蓝本重写为模板:只含沙箱适配(harness.registerTool、harness.handle RPC、collector 推送、exe 解析 env 守卫),**顶部两个占位符** `/*__KIT__*/`(bridge-kit 内联)与 `/*__PROVIDER__*/`(providers/<id>.mjs 内联),其余逻辑走描述符 |
|
|
183
|
+
| `dynamic/<id>.host.js` | 生成物 | `node scripts/build.mjs` 产物,勿手改 |
|
|
184
|
+
| `mcp/providers/<id>.mjs` | MCP 工具面 | §4 |
|
|
185
|
+
| `tests/<id>/*.test.mjs` | 测试 | `node --test`;覆盖 descriptor 纯函数、buildArgv/parse/result、状态引擎集成、preset apply 冒烟(mock ctx)、MCP tools/call 冒烟(fake exe fixture 放 `tests/<id>/fixtures/`) |
|
|
186
|
+
| `docs/history/<id>/CHANGELOG.md` | 历史 | 旧仓 CHANGELOG verbatim(勿改写) |
|
|
187
|
+
|
|
188
|
+
## 6. 验收闸门(Lead 会统一跑,你的 scope 必须全绿)
|
|
189
|
+
|
|
190
|
+
1. `node --check` 每个交付 .mjs/.js。
|
|
191
|
+
2. `node scripts/build.mjs`(全量生成)+ `--check` 幂等。
|
|
192
|
+
3. `node --test tests/<id>/`。
|
|
193
|
+
4. `node mcp/cli-bridge-mcp.mjs --check`(聚合后;你的模块缺失时 Lead 的文件会明确报错)。
|
|
194
|
+
5. 不新增 npm 依赖;`git` 提交信息 conventional commits。
|
|
195
|
+
|
|
196
|
+
## 7. 移植基线(旧仓 → 新仓映射速查)
|
|
197
|
+
|
|
198
|
+
- agy:`preset/agy-first/agy-first-bridge.mjs` 内联逻辑 → descriptor + 薄 preset;
|
|
199
|
+
`bin/agy-quota.mjs` → `bin/agy-quota.mjs`(原样,路径改环境变量 `CLI_BRIDGE_AGY_QUOTA` 优先);
|
|
200
|
+
`mcp/agy-mcp-server.mjs` 的 framing 归 keystone 服务器,工具逻辑进 `mcp/providers/agy.mjs`。
|
|
201
|
+
- codebuddy:`core/codebuddy-core.mjs` 中与 provider 无关的骨架**不要**复制(已在 bridge-kit),
|
|
202
|
+
provider 特有部分(BACKENDS/endpoint/auth/model catalog/settings/plan-mode Bash 预批 argv)进 descriptor;
|
|
203
|
+
`dynamic/host.template.mjs` 的占位符改造为双占位符模板。
|
|
204
|
+
## 8. 运行时事实与红线速查(team 必读)
|
|
205
|
+
|
|
206
|
+
- **client id 红线**:`home-plugin/cli-bridge-indicator/lib/client.js` 的
|
|
207
|
+
`__ModuleLoader__.load({ id: "@luchenglong/cli-bridge" })` 必须逐字等于包名,
|
|
208
|
+
由 `scripts/verify.mjs`(prepack 自动跑)机器把关。**任何人任何任务不得改这个 id**,
|
|
209
|
+
除非同时改包名并走 Lead 评审。改错 = 整个客户端组合加载失败 = DSH 启动致命屏。
|
|
210
|
+
- **红线 1**:任何任务不得重启/杀掉正在运行的 DSH 后端;不得改
|
|
211
|
+
`%APPDATA%\DSH Desktop\dsh-home\profiles\web\package.json`(本次交付不切运行时)。
|
|
212
|
+
- **红线 3**:不得在本仓库创建 junction/symlink(360 会连带删目标)。
|
|
213
|
+
- preset 形态模块 = 宿主进程内真 ESM:可 `import node:fs` 等内建、可用 `process`;
|
|
214
|
+
但**不得 import `@deepseek-ai/*`**(本地包解析根够不到 harness 包,历史论证);
|
|
215
|
+
模块内相对 import(如 `'../../providers/agy.mjs'`)是标准 ESM 解析,安全可用。
|
|
216
|
+
- dynamic 形态:`dynamic/<id>.host.js` 由 build 内联生成;**模板里禁止任何 import**
|
|
217
|
+
(沙箱 new Function),宿主能力全部来自沙箱注入的 `harness.*`。
|
|
218
|
+
- MCP 形态:真 Node 进程,可 import node:*;没有 ctx.emit,状态只能走快照文件
|
|
219
|
+
(`{DSH_HOME}/cli-bridge-mcp-<id>.json`,bridge-kit `buildMcpBridgePayload` + 原子写)。
|
|
220
|
+
- 家级灯路由(keystone 已实现,别重复注册):`GET /cli-bridge/status`、
|
|
221
|
+
`GET/POST /cli-bridge/settings`、三个旧路径 `/agy-indicator/status` 等保持兼容、
|
|
222
|
+
`GET /agy-indicator/quota`(脚本定位 = env `CLI_BRIDGE_AGY_QUOTA` > 本包 bin)。
|
|
223
|
+
- 事件契约(provider 只管发,keystone 听):`<id>/status` payload
|
|
224
|
+
`{ snapshot: <engine.statusSnapshot() 输出> }`;`<id>/mode` payload
|
|
225
|
+
`{ active: true, sessionId }`(每 30s 心跳续租,TTL 75s)。
|
|
226
|
+
- 旧包工具入参语义保持逐字不变(老提示词/会话仍在用):移植时以旧仓测试为准,
|
|
227
|
+
不许「顺手改 schema」。
|
|
228
|
+
|
|
229
|
+
## 9. 移植基线补充
|
|
230
|
+
|
|
231
|
+
- mimo:`core/mimo-core.mjs` + `core/runtime-settings.mjs` 的纯逻辑进 descriptor/mcp 模块;
|
|
232
|
+
桌面 HTTP 路径(desktopFetch/desktopSendTurn 等):preset/MCP 形态可用全局 fetch 与
|
|
233
|
+
node: 模块,dynamic 沙箱形态若拿不到 fetch 则 preflight 报 `DESKTOP_UNREACHABLE`
|
|
234
|
+
并提示改用 mimocode 后端(保持旧包语义)。
|
|
235
|
+
|
package/README.en.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# CLI Bridge
|
|
2
|
+
|
|
3
|
+
**Chinese only for now** · [中文 README](README.md)
|
|
4
|
+
|
|
5
|
+
> A Cordis plugin package for **DeepSeek Harness (DSH)**: dispatch real coding /
|
|
6
|
+
> build / debug / investigation work to **local CLI agents** — Google
|
|
7
|
+
> **Antigravity (`agy`)**, Tencent **CodeBuddy Code**, Xiaomi **MiMo (MiMoCode CLI /
|
|
8
|
+
> MiMo Desktop)** — with DSH fully controlling each CLI (non-interactive, never
|
|
9
|
+
> prompts), a **rate-limit/network fallback dialog** (switch to the DSH local API
|
|
10
|
+
> configuration), one **aggregated live status pill** in the session header
|
|
11
|
+
> (segmented per provider), and a **unified settings panel** for preferences and
|
|
12
|
+
> credentials across all three.
|
|
13
|
+
>
|
|
14
|
+
> This package merges and replaces three legacy packages — `agy-first-bridge`
|
|
15
|
+
> (final 1.7.1), `codebuddy-first-bridge` (final 1.6.2), `mimo-first-bridge`
|
|
16
|
+
> (final 1.2.9). All legacy features are preserved verbatim; see
|
|
17
|
+
> [docs/MIGRATION.md](docs/MIGRATION.md) (Chinese) for the compatibility matrix.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What you get
|
|
22
|
+
|
|
23
|
+
1. **Three model tools per provider** — `<id>_run` / `<id>_continue` / `<id>_status`
|
|
24
|
+
(plus `agy_quota` and `mimo_settings`). **Tool names, parameters and result
|
|
25
|
+
semantics are byte-compatible with the legacy packages**, so existing sessions
|
|
26
|
+
and prompts keep working untouched.
|
|
27
|
+
2. **A CLI-first policy section** injected per provider so the model dispatches
|
|
28
|
+
implementation work to the CLI in every mode (plan / accept-edits / subagents /
|
|
29
|
+
workflow / goal rounds) while native tools stay for read-only queries and final
|
|
30
|
+
verification.
|
|
31
|
+
3. **One aggregated status pill** (home-level plugin, auto-loaded with DSH): green
|
|
32
|
+
ready/success, yellow running, red failed, grey unavailable, amber local
|
|
33
|
+
fallback, highlighted when the session itself runs under a bridge preset.
|
|
34
|
+
Hover shows the live step; click opens a per-provider, per-project activity
|
|
35
|
+
panel (folded current step + trail, cumulative runs / tokens, last finished run).
|
|
36
|
+
4. **Unified settings** (DSH settings page, one card per provider, meta-driven):
|
|
37
|
+
secrets are never returned in plaintext (masked, "empty keeps, Clear erases"
|
|
38
|
+
semantics preserved from CodeBuddy v1.3+). Persisted to
|
|
39
|
+
`{DSH_HOME}/cli-bridge-settings.json` partitioned by provider, with **one-time
|
|
40
|
+
field-level migration from the legacy settings files**.
|
|
41
|
+
|
|
42
|
+
## Four shapes, one descriptor
|
|
43
|
+
|
|
44
|
+
A single provider descriptor drives every runtime shape (zero duplicated logic):
|
|
45
|
+
|
|
46
|
+
| Shape | Where | Notes |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| **Agent presets** (recommended) | [`preset/`](preset/) | `cordis-agy` / `codebuddy-first` / `cordis-mimo` — ids unchanged from legacy |
|
|
49
|
+
| **Home-level indicator bundle** | [`home-plugin/cli-bridge-indicator/`](home-plugin/cli-bridge-indicator/) | pill + settings + routes + declaration-based preset registration; ships via `dsh.bundle.patch` |
|
|
50
|
+
| **Dynamic sandbox host** | [`dynamic/<id>.host.js`](dynamic/) (generated from templates) | for compositions that cannot mount a preset |
|
|
51
|
+
| **MCP stdio server** | [`mcp/cli-bridge-mcp.mjs`](mcp/) (bin `cli-bridge-mcp`) | one server exposes all providers; `mcp/<id>-mcp-server.mjs` = single-provider drop-in for legacy configs |
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{ "mcpServers": { "cli-bridge": {
|
|
55
|
+
"command": "node",
|
|
56
|
+
"args": ["<install>/node_modules/@luchenglong/cli-bridge/mcp/cli-bridge-mcp.mjs"] } } }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
MCP runs out-of-process, so it publishes state by atomically writing
|
|
60
|
+
`{DSH_HOME}/cli-bridge-mcp-<id>.json` (stale after 90 s) which the home pill merges
|
|
61
|
+
live — running `agy` from Claude Code still lights up the DSH title bar.
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install -g @luchenglong/cli-bridge
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
DSH wiring (bundle + presets + indicator in one step): see
|
|
70
|
+
[docs/INSTALL.md](docs/INSTALL.md) (Chinese; read the red lines first — stop the DSH
|
|
71
|
+
backend before touching runtime wiring). `npm run deploy:local` only stages a
|
|
72
|
+
directory; it never edits your profile.
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node scripts/build.mjs # regenerate dynamic hosts + legacy YAML
|
|
78
|
+
node scripts/verify.mjs # publish red-line gate
|
|
79
|
+
node --test # unit tests (kit + keystone + per provider)
|
|
80
|
+
node mcp/cli-bridge-mcp.mjs --check # MCP self-check
|
|
81
|
+
npm run check # all gates
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Adding a fourth CLI? Implement one descriptor per
|
|
85
|
+
[PROVIDER-CONTRACT.md](PROVIDER-CONTRACT.md) — every shape comes free.
|
|
86
|
+
|
|
87
|
+
## Docs
|
|
88
|
+
|
|
89
|
+
- [README.md](README.md) — full Chinese documentation (canonical)
|
|
90
|
+
- [docs/INSTALL.md](docs/INSTALL.md) — install & wiring, env-var matrix
|
|
91
|
+
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — shared core, state machine, red lines
|
|
92
|
+
- [docs/MIGRATION.md](docs/MIGRATION.md) — legacy package compatibility table
|
|
93
|
+
- [docs/RELEASE-SOP.md](docs/RELEASE-SOP.md) — release procedure & gates
|
|
94
|
+
- [CHANGELOG.md](CHANGELOG.md) + [docs/history/](docs/history/) — merged history and full legacy lineages
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
[MIT](LICENSE)
|