为 DeepSeek Harness 提供"伪 LLM"通道:用脚本让 agent 不调用真实模型,而是按 JSON/JSONL 剧本触发预设的工具调用,用于离线测试、教学演示与 CI 回归。
$ dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/mockRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
落地页对应的仓库子路径是
mock,npm 包名dsh-mock(mock/package.json:2-4),是Ephemeral-AI-Lab/dsh-pluginsmonorepo 下的子包之一。本百科聚焦mock路径对应的能力。
为 DeepSeek Harness 注册一个"伪 LLM"通道,让 agent 在不调用真实模型的前提下,按你写好的剧本触发预设的工具调用,用于离线复现、自动化测试与教学演示。
mock/mock(src/index.ts:132):被 AgentLoop 用来把"LLM 输出"换成预先编排的"工具调用流",真实的模型选择器不显示它。/mock 斜杠命令(src/index.ts:133-145):命令处理器只把整行原样塞回 session inbox 当作用户消息,让正常 AgentLoop 来执行——不绕过任何宿主逻辑。run 子命令:在输入框直接写 tool({"k":"v"}) 触达单次工具调用,或写 [a({...}),b({...})] 触发一组并行调用(src/parser.ts:71-108)。replay 子命令:从本地脚本文件读取预先编排的剧本逐步重放(src/parser.ts:111-132),可选 --overwrite-wait-time-ms N 覆盖剧本里所有显式等待(src/converter.ts:134-160)。dsh-mock-script JSON 和原生的 DSH JSONL session 日志,自动识别转换(src/converter.ts:172-251、src/index.ts:341-360)。src/client/index.ts:19-26、src/client/MockStatusRow.tsx:90-92)。mockStatus projection 暴露(src/projection.ts:34-57),失活或中止会回写为 cancelled,下次会话恢复时识别为过期。tsconfig.json:3-21 严格模式,目标 ES2024 / NodeNext)@deepseek-ai/dsh-llm(>=0.1.0-rc.5):扩展 LlmAdapter 注册内部 mock 路由@deepseek-ai/commands(>=0.1.0-rc.6):用 ctx.commands.register 注册 /mock@deepseek-ai/cordis(>=4.0.0):宿主插件框架,监听 agent/pre-step / agent/request / agent/error / agent/disposed 等事件@deepseek-ai/dsh-session-projection(>=0.1.0-rc.6):注册 mockStatus projection 把状态折叠给客户端@deepseek-ai/dsh-client-ui-slots + @deepseek-ai/dsh-client-ui-conversation + @deepseek-ai/dsh-client-runtime:把 MockStatusDock 注入到 conversation.input.dock 槽位react(>=18.2.0):状态行是 React 组件zod(^4.4.3):projection schema 强校验cordis.patch.yml 同时禁用 directory-picker 并把 mock 注入到宿主插件目录(cordis.patch.yml:1-9)。apply(ctx) 注册一个 MockAdapter 给 provider:'mock',再注册 /mock 命令并通过 agent/pre-step 拦截钩子把 /mock … 文本转成 plan 提交;adapter 内部按编译好的脚本逐步产出 StreamChunk,由宿主 AgentLoop 正常执行 tool 调用。mock/src/index.ts(export name = 'mock'、inject = ['llm','commands'],src/index.ts:29-30),客户端入口为 mock/src/client/index.ts当你需要让 DSH agent 在不消耗真实模型配额的前提下,按一份固定剧本触发工具调用——比如把一段 DSH JSONL 录播回放成回归测试用例、给新人演示 agent 与工具的交互流程、给 CI 跑一段无网环境下的端到端验证——都可以装这个插件;只要能写出一份 canonical JSON 或现成的 session 日志,/mock replay 一行就能重跑。
| 依赖 | 最低版本 | 说明 |
|---|---|---|
@deepseek-ai/cordis | >=4.0.0 | peerDependencies,宿主插件框架 |
@deepseek-ai/dsh-llm | >=0.1.0-rc.5 | peerDependencies,注册 LLM adapter 必需 |
@deepseek-ai/dsh-commands | >=0.1.0-rc.6 | peerDependencies,注册 /mock 命令必需 |
@deepseek-ai/dsh-agent | >=0.1.0-rc.6 | devDependencies,运行时直接持有 Agent 实例 |
@deepseek-ai/dsh-session + @deepseek-ai/dsh-session-projection | >=0.1.0-rc.6 | peerDependencies,写 mock/status 事件并暴露 projection |
@deepseek-ai/dsh-client-runtime + @deepseek-ai/dsh-client-locale + @deepseek-ai/dsh-client-ui-conversation + @deepseek-ai/dsh-client-ui-slots | 各 >=0.1.0-rc.6 | peerDependencies,package.json:27-35 把这四个列在 dsh.client.inject,缺一 Web 端 dock 加载不到 |
react | >=18.2.0 | peerDependencies,状态行组件运行时 |
zod | ^4.4.3 | devDependencies,projection schema 校验 |
| 平台 | DSH Web | package.json:28 显式声明 dsh.client.platform: "web",命令行/桌面端未声明 |
| Node.js | 未声明 | package.json 无 engines 字段;devDependencies 中 @types/node ^22.20.0 |
| 原生模块 | 无 | 仅依赖纯 JS 包,无 node-gyp 构建项 |
dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/mock
本插件无需额外配置。它不读取任何环境变量或 ctx.config,也没有配置文件;唯一的"配置面"由 /mock 命令参数决定:
| 命令 / 参数 | 位置 | 类型 | 说明 | 默认值 |
|---|---|---|---|---|
/mock run <tool({...})> 或 /mock run [a({...}),b({...})] | 输入框 | 一次或并行一组工具调用 | inline 触发;多工具必须放在 [ ] 里(src/parser.ts:80-100) | 无 |
/mock replay <path> | 输入框 | 绝对路径或相对会话工作目录的脚本文件 | 读取脚本后按步重放;相对路径要求 session 当前 header.cwd 已设置(src/index.ts:362-368) | 无 |
--overwrite-wait-time-ms <N> | replay 命令尾部 | 非负整数 | 覆盖剧本里所有显式 wait 步骤的毫秒数(src/converter.ts:134-148) | 不传则保留剧本里写的原始值 |
Q: 装完之后我能在模型下拉框里直接选 "mock" 吗?
A: 不能。mock 路由被刻意从对外暴露的模型目录里隐藏(README.md:21-28),普通的模型选择器不会列出它;唯一激活方式是输入 /mock run 或 /mock replay 这类斜杠命令。
Q: /mock run 和 /mock replay 的差别是什么?
A: run 是 inline 触发——直接写一段 tool({"k":"v"}) 或 [a({...}),b({...})] 让 agent 立即执行,session 内一次用完即弃;replay 是从本地脚本文件读一份预先编排的剧本逐步重放,适合固定场景的回归测试。两者内部都用同一个 MockAdapter,差别只在脚本来源(src/index.ts:312-339)。
Q: replay 脚本支持哪些文件格式?
A: 两种:(1) canonical dsh-mock-script JSON——{"type":"dsh-mock-script","version":1,"steps":[…]},步骤可以是 tool、parallel 或 wait;(2) 原生 DSH JSONL session 日志——以 {"type":"session"} 开头,转换器会自动折叠出工具调用并组装成 canonical 脚本(src/converter.ts:172-251)。ZIP 压缩包直接传入会被显式拒绝,需要先解压拿出 session.jsonl(src/replay-input.ts:9-17)。
Q: 用 mock 触发的工具调用,会被宿主正常记录吗?
A: 会。MockAdapter 只负责产出 StreamChunk,工具查找、参数校验、授权、执行、结果回写和持久化全部走宿主 AgentLoop 与 ToolRuntime 流水线(src/mock-adapter.ts:89-95);session 事件日志里出现的就是常规的 tool/call、tool/result、turn 等条目。
Q: 一次 mock turn 结束后,下一会话会自动继续走真实模型吗?
A: 会。agent/request 钩子会记录该 session 上一次用的真实 provider/model;mock turn 跑完后,下一次普通 turn 自动还原(src/index.ts:217-247),不需要手动切换。
Q: 怎么卸载 mock?
A: 用 dsh plugin --profile web remove 移除安装源即可。effect 回收时会调 adapter.dispose()、注销 /mock 命令与 llm adapter,并清空 session 维度的状态缓存(src/index.ts:282-293)。
进阶 — 入门用 /mock run tool({...}) 触一次调用很简单,但要做有意义的 replay(写 canonical JSON 或导出 JSONL)需要先了解 DSH session 事件结构;并且需要理解 agent 内部 provider/model 切换的工作机制才能在出错时排查。
dsh-mock@0.1.1 的命令、API 与 UI 都可能在稳定版前再变(README.md:3-5)。ReplayInputError(UNSUPPORTED_ARCHIVE) 提示先解压出 session.jsonl 再传(src/replay-input.ts:3-17)。replay 模式显式拒绝嵌套/子 agent 工具:工具名匹配正则 (?:^|[-_])(nested|subagent|agent[-_]spawn|spawn[-_]agent)(?:$|[-_]) 时直接抛 UNSUPPORTED_NESTED_TOOL(src/index.ts:370-375)。/mock run 不支持 wait 步骤——wait 语法只能在 canonical 脚本里使用(src/parser.ts:92,103)。dsh.client.platform: "web"(package.json:28),命令行 / 桌面端是否可用源码中未明确。1,其它版本会被 MockScriptError(INVALID_SCRIPT) 拒绝(src/converter.ts:84-85)。tool/call 事件虽然会出现但宿主侧会报"unknown tool",mock 本身不会"凭空"伪造工具。