像网页版一样聊天,模型会自己多轮思考再作答
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add zdjmrq/dsh-better-chat该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · chat
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 35 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包think_better(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/8 09:40:52
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-session@deepseek-ai/dsh-tools@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 纯对话聊天模式
- 模型多轮思考作答
给 DeepSeek Harness 的「纯对话」模式:像网页版一样聊天,但会自己多轮思考
README
由 DeepSeek 最新模型翻译生成dsh-better-chat
给 DeepSeek Harness 的「更好的对话模式」模式:像 DeepSeek 网页版一样聊天,但会自己多轮思考。
一个 DSH 本地 bundle,向 Web 端注册名为「更好的对话模式」的 agent preset,并附带一个 keep_thinking 工具。
它是什么
- 一个模式(agent preset),在 DSH 的设置页出现,名字叫「更好的对话模式」
- 一个工具 keep_thinking:纯文字的控制流工具,不碰文件、不联网、无任何副作用
- 模型自己决定要想 1 轮还是 N 轮,自己判断什么时候该停
- 只有一个硬上限(默认 10 轮)防止无限循环
「多轮思考」是怎么实现的
DSH 的 agent 循环规则是:让轮次继续的唯一燃料是「工具调用」或「steering」。没有工具调用,模型答完就结束。
所以这里给模型一个只用来表达“我还没想完”的空工具:
| 模型的行为 | 循环的行为 |
| 调用 keep_thinking | 执行工具 → 再跑一步(又一次模型请求) |
| 不调用、直接输出答案 | 轮次结束 |
这就是 agent loop 原生的控制流,不需要监听轮次边界、不需要往对话正文里塞协议标记。「停止」就等于「不再调用」。
展开完整文档(README 剩余 1 节)
dsh-better-chat
给 DeepSeek Harness 的「更好的对话模式」模式:像 DeepSeek 网页版一样聊天,但会自己多轮思考。
一个 DSH 本地 bundle,向 Web 端注册名为「更好的对话模式」的 agent preset,并附带一个 keep_thinking 工具。
它是什么
- 一个模式(agent preset),在 DSH 的设置页出现,名字叫「更好的对话模式」
- 一个工具 keep_thinking:纯文字的控制流工具,不碰文件、不联网、无任何副作用
- 模型自己决定要想 1 轮还是 N 轮,自己判断什么时候该停
- 只有一个硬上限(默认 10 轮)防止无限循环
「多轮思考」是怎么实现的
DSH 的 agent 循环规则是:让轮次继续的唯一燃料是「工具调用」或「steering」。没有工具调用,模型答完就结束。
所以这里给模型一个只用来表达“我还没想完”的空工具:
| 模型的行为 | 循环的行为 |
| 调用 keep_thinking | 执行工具 → 再跑一步(又一次模型请求) |
| 不调用、直接输出答案 | 轮次结束 |
这就是 agent loop 原生的控制流,不需要监听轮次边界、不需要往对话正文里塞协议标记。「停止」就等于「不再调用」。
和 DeepSeek 网页版的对照
| DeepSeek 网页版 | 本模式 |
| 联网搜索 | ✅ web_search + web_fetch |
| 文件上传 / 文本提取 | ✅ 全局附件能力(DSH 自带) |
| 图片识图 | ✅ 全局多模态输入 + read_image |
| 语音输入 | ✅ 取决于 profile 是否装了语音 bundle |
| 深度思考 | ✅ reasoningEffort(profile 级配置) |
| 快速 / 专家模式 | ✅ 就是 DSH 的 preset 概念,本模式是其中一个 |
| —— | ➕ 多轮纯文字思考(本模式独有) |
挂载了哪些插件
全部内容就是 cordis.patch.yml 里的一个 preset 声明。
宿主层(profile 层)
空的。 本 bundle 以前在这里放一行 think-better-tool,现在没有了——原因见 「为什么工具行在 preset 里面」。
preset 层(模式内部)
5 个官方工具行 + 本仓库自己的工具行,全部挂在 preset-chat 的 config.plugins 里:
| 行 id | 包 | 配置 | 提供的工具 |
| think-better-tool | think_better(本仓库),以绝对 file URL 引入 | maxRounds: 10 | keep_thinking |
| persona | @deepseek-ai/dsh-persona | 见 persona | —(系统提示词) |
| tool-web | @deepseek-ai/dsh-tool-web | fetch: truesearchTimeoutMs: 60000 | web_search web_fetch |
| tool-ask-user | @deepseek-ai/dsh-tool-ask-user | — | ask_user_question |
| tool-fs | @deepseek-ai/dsh-tool-fs | — | read write edit read_image |
| tool-fs-search | @deepseek-ai/dsh-tool-fs-search | sampleOverCapGlobResults: false | glob grep |
| present | @deepseek-ai/dsh-tool-present | — | present |
合计 11 个工具。 实测「更好的对话模式」一轮实际下发 25 个工具——多出来的 14 个来自宿主层的其它 bundle,见 已知限制。
因为工具行就在 preset 里,ctx.tools.register() 走的是 preset 的作用域:只有「更好的对话模式」的 agent 看得见它,其它模式不需要被摘掉任何东西。
刻意没有挂的
| 没挂 | 原因 |
| dsh-tool-goal + dsh-command-goal | goal-round-driver 在 base 中默认启用,模型一旦能建 goal 就会自动续轮,直接破坏“模型自己决定何时停” |
| dsh-tool-ralph | 天生自我循环 |
| dsh-tool-subagent / dsh-tool-workflow / agent-team | 请求数成倍放大 |
| dsh-tool-todo | 会把人格拉向“干活” |
| dsh-tool-pwsh / dsh-tool-bash / dsh-tool-jobs / dsh-tool-terminal | 重型,与“更好的对话模式”定位冲突 |
| dsh-agent-instructions | 必须不挂,否则会去读 AGENTS.md,模型一上来就进入编码 agent 人格 |
| dsh-plan-mode | 与更好的对话模式无关 |
不用挂、base 已经有的
dsh-compaction-basic(长对话自动压缩)、dsh-fs-observation-policy(先读后写门禁)、dsh-repeat-tool-reminder、dsh-tool-call-timeout-policy、dsh-session-title 系列。
配置参数
maxRounds —— 唯一需要理解的参数
- id: preset-chat
name: '@deepseek-ai/dsh-agent-preset'
config:
id: chat
plugins:
- id: think-better-tool
name: 'file:///…/think_better/lib/index.js' config: maxRounds: 10 # ← 改这里
maxRounds 是每个用户轮次允许的思考轮数上限(每个 turn/start 清零)。它的行为:
| 第几次调用 | 工具返回 | 循环行为 |
| 1 … maxRounds-1 | 继续。(n/10,还剩 m 轮) | 再跑一步 |
| maxRounds | 已达思考上限(10 轮)。现在必须直接给出最终答案,不要再调用本工具。 | 再跑一步,模型在这一步作答 |
| > maxRounds | 思考已达 10 轮上限,本次回答到此结束。 + concludeTurn() | 本轮立即强制结束 |
净效果:最多 maxRounds 轮思考 + 1 轮最终回答,绝对收敛。
其它可调参数
| 行 | 参数 | 默认 | 说明 |
| think-better-tool | maxRounds | 10 | 见上 |
| persona | prefix | 见下 | 人设文本,可自由替换 |
| persona | suffix | '当前工作目录是 {{cwd}}。' | 见 为什么 suffix 不能留空 |
| persona | includeRuntimeContext | true | 是否注入运行时上下文(时间等)。设 false 提示词更干净,但模型不知道当前日期 |
| tool-web | fetch | true | 是否启用 web_fetch |
| tool-web | searchTimeoutMs | 60000 | 搜索超时 |
| tool-fs-search | sampleOverCapGlobResults | false | 必填(该插件的 Config schema 要求)。控制超出结果上限时是"跨顶层条目抽样"还是"保留前 N 条" |
改完 cordis.patch.yml 需要重启 DSH:HMR 只监听 profile 自己的 cordis.patch.yml 和 package.json,不监听 bundle 内部的 patch。
persona(可自行更换)
当前 persona.prefix 内容:
你是一位专业、耐心的对话助手,既能深入讨论专业问题,也能自然闲聊。
专业问题上:结论先行、依据清楚、不确定处直言不讳。
日常对话上:自然、简洁、不端着。
需要查证时使用联网搜索或文件工具,不做无意义的工具调用;简单问题直接回答。
推演不充分时调用 keep_thinking 继续思考,足够时立即作答。
这段文字可以按需要随意替换。 它就是 cordis.patch.yml 里 persona 行的 prefix,改完重启即可。
几点说明:
- prefix 会遮蔽部署级人设(Web 端默认是 You are a coding agent powered by the {{model}} model.),所以人格是被替换而不是被追加。
- 不要加 complete: true。complete 控制的是"除人设以外的东西还要不要":设了它,工具引导段落会被一并抹掉,模型更容易用错工具。这里要的是"换人格、留工具提示"。
- prefix 支持模板变量,例如 {{model}}、{{cwd}}。
- 想让它更像纯聊天机器人,可以把专业/严谨那两句删掉;想让它更严谨,可以加更多约束。
为什么 suffix 不能留空
suffix 默认是空字符串,而空后缀会遮蔽掉部署级的 Your working directory is {{cwd}}.。
运行时上下文里没有任何 cwd 提供方(packages/context/ 下只有 agent-instructions、file-reference、session-reference、time-context、tmux-context),也就是说 {{cwd}} 是工作目录进入模型视野的唯一通道。而本模式挂了 read / glob / grep / write 四个按会话 cwd 解析相对路径的工具——不知道 cwd,模型就只能等你给绝对路径。
所以这里要显式写一句:suffix: '当前工作目录是 {{cwd}}。'
安装
方式一:直接从 git 仓库安装(推荐)
dsh plugin --profile add https://github.com/zdjmrq/dsh-better-chat
DSH 的 install_bundle 原生支持 git 仓库 URL,pnpm 会克隆仓库并把它装进 profile,不需要先 clone、也不需要发到 npm。
想锁定版本就加 commitish:
dsh plugin --profile add "https://github.com/zdjmrq/dsh-better-chat#v0.1.0"
方式二:克隆后按本地路径安装
git clone https://github.com/zdjmrq/dsh-better-chat.git
dsh plugin --profile add ""
适合要自己改代码的场景——就地改,重装一次即生效。
方式三:Web 插件页
侧边栏 插件 页 → 安装组合包 → 填上面任意一种 spec(git URL 或绝对路径)。
三种方式装完都需要重启 DSH 才会看到新模式。
本地路径方式会创建目录链接(junction / symlink),那个目录不要删除或移动,否则 profile 启动时会跳过这个 bundle。
本插件没有发布到 npm:git 安装方式已经覆盖同样的效果,没必要多维护一个发布渠道。
为什么工具行在 preset 里面 cordis.patch.yml 里只有一行(preset-chat);keep_thinking 是它 config.plugins 里的一个子行,而且用绝对 file URL 而不是包名引入:
- id: think-better-tool
name: 'file:///E:/DeepSeekHarness_own_plugin/think_better/lib/index.js'
config:
maxRounds: 10
为什么不能用包名
用裸包名 think_better 时会失败,诊断是:
think-better-tool (think_better): never started
(never started 在 packages/preset/agent-preset-registry/src/mount.ts 中等价于「模块根本没解析成功」。)
因为那条允许 profile 本地包名的规则是层级专属的:
// packages/boot/app-boot/src/profile-resolution/resolver.ts
private routeLocalPackage(request, parentRoutes, resolution) {
...
if (name === undefined || layer.kind !== 'profile' || !layer.active
|| !resolution.localPackageNames.has(name)) return undefined
return { route: { kind: 'native' as const } } // 放行给 Node
}
只有 layer.kind === 'profile' 的导入方会走这条路,而 preset 的行挂在注册表拥有的内存子树里。
为什么 file URL 可以
绝对 file: URL 完全不需要包解析——Node 直接 import 那个 URL。而且 compatibility-preflight.ts 把这个情形显式写进了判断:
if (!isAbsolute(specifier) && !specifier.startsWith('.') && !specifier.startsWith('file:')) return undefined
所以这样的行会被当成普通行接纳。
真正的收益是作用域
工具行挂在 preset 里,ctx.tools.register() 就落在 preset 的作用域上:只有从「更好的对话模式」组合出来的 agent 看得见 keep_thinking,其它模式什么都不用摘。插件因此没有任何可见性逻辑——不监听 agent/created、不推断当前预设、不调用 tools.restrict()。
实测记录(把没验证的结论跟验证过的分开写)
- 用一个一次性的探针预设实测:preset 子树里按 file URL 挂一行,IMPORTED 和 APPLIED 都会发生 ✅
- 探针读到的 ctx.baseUrl 是 profile 目录(file:///…/profiles//),不是 app.asar。
- 这一点跟上面那条「裸包名不行」是冲突的:baseUrl 落在 profile 目录里,按 routeLocalPackage 的规则裸包名本该能解析。所以当初那次 never started 的确切原因没有定论(一个可能是当时 think_better 还没写进 profile 的 dependencies,于是 localPackageNames 里没有它)。
- 结论:file URL 是验证过可行的那条路;裸包名现在到底行不行,没测过。
顺带记录:切换预设的窗口
- 会话头里的 agentPreset 是创建时的冻结事实,不是当前值。agent-preset-registry/src/session.ts 的原文是:"reads the agentPreset Session projection, never the header alone"。
- select() 会拒绝已经开过轮的会话(抛 agent-preset/locked: This session has already started)。预设只能在第一次对话之前选,一旦跑过一轮就冻结——所以在旧会话里换不到「更好的对话模式」,只能新建一个。
这两条在旧版本里曾经是个坑(那时可见性靠「按会话头 deny、切预设再解除」,还会踩到 select() 的时序)。现在工具跟着配方走,可见性已经与预设身份无关。
插件列表里的显示名
插件页显示的不是包名,而是一份可本地化的显示元数据。取法(packages/boot/app-boot/src/package-meta.ts 的 readPluginMeta):
1. 先解析 /locale/en.json —— 这个文件是入口,没有它,其它语言文件根本不会被扫描;
2. 再扫同目录下所有 .json,文件名就是查表用的键(小写化:zh-CN.json → zh-cn);
3. meta.title / meta.description 取到就用;取不到则回落到 package.json 的 name / description;
4. 客户端 presentation.ts 是 title: pkg.meta?.title ?? pkg.name —— 所以包名和显示名是两回事。
⚠️ 文件名必须和 DSH 的语言 id 一模一样
这一步很容易错。 DSH 内置的语言 id 是 zh 和 en(packages/client/locale/src/locale-settings.ts:LOCALE_IDS = ['zh', 'en']),不是 zh-CN。
查表是按当前语言 id 做的(locale/src/client/index.ts):
resolveText(text) {
return this.fallbackChain(this.snapshot.active).reduceRight(
(resolved, locale) => text[localeKey(locale)] ?? resolved, // localeKey = toLowerCase()
text.en,
)
}
所以文件名写成 zh-CN.json 时,键是 zh-cn,而当前语言是 zh → 查不到 → 静默回落到英文。页面就会显示英文标题和英文描述,而且不报任何错。
本仓库因此同时放两个,覆盖 zh 和可能的 zh-CN 语言包:
// locale/zh.json ← 内置语言,主要就靠这个 // locale/zh-CN.json ← 兼容自定义 zh-CN 语言包 { "meta": { "title": "更好的对话模式", "description": "…" } }
// locale/en.json ← 入口文件 + 英文兜底 { "meta": { "title": "Better Chat Mode", "description": "…" } }
插件页上哪些能改、哪些改不了
| 页面元素 | 来源 | 能不能中文化 |
| 标题 | meta.title | ✅ |
| 描述 | meta.description | ✅ |
| 版本号 | package.json 的 version | ❌ 本来就不该翻译 |
| 包名(等宽字体那一行) | package.json 的 name | ❌ 原样显示(PluginManagerPage.tsx 里是 {pkg.name}),而且 npm 包名不允许中文,它同时是 dsh plugin remove 要用的句柄 |
两个前提,缺一不可:
- package.json 的 exports 必须放行这个路径("./locale/": "./locale/")——解析走的是 Node 的 ESM resolver,exports 不放行就等于没有这个文件(报 ERR_PACKAGE_PATH_NOT_EXPORTED,被当成“没配元数据”静默回落);
- files 里要有 locale,否则打包/安装时不会带上。
包名 think_better、行 id think-better-tool、模块名都不用动——显示名和它们是分开的两层。另外 package.json 顶层可以放 icon(相对路径,SVG/PNG/JPEG/WebP,≤256 KiB),会被内联成 data URL 显示在插件页。
元数据在启动时读取,改完要重启。
卸载
dsh plugin --profile remove think_better
本地自测
lib/index.js 的两个 harness import 被 test/stub-loader.mjs 顶替成桩,所以测试直接跑线上那个文件,不需要装 DSH:
pnpm test # = node --import ./test/register.mjs test/behaviour.test.mjs
覆盖:只注册一个工具、从不调用 tools.restrict()(可见性归作用域管,插件不该有可见性逻辑)、轮数计数与 turn/start/agent/disposed 的重置、每会话独立计数、maxRounds 行为、三档返回文案。
0.2.x 那版测的是「从会话日志推断当前预设 + 解除 deny」;那套逻辑已经删掉了,相应的断言也一起删了。
已知限制
- keep_thinking 的可见性由作用域决定,不由插件决定:工具行挂在 preset-chat 里,所以只有「更好的对话模式」的 agent 看得见它。插件里没有任何可见性逻辑,也不需要。
- 工具行用绝对 file URL 引入,所以换仓库位置、改目录名都要同步改 cordis.patch.yml 里那一行。
- 「更好的对话模式」的系统提示词不止人设那 5 行,工具也不止 11 个。 因为 persona.prefix 只遮蔽部署级人设、没设 complete: true,harness 的工具引导段落(read/grep/glob/web_search/present 的用法)会照常注入;Agent Teams 那一大段 POLICY 文字也会进来。实测一轮下发 25 个工具:本 preset 挂的 11 个,加上 agent-team 的 9 个(spawn_teammate/send_message/list_agents/wait_agent/interrupt_agent/team_task_)、schedule_ 4 个、load_workspace_dependencies 1 个。
- 这 14 个不是“忘了挂”,是本插件收不掉。 tool-agent-team 和 schedule 都在 agent/created 时把工具注册进 agent 自己的作用域(tool-agent-team/src/index.ts:const scoped = agent.ctx;schedule/src/index.ts:registerScheduleTools(ctx, agent.ctx, agent)),而 tools.restrict() 只能遮蔽全局工具——拿作用域内的名字去 restrict 会直接抛 unknown global tool。所以「刻意没有挂的」那张表管不到它们,“把 deny 列表做成配置项”也解决不了;要让「更好的对话模式」真的干净,只能在整个 profile 层面不挂 dsh-experimental-agent-team-profile / dsh-experimental-schedule-bundle(所有模式一起去掉)。这 14 个里只有 load_workspace_dependencies 是全局注册。(本插件现在不做任何 restrict,所以这条只是说明“为什么连做成配置项也收不掉”。)
- 已经被旧版本 deny 过的运行中会话,需要重启 DSH 后才会恢复(旧版把限制记录在插件内存里;现在改用作用域,重启后天然干净)。
- tool-fs 带写权限。想要只读,把会话权限切到 profile 里的 read-only 预设。
- keep_thinking 在对话记录里渲染为通用工具卡片。想做成定制的“思考”卡片,需要另写一个 Client 插件在 tool.call.toolview 槽位注册组件。
- 插件依赖 DSH 内部插件 id(@deepseek-ai/dsh-*)。DSH 升级后若某个 id 改名,需要同步更新 cordis.patch.yml。
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
zdjmrq/dsh-better-chat
像网页版一样聊天,模型会自己多轮思考再作答
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,489已汉化DSH
73.1
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,918已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,453已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
Download DS Bot for Windows 10/11 64-bit / 下载 Windows…
★ 5,293已汉化DSH
71.2
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,797已汉化DSH
71.1
这是你的仓库?认领条目