READMESource: main@daac51a0
dsh-ask-template
DSH(DeepSeek Harness)Web 里 /ask 的改造:把结构化填表从「模型弹表」变成「零模型调用填表」。
本仓库交付配套的两半:
| 半 | 载体 | 手势 | 谁在弹表 | 模型调用 |
|---|---|---|---|---|
| 客户端命令(仓库主体) | DSH 客户端插件 | 裸 /ask + 回车 |
浏览器本地写草稿 | 0 次 |
配套 skill ask-user |
技能文件(模型驱动) | /ask-user,或 / 菜单选行 |
模型调 ask_user_question |
有 |
两者共用同一套五段字段,区别只是"谁来弹这张表":
- 想省一次模型往返、自己打字填 —— 用
/ask(命令,本插件); - 想让 agent 在对话里逐项问你、你点选即可 —— 用
/ask-user(skill)。
命令这一半是怎么工作的
敲 /ask + 回车时,全程不碰模型:
/命令源在裸 token(/ask后没有空格参数)上命中本插件的命令贡献;- 贡献是
action类型:消费掉/ask这个词,执行一个纯客户端回调,不提交任何消息; - 回调里
ctx.sessions.scope(sessionId)取到会话作用域,ctx.conversation.input.for(actx).setDraft(模板)把空白模板整段写进输入框草稿; - 你填完按回车 —— 这时才是普通用户消息,模型只看到填好的五段表。
/ask 参数…(带空格)不命中命令,会照旧当普通文本发出,所以 skill 那条路依然可用。
五段模板
【背景情况】
【核心问题】
【约束与要求】
【输出格式】
未提供
【已有尝试】
未提供
两个选填段预填 未提供,不动即为该项的最终取值;必填三段留空等你填。
未提供 是"没填"的正式表达,不需要删改。
安装
1. 客户端命令(插件)
dsh plugin --profile web add link:<本仓库路径>
该命令转发 pnpm 安装,随后自动把 dsh-ask-template 追加进
~/.dsh/profiles/web/package.json 的 dsh.profile.bundles,即装即挂载;装完刷新页面。
也可以直接 npm 源安装(发布后):
dsh plugin --profile web add dsh-ask-template
2. 配套 skill ask-user
把下面这段存成 skills/ask-user/SKILL.md(本机实际位置 ~/.agents/skills/ask-user/SKILL.md):
---
name: ask-user
description: 结构化填表提问(模型驱动的 ask_user_question 弹表;纯客户端写模板用 /ask 命令)
user-invocable: true
---
进入填表模式:第一步就调用 ask_user_question,把五项作为一次请求里的五个问题提出。
必填:背景情况 / 核心问题 / 约束与要求;
选填:输出格式(结论先行 再分步落地 / 对比表格 / 可执行代码 / 要点清单)、已有尝试。
收到答案后整理成五段(未回答写"未提供"),再作答。
字段与命令那条路完全一致,所以你从任一路径得到的表,格式都相同。
卸载(一键回滚)
dsh plugin --profile web remove dsh-ask-template
skill 侧直接删掉 skills/ask-user/ 目录即可;它原本叫 ask,改名是为了把裸 /ask
这个手势让给命令,避免 / 菜单出现两行同名。
实现要点(复现/维护用)
- 命令贡献契约:
ctx.commandUi.register({ name, label, description, available, ui }),ui: { kind: 'action', run(session) },session只带sessionId。 sessionId→ 会话作用域:ctx.sessions.scope(sessionId)(返回undefined即无 composer)。- 写草稿:
ctx.conversation.input.for(actx).setDraft(text),再.focus()把焦点交还输入框。 - 回车命中
action时,提交机器把该次裁决记为handled并不产生任何 effect, 所以这里写入的草稿不会被"提交后清空"逻辑吃掉。 - 浏览器半是手写 CJS 闭包 bundle:
window.__ModuleLoader__.load({ id, factory }), 无 React、无构建步骤、无运行时依赖,改完刷新页面即生效。 - 主机半(
lib/index.js)是空挂载:profile 层要靠一条 Loader 行寻址,客户端 bundle 由 该行所属的包被发现。
已知限制
setDraft把光标停在草稿末尾(【已有尝试】的未提供之后),要填第一段需自己点上去。 契约里没有"带光标位置写草稿"的入口;要解决得改走自绘表单 slot(conversation.input.overlay)。- 输入框已有文字时会被整段替换,替换前会给一条提示;旧草稿不保留。
- 命令与 skill 目前共用同一套五段字段,改字段要两边一起改。
License
MIT
No comments yet. Be the first to write one.