Bundle
dsh-llama-responses
DeepSeek Harness plugin: run subagents on a local llama.cpp model via the OpenAI Responses (/v1/responses) protocol, with a subagent delegation skill
- Source
- SnowRikka
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 21 hours ago
Readme
# dsh-llama-responses
DeepSeek Harness(dsh)的本地大模型适配器插件:**OpenAI Responses 协议**(`/v1/responses`),对接本地 llama.cpp `llama-server`。
用途:dsh 主代理继续用 DeepSeek 官方 API,**子代理(spawn/fork)路由到本地模型**,省 API 成本。
**隔离设计(重要)**:所有子代理**不继承父对话**——`subagent_fork` 已通过 patch 重定向到 spawn 提供方
(`provider: spawn`),两个委派工具的子代理都只看到父代理下发的指令文本,父会话任何内容
(含已完成轮次)都不会进入子代理上下文,避免上下文膨胀与信息泄漏。父代理要传递背景,
必须显式写进委派指令。(已实测:父对话中的信息子代理明确回答"看不到"。)
## 重要提示(子代理走本地模型的前置操作)
已知坑:每次启动必须先在 DeepSeek Harness 中**手动选择一次本地的 qwen3.8-27b 并提问一次**,然后把主代理
**换回 DeepSeek V4 模型**——之后子代理才会正常走本地的 qwen3.8-27b。不做这一次"本地提问再切回",
子代理不会正常路由到本地模型。
## 安装(生态方式)
```bash
# 方式一:dsh 官方插件命令(推荐)
dsh plugin --profile web add git+https://github.com/SnowRikka/dsh-llama-responses.git
# 方式二:手动软链(便于改源码)
git clone https://github.com/SnowRikka/dsh-llama-responses.git ~/dsh-llama-responses
ln -sfn ~/dsh-llama-responses ~/.dsh/profiles/web/node_modules/dsh-llama-responses
```
包内自带 `cordis.patch.yml`(bundle 层,注册默认适配器)与 `skill/`(委派规范 skill,
`package.json` 的 `dsh.skills` 声明)。装好后按下文 patch 把子代理路由到
`provider: llama-responses` 即可。npm 未发布前,以上两种方式等效。
## 文件
| 文件 | 说明 |
|---|---|
| `index.js` | 插件入口:Config schema + `ctx.llm.registerAdapter(['llama-responses'], ...)` |
| `adapter.js` | 适配器本体:GenerateOptions → Responses 请求、Responses SSE → dsh StreamChunk(文本/工具调用流式/用量/finish) |
| `test_adapter.mjs` | 单元测试(不经 dsh 直连 llama-server:多轮、工具调用、工具结果回传) |
| `node_modules/` | 指向 dsh 自带依赖的符号链接(dsh-llm、schemastery) |
## 已验证(2026-08-23,Qwen3.8-27B)
- 单元测试:多轮记忆、function_call 流式、function_call_output 回传,全部通过
- 端到端(DeepSeek 主代理 + 本地子代理):
- `subagent`(spawn/可继续后台)✅
- `subagent_fork`(one-shot 前台,已重定向 spawn=完全不继承父对话)✅ 隔离已实测
- `send_message`(追问排队下一回合)✅
- `list_agents`(显示 running/ready 状态)✅
- `interrupt_agent`(中断成功,子代理转 ready)✅
- `report`/结算通知(运行时通知链路)✅
## 如何启用 DeepSeek Harness 自带的子代理功能(前置条件)
本插件挂载在 dsh 的子代理体系上,先把 dsh 自带的子代理功能启用(这是必要前置):
### 现状:哪些默认开、哪些默认关
| Profile | 子代理引擎(spawn/fork 提供方、继续执行管理器) | 模型侧工具(subagent 等) |
|---|---|---|
| `headless` | 默认启用 | **默认启用** |
| `web` | 默认启用 | **默认禁用**(web-app 组合包有意禁用,需 patch 开启) |
确认方法:
```bash
dsh --profile web --dump-config | grep -B1 -A4 "id: tool-subagent" # 看 disabled 字段
```
### web profile 启用 patch
在 `~/.dsh/profiles/web/cordis.patch.yml` 加入(不带 config 的覆盖型条目):
```yaml
- id: tool-subagent-control # send_message / interrupt_agent
disabled: false
- id: tool-subagent-list-agents # list_agents
disabled: false
- id: tool-subagent # 委派工具(可继续后台子代理)
disabled: false
- id: tool-subagent-fork # 委派工具(one-shot,已重定向 spawn=无父对话)
disabled: false
```
启用后模型会看到 5 个工具:`subagent`、`subagent_fork`、`send_message`、`interrupt_agent`、`list_agents`
(子代理内部另有 `report` 回报通道,自动生效)。
### 验证子代理功能本身(未挂本插件也能测,子代理会走默认 DeepSeek 模型)
```bash
dsh --profile headless "用 subagent 工具委派一个子代理回答:1+1等于几?转述它的答案"
```
---
## 如何启用本插件(本地模型路由)
前置:本地模型服务已运行(例:`~/qwen/start_server.sh`,监听 `127.0.0.1:8080`),
且建议加 `--reasoning off` 避免思考占用子代理输出预算。
### 1. 放置插件(软链到 profile)
```bash
# 对每个要用它的 profile 执行(web / headless)
ln -sfn /home/lmj/zi-dai-deep ~/.dsh/profiles/web/node_modules/dsh-llama-responses
ln -sfn /home/lmj/zi-dai-deep ~/.dsh/profiles/headless/node_modules/dsh-llama-responses
```
(依赖符号链接 `node_modules/@deepseek-ai/{dsh-llm,schemastery}` 已就位,一般无需动)
### 2. 配置 patch(`~/.dsh/profiles/<profile>/cordis.patch.yml`)
```yaml
# 注册适配器
- insert:
- id: llm-responses-local
name: dsh-llama-responses
config:
baseURL: http://127.0.0.1:8080/v1
providerName: llama-responses
apiKeyEnv: DSH_LOCAL_LLM_KEY
models:
- id: qwen3.8-27b # 与 llama-server 加载的模型对应
name: Qwen3.8-27B IQ4_XS (local)
contextWindow: 163840
defaultContextWindow: 163840
defaultMaxTokens: 8192
# 子代理固定本地模型(已含完整示例见两个 profile 里的现成 patch)
- id: tool-subagent
config:
provider: spawn
toolName: subagent
backgroundMode: continuable
agentOptions:
provider: llama-responses # 关键:路由到本地
model: qwen3.8-27b
maxTokens: 8192
```
web profile 还需要 `- id: tool-subagent(-control/-list-agents/-fork) disabled: false`(web-app 默认禁用这些工具,headless 默认启用)。
### 3. 环境变量
```bash
# ~/.bashrc 已有;本地服务不校验鉴权,占位即可
export DSH_LOCAL_LLM_KEY=local-no-auth
```
### 4. 验证
```bash
dsh --profile web --dump-config | grep -A3 llm-responses-local # 应看到插件条目
dsh --profile headless "用 subagent 工具委派子代理回答:1+1等于几?" # 子代理答案应回传
```
## 协议细节(踩过的坑)
- 历史消息条目**必须带顶层 `type:'message'`**,assistant 内容用 `output_text`
(裸 role 条目会报 "Cannot determine type of 'item'")
- 工具:`{type:'function', name, description, parameters}` 扁平格式;
结果回传用 `{type:'function_call_output', call_id, output}`
- SSE 事件:`response.output_text.delta` / `response.function_call_arguments.delta` /
`response.output_item.done` / `response.completed`(usage 在 completed 里)
- Node fetch 不走系统代理,本地 `127.0.0.1` 直连无碍
## 配置项参考
| 字段 | 默认 | 说明 |
|---|---|---|
| baseURL | `http://127.0.0.1:8080/v1` | 适配器自动拼接 `/responses` |
| providerName | `llama-responses` | 注册到 `ctx.llm` 的路由名 |
| apiKeyEnv | `DSH_LOCAL_LLM_KEY` | 读该环境变量作 Bearer |
| models | qwen3.8-27b/160K | 模型目录(id 须与服务端一致) |
| defaultContextWindow | 163840 | 上下文窗口(与服务端 llama-server 的 `--ctx-size` 一致) |
| defaultMaxTokens | 8192 | 单请求输出上限 |
## 附带 SKILL:local-subagent-delegation
`skill/local-subagent-delegation/SKILL.md` — 面向主代理的子代理委派规范:
- 子代理 = 160K 上下文本地代码模型(身份自称不可信,忽略之)
- 指令必须自包含且详尽(六要素自查:目标/输入/约束/输出格式/验收标准/输出规模(由主代理判断,无固定上限))
- 硬性红线:同一时刻最多 1 个子代理(委派前 `list_agents` 检查)
- 默认一次性使用;仅同任务紧邻小追问且上下文 <80K 时允许 `send_message` 复用
- 何时不该委派(直接做/密集上下文交互/超长输出)
安装方式(已完成):软链到 `~/.dsh/skills/local-subagent-delegation`;
web profile 需 patch 启用 `tool-skill`(`disabled: false`),headless 默认启用。
已实测:模型能发现并加载该 skill,委派行为完全符合规范(六要素齐备、先查单实例、声明一次性)。
## 如何启用 skill 功能(tool-skill,前置条件)
skill 的发现与加载由 `@deepseek-ai/dsh-tool-skill` 插件提供,各 profile 默认状态不同:
| Profile | tool-skill 默认状态 |
|---|---|
| `headless` | **默认启用** |
| `web` | **默认禁用**(web-app 组合包禁用),需 patch 开启 |
### web profile 启用方法
在 `~/.dsh/profiles/web/cordis.patch.yml` 加入:
```yaml
# 启用 skill 工具(模型发现/加载 SKILL.md)
- id: tool-skill
disabled: false
```
(本机已配置;生效需要重启 `dsh web`,patch 热更新对工具启停不总是即时。)
### 验证
```bash
# 1. 配置树确认条目已启用(应显示 disabled: false)
dsh --profile web --dump-config | grep -A2 "id: tool-skill"
# 2. 运行时确认模型能发现 skill(应列出 local-subagent-delegation)
dsh --profile headless "你现在有哪些可用的 skill?只列名称和描述"
```
### skill 的安装位置(发现优先级,供排错参考)
| 优先级 | 来源 | 目录 |
|---|---|---|
| 100 | 项目级 | `<项目根>/.dsh/skills/<name>/SKILL.md` |
| 200 | 项目级 | `<项目根>/.agents/skills/` |
| 300 | 自定义 | `Config.customSkillDirs` |
| 400 | 用户级 | `~/.dsh/skills/<name>/SKILL.md`(本 skill 装在这里) |
| 500 | 用户级 | `~/.agents/skills/` |
同名 skill 低 rank 值优先;仅目录包 `<name>/SKILL.md` 与扁平 `<name>.md` 两种形式,
不支持嵌套递归发现。
Install
dsh plugin --profile web add github:SnowRikka/dsh-llama-responses
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-llama-responses from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.