为 DeepSeek Harness 提供"伪 LLM"通道:用脚本让 agent 不调用真实模型,而是按 JSON/JSONL 剧本触发预设的工具调用,用于离线测试、教学演示与 CI 回归。
- 语言
- Python
- License
- MIT
- 分支
- main
安装
$ dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/mock在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
落地页对应的仓库子路径是
mock,npm 包名dsh-mock(mock/package.json:2-4),是Ephemeral-AI-Lab/dsh-pluginsmonorepo 下的子包之一。本百科聚焦mock路径对应的能力。
一句话定位
为 DeepSeek Harness 注册一个"伪 LLM"通道,让 agent 在不调用真实模型的前提下,按你写好的剧本触发预设的工具调用,用于离线复现、自动化测试与教学演示。
核心能力
- 注册内部专用的 provider/model
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)。- 同时支持两种 replay 源格式:canonical
dsh-mock-scriptJSON 和原生的 DSH JSONL session 日志,自动识别转换(src/converter.ts:172-251、src/index.ts:341-360)。 - 实时把状态推给宿主 UI:在对话输入框上方渲染一个紧凑的 Mock status dock,展示当前第几步、总共几步、是否在等待工具回执(
src/client/index.ts:19-26、src/client/MockStatusRow.tsx:90-92)。 - 状态经
mockStatusprojection 暴露(src/projection.ts:34-57),失活或中止会回写为cancelled,下次会话恢复时识别为过期。
技术实现
- 语言: TypeScript(
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):注册mockStatusprojection 把状态折叠给客户端@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 插件,
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 切换的工作机制才能在出错时排查。
已知问题与限制
- v1 处于不稳定发布:
dsh-mock@0.1.1的命令、API 与 UI 都可能在稳定版前再变(README.md:3-5)。 - 直接把 ZIP 包当作 replay 源会被拒:
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)。- inline
/mock run不支持wait步骤——wait语法只能在 canonical 脚本里使用(src/parser.ts:92,103)。 - 仅声明
dsh.client.platform: "web"(package.json:28),命令行 / 桌面端是否可用源码中未明确。 - canonical 脚本版本被钉死为
1,其它版本会被MockScriptError(INVALID_SCRIPT)拒绝(src/converter.ts:84-85)。 - MockAdapter 只产出 chunk、不做执行:如果宿主的 ToolRuntime 不认识 replay 脚本里写到的工具名,
tool/call事件虽然会出现但宿主侧会报"unknown tool",mock 本身不会"凭空"伪造工具。
Small, focused plugins that make DeepSeek Harness more capable, expressive, and pleasant to use.
Quick start · Packages · Development · Documentation
🧠 Give your DSH sessions better tools, durable workflows, and a cleaner path from idea to execution.
⚡ Quick start
Published plugins install directly into a DSH profile with one command. The
examples below target the web profile; replace web with the profile you use.
🐚 Codex Terminal
# With the DSH CLI:
dsh plugin --profile web add dsh-codex-terminal@0.1.3
# Without the `dsh` CLI:
npm install dsh-codex-terminal@0.1.3
🔐 Codex Coding Plan
Reuse an existing file-backed codex login from the DSH Models page:
dsh plugin --profile web add ./coding-plan/codex
# Grok Coding Plan models from the existing `grok login`
dsh plugin --profile web add ./coding-plan/grok
⏰ Loop
# With the DSH CLI:
dsh plugin --profile web add dsh-loop@0.1.3
# Without the `dsh` CLI:
npm install dsh-loop@0.1.3
🧪 Mock — unstable
dsh-mock is published for early testing. Its commands, API, and UI may
change before a stable release.
# With the DSH CLI:
dsh plugin --profile web add dsh-mock@0.1.0
# Without the `dsh` CLI:
npm install dsh-mock@0.1.0
🧭 Sessions
Inspect, create, read, and message DSH sessions with the current session tools:
# With the DSH CLI:
dsh plugin --profile web add dsh-sessions@0.1.1
# Without the `dsh` CLI:
npm install dsh-sessions@0.1.1
Restart DSH and create a new session after installing a plugin. If dsh is not
on your PATH, run the same command from a DeepSeek Harness source checkout with
pnpm dsh instead.
Direct npm installation downloads the package for use by your project. DSH profile installation is still required when you want DSH to load the plugin as part of a profile.
📦 Packages
| Package | Status | What it adds | Docs |
|---|---|---|---|
dsh-codex-coding-plan | 🧪 Local · 0.1.0 | Reuses a file-backed Codex ChatGPT login through the existing openai-codex pi-ai provider. | README |
dsh-grok-coding-plan | 🧪 Local · 0.1.0 | Reuses a file-backed Grok subscription login through the existing xai pi-ai provider. | README |
dsh-codex-terminal | ✅ Published · 0.1.3 | Codex-compatible exec_command and write_stdin tools with persistent command sessions. | README · npm |
dsh-loop | ✅ Published · 0.1.3 | Session-scoped recurring alarms, loop tools, slash commands, and a web UI. | README · npm |
dsh-mock | ⚠️ Unstable · ✅ Published · 0.1.0 | Deterministic mock model turns and replay commands routed through the real DSH AgentLoop and ToolRuntime. | README · SPEC · npm |
dsh-sessions | ✅ Published · 0.1.1 | Session discovery, bounded reads, creation, and delivery through session tools and /sessions. | README · SPEC · npm |
🐚 dsh-codex-terminal
Run shell commands like a Codex-style agent: start long-running processes, poll for output, and send input to persistent sessions. PTY transport is used by default with a configured pipe fallback when PTY allocation is unavailable.
⏰ dsh-loop
Create durable, session-local recurring prompts that can be managed through
agent tools, /loop commands, and the web UI. Loops resume with the session
and keep each alarm independent from the others.
🧪 dsh-mock
Exercise deterministic mock model turns through /mock run and /mock replay
while preserving the real DSH AgentLoop, ToolRuntime, policy, and event flow.
⚠️ Unstable: published as
dsh-mock@0.1.0for early testing. The command, API, and UI surface may change before a stable release.
Install it into the DSH web profile with one command:
dsh plugin --profile web add dsh-mock@0.1.0
🛠️ Development
Each plugin is independently installable and testable. For example:
cd loop
pnpm install
pnpm test
pnpm build
The source tree intentionally stays outside the DeepSeek Harness repository; DSH composes plugins through profile-scoped installation and patch layers.
📚 Documentation
- Codex Terminal documentation
- Coding Plan core
- Codex Coding Plan documentation
- Grok Coding Plan documentation
- Loop documentation
- Mock documentation
- Mock implementation specification
- Sessions documentation
- Sessions specification
- DeepSeek Harness
🤝 Contributing
Issues, ideas, and pull requests are welcome. Keep plugins focused, document their runtime contracts, and include tests for changes to tools, persistence, or UI behavior.
📄 License
Released under the MIT License.