🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

多智能体编排层 lakii2982/mocl

DeepSeek Harness
lakii29829 天前有提交已提供中文文档扫描:含敏感能力

把多个编码智能体统一成可编排的子智能体

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lakii2982/mocl
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · tool
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 102 处,展示前 70 条)
  • 执行外部命令固定命令
    scripts/assert-dsh-tool.mjs:49
    const result = spawnSync("dsh", args, { encoding: "utf8", timeout: timeoutMs, maxBuffer: 32 * 1024 * 1024 });
  • 写入本地文件
    scripts/assert-dsh-tool.mjs:111
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    scripts/assert-dsh-tool.mjs:113
    writeFileSync(
  • 写入本地文件
    scripts/assert-dsh-tool.mjs:122
    writeFileSync(
  • 读取本地文件
    scripts/assert-dsh-tool.mjs:152
    if (!existsSync(profileDir)) {
  • 读取本地文件
    scripts/assert-dsh-tool.mjs:187
    if (!existsSync(installedPkg)) return skip("verify-install", "node_modules/@mocl/dsh-plugin/package.json missing");
  • 读取本地文件
    scripts/assert-dsh-tool.mjs:220
    console.log(readFileSync(fileURLToPath(import.meta.url), "utf8").split("\n").slice(1, 18).join("\n"));
  • 读取本地文件
    src/plugin/patch.ts:213
    if (!existsSync(path)) throw new Error(`missing patch file: ${path}`);
  • 读取本地文件
    src/plugin/patch.ts:215
    const cordisText = readFileSync(cordisPath, "utf8");
  • 读取本地文件
    src/plugin/patch.ts:216
    const legacyText = readFileSync(legacyPath, "utf8");
  • 读取本地文件
    agents/verify-agents.mjs:53
    if (!existsSync(abs)) throw new Error(`缺少文件:${relPath}`);
  • 读取本地文件
    agents/verify-agents.mjs:54
    const text = readFileSync(abs, "utf8");
  • 读取本地文件
    agents/verify-agents.mjs:225
    const missing = DOCS.filter((d) => !existsSync(rel(d.file))).map((d) => d.file);
  • 读取本地文件
    agents/verify-agents.mjs:318
    const missingFile = mustExist.filter((f) => !existsSync(rel(f)));
  • 读取本地文件
    orchestrator/lib/gates.mjs:73
    raw = await readFile(target, "utf8");
  • 读取本地文件
    orchestrator/lib/issue.mjs:97
    raw = JSON.parse(await readFile(path, "utf8"));
  • 读取本地文件
    orchestrator/lib/labels.mjs:100
    text = await readFile(path, "utf8");
  • 读取本地文件
    orchestrator/lib/prompts.mjs:96
    const text = await readFile(path, "utf8");
  • 写入本地文件
    orchestrator/lib/runlog.mjs:19
    let queue = persist ? mkdir(dir, { recursive: true }).then(() => undefined) : Promise.resolve();
  • 写入本地文件
    orchestrator/lib/runlog.mjs:29
    queue = queue.then(() => appendFile(path, line, "utf8")).catch(() => undefined);
  • 写入本地文件
    orchestrator/lib/state.mjs:43
    await mkdir(join(root, "runs"), { recursive: true });
  • 写入本地文件
    orchestrator/lib/state.mjs:44
    await mkdir(join(root, "issues"), { recursive: true });
  • 写入本地文件
    orchestrator/lib/state.mjs:51
    await mkdir(dir, { recursive: true });
  • 读取本地文件
    orchestrator/lib/state.mjs:53
    if (!existsSync(ignore)) {
  • 写入本地文件
    orchestrator/lib/state.mjs:54
    await writeFile(ignore, "# generated by mocl-agent — local run artifacts, never committed\n*\n", "utf8");
  • 读取本地文件
    orchestrator/lib/state.mjs:61
    const raw = await readFile(stateFile(cwd), "utf8");
  • 写入本地文件
    orchestrator/lib/state.mjs:88
    await writeFile(tmp, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
  • 写入本地文件
    orchestrator/lib/state.mjs:89
    await rename(tmp, file);
  • 读取本地文件
    orchestrator/lib/status.mjs:49
    return JSON.parse(await readFile(cachePath, "utf8"));
  • 读取本地文件
    orchestrator/lib/templates.mjs:44
    return await readFile(path, "utf8");
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:184
    accessSync(candidate, constants.X_OK);
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:185
    if (statSync(candidate).isFile()) return candidate;
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:202
    accessSync(candidate, constants.X_OK);
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:203
    if (!statSync(candidate).isFile()) return { ok: false, reason: `不是普通文件: ${candidate}` };
  • 执行外部命令来自配置/变量
    scripts/assert-codex-baseline.mjs:223
    const stdout = execFileSync(binaryPath, ["--version"], {
  • 执行外部命令来自配置/变量
    scripts/assert-codex-baseline.mjs:232
    execFileSync(binaryPath, ["app-server", "generate-json-schema", "--out", outDir], {
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:244
    const doc = JSON.parse(readFileSync(filePath, "utf8"));
  • 读取本地文件
    scripts/assert-codex-baseline.mjs:273
    if (!existsSync(profileRoot)) return [];
  • 删除本地文件递归
    scripts/assert-codex-baseline.mjs:514
    rmSync(schemaDir, { recursive: true, force: true });
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:198
    if (statSync(candidate).isFile()) return candidate;
  • 执行外部命令来自配置/变量
    scripts/upgrade-dsh-codex-payload.mjs:208
    const result = spawnSync(argv[0], argv.slice(1), {
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:226
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:235
    return createHash("sha256").update(readFileSync(path)).digest("hex");
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:240
    if (!existsSync(dir)) return out;
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:241
    for (const name of readdirSync(dir).sort()) {
  • 读取本地文件
    scripts/upgrade-dsh-codex-payload.mjs:243
    const stat = statSync(abs);
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:257
    mkdirSync(destination, { recursive: true });
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:274
    mkdirSync(dirname(destination), { recursive: true });
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:275
    copyFileSync(source, destination);
  • 执行外部命令来自配置/变量
    scripts/upgrade-dsh-codex-payload.mjs:306
    const out = execFileSync(binary, ["--version"], {
  • 执行外部命令来自配置/变量
    scripts/upgrade-dsh-codex-payload.mjs:353
    execFileSync(vendorBin, ["--version"], { encoding: "utf8", timeout: HOST_VERSION_TIMEOUT_MS, stdio: ["ignore", "pipe", "pipe"] }),
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:534
    mkdirSync(plan.backupDir, { recursive: true });
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:565
    writeFileSync(join(plan.backupDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
  • 写入本地文件
    scripts/upgrade-dsh-codex-payload.mjs:566
    writeFileSync(join(plan.backupDir, "PLAN.txt"), state.lines.join("\n") + "\n");
  • 执行外部命令来自配置/变量
    scripts/upgrade-dsh-codex-payload.mjs:634
    execFileSync(plan.vendorBin, ["--version"], { encoding: "utf8", timeout: HOST_VERSION_TIMEOUT_MS, stdio: ["ignore", "pipe", "pipe"] }),
  • 读取本地文件
    src/abi/validate.ts:104
    parsed = JSON.parse(readFileSync(file, "utf8"));
  • 写入本地文件
    src/broker/session-registry.ts:127
    await mkdir(dirname(this.#path), { recursive: true });
  • 读取本地文件
    src/broker/session-registry.ts:130
    fileText = await readFile(this.#path, "utf8");
  • 读取本地文件
    src/broker/session-registry.ts:154
    text = await readFile(this.#journalPath, "utf8");
  • 写入本地文件
    src/broker/session-registry.ts:201
    await mkdir(dirname(this.#path), { recursive: true });
  • 写入本地文件
    src/broker/session-registry.ts:203
    await appendFile(this.#journalPath, JSON.stringify({ op: "upsert", at: record.createdAt, record } satisfies JournalRecord) + "\n", "utf8");
  • 写入本地文件
    src/broker/session-registry.ts:218
    await mkdir(dirname(this.#path), { recursive: true });
  • 写入本地文件
    src/broker/session-registry.ts:219
    await appendFile(this.#journalPath, JSON.stringify({ op: "epoch", at: new Date().toISOString(), childId, epoch } satisfies JournalRecord) + "\n", "utf
  • 写入本地文件
    src/broker/session-registry.ts:246
    await mkdir(dirname(this.#path), { recursive: true });
  • 删除本地文件
    src/broker/session-registry.ts:268
    await rm(tmp, { force: true });
  • 读取本地文件
    src/facade/config.ts:273
    text = await readFile(target, "utf8");
  • 读取本地文件
    src/plugin/panel-route.ts:302
    const parsed = JSON.parse(readFileSync(file, "utf8")) as unknown;
  • 写入本地文件
    src/plugin/panel-route.ts:315
    mkdirSync(dirname(input.file), { recursive: true });
  • 写入本地文件
    src/plugin/panel-route.ts:318
    writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`);
  • 写入本地文件
    src/plugin/panel-route.ts:319
    renameSync(tmp, input.file);
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
MOCL DeepSeek Harness(DSH) 的多智能体编排兼容层。 MOCL 用一套 ABI 统一 codex、claude-code、kimi、opencode,把它们暴露为可编排的子智能体,且不修改 DSH 本体。 MOCL 处于 1.0 之前(0.1.0)。本仓库是 MOCL 实现与设计文档的唯一真源。 1. MOCL 做什么 四个后端各说各的协议、各暴露各的能力。MOCL 位于 DSH 与后端之间,只做四件事: 1. 统一会话:把每个后端会话变成可寻址、可续接、可中断、可观测的逻辑会话。 2. 统一事件流:把四套原生事件归一化成一条有界、可折叠、可重放的事件流(对父会话的投递有硬上限)。 3. 统一失败形态:把四套原生错误归一化成一棵错误分类树 + 固定降级路径。 4. 一套 ABI:新增后端 = 新增一个适配器;broker、事件总线、门面、DSH 插件不变。 非目标:GUI 视觉设计、fork/修改 DSH 内部实现、后端产品自身功能、跨后端会话迁移。 ABI 契约由 tools/validate-abi.mjs 机器校验:46 错误码、34 能力位、 35 事件类型、18 方法(其中 9 个由 schema 冻结)。
展开完整文档(README 剩余 1 节)
MOCL

DeepSeek Harness(DSH) 的多智能体编排兼容层。
MOCL 用一套 ABI 统一 codex、claude-code、kimi、opencode,把它们暴露为可编排的子智能体,且不修改 DSH 本体。

MOCL 处于 1.0 之前(0.1.0)。本仓库是 MOCL 实现与设计文档的唯一真源。

1. MOCL 做什么

四个后端各说各的协议、各暴露各的能力。MOCL 位于 DSH 与后端之间,只做四件事:

1. 统一会话:把每个后端会话变成可寻址、可续接、可中断、可观测的逻辑会话。
2. 统一事件流:把四套原生事件归一化成一条有界、可折叠、可重放的事件流(对父会话的投递有硬上限)。
3. 统一失败形态:把四套原生错误归一化成一棵错误分类树 + 固定降级路径。
4. 一套 ABI:新增后端 = 新增一个适配器;broker、事件总线、门面、DSH 插件不变。

非目标:GUI 视觉设计、fork/修改 DSH 内部实现、后端产品自身功能、跨后端会话迁移。

ABI 契约由 tools/validate-abi.mjs 机器校验:46 错误码、34 能力位、 35 事件类型、18 方法(其中 9 个由 schema 冻结)。

2. 后端支持

| 后端 | 传输(首选) | 基线版本 | 本机实测状态 |
| codex | app-server JSON-RPC(stdio) | codex-cli 0.164.0 | 离线链路已验证;live turn 受环境限制(app-server 约 47s 后返回 turn.failed) |
| claude-code | Claude Agent SDK(适配器基线 SDK 0.3.263,内置 CLI 2.1.263) | Agent SDK 0.3.263 | live smoke 通过 |
| kimi | ACP over stdio | kimi-code 2.3.1 | 只读探针通过;live smoke 消耗保留额度(默认不跑) |
| opencode | v2 HTTP API(ACP 作备选通道) | opencode 2.1.4 | 免费模型池端到端实测通过(rc=0、可续接);付费 key 已过期(401 api_key_expired) |

完整的 4 × 15 能力矩阵(每格带证据与复跑入口)见 docs/research/capability-matrix.md。
能力状态来自实测:握手探测不到原生能力的适配器会如实报告缺失,而不是假装可用。

3. 架构

MOCL 是旁路层:DSH 保留自己的 subagent seam,MOCL 以插件形式组合进去。会话真相由 MOCL 的 broker 自管,因为 seam 把外部后端当作「一次执行、拒绝后续输入」。

父 DSH 会话 │ subagent_agent(backend = codex | claude-code | kimi | opencode) ▼ ┌─────────────────────────────────────────────────────────────┐ │ 门面 open / send / status / list / resume / │ │ interrupt / close → MoclError → ABI ErrorRef│ ├───────────────────────────┬─────────────────────────────────┤ │ broker │ 事件总线 │ │ 会话注册表、幂等、 │ 折叠、环形缓冲、限流、 │ │ kill / 冷恢复 │ 父会话投递(每轮 ≤1 条终态) │ ├───────────────────────────┴─────────────────────────────────┤ │ ABI v0:46 错误码 · 34 能力位 · 35 事件 · 18 方法 │ ├─────────────────────────────────────────────────────────────┤ │ 适配器 codex │ claude-code │ kimi │ opencode │ └──────────────┬────┴──────┬───────┴───┬──┴────────────────────┘ │ │ │ app-server JSON-RPC Agent SDK ACP / v2 HTTP │ │ │ codex 进程 claude CLI kimi 进程 opencode 服务

分层(见 docs/architecture/01-layers.md): L0 传输 → L1 适配器 → L2 broker → L3 事件总线 → L4 父会话投递 → L5 门面/插件。

4. 快速开始

要求:Node.js >= 24(仓库带 .nvmrc)、pnpm,以及用于文档闸门的 Python 3.9+。

git clone https://github.com/lakii2982/mocl.git
cd mocl
pnpm install

pnpm typecheck # 严格 TypeScript 类型检查(noEmit)
pnpm test # 离线测试(vitest)
pnpm validate # ABI 闸门(46/34/35/18)
node tools/sync-schema.mjs --check # schema 副本与 docs/abi/schema 逐字节一致
pnpm docs:check # 文档结构 / 计数 / 链接
pnpm leak-scan # 无个人路径、凭据或内部台账

以上 6 条命令均应 exit 0。离线测试套件不需要任何凭据;live 测试与探针为 opt-in,缺少对应后端 CLI 时会自动跳过。

可选的端到端演练(离线,使用临时 git worktree + 假后端):

node e2e/pr-scenario.mjs # 期望:RESULT: PASS (offline)
MOCL_LIVE=1 node e2e/pr-scenario.mjs # live 档,需要可用后端

发布前场景回归(离线;按真人使用路径走 DSH 工具面,并重跑发布门禁):

node scenarios/run.mjs # 12 个场景 + 11 条门禁,产出签收单
node scenarios/run.mjs --strict-known # 已知缺口也阻塞(发布签收推荐)
node scenarios/run.mjs --live # 额外跑真实后端 smoke

场景清单、已知缺口政策与报告格式见 scenarios/README.md。

5. 在 DSH 中使用

MOCL 以 DSH 插件形式交付,注册两个工具:

- subagent_agent(backend, task, ...) —— 把任务派发给四个后端之一,返回子会话 id;
- mocl_status(childId?, cursor?) —— 按 cursor 查询会话状态/事件。

仓库提供:

- config.default.json —— fail-closed 默认值:四后端全禁用、 permissionMode: read-only、禁止危险模式、写入必须 worktree 隔离;
- config.example.json —— 同形状示例,可作为起点复制;本地配置文件已被 git 忽略,不得提交;
- patch/cordis.patch.yml —— 新增插件行,并停用旧的一次性 subagent-codex / subagent-claude-code 工具。

启用/回滚步骤、完整配置项与 GUI 数据面说明见:

- docs/integration/01-config-and-enable.md
- docs/integration/00-dsh-integration.md
- docs/integration/02-ui-data-plane.md

6. 目录结构

mocl/
├── src/
│ ├── abi/ # ABI v0 类型、常量、AJV 运行时校验 │ ├── adapters/ # codex、claude-code、kimi、opencode │ ├── broker/ # 会话注册表、幂等、并发、kill/冷恢复 │ ├── bus/ # 事件总线、折叠、环形缓冲、父会话投递 │ ├── facade/ # 后端无关门面(配置、错误、适配器装配) │ └── plugin/ # DSH 薄插件:subagent_agent / mocl_status ├── schema/ # docs/abi/schema/*.json 的逐字节副本 ├── fixtures/ # ABI 契约样例(合法 + 非法) ├── tests/ # 单元 / 契约 / e2e 测试(vitest) ├── tools/ # validate-abi、sync-schema、check_docs、leak-scan、build-plugin ├── scripts/ # codex 基线断言/升级、DSH 工具断言 ├── e2e/ # 离线 PR 演练(假后端 + worktree) ├── repro/ # 只读、零额度的后端探测脚本 ├── patch/ # DSH patch(启用插件、停用旧工具) ├── config.default.json / config.example.json └── docs/ # ABI、架构、适配器、集成、调研等设计文档

7. 文档索引

| 文档 | 内容 |
| docs/index.md | 一页入口与阅读路径 |
| docs/abi/abi-v0.md | ABI v0:能力位、方法、事件、错误码、幂等、上限 |
| docs/architecture/00-overview.md | 分层总览、DEC-1 决策、部署形态 |
| docs/architecture/01-layers.md | L0–L5 契约、不变量、降级 |
| docs/architecture/02-state-machine.md | 会话状态机、转移、幂等、冷恢复 |
| docs/architecture/03-failure-modes.md | 失败模式分类、重试、降级阶梯 |
| docs/adapters/ | 各后端 L1 映射(握手、事件、权限、验收) |
| docs/research/capability-matrix.md | 4 × 15 能力矩阵与证据 |
| docs/integration/ | DSH 集成路线、配置、UI 数据面 |
| docs/risk/00-risk-register.md | 风险登记册 |
| docs/risk/01-threat-model.md | 威胁模型(凭据、路径穿越、沙箱、提示注入、供应链) |
| docs/test/01-acceptance.md | 验收矩阵与命令 |
| docs/runbook.md | 运维手册(codex 基线、插件 bootstrap、e2e) |

文档由 tools/check_docs.py 做机械闸门校验(结构、必填小节、ABI 计数、错误码词表、相对链接可解析)。设计文档以中文为主,README 提供中英双版。

8. 项目状态与已知限制

本仓库已验证(命令与退出码可复跑):

- ABI 契约闸门:46 / 34 / 35 / 18 —— node tools/validate-abi.mjs
- schema 副本闸门:node tools/sync-schema.mjs --check
- 离线端到端演练:node e2e/pr-scenario.mjs → RESULT: PASS (offline)

已知限制(详见 CHANGELOG.md):

- codex live turn 在本机受环境限制,live e2e 记为 skipped:host-unavailable;
- kimi live smoke 消耗保留额度,默认探针零额度且只读;
- opencode 付费模型凭据已过期,适配器自动降级到免费模型池(已实测);恢复需在 OpenCode Console 新建 key;
- DSH 宿主 API 基线为 0.2.1-rc.3,升级 DSH 需复核 src/plugin/dsh-types.d.ts 与工具注册签名;
- 官方 DSH GUI 对外部子代理只显示不可打开的叶子行,状态/进度请用 mocl_status 与会话 journal;
- 不做 npm 发布,安装方式为 clone 本仓库。

9. 贡献

欢迎贡献。请先阅读 CONTRIBUTING.md 与 CODE_OF_CONDUCT.md。提交 PR 前请跑第 4 节的闸门(typecheck、test、validate、sync-schema --check、docs:check、 leak-scan)。

安全问题不要开公开 issue,请按 SECURITY.md 私下报告。

10. 许可证

MIT © 2026 lakii2982
预览分享卡片长什么样 ↓lakii2982/mocl
分享 · DeepSeek Harness Hub
lakii2982/mocl

把多个编码智能体统一成可编排的子智能体

这是你的仓库?认领条目

回到顶部