@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
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// dynamic/mimo.host.template.mjs — mimo 动态沙箱宿主模板(cordis_define code.host 源)。
|
|
2
|
+
//
|
|
3
|
+
// 构建(node scripts/build.mjs --only=mimo)把 core/bridge-kit.mjs 与
|
|
4
|
+
// providers/mimo.mjs 分别内联进下方两个占位标记行(各占一行、行内仅此标记),
|
|
5
|
+
// 生成 dynamic/mimo.host.js。注意:标记字面量绝不能出现在本注释里 —— 构建做全局
|
|
6
|
+
// 替换,注释中出现同样会被替换成正文代码而炸掉语法。
|
|
7
|
+
// 沙箱纪律(旧仓 dynamic/host.js 头注 verbatim 精神):
|
|
8
|
+
// - 禁 import/require、无 TypeScript;无 AbortController/process 裸引用/Buffer/原生
|
|
9
|
+
// 定时器 —— process 只经 typeof 守卫探测;宿主能力全部来自注入的 harness.*/ctx。
|
|
10
|
+
// - 顶层 return { inject, apply } 为动态宿主约定形态(生成物是 .js/CJS 包装,顶层
|
|
11
|
+
// return 合法;本模板文件是 .mjs,不要直接 node --check 模板本身,只 check 生成物)。
|
|
12
|
+
// - 无 ctx.emit:状态经 ctx.get('cliBridgeCollector').mergeSnapshot('mimo', snap)
|
|
13
|
+
// 推给家级灯(旧 mimoCollector 服务名在 keystone 里保留别名);动态形态不宣告
|
|
14
|
+
// mode(旧语义:普通模式灯仅在调用 mimo 时临时显示)。
|
|
15
|
+
// - mimo-desktop 在沙箱的形态(契约 §9):无 fs 发现 desktop-api.json,且多数沙箱
|
|
16
|
+
// 无 fetch —— 描述符 preflight 直接 abort 为 DESKTOP_UNREACHABLE 并提示改用
|
|
17
|
+
// backend=mimocode(旧仓返回 DESKTOP_UNSUPPORTED 的替代;语义升级,Lead 定案)。
|
|
18
|
+
// 宿主若注入了 globalThis.fetch 且给出 MIMO_DESKTOP_PORT/MIMO_DESKTOP_TOKEN env,
|
|
19
|
+
// 委托 execute 仍可走通(fetch 路径全部 typeof 守卫)。
|
|
20
|
+
// - mimo_settings 在沙箱不持久化(无 nodeFs → 描述符回显语义;旧 dynamic echo 形态)。
|
|
21
|
+
// - exe 解析(旧动态候选无 existsSync 校验,盲取候选 [0] 易 spawn 失败):升级走
|
|
22
|
+
// agy 模板同款链路 —— MIMO_BIN/MIMO_CLI env > subprocess.resolveExecutable(PATH)。
|
|
23
|
+
/*__KIT__*/
|
|
24
|
+
/*__PROVIDER__*/
|
|
25
|
+
/*__SCHED__*/
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
inject: ['tools', 'subprocess', 'systemPrompt', 'timer'],
|
|
29
|
+
apply(ctx) {
|
|
30
|
+
// 调度门禁(0.2.0):设置面板关掉 mimo → 本形态不注册工具/政策段;fail-open。
|
|
31
|
+
if (!isBridgeEnabled('mimo', SCHED_ALL_IDS)) return
|
|
32
|
+
const subprocess = ctx.subprocess
|
|
33
|
+
const planMode = ctx.get('planMode')
|
|
34
|
+
const sandboxPolicy = ctx.get('sandboxPolicy')
|
|
35
|
+
// 沙箱可能运行在无 process 的环境:typeof 守卫读 env(旧仓 dynamic 的等价面)。
|
|
36
|
+
const env = (typeof process !== 'undefined' && process.env) ? process.env : {}
|
|
37
|
+
|
|
38
|
+
const provider = defineProvider({ env })
|
|
39
|
+
|
|
40
|
+
function publish(snapshot) {
|
|
41
|
+
try {
|
|
42
|
+
const collector = ctx.get('cliBridgeCollector')
|
|
43
|
+
if (collector && typeof collector.mergeSnapshot === 'function') { collector.mergeSnapshot('mimo', snapshot); return }
|
|
44
|
+
} catch (e) { /* fall through to legacy alias */ }
|
|
45
|
+
try {
|
|
46
|
+
const legacy = ctx.get('mimoCollector')
|
|
47
|
+
if (legacy && typeof legacy.mergeSnapshot === 'function') legacy.mergeSnapshot(snapshot)
|
|
48
|
+
} catch (e) { /* 灯数据尽力而为 */ }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// exe:MIMO_BIN/MIMO_CLI env > PATH 查找 mimo(subprocess.resolveExecutable)。
|
|
52
|
+
// mimo-desktop 后端不 spawn:返回占位字符串让 kit 直达 delegates→execute/preflight。
|
|
53
|
+
async function resolveExe(backend, signal) {
|
|
54
|
+
if (backend === 'mimo-desktop') return 'mimo'
|
|
55
|
+
const bin = env.MIMO_BIN || env.MIMO_CLI || ''
|
|
56
|
+
if (bin) {
|
|
57
|
+
if (/\.(mjs|cjs|js)$/i.test(bin) && typeof process !== 'undefined' && process.execPath) return [process.execPath, bin]
|
|
58
|
+
return bin
|
|
59
|
+
}
|
|
60
|
+
return await subprocess.resolveExecutable('mimo', undefined, signal)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 旧仓 CWD_FALLBACK 硬编码机器绝对路径;新语义:MIMO_MCP_CWD > MIMO_BRIDGE_CWD >
|
|
64
|
+
// workspaceRoot > process.cwd > '.'(沙箱无 process.cwd 可用时以 '.' 兜底)。
|
|
65
|
+
function getCwdFallback() {
|
|
66
|
+
if (env.MIMO_MCP_CWD) return String(env.MIMO_MCP_CWD)
|
|
67
|
+
if (env.MIMO_BRIDGE_CWD) return String(env.MIMO_BRIDGE_CWD)
|
|
68
|
+
if (sandboxPolicy && typeof sandboxPolicy.workspaceRoot === 'string' && sandboxPolicy.workspaceRoot) return sandboxPolicy.workspaceRoot
|
|
69
|
+
if (typeof process !== 'undefined' && typeof process.cwd === 'function') { try { return process.cwd() } catch (e) {} }
|
|
70
|
+
return '.'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 预选链(沙箱无 fs 读设置文件):env MIMO_BRIDGE_BACKEND / MIMO_BACKEND。
|
|
74
|
+
function getPreferredBackend() {
|
|
75
|
+
return env.MIMO_BRIDGE_BACKEND || env.MIMO_BACKEND || null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function planActiveFor(exec) {
|
|
79
|
+
try {
|
|
80
|
+
if (planMode && exec && exec.agent) {
|
|
81
|
+
const st = planMode.get(exec.agent)
|
|
82
|
+
return !!(st && st.active)
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {}
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
provider.attach({ ctx, subprocess, resolveExe, getCwdFallback, getPreferredBackend, planActiveFor, publish })
|
|
89
|
+
|
|
90
|
+
const OUTPUT_SCHEMA = { type: 'object', additionalProperties: true }
|
|
91
|
+
|
|
92
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
93
|
+
name: provider.tools.run.name,
|
|
94
|
+
description: provider.tools.run.description,
|
|
95
|
+
parameters: provider.tools.run.inputSchema,
|
|
96
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderResult(value, provider) } },
|
|
97
|
+
execute: function (args, exec) { return provider.runToolLogic(args, exec) }
|
|
98
|
+
}))
|
|
99
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
100
|
+
name: provider.tools.continue.name,
|
|
101
|
+
description: provider.tools.continue.description,
|
|
102
|
+
parameters: provider.tools.continue.inputSchema,
|
|
103
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderResult(value, provider) } },
|
|
104
|
+
execute: function (args, exec) { return provider.continueToolLogic(args, exec) }
|
|
105
|
+
}))
|
|
106
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
107
|
+
name: provider.tools.status.name,
|
|
108
|
+
description: provider.tools.status.description,
|
|
109
|
+
parameters: provider.tools.status.inputSchema,
|
|
110
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderStatus(value, provider) } },
|
|
111
|
+
execute: function (args) { return provider.statusToolLogic(args) }
|
|
112
|
+
}))
|
|
113
|
+
// mimo_settings:沙箱无 nodeFs → 描述符内部自动降级为回显(不持久化)。
|
|
114
|
+
// render 适配:harness 契约是 render(args, value),extraTools[].render 是
|
|
115
|
+
// renderSettings(value) 单参 —— 直接透传会把 args 当 value(渲染全空)。
|
|
116
|
+
for (const et of provider.extraTools) {
|
|
117
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
118
|
+
name: et.name,
|
|
119
|
+
description: et.description,
|
|
120
|
+
parameters: et.inputSchema,
|
|
121
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return et.render ? et.render(value) : renderResult(value, provider) } },
|
|
122
|
+
execute: function (args, exec) { return et.logic(args, exec) }
|
|
123
|
+
}))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 浏览器指示灯轮询的 RPC 面(旧 dynamic/handle('mimo_status') 语义)。
|
|
127
|
+
harness.handle('mimo_status', function () { return provider.statusToolLogic({}) })
|
|
128
|
+
|
|
129
|
+
// 旧 policy 文案 verbatim(提示词连续性红线)。
|
|
130
|
+
const policyText = [
|
|
131
|
+
'mimo-first execution policy (Xiaomi MiMo: MiMoCode CLI or MiMo Desktop client).',
|
|
132
|
+
'',
|
|
133
|
+
'Local backends (selectable in settings: backend = mimocode | mimo-desktop):',
|
|
134
|
+
'- mimocode (default): local `mimo` CLI (MiMoCode). Full DSH control (--dangerously-skip-permissions, never prompts).',
|
|
135
|
+
'- mimo-desktop: Xiaomi MiMo Desktop client local API (running Desktop app; uses its login/model/session UI).',
|
|
136
|
+
'',
|
|
137
|
+
'By default, dispatch runs in the background and returns a jobId immediately; collect via job_output and watch live progress via mimo_status.',
|
|
138
|
+
'',
|
|
139
|
+
'Decision table for tool selection:',
|
|
140
|
+
'- Single read/glob/grep or short (<30s) command -> Native tools.',
|
|
141
|
+
'- Implementing, editing, refactoring, debugging, builds, multi-file investigation -> mimo_run.',
|
|
142
|
+
'- Follow-ups on the same topic -> mimo_continue (with latest=true or sessionId; context is preserved).',
|
|
143
|
+
'- Final build/test verification of mimo output -> Native tools.',
|
|
144
|
+
'- Plan / read-only analysis -> mimo_run with mode=plan.',
|
|
145
|
+
'- Desktop-native work (Desktop session UI, shared Desktop login/model) -> prefer backend=mimo-desktop (or preselect it in settings).',
|
|
146
|
+
'',
|
|
147
|
+
'Backend preselection (settings):',
|
|
148
|
+
'- Default backend is configured OUT-OF-BAND (plugin config.backend / env MIMO_BRIDGE_BACKEND / settings file).',
|
|
149
|
+
'- Per-call `backend` argument overrides the default only when necessary.',
|
|
150
|
+
'- Do NOT invent a backend every call — use the preselected default.',
|
|
151
|
+
'',
|
|
152
|
+
'Context protocol (one topic = one mimo session):',
|
|
153
|
+
'- First dispatch on a topic: compact CONTEXT preamble (point to paths, do not paste file contents).',
|
|
154
|
+
'- Follow-ups: call mimo_continue and state only what is new.',
|
|
155
|
+
'',
|
|
156
|
+
'Execution & Fallback protocol:',
|
|
157
|
+
'- Dispatch defaults to background=true. Collect via job_output.',
|
|
158
|
+
'- On rate-limit/network/auth failure, a confirmation dialog offers DSH-local fallback.',
|
|
159
|
+
'- If result has fallback=true (status FALLBACK_TO_DSH), finish with native tools and NEVER call mimo again for this task.',
|
|
160
|
+
'- Never loop mimo calls; never ask mimo to call back into DSH.'
|
|
161
|
+
].join('\n')
|
|
162
|
+
|
|
163
|
+
ctx.systemPrompt.section({
|
|
164
|
+
name: 'mimo:policy',
|
|
165
|
+
order: (typeof ctx.systemPrompt.getSectionOrder === 'function' ? ctx.systemPrompt.getSectionOrder('TOOL_SUBAGENT') : 2800) + 10,
|
|
166
|
+
text: policyText
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
}
|