@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,140 @@
|
|
|
1
|
+
// dynamic/agy.host.template.mjs — agy 动态沙箱宿主模板(cordis_define code.host 源)。
|
|
2
|
+
//
|
|
3
|
+
// 构建(node scripts/build.mjs --only=agy)把 core/bridge-kit.mjs 与
|
|
4
|
+
// providers/agy.mjs 分别内联进下方两个占位标记行(各占一行、行内仅此标记),
|
|
5
|
+
// 生成 dynamic/agy.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('agy', snap)
|
|
13
|
+
// 推给家级灯(旧 agyCollector 服务名在 keystone 里保留别名);动态形态不宣告
|
|
14
|
+
// mode(旧语义:普通模式灯仅在调用 agy 时临时显示)。
|
|
15
|
+
// - agy_quota 与 5h 额度门禁在沙箱形态省略(deps 无 process/nodeChild → 描述符
|
|
16
|
+
// 静默降级;Lead 定案 4)。
|
|
17
|
+
/*__KIT__*/
|
|
18
|
+
/*__PROVIDER__*/
|
|
19
|
+
/*__SCHED__*/
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
inject: ['tools', 'subprocess', 'systemPrompt', 'timer'],
|
|
23
|
+
apply(ctx) {
|
|
24
|
+
// 调度门禁(0.2.0):设置面板关掉 agy → 本形态不注册工具/政策段;fail-open。
|
|
25
|
+
if (!isBridgeEnabled('agy', SCHED_ALL_IDS)) return
|
|
26
|
+
const subprocess = ctx.subprocess
|
|
27
|
+
const planMode = ctx.get('planMode')
|
|
28
|
+
const sandboxPolicy = ctx.get('sandboxPolicy')
|
|
29
|
+
// 沙箱可能运行在无 process 的环境:typeof 守卫读 env(旧仓 dynamic 的等价面)。
|
|
30
|
+
const env = (typeof process !== 'undefined' && process.env) ? process.env : {}
|
|
31
|
+
|
|
32
|
+
const provider = defineProvider({ env })
|
|
33
|
+
|
|
34
|
+
function publish(snapshot) {
|
|
35
|
+
try {
|
|
36
|
+
const collector = ctx.get('cliBridgeCollector')
|
|
37
|
+
if (collector && typeof collector.mergeSnapshot === 'function') { collector.mergeSnapshot('agy', snapshot); return }
|
|
38
|
+
} catch (e) { /* fall through to legacy alias */ }
|
|
39
|
+
try {
|
|
40
|
+
const legacy = ctx.get('agyCollector')
|
|
41
|
+
if (legacy && typeof legacy.mergeSnapshot === 'function') legacy.mergeSnapshot(snapshot)
|
|
42
|
+
} catch (e) { /* 灯数据尽力而为 */ }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// exe:AGY_BIN/AGY_CLI env > PATH 查找 agy(subprocess.resolveExecutable)。
|
|
46
|
+
async function resolveExe(backend, signal) {
|
|
47
|
+
const bin = env.AGY_BIN || env.AGY_CLI || ''
|
|
48
|
+
if (bin) {
|
|
49
|
+
if (/\.(mjs|cjs|js)$/i.test(bin) && typeof process !== 'undefined' && process.execPath) return [process.execPath, bin]
|
|
50
|
+
return bin
|
|
51
|
+
}
|
|
52
|
+
return await subprocess.resolveExecutable('agy', undefined, signal)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 旧仓 CWD_FALLBACK 硬编码机器绝对路径;新语义:AGY_MCP_CWD > workspaceRoot > '.'
|
|
56
|
+
//(沙箱无 process.cwd 可用时以 '.' 交给宿主进程工作目录兜底)。
|
|
57
|
+
function getCwdFallback() {
|
|
58
|
+
if (env.AGY_MCP_CWD) return String(env.AGY_MCP_CWD)
|
|
59
|
+
if (sandboxPolicy && typeof sandboxPolicy.workspaceRoot === 'string' && sandboxPolicy.workspaceRoot) return sandboxPolicy.workspaceRoot
|
|
60
|
+
if (typeof process !== 'undefined' && typeof process.cwd === 'function') { try { return process.cwd() } catch (e) {} }
|
|
61
|
+
return '.'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function planActiveFor(exec) {
|
|
65
|
+
try {
|
|
66
|
+
if (planMode && exec && exec.agent) {
|
|
67
|
+
const st = planMode.get(exec.agent)
|
|
68
|
+
return !!(st && st.active)
|
|
69
|
+
}
|
|
70
|
+
} catch (e) {}
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
provider.attach({ ctx, subprocess, resolveExe, getCwdFallback, planActiveFor, publish })
|
|
75
|
+
|
|
76
|
+
const OUTPUT_SCHEMA = { type: 'object', additionalProperties: true }
|
|
77
|
+
|
|
78
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
79
|
+
name: provider.tools.run.name,
|
|
80
|
+
description: provider.tools.run.description,
|
|
81
|
+
parameters: provider.tools.run.inputSchema,
|
|
82
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderResult(value, provider) } },
|
|
83
|
+
execute: function (args, exec) { return provider.runToolLogic(args, exec) }
|
|
84
|
+
}))
|
|
85
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
86
|
+
name: provider.tools.continue.name,
|
|
87
|
+
description: provider.tools.continue.description,
|
|
88
|
+
parameters: provider.tools.continue.inputSchema,
|
|
89
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderResult(value, provider) } },
|
|
90
|
+
execute: function (args, exec) { return provider.continueToolLogic(args, exec) }
|
|
91
|
+
}))
|
|
92
|
+
harness.registerTool(ctx, harness.defineTool({
|
|
93
|
+
name: provider.tools.status.name,
|
|
94
|
+
description: provider.tools.status.description,
|
|
95
|
+
parameters: provider.tools.status.inputSchema,
|
|
96
|
+
output: { schema: OUTPUT_SCHEMA, render: function (args, value) { return renderStatus(value, provider) } },
|
|
97
|
+
execute: function (args) { return provider.statusToolLogic(args) }
|
|
98
|
+
}))
|
|
99
|
+
|
|
100
|
+
// 浏览器指示灯轮询的 RPC 面(旧 dynamic/handle('agy_status') verbatim 语义)。
|
|
101
|
+
harness.handle('agy_status', function () { return provider.statusToolLogic({}) })
|
|
102
|
+
|
|
103
|
+
// 旧 policy 文案 verbatim(提示词连续性红线)。
|
|
104
|
+
const policyText = [
|
|
105
|
+
'agy-first execution policy (local agy CLI bridge).',
|
|
106
|
+
'',
|
|
107
|
+
'Local agent CLI "agy" handles coding tasks under full DSH control (permissions auto-approved, never prompts). By default, agy runs in the background and returns a jobId immediately; collect results via job_output and watch live progress via agy_status anytime.',
|
|
108
|
+
'',
|
|
109
|
+
'Decision table for tool selection:',
|
|
110
|
+
'- Single read/glob/grep or short (<30s) command -> Native tools.',
|
|
111
|
+
'- Implementing, editing, refactoring, debugging, builds, multi-file investigation -> agy_run.',
|
|
112
|
+
'- Follow-ups on the same topic -> agy_continue (with latest=true or conversationId; agy preserves session context).',
|
|
113
|
+
'- Final build/test verification of agy output -> Native tools.',
|
|
114
|
+
'- Image/video generation -> agy_run WITHOUT picking a model (agy selects the appropriate model).',
|
|
115
|
+
'',
|
|
116
|
+
'Context protocol (one topic = one agy conversation):',
|
|
117
|
+
'- First dispatch on a topic: provide the task with a compact CONTEXT preamble (point to paths, do not paste file contents):',
|
|
118
|
+
' CONTEXT: 2-6 lines — goal; repo root; key paths; decisions/constraints; current state.',
|
|
119
|
+
' TASK: the complete instruction.',
|
|
120
|
+
'- Follow-ups: call agy_continue and state only what is new.',
|
|
121
|
+
'',
|
|
122
|
+
'Execution & Fallback protocol:',
|
|
123
|
+
'- Dispatch defaults to background=true (set background=false only to block). Collect via job_output.',
|
|
124
|
+
'- On rate-limit or network failure, a confirmation dialog opens in BOTH foreground and background while in flight.',
|
|
125
|
+
'- If result has fallback=true (status FALLBACK_TO_DSH), the user chose DSH-local: finish with native tools and NEVER call agy again for this task.',
|
|
126
|
+
'- If status is QUOTA_BLOCKED (Gemini 5h pool <10%), finish natively. Never loop agy calls; never ask agy to call back into DSH.',
|
|
127
|
+
'',
|
|
128
|
+
'Model selection & Quota guard:',
|
|
129
|
+
'- The Gemini 5h pool (<10% threshold) is enforced automatically as the sole per-task gate; do NOT pre-call agy_quota before every dispatch. Call agy_quota only when you want to compare model availability.',
|
|
130
|
+
'- Use Gemini pool (gemini-*) or utility models (tab_*, chat_*). Never pass Claude or GPT (3p) models.',
|
|
131
|
+
'- Weekly quota is NOT a per-task gate: low weekly quota only informs future planning, never aborts current work.'
|
|
132
|
+
].join('\n')
|
|
133
|
+
|
|
134
|
+
ctx.systemPrompt.section({
|
|
135
|
+
name: 'agy:policy',
|
|
136
|
+
order: (typeof ctx.systemPrompt.getSectionOrder === 'function' ? ctx.systemPrompt.getSectionOrder('TOOL_SUBAGENT') : 2800) + 10,
|
|
137
|
+
text: policyText
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|