dsh-prompt-tuner

DSH PLUGIN记忆与知识

仓库 lzyyzznl/dsh-prompt-tuner

记忆与知识 L5 · 运行验证通过 安全审查:低风险 可信度:金 可安装插件
安装这个插件

为 DeepSeek Harness Web 界面提供提示词改写:一键把输入草稿优化成清晰可执行的提示词,支持预览确认、档位切换与撤销。

验证等级 L5 L5 · 运行验证通过
GitHub 星标 1 复刻 0 · 未关闭 issue 未标注
最近更新 2026-10-11 创建于 2026-10-03
README 30.3 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
dsh plugin --profile web add github:lzyyzznl/dsh-prompt-tuner
兼容 DSH 版本0.2.0-rc.2版本不匹配时安装会报错
Node.js 要求未标注来自仓库 package.json 的 engines 字段
前置依赖无需要同时安装的同级依赖
npm 包名未发布到 npm可用 npm view 查看包信息

能做什么

5 项功能
字段来自项目仓库与公开索引,中文说明由本站标注

dsh-prompt-tuner:DeepSeek Harness 输入框里的提示词改写插件

  • 一键改写输入草稿为清晰提示词
  • 预览卡片确认,可撤销与再改一次
  • 标准/精简/结构化/扩写档位切换
  • 设置页配置模型与思考强度
  • 默认跟随会话模型,零配置可用

适用场景

联网搜索代码评审

上游标签

deepseek-harnessdshdsh-pluginprompt-engineering

验证等级与安全审查

L5 · 运行验证通过
自动化流程结论,不是人工审核
验证等级L5 · 运行验证通过在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来
安全审查低风险静态分析结论,未标注不代表已通过审查
仓库健康度活跃按仓库活跃度与最近更新时间给出
可信度金综合仓库活跃度与验证结果

上面的结论来自上游最近一次自动化验证(2026-10-08): 同一套检查会在插件发新版后重跑,页面显示的是最新一次的逐项结果。

逐项检查结果

L1 · 已找到 ✓ 通过
  • L1.0_DEFAULTED_FROM_L3 由 L3 推定 默认通过——L3 安装规范已通过(全库 L3 扫描策略)
L2 · 结构化 ✓ 通过
  • L2.0_DEFAULTED_FROM_L3 由 L3 推定 默认通过——L3 安装规范已通过(全库 L3 扫描策略)
L3 · 安装规范 ✓ 通过
  • L3.1_INSTALL_COMMAND_PARSED 安装命令已解析 方式:安装规范解析
  • L3.2_DSH_VERSION_DECLARED DSH 版本已声明 方式:DSH 版本声明
L4 · 安装已测 ✓ 通过
  • L4.1_INSTALL_EXECUTED_CONFINED 受限沙盒内执行安装 方式:沙盒安装执行
  • L4.2_INSTALL_SUCCESS 沙盒安装成功 方式:沙盒安装执行
  • L4.3_ARTIFACT_CONFIRMED 安装产物已确认 方式:沙盒安装执行
L5 · 运行已测 ✓ 通过
  • L5.1_INSTALL_PASSED_SANDBOXED 沙盒安装通过 方式:沙盒安装执行
  • L5.2_WEB_BOOT_READY Web 启动就绪 方式:Web 启动
  • L5.3_HTTP_SERVED HTTP 服务响应 方式:HTTP 请求
  • L5.4_PLUGIN_INVENTORY_ACTIVE 插件清单中已激活 方式:插件清单查询

风险详情

  • 审查结论 通过
  • 结论说明 vet 静态分析未发现可疑行为,判定为干净(clean)。
  • 风险计数 严重 0 / 高 0 / 中 0
  • 风险详情 未发现严重或警告级问题。

仓库档案

记忆与知识
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方lzyyzznl仓库 dsh-prompt-tuner · 默认分支 未标注
分类记忆与知识knowledge
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言JavaScript仓库主语言
许可证BSD-3-Clause商用或二次分发前请确认条款原文
星标 / 复刻 / issue1 / 0 / 未标注收录时的数值,非实时
创建 / 更新2026-10-03 · 2026-10-11最后推送 未标注
本站收录2026-10-03首次进入本站目录的时间

README 全文

30.3 KB
作者原文,中文版优先;只做安全转义,不改内容

DSH 插件优化集合(dsh-prompt-tuner)

一个个人向的 DSH Web 插件集合:把日常真正用得上的优化做进输入框旁边,而不是只做一件事。目前五件:

  • ✨ 提示词改写(单一模式):把输入框里已经写好但还不够明确的内容,用一套内置默认提示词(或你自己写的那一份)改写为指向清楚、更有逻辑、可直接执行的提示词,再交给 agent;可把最近 n 条会话消息按时间正序一起拼进提示词,可选改写结果用中文还是英文,并可指定用哪个模型、思考到什么档位(默认跟随当前会话、不思考)。改写输出期间输入框里的发送被禁用(打字不受影响),结果落进输入框那一刻起才放开(见历史改进记录 · 提示词改写、优化期间锁住发送与改写自己的模型与强度)。
  • 💬 旁路提问(/btw):主任务跑着的时候,顺手问一个小问题——答案只浮在输入框上方,不写进主对话、不打断 agent(见历史改进记录 · 旁路提问)。
  • 🔔 任务完成通知:每个对话任务结束时弹一条系统桌面通知,标题取会话标题,正文先由你指定的模型把本轮回答压缩成一句能完整显示的话(这次调用的思考强度可配,默认关闭;也绝不把最后一条消息原样推出去)——压不进设置的长度才以 ... 结尾;宿主按平台分发——Linux 用 notify-send、Windows 用 PowerShell 通知、WSL 走 Windows(见历史改进记录 · 任务完成通知)。
  • 🏷 会话标题重总结:初始标题仍是会话的第一句话(DSH 自己写的,插件不动);此后每积累 N 条你的消息,用你指定的模型根据最近 N 条消息重写一次标题(长度上限与 N 都在设置页里调)。计数按历史会话长度,重启不会清零——长会话在启动时就会按历史长度补一次重总结;composer 工具行还有一个「重建标题」按钮,随时可以跳过轮数立刻重写,成功与失败都会写进会话日志留痕(见历史改进记录 · 会话标题)。
  • 🛣 供应商熔断与顺序切换(已拆成本地独立服务):某个供应商任何失败都在原路由上重试 N 次,用完即熔断,按顺序表切到下一个可用供应商(不必等原供应商的退避);冷却时长随连续熔断次数递增,成功一次归零;到期后按所选方式恢复——默认 probe:先放行一次探测请求,成功才真正切回,也可选 immediate。这一半不再跑在插件里:插件只负责把它作为独立进程拉起来,顺序表、供应商与密钥、熔断参数都在服务自己的页面上改,插件设置页的「路由」页签变成只读状态 + 跳转链接。服务对外是一个 OpenAI 兼容的本地代理(默认 http://127.0.0.1:8790/v1),所以本机任何 agent 都能用,不限于 DSH。它还带一个可注册的协议转换器接口,内置的 maas 转换器把 ZTE 网关那两个模型(maas-dsv4/deepseek-v4-flash、maas-coclaw/co-claw)的出入参对齐到 api.deepseek.com 的契约(见路由服务与历史改进记录 · 路由服务与 maas 转换器)。

所有模型调用都在宿主进程里发生:浏览器不接触凭据,也不直接调用任何 provider;桌面通知同样由宿主按平台派发;熔断状态也只活在宿主进程内存里(不落盘、不写会话)。

> 包名、路由前缀(/dsh-prompt-optimizer/*)、设置与旁路历史文件名、dspo- 类名前缀等标识符保持不变:它们是已装实例与用户设置的引用点,改名会丢配置或需要重装,不属于定位更名。

入口

插件占四个座位(五个注册入口),没有自己的面板(集合里的每个功能各占一格):

座位 内容
conversation.input.left 工具行里的 ✨ 优化提示词 按钮与一行状态(Alt+O 等价);同排的 💬 旁路提问 按钮(Alt+B、斜杠命令 /btw 等价)。改写输出期间它还会把输入框自己的发送按钮握在关闭状态(编辑器照常可打字),见优化期间锁住发送。
conversation.input.dock 改写预览卡片:原文与结果并排、模型标注的待确认、采用/撤销/再改一次/关闭。
conversation.input.overlay 旁路提问浮层(刻意不是模态框,主对话仍在后面继续跑)与一个不可见的完成通知座位。
settings.section 「插件优化集合」设置页(5 个页签)。

界面示意(浮层与卡片的实际样子)见历史改进记录 · 界面。

设置

设置页按功能模块分成 5 个页签:优化提示词 / 旁路提问 / 标题 / 通知 / 路由。改写功能只占「优化提示词」一个页签:它没有任何模式开关,页签里只有该功能真正暴露的五项(优化用的模型 + 改写的思考强度 + 自定义提示词 + 改写结果的语言 + 携带最近会话消息);模型默认「跟随当前会话」、强度默认 off,不填就是零配置行为。四个用到模型的功能(改写 / 旁路提问 / 标题 / 通知)都各自可选模型并各自可选思考档位,互不影响;固定了改写模型后,改写也不再走「路由」页签的熔断切换(那条链路只接管会话自己的模型调用)。「路由」页签不再编辑任何东西:配置与熔断状态都在独立服务里,这个页签只显示服务的地址、存活状态、实时的熔断表与最近的切换记录,并提供跳转到服务自身页面的入口——两处都能改同一份配置就会漂移,所以这里只读。

配置文件:$DSH_HOME/prompt-optimizer.json(默认 ~/.dsh/prompt-optimizer.json),设置页底部显示实际路径。

{
"systemPrompt": null,
"recentMessages": 8,
"outputLang": null,
"provider": null,
"model": null,
"reasoningEffort": "off",
"btwContextTurns": "all",
"btwContextCount": 8,
"btwSaveHistory": true,
"btwProvider": null,
"btwModel": null,
"btwReasoningEffort": "off",
"notifyOnComplete": true,
"notifyMaxChars": 120,
"notifyProvider": null,
"notifyModel": null,
"notifyReasoningEffort": "off",
"titleProvider": null,
"titleModel": null,
"titleReasoningEffort": "off",
"titleRerollTurns": 100,
"titleMaxChars": 24
}

每个设置项的逐条说明在历史改进记录 · 设置页,已移除的旧键如何处理见历史改进记录 · 配置文件与已移除的旧键。

思考档位发到网关上是什么:插件自己只声明标准的 reasoningEffort,不发任何网关私有字段(profile 里那两条 MaaS 路由的 reasoningEfforts 仍然有效)。而经过路由服务的调用,转换器会进一步把入参按参照契约翻译:thinking: {type: 'disabled'} 落成 reasoning_effort: "none",thinking: {type:'enabled', budget_tokens} 落成就近的档位,max_completion_tokens 折成 max_tokens,response_format: json_object 按官方的前置条件校验;出参则把 reasoning 改名为 reasoning_content、摘掉网关常驻的空字段、补齐 usage 与 system_fingerprint。判据是实测而不是文档,逐条对照见路由服务。

路由服务(独立进程)

熔断与路由不再属于插件运行时,而是一个本地独立服务:lib/service/。插件只做三件事——在插件激活时把它 fork 起来(没在跑的话)、
把设置页的「路由」页签指向它、把三个按钮(探测 / 清空熔断 / 刷新)转达过去。没有任何熔断状态留在插件进程里,也没有第二份实现。

它对外长什么样

面 地址 说明
OpenAI 兼容 POST http://127.0.0.1:8790/v1/chat/completions(GET /v1/models) 把任何 OpenAI 客户端/agent 的 baseURL 指过来即可;对外只服务三个模型名 auto / peak / off-peak,入参出参按参照契约(见下)
管理页 http://127.0.0.1:8790/ 配置供应商与密钥、顺序表、熔断参数;看实时熔断表、最近切换与统计
管理 API POST/GET http://127.0.0.1:8790/admin/api/{state,config,reset,probe,models,keys/restore,converters} 管理页用的接口,需要 X-Router-Token(页面自带,令牌在配置文件里)
存活 GET /healthz 插件用它判断该接入还是该拉起

只监听 127.0.0.1,不做鉴权面之外的暴露。/admin/api/* 需要令牌:一个用户随手打开的网页可以对 127.0.0.1 发跨源 POST,
但不该能改路由或读到(掩码的)凭据。/v1/* 不需要,因为它只对本机开放,而它持有的凭据本来就已经在这台机器上。

接入方式

自己把本地模型地址指过去就行,插件不会替你改 profile:

// 以 DSH 的 pi-ai provider 为例(也可以改用任何 OpenAI 客户端)
"local-router": {
"api": "openai-completions",
"baseURL": "http://127.0.0.1:8790/v1",
"models": [{ "id": "auto" }]
}

北向只服务三个模型名,且它们选的是「时段语境」而不是某一行:调用方不需要知道(也无从影响)里面有哪些供应商和模型,选中谁是路由规则的事。GET /v1/models 就广告这三条,管理页「路由」页签与插件只读页签也列出它们。

model 用哪张顺序表 什么时候用
auto 日历决定:高峰表或低谷表 默认。调用方不想操心时段
peak 强制高峰表 调用方自己知道这单就该按高峰试序走
off-peak 强制低谷表 批量/不着急的活,明确想走空闲时段那张表
  • 点名语境有效,点名内部行无效:peak / off-peak(offpeak、大小写与首尾空白都算同义词)会压过时钟,直接用对应的那张表;除此之外没有任何「按名字匹配到某一行」的入口——写 deepseek-v4-flash、写 maas-dsv4/deepseek-v4-flash、写错、甚至不写,一律当 auto 服务(不是被拒绝),并记一条 warn 日志,方便发现过期的客户端配置。
  • 点名的表是空的就退回 auto:不报错、也不静默换到另一张表;只有当两张表都空时才 503(no route is configured)。
  • 回显是服务时的那个规范名:非流式响应与每个 SSE 分片的 model 只可能是 auto / peak / off-peak,绝不泄漏实际作答的供应商/模型(想看实际走了谁,去管理页或 /state,那是运维面)。
  • 当前时段(高峰/低谷)的那张顺序表就是候选池:它决定先试哪一行,之后按排好的顺序往后走,回绕——顺序表是池子加偏好,不是单向链表。切换对调用方透明:只要上游还没吐出第一个字节,失败的那一跳不会出现在响应里。
  • 回显也是 auto:非流式响应与每个 SSE 分片的 model 一律是 auto,不会泄漏实际作答的供应商/模型(想看实际走了谁,去管理页或 /state,那是运维面)。
  • enabled: false(纯代理):规则仍然决定先试哪一行,但只打一次、不重试也不记熔断。

转换器

服务提供一个注册接口,转换器是代码模块(lib/service/converters/),在配置里按 id 列出来即可:

defineConverter({ id, label, match, toUpstream, fromUpstream, fromUpstreamChunk, errorBody, listModels })

只有 id/label 是必填,其余缺省都是原样透传——所以「没注册转换器的路由」行为不变。这么设计是因为转换器要改的是流式 SSE 的增量、
要合成的 usage、要重写的错误体:那是状态机,不是替换表,声明式规则表达不了。内置一个 maas 转换器:

轴 参照契约(api.deepseek.com) ZTE 网关 转换器怎么做
思考开关 thinking: {type: 'disabled'\|'enabled', budget_tokens} + effort 忽略 thinking;认 reasoning_effort(none 真的关) 翻译成 reasoning_effort,并把 thinking/effort 从上游请求里删掉
输出上限 max_tokens(含思考 token) 两种都认 max_completion_tokens 折进 max_tokens
response_format: json_object 提示词里没有 "json" 就 400 无条件接受 强制参照契约的前置条件(这是唯一一处比上游更严)
思考正文 message.reasoning_content message.reasoning 改名
思考 token 数 总是上报 co-claw 上报,deepseek-v4-flash 不上报 没思考就写 0;思考了但上游没报就省略,不估算
model 回显 请求的名字 后端名(DeepSeek-V4-Flash-0731) 一律写成 auto(内部模型不外泄)
usage 细节 prompt_cache_hit_tokens / miss_tokens prompt_tokens_details.created_cache_tokens 等 归一到参照契约;网关多出来的计数器丢掉
system_fingerprint 有 有(vllm-…) 原样透传,没有时按 provider+后端名合成
错误体 {error: {message, type, param, code}} vLLM 自己的形状 按状态码重写
未知字段 — — 一律原样透传,不丢数据

转换器会把思考档位缺省成一个明确的默认:调用方什么都没说时,按路由规则登记成 reasoning_effort: "max"(缺省 = 思考,两条路由都按这一档运营),要关思考只能显式传 none(各种拼法都归一成 none,模板开关同步为 false)。它保证的是「显式控制两边同义,没说就默认思考」。逐条实测见历史改进记录 · 路由服务与 maas 转换器。

配置与密钥

配置在 $DSH_HOME/router-service.json(默认 ~/.dsh/router-service.json,0600),由服务的页面读写。首次运行会从插件的旧设置里
把顺序表搬过来,并预置两条 MaaS 路由的地址——但不预置任何密钥,密钥要你自己在页面上填。服务不会去读 DSH 的凭据库。

一个供应商可以配多把 key,每把有自己的稳定 id、标签和密钥。稳定 id 是刻意的:熔断、失败计数、拉黑都按这个 id 记账,
所以轮换密钥不会丢掉它已有的熔断状态,也不会把两把 key 的状态混在一起(按明文或按掩码认领都会——掩码会撞)。旧配置里的
单个 apiKey 会被读成一条 key(id 固定为 k1),所以老文件照常能用。

页面上留空即保留已存密钥:服务从不把明文回传给页面,只回掩码,所以"不改密钥"只能是留空;填入新值即覆盖,从列表里删掉即删除。
请求头仍然是一个字符串值的扁平 JSON 对象,直接合并进上游请求。

每个模型可以单独覆盖上下文窗口:GET /v1/models 给三个语境名各报一个 context_window(取各自候选里最小的那个),取值顺序是
管理页填的窗口 → 上游 GET /models 自己声明的窗口 → 100 万 token 默认。ZTE 那两个网关的 /models 是 404 不报窗口,
所以不填的话它们和直连官方的小窗口模型都按 1M 报——想要真实数字,就在供应商区块的「上下文窗口」里给对应模型填一个:窗口留空 =
用上游发现的值(都没有才落到 1M 默认),把整行删掉再保存 = 清掉覆盖回到默认/发现。窗口存在配置(providers..contextWindows)里,
页面保存时校验 1–100,000,000 的整数。

熔断:颗粒度在 key,不在供应商

  • 切换颗粒度是 key:某个 key 失败时,先在同一供应商的其它 key 之间切换;只有该供应商所有 key 都不可用,才轮到顺序表里的下一家。
    无密钥的供应商(本地 Ollama 这类)仍然是一个单位,行为与从前一致。
  • 只有该记账的失败才记账:失败先被分类(lib/service/failure.js)。请求本身写错(400/404/422…)、模型不存在、调用方自己取消——
    这些是调用方的问题,一次都不计,否则一个坏客户端就能把健康的供应商熔断掉。5xx/超时/传输错误算 retryable;
    429/503/529 算 overloaded,当次即熔断(上游已经在说"慢点",再等一次确认只是多花一个请求)。
  • 凭据死了就摘掉,不是冷却:401 / 402 / 403 是回答而不是抽风,它们进拉黑表——该 key 之后被完全跳过(不再向上游发请求),
    直到你手动恢复、或上游给了恢复时间到期、或那把密钥被轮换/删除。把它们交给冷却式熔断,只会得到"永远在重试一把废掉的 key"。
  • 双阈值:连续失败到 failureThreshold(默认 2,且"连续"限定在窗口内,隔一周的两次失败不算)或窗口内失败率到
    failureRateThreshold(默认 0.7,且至少要有 minSamples 个样本才让比例说话)。前者在低频使用下也能生效,后者抓"时好时坏"。
  • half-open 是租约:冷却到期只放行一次探测,halfOpenSuccesses 次连续成功才闭合;探测失败立刻重新熔断且冷却升级
    (cooldownMs 起、每轮乘 cooldownFactor、封顶 cooldownMaxMs)。上游给了 retry-after 就用它的时长,但仍受同一个上限约束。
    探测一结束就交还租约(成功、被忽略的失败、转换器拒绝、调用方中途取消都算),否则"两次确认"会变成"两次确认相隔一个冷却"。
  • 候选全部用完时,回写最后一个上游答案:上游真的答了 4xx/5xx,就把它自己的状态码与错误体(经转换器对齐契约)交给调用方——
    "这个模型不存在"、"余额不足"是可行动的,换成服务自造的 503 恰好抹掉了唯一能用的信息。反过来,超时、连接断开、200 但 body
    不是 JSON 这些不是"上游的答案"
    ,它们拿到的是服务自己的 502 错误体(带具体原因),绝不把不可解析的字节透传给调用方。
    真正没有候选(没有路由、供应商未配置、所有凭据都被拉黑、所有候选都被熔断跳过)才回 503。
  • 顺序表里的模型列是可手填的下拉:选项来自该供应商的手工模型列表 ∪ 从 GET {baseURL}/models 拉到的列表。页面上的「刷新模型」
    按钮会真的去问上游(零 token,顺便验证凭据),结果记在运行态里,重启后仍在。手工列表可以留空(只有一条不拦保存的提醒):
    留空的含义是"以上游拉到的为准",这也正是新建供应商唯一合理的第一步——一个还没保存的供应商根本无处可拉。

高峰/低谷:排序就是两张可拖动的顺序表

时间路由没有数字、没有开关、没有时间窗口——排序本身就是优先级。路由页签上是两张一模一样的顺序表,分别叫
「高峰顺序」与「低谷顺序」:用鼠标拖动行(或点行首的 ↑↓ 按钮)调整顺序,谁排在前面谁更优先,同样也是失败切换的顺序;改完保存立即生效。

  • 只判定一次「高峰 or 低谷」,然后当场选表:判定条件是「今天算不算工作日」+「现在在不在 09:00–12:00 /
    14:00–18:00 之间
    」(北京时间,固定 UTC+8,不看进程时区)。两个都满足才是高峰,其余全部是低谷:非工作日全天、工作日的
    午休 12:00–14:00 与夜间 18:00–09:00。此刻是哪个语境,就用哪张表当候选链(页面顶部与 /state 都写着
    「当前=高峰/低谷(时刻)→ 实际试序」,并注明这次是谁判的、为什么)。
  • 排前面 = 更优先:候选链就是当前表的行序,第一行最先试,失败后按行序往下切;整张表仍是候选池,走完回绕、对调用方透明。
  • 不在表里 = 该时段不试:把一家供应商从某张表里删掉,就是它在那个时段被「停用」——没有数字档位、没有单独的开关,删除是唯一的停用方式。
  • 两张表拖成一样 = 时间无关:这就是旧版那单一顺序表的行为;想忽略峰谷,把两张表拖成一样即可。
  • 迁移:老文件的 router.order 读成「低谷顺序」;老 router.timeSlots 的档位表迁移成「高峰顺序」(档位 1…9 升序排前、0
    剔除、没档位就复制低谷表);老 timeSlots / businessRule 的写入会被大声拒绝,提示改成 peakOrder / offPeakOrder。
  • enabled: false(纯代理):仍然按当前表的行序选第一行,只打一次、不重试也不记熔断。
  • 可核对:/state 与 /admin/api/state 返回 timeSlot: { flavor, status, calendar, order: { offPeak, peak } }——flavor 是此刻的峰谷
    判定、order 是两张表,status 带北京时间的 { status, weekday, minutes, weekend, holiday, date, workday, makeup, source, info }
    (workday = 计费意义上的高峰日、makeup = 调休上班的周末、source = 这次判定由谁给出),calendar 是日历层自身的状态
    (缓存条目、来源、最近一次失败)。
    插件设置页「路由」页签只读展示同一句「当前=高峰/低谷 → 实际试序」加一行「日历判定」。

图片输入:带图的请求只走「图片」行,当前表一行都没有就报错

各家网关能力不均匀——maas 那几行现在都不吃图片,只有直连官方的行是多模态。所以顺序表的每一行多了一个「图片」勾选框
(行级能力,存成 vision: true),带图片的请求只在这些行里挑:

  • 不带图 → 按原规则走:正常按当前时段的顺序表试,一行不漏。
  • 带图 → 收窄到「图片」行:只在当前表里勾过「图片」的行里按序试(熔断/重试/切换照旧),排在前面的非图片行会被跳过。
  • 当前表一行「图片」都没有 → 400:错误信息点名是哪个时段缺能力(peak / off-peak),不跨到另一张表去找人、也不落到会拒图的
    模型上。比如现在高峰表只有 maas-dsv4 / maas-coclaw,高峰时段带图请求就会明确报错,直到你把官方那行也排进高峰表。
  • 图片的判据:任一消息的 content 数组里含有 {type: "image_url"} 部件即算(参照契约里纯字符串 content 装不了图)。
  • 插件只读页签里支持图片的行带 🖼 标记,并有一行「图片行」列出当前能吃图的行;管理页「路由」页签每行一个勾选框,勾完保存立即生效。

口径以 DeepSeek 的峰谷计费为准:调休上班的周末、法定节假日全天都算空闲时段

这条是参考方的规则,不是我们发明的:DeepSeek API 的峰谷说明里,调休上班的周末与中国法定节假日全天均按空闲时段计费。
所以这里的「工作日」指的是计费意义上的高峰日,不是「政府说这天上班」:

  • 周末一律低谷,哪怕它是调休上班的周六——那一天人们确实在上班,但价格表仍按空闲时段算,路由就跟着低谷走。
  • 法定节假日全天低谷,落在工作日也一样。
  • 只有「普通工作日 + 在 09:00–12:00/14:00–18:00 之内」才是高峰。

两个事实、两个来源,都在 lib/service/calendar.js 里:

  • 今天是不是周末:纯日历算术,不容商量,任何来源都改不了它。
  • 这个工作日是不是法定节假日:这是内置表最弱的一环(手写清单、不知道明年的安排、写错一个日期会静默算错价),所以去问公开的
    工作日接口(https://www.iamwawa.cn/workingday/api?date=YYYY-MM-DD,返回 is_workingday)作为修正层。

也就是说:接口能把高峰从某个工作日拿掉,但绝不能把高峰给一个周末。接口说某个周末上班时,那个事实被记在 makeup
字段里(makeup: true),页面会写明「补班周末:调休上班的周末按空闲时段计费,故按低谷处理」——不写清楚,一条「周六 = 低谷」的
日志看起来就像 bug。

三条硬规矩:

  • 一天一问:每个北京日期最多请求一次,结论缓存在运行态文件 $DSH_HOME/router-service.state.json 的 calendar
    字段里;服务重启直接读盘上的结论,不再打扰接口(那个接口几次调用后就会限流,status: 0 并提示 48 秒)。
  • 失败就退回内置表,绝不猜测:没网、超时、HTTP 错、返回不是 JSON、被限流、答的是别的日期——一律回退到内置日历(lib/service/time-slots.js
    的 STATUTORY_HOLIDAYS + 周末判断),并在 /state 的 timeSlot.calendar.lastError 里如实写出来;失败后还有 30 分钟退避,
    不会被自己的重试打爆。想彻底离线(自检、内网机器)就把 startService({ calendarFetch: null }) 传进去。
  • 绝不阻塞请求:路由判定读的是同步的 calendar.status(),网络刷新是服务启动时和每 60 秒的一次后台动作;所以最坏情况下
    只是「新的一天开头一小段时间还用内置表口径」,永远不会有一个请求在等接口。

内置表是兜底而不是装饰:接口不认的日期(比如表外年份)、或者接口整个不可用时,判定完全由它给出——内置 2025–2026 的常见节假日
区间(元旦 / 春节 / 清明 / 劳动节 / 端午 / 中秋 / 国庆),依据是国务院每年公布的放假安排,跨年时按新公告更新
lib/service/time-slots.js 里的 STATUTORY_HOLIDAYS;表外年份一律按「非节假日」处理,也就是只按周末判定。接口答得上来的日子里
以接口为准(内置表把某天列成假、接口说那天上班,就按上班算)。页面与 /state 会明确标出这次判定是 source: 'api'
(外部工作日接口,带 info 名称,如「国庆节后补班」)还是 source: 'builtin'(内置表兜底)。

运行态与配置是两件事

配置是人的意图(页面保存时不可接受就拒绝,不悄悄改),运行态是运行时的事实(拉黑表、已发现的模型、当天的工作日结论),放在
$DSH_HOME/router-service.state.json(0600,原子写)。分开的理由很实际:运行态由服务自己写,如果和配置同文件,服务就会去改一份
你可能正在手编的文件;而且一份坏掉的运行态绝不应该让服务起不来——配置那边"写时拒绝"的规则在这里不适用。

改供应商,路由表跟着改

顺序表是针对某一个供应商集合写的,所以增删改供应商时服务会对账这张表:provider 已经不在、或它所用的模型已经不在该供应商
可用模型里的行会被移除,并在保存的返回值里报告删了哪些行(页面会提示,不静默)。反过来,供应商只声明了空模型列表时不删任何行——
空是"未知"而不是"没有",在那里猜会删掉用户有理由写的行。

生命周期

服务由插件 fork,随 DSH 退出而停。这是刻意的取舍:换来的是零手工步骤。想让它活过 DSH 重启,本机已有现成的约定——
systemd-run --user --unit= node <插件目录>/lib/service/main.js(dsh-remote-gateway 就是这么做的);
服务本身不关心是谁拉起它的,插件发现端口上已经有服务在跑时会接入而不是再拉起一个。

自检

npm run check:service   # 458 项:桩上游 + 真服务 + 真 socket,离线、零 token
npm run check:ui        # 115 项:管理页(假 DOM 跑真脚本),离线、零 token
npm run check:live      # 28 项:对真实网关的端到端实测,需网络与密钥,非离线自检

覆盖转换器的入参/出参映射、熔断与切换、重试、坏响应、管理面鉴权、配置校验与迁移、转换器注册表、SSE 解析、按时段选路与三个对外模型名、以及插件真的能把它拉起来并转达。
另有 npm run check:live:对真实网关的端到端实测(28 项,需要网络、需要你自己在凭据库里配好那两个 ref,会花真实 token),所以它故意不进 npm run check;结论记在历史改进记录里。

安装

dsh plugin add github:lzyyzznl/dsh-prompt-tuner

仓库根有 cordis.patch.yml(一条 insert),package.json 声明 dsh.bundle.patch 与 dsh.client.platform=web;不含构建步骤,lib/ 即源码。

npm run check        # 自检(858 项),不需要本机装 DSH
npm run eval:prompt  # 三臂盲评:只打印计划,加 --live / --judge 才发真实请求
npm run eval:attribution  # 归因审计:读已有运行记录,量「改写加了什么用户没提的东西」

文档

  • 历史改进记录:每个功能的设计取舍与固定行为、实测延迟与失败阶梯、与其他同类插件的差异、架构与文件职责、自检覆盖范围,以及全部已知限制。
  • 内置提示词的依据与实测:默认提示词为什么是这六步、三臂盲评的方法与数字、归因审计(改写里有多少东西是用户没提的)的口径与结果,以及中英两条输出路径的对照与偏差。
  • 通知路径的实测记录:Windows toast 派发的实测与推断边界。

许可

BSD-3-Clause。

常见问题

7 问
答案由本站依据条目字段整理,不引用上游原文
dsh-prompt-tuner 怎么安装?

在 DSH 里执行 `dsh plugin --profile web add github:lzyyzznl/dsh-prompt-tuner` 即可。

dsh-prompt-tuner 的验证等级是什么意思?

L5 · 运行验证通过。在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来

dsh-prompt-tuner 安全吗?

低风险。vet 静态分析未发现可疑行为,判定为干净(clean)。

dsh-prompt-tuner 支持哪些 DSH 版本?

上游记录的兼容版本包括 0.2.0-rc.2。

dsh-prompt-tuner 用的是什么许可证?

上游标注为 BSD-3-Clause。商用或二次分发前请到仓库确认许可证原文。

dsh-prompt-tuner 有哪些功能?

一键改写输入草稿为清晰提示词、预览卡片确认,可撤销与再改一次、标准/精简/结构化/扩写档位切换、设置页配置模型与思考强度、默认跟随会话模型,零配置可用。

这条记录的数据可靠吗?

本站按仓库名去重后合并整理,字段以作者仓库与 npm 元数据为准;安装命令、仓库地址与 README 保持原文,带 L4 / L5 标记的安装命令已在隔离沙盒里真实跑通。

记忆与知识
按星标排序,可作替代方案

ruflo

ruflo

L3 · 安装规范通过 7.4 万 星

OpenViking

OpenViking

面向 DeepSeek Harness 的 OpenViking 记忆与上下文插件:pre-step 自动召回与画像注入、会话捕获、`vik

L3 · 安装规范通过 3.9 万 星

WeKnora

WeKnora

把 WeKnora 知识库接入 dsh 的四个只读工具:列出知识库、混合检索原文片段、按顺序还原单篇文档,以及直接取用 WeKnora 自己

L4 · 沙盒安装通过 3.3 万 星

distilly

distilly

Distilly — Distill how they think into reusable Skills for any Agent o

L4 · 沙盒安装通过 2.5 万 星

EverOS

EverOS

L4 · 沙盒安装通过 1.3 万 星

MemOS

MemOS

L4 · 沙盒安装通过 1.2 万 星

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 2026-10-08。