Skip to content

dsh-ohna

Verified

dsh-ohna · v0.1.4 · MIT · Web UI

Multi-tool development toolkit for the agent runtime: ohna_devline_run (parallel, context-isolated dev pipeline) + ohna_bug_record / ohna_bug_fixed (workspace bug log) + a Web GUI bug table. The orchestrating tool named by the one-click fix prompt is conf

Install

dsh plugin add dsh-ohna

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Tags

Creators

Readme

dsh-ohna

开发闭环工具包:并行隔离开发流水线 + 工作区 bug 记录 + Web GUI 表格,一个插件跑通 「用户报 bug → 一键修复 → 编排修复流程 → 标记完成」。

  • 包名:dsh-ohna · 版本:0.1.4 · private: false(可发布)
  • 对外暴露 3 个模型可调用工具,共用一份 host 依赖、一个前端入口、一份 cordis.patch.yml
用户报 bug                    ┌────────────────── 本插件 ─────────────────┐
   │                          │                                          │
   ▼                          ▼                                          │
ohna_bug_record  ──►  <workspace>/tmp/dsh-repo-bug.json                  │
   │                          │                                          │
   │   GUI「一键修复」         ▼                                          │
   └────────────────►  ohna_devline_run ──► 并行 coder → reviewer → 原 coder 修复
                                                                         │
                              ohna_bug_fixed  ◄── 每修完一条回写 fixed ───┘

1. 三个工具(名称固定,不可配置)

工具 作用 原归属
ohna_devline_run 并行、上下文隔离的开发流水线:coders → reviewer → 原 coder 修复,直到 pass 或 maxFixRounds 原 dsh-dev-line
ohna_bug_record 把用户在提示词里明确表述的 bug / 问题追加写入工作区 bug JSON 原 dsh-repo-dashboard
ohna_bug_fixed 翻转记录上的 fixed 标志(GUI 据此渲染) 原 dsh-repo-dashboard

为什么这三个名字固定且带 ohna_ 前缀: 它们是本插件对外暴露的接口,应当稳定;而 devline_run / repo_bug_record / mark_bug_fixed 都是通用词,与其他市场插件重名概率不低 —— DSH 的 tools.register 对同一层内重名直接抛错 (tool "X" is already registered,不是覆盖、也不是后者赢),会让后加载的插件整个启动失败。 因此统一加 ohna_ 前缀主动避让;注册时若仍冲突,本插件选择 fail-loud 清晰报错,不静默吞掉。

唯一可配置的是 fixTool(见 §2),它只决定「一键修复」提示词第 3 步引用哪个编排工具, 不影响本插件自己注册的工具名。


2. 一键修复 与 fixTool

GUI 的「一键修复」会把修复指令填入输入框(不自动发送,用户确认后手动发送)。 提示词中只带日志文件路径,不含具体条目 —— 模型自行读文件筛选 fixed !== true, 因此提示词长度与 bug 条数无关。

请修复 <workspace>/tmp/dsh-repo-bug.json 中所有 fixed 不为 true 的 bug。

步骤:
1. 读取 <workspace>/tmp/dsh-repo-bug.json
2. 筛出所有 fixed !== true 的记录
3. 使用 {fixTool} 工具的开发流程逐条修复(该插件负责流程编排与冲突分析)
4. 每修复完一条,调用 ohna_bug_fixed 工具把该条标记为已修复

全部修完后,汇总说明每条 bug 的修复方式。
步骤 工具名 是否可配置
第 3 步(编排修复) 由 fixTool 决定,默认 ohna_devline_run ✅ 可改成任意第三方工具名
第 4 步(标记已修复) 恒为 ohna_bug_fixed(常量 MARK_TOOL) ❌ 固定,不可配置

为什么第 4 步不可配置

ohna_bug_fixed 写的是本插件自己的 bug JSON。第三方编排工具做不到这个写入动作, 所以无论 fixTool 配成什么,第 4 步都必须指向本插件的标记工具。

幽灵工具防线

用户配了第三方工具名但该工具实际未安装/未注册时,提示词会引用一个不存在的工具,主 agent 调用会得到 UNKNOWN_TOOL。因此 host 侧在只读路由返回 fixTool 前,会用 ctx.tools.get(name) 校验它确实已注册:

场景 行为
fixTool 未配置 / 为空 回退到默认 ohna_devline_run,仍然走注册校验
校验通过(工具已注册) 第 3 步正常引用该工具名
校验失败(未注册) 返回 null,GUI 把第 3 步降级为工具无关的通用指令:3. 逐条修复(按当前会话可用的工具自行组织开发流程)

提示词组装逻辑是无副作用的纯函数 buildFixPrompt(logPath, fixTool),位于 fixprompt.js(gui.js 是浏览器 bundle,无法被 node --test 导入, 因此与测试共用这一个数据源)。


3. ohna_devline_run —— 并行隔离开发流水线

由**主 agent(编排者)**调用,把任务拆解后一次性执行:

主 agent(编排者)                    子 agent(上下文互相隔离)
─────────────────────               ─────────────────────────────
分析任务 → 拆解 work items
(数量 = 可并行开发的数量)
     │  调用 ohna_devline_run
     ▼
     并行 spawn N 个 coder/architect ──► 每个在全新隔离上下文中开发
     │
     spawn 1 个 reviewer             ──► 审核全部 coder 输出(结构化结论)
     │
     ┌─ 发现问题 → 续跑原 coder 会话(sendMessage 投递反馈)修复 ──► 重新审核
     └─ 直到 pass 或 maxFixRounds
     │
     ▼ 返回汇总报告
主 agent 独立完成完整测试 + 文档同步(在工具之外)

关键设计

  • 上下文隔离:子 agent 统一由 spawn 后端启动(inheritsParentContext: false), 每个 coder / reviewer 都是全新会话,只拿到自己的任务描述与共享文档,互不相通。
  • 原 coder 修复:审核发现问题时,用 ctx.subagents.sendMessage 把反馈直接投递给 原 coder 的同一个会话(continuable child:启动时预留 childId)。修复消息只携带 审核反馈 + 语言提醒,不再重传 task / 共享上下文 / 上一轮报告 —— 这些本就在原 coder 的会话里, 因此每轮修复都不必重建上下文,省掉大量 token。
  • 语言跟随:language 参数(zh / en / auto)决定子 agent 的思考与输出语言。 DSH 的界面语言是 client 端服务(ctx.locale),宿主插件所在的 host 端读不到, 因此由主 agent 通过参数把用户界面语言传下来;auto 或缺省时按 task + shared_context 是否含汉字推断。语言约束同时锁住「思考」与「正文输出」,并显式要求代码、标识符、文件路径、 命令输出保持原样(永不翻译)。
  • 主 agent 的职责:文档同步 + 最终完整测试由主 agent 自己在工具返回之后完成,工具只负责开发与审核。

工具参数

参数 必填 说明
task 是 整体开发任务与验收标准,注入每个子 agent
work_items 是 并行工作项数组;数量即并行度。每项 { id, title, role, description },role 取 architect / senior_developer / developer(缺省 developer)
parallelism 否 最大并发 coder 数;缺省全部并行(上限 maxParallel)
cwd 否 子 agent 工作目录;缺省继承调用方目录
shared_context 否 共享项目上下文(规格 / 架构 / 规范)注入每个子 agent
max_fix_rounds 否 审核→修复最大迭代次数;缺省取配置 maxFixRounds
language 否 zh / en / auto(默认 auto)。请按用户界面语言传 zh 或 en

返回值是一份 Markdown 汇总报告:状态 / 轮次、每个 work item 的摘要与修复次数、 reviewer 结论与遗留问题、交接给主 agent 的测试与文档待办。


4. ohna_bug_record / ohna_bug_fixed

记录原则

  • 只记录用户在提示词里明确表述的 bug / 问题;
  • agent 在 coding 过程中自己发现的编码问题不记录;
  • 用户说「这个有点难用」这类没说 bug 的体验抱怨 → 记为 体验优化。

工具参数(ohna_bug_record)

参数 必填 说明
title 是 简短摘要(≤ 80 字为宜)
type 是 类型,见下表;建议值不强制,可自由扩展
detail 否 详细描述(用户的原话 + 上下文),软上限 detailMaxChars(默认 2000,超长截断并提示)
note 否 备注
fixed 否 是否已修复,默认 false
location 否 { file, symbol, line, snippet },初步(不可信)定位
locate 否 为 true 时由插件 spawn 一个 subagent 帮忙定位代码;默认不 spawn

工具参数(ohna_bug_fixed)

参数 必填 说明
ids 是 要更新的编号数组,如 ["BUG-001","BUG-002"];["*"] 表示全部
fixed 否 新状态,默认 true;传 false 表示重新打开(用户反馈仍存在)
note 否 可选备注,写入 fixed_note

已是目标状态的记录不会被重复改写;修复完成后由主 agent 调用,回写 fixed / fixed_at。

建议类型(不强制)

类型 说明
阻断 阻塞主流程,无法继续
功能缺陷 功能不符合预期 / 结果错误
体验优化 能用但难用、别扭
代码规范 风格、命名、结构问题
文档对齐/冲突 文档与实现不一致或互相矛盾
性能问题 慢、资源占用高
安全问题 安全隐患 / 漏洞

5. 数据模型

<workspace>/tmp/dsh-repo-bug.json(相对路径按会话工作目录解析,见 §7):

{
  "meta": { "version": 1, "updated_at": "..." },
  "records": [
    {
      "id": "BUG-001",
      "title": "简短摘要",
      "type": "功能缺陷",
      "fixed": false,
      "note": "备注",
      "detail": "详细描述",
      "location": { "file": "src/a.js", "symbol": "foo", "line": 12, "snippet": "...", "line_volatile": true },
      "recorded_at": "2026-10-22T00:00:00.000Z",
      "git_sha": "abc1234",
      "fixed_at": null
    }
  ]
}

字段说明

字段 说明
id BUG-001 起,三位补零;超过 999 不截断(BUG-1000),由插件分配
title 简短摘要
type 类型(建议值见 §4,可自由扩展)
fixed 是否已修复,GUI 据此渲染
note 备注(可选)
detail 详细描述(可选)
location 初步定位:file / symbol / snippet 是主要锚点,line 仅作记录时参考并标注 line_volatile: true;用 locate: true 时还会带 located_by: "subagent"
recorded_at 记录时间(ISO 8601)
git_sha 记录时的 git rev-parse --short HEAD,便于追溯
fixed_at 标记修复的时间;未修复为 null
fixed_note 仅当 ohna_bug_fixed 传了 note 时写入

写入保证

  • 只追加,从不整文件覆写;
  • 原子写:同目录临时文件 + rename;写入前重读防并发覆盖,id 冲突时重试;
  • 文件损坏:移到 <dataPath>.corrupt-<ts> 备份后重建,不丢数据。

6. Web GUI

slot 位置 说明
conversation.view(order: 20) 会话上方的 Bugs tab,与「对话」「轨迹」并列 session 作用域,表格主体
conversation.input.left(order: 20) 输入框工具行左侧(「切换模型」左边)的 Bug 记录 按钮 点击弹出浮层,复用同一表格

第二个入口在新建会话尚未发消息时同样可见 —— 此时 DSH 会隐藏整个 tab 栏(含「轨迹」) 与头部 utilities,只有 composer 工具行仍渲染,且它仍能拿到 inputActions, 所以「一键修复填输入框」在 blank 会话下依然可用。

表格能力:

  • 列:编号 / 摘要 / 类型 / 已修复 / 备注 / 记录时间 / 操作;点击行展开详细描述与代码定位弹层;
  • 一键修复:把未修复 bug 的修复指令写进输入框(不自动发送);
  • 每行操作:一个按钮翻转该条 fixed(修好了标已修复;验证没修好改回未修复以便二次修复);
  • 不提供删除:新增由 ohna_bug_record 完成,状态变更由 ohna_bug_fixed 或 GUI 操作完成;
  • 每个工作区只显示自己的 tmp/dsh-repo-bug.json,不串台(组件从当前 session 取 cwd)。

7. HTTP 接口

GET  {apiPrefix}/bugs?cwd=<会话工作目录>      # 读取
POST {apiPrefix}/bugs?cwd=<会话工作目录>      # 翻转 fixed

默认 apiPrefix = /api/dsh-repo-dashboard,即 /api/dsh-repo-dashboard/bugs。

GET 返回:

字段 说明
meta { version, updated_at }
records 记录数组
workspace 解析后的工作目录绝对路径
data_path bug JSON 的绝对路径
fix_tool 经注册校验后的编排工具名;未配置或未注册时为 null(GUI 据此降级第 3 步)

POST 接收 { ids, fixed },返回 { updated, total, data_path, workspace }。 非 GET/POST 方法返回 405;无法解析出绝对工作目录时返回 400。


8. 配置(cordis.patch.yml)

- insert:
    - id: dsh-ohna
      name: 'dsh-ohna'
      config:
        # —— 开发流水线(ohna_devline_run) ——
        provider: spawn
        maxParallel: 8
        maxFixRounds: 3
        insertionGraceMs: 1000
        # —— bug 记录(ohna_bug_record / ohna_bug_fixed) ——
        dataPath: tmp/dsh-repo-bug.json
        detailMaxChars: 2000
        apiPrefix: /api/dsh-repo-dashboard
        locatorProvider: spawn
        # —— 一键修复提示词:第 3 步引用的修复编排工具 ——
        # 默认指向本插件自带的 ohna_devline_run;可改成任意第三方 tool 名。
        # 第 4 步的标记工具恒为 ohna_bug_fixed,不可配置。
        fixTool: ohna_devline_run
键 默认 说明
provider spawn 子 agent 后端(spawn = 隔离上下文)
maxParallel 8 并发 coder 上限(夹取到 1–64)
maxFixRounds 3 审核→修复迭代上限(夹取到 0–10)
insertionGraceMs 1000 修复轮等待「本条反馈写入子会话日志(user/message)」的兜底上限:仅用于只上报 subagent/end 却从不上报该记录的宿主,避免修复轮卡死;正常宿主由后续 subagent/end 直接结算,不会触及
dataPath tmp/dsh-repo-bug.json 记录文件路径;相对路径按会话工作目录解析,绝对路径原样使用
detailMaxChars 2000 详细描述软上限(下限 200)
apiPrefix /api/dsh-repo-dashboard HTTP 路由前缀
locatorProvider spawn locate: true 时定位 subagent 的后端
fixTool ohna_devline_run 「一键修复」提示词第 3 步引用的编排工具,可换成任意第三方 tool 名

另有可选的 workspace:仅作为 GUI 请求未带 ?cwd= 时的兜底工作目录, 不会被工具调用更新(该状态是跨会话共享的,若被改写会让每个会话的 tab 都指向同一个文件)。

服务依赖

inject = ["tools", "subagents"]。workingDirectory 与 webServer 不声明 —— cordis 没有 optional-inject 形式,声明了会让缺该服务的 profile 永久 pending, 因此二者一律运行时用 ctx.get / ctx.inject 惰性获取。


9. 安装

方式一:npm 安装(推荐)

在 the agent runtime 的 Plugins 页(插件市场) 搜索安装本包,或用 install_bundle 安装。 安装后重载 profile(重启 DSH,或在插件市场重装本 entry),三个工具即对当前 profile 的 agent 可见。

也可以直接装进 profile:

npm install dsh-ohna

然后在 ~/.dsh/profiles/<profile>/package.json 把 dsh-ohna 加入 dsh.profile.bundles:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-ohna"
      ]
    }
  }
}

需要 Node >= 22(本插件使用了 Promise.withResolvers())。

方式二:本地 link(开发用)

把本地开发目录 link 进 profile,便于改代码即时验证:

{
  "dependencies": {
    "dsh-ohna": "link:/path/to/your/dsh-ohna"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-ohna"
      ]
    }
  }
}

把 /path/to/your/dsh-ohna 换成你的实际目录,然后重载 profile。


10. 从旧插件迁移

dsh-ohna 由两个插件合并而来,二者原本是「一个闭环被拆成两个包」:

原插件 原工具 现工具
dsh-dev-line devline_run ohna_devline_run
dsh-repo-dashboard repo_bug_record ohna_bug_record
dsh-repo-dashboard mark_bug_fixed ohna_bug_fixed

迁移要点:

  1. 工具名统一加 ohna_ 前缀。DSH 的 tools.register 对同一层内重名直接抛错, 而 devline_run / repo_bug_record / mark_bug_fixed 都是通用词,与其他市场插件重名概率不低, 重名会让后加载的插件整个启动失败 —— 加前缀是主动避让冲突。调用方需改用新名字。
  2. fixTool 取代了写死的工具名。旧 dsh-repo-dashboard 的「一键修复」提示词里写死了 devline_run + mark_bug_fixed;现在第 3 步由 fixTool 配置(默认 ohna_devline_run), 第 4 步固定为 ohna_bug_fixed。
  3. 数据文件与 GUI 行为不变:仍是 <workspace>/tmp/dsh-repo-bug.json, API 前缀仍是 /api/dsh-repo-dashboard/bugs,旧记录可直接沿用,无需迁移数据。
  4. 卸载旧插件:避免两个插件同时注册重复工具导致启动失败。

11. 目录结构与测试

dsh-ohna/
├── package.json        # name: dsh-ohna, version 0.1.4, private: false
├── cordis.patch.yml    # 合并后的一份 config
├── index.js            # host 入口:注册 3 个工具
├── devline.js          # ohna_devline_run(并行流水线)
├── buglog.js           # ohna_bug_record / ohna_bug_fixed + HTTP 路由
├── storage.js          # bug 存储:编号 / 原子写 / 损坏备份
├── fixprompt.js        # 一键修复提示词(纯函数,无副作用)
├── gui.js              # client 侧:tab + 浮层 + 一键修复
├── locale/{en,zh}.json
├── icon.svg
└── tests/              # node --test
npm test     # node --test "tests/*.test.js" —— 63 个测试

测试覆盖:devline 的 fix 循环归属(FEEDBACK_MARKER + session/event + subagent/end 时序消歧)、三个工具名固定且互不相同、重复注册 fail-loud、路由 GET/POST 与 fix_tool 校验降级、提示词纯函数的第 3/4 步与降级分支、工作区隔离。

仅依赖 Node 内置模块,任何提供 tools / subagents 服务的 profile 都能激活。

License

见 LICENSE。