跳到正文
dsh-market 浏览插件 GitHub EN

drscrewdriver/dsh-date-wrapper

将 DSH 时间上下文从约 280 字符压缩到 46 字符,向运行期快照注入紧凑日期行,无运行时依赖。

Star 数 ★ 2 分类 会话与消息 收录于 2026-09-10 npm dsh-date-wrapper

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add dsh-date-wrapper

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

README

▼ DSH 版本适配

DSH 版本 加载 宿主契约 客户端半
0.1.0-rc.7 ~ 0.1.7.x(0.1.x 线) ✅ 产物 ≤ 0.2.0 systemPrompt.context({ name, order, text }) —(纯宿主插件)
0.2.0-rc.1+(>=0.2.0-rc.1 <0.2.1-0) ✅ 产物 ≥ 0.3.0 同一签名;packages/core/system-prompt 相对 dsh-v0.1.7-rc.2 的 diff 仅版本号一行 —(纯宿主插件)

一份契约覆盖所有版本线:插件只调用 systemPrompt.context,其签名与语义从 dsh-v0.1.1-rc.2 到 dsh-v0.2.0-rc.1 未变。它不注册设置命名空间、不读会话 数据、不发 RPC,因此 0.1.1 → 0.1.2 的客户端/会话/持久化重写与 0.1.7 → 0.2.0-rc.1 的宿主改动都与它无关。旧 0.1.x 宿主请使用产物 ≤ 0.2.0(dist-tag dsh-0.1.7);0.2.0 线由产物 ≥ 0.3.0 服务。

精简版时间注入:把 Current date: 2026-09-08 Asia/Shanghai Tuesday(46 字符 ≈ 12 token)挂进 DSH 自带的运行上下文快照。 不加载 @deepseek-ai/dsh-time-context,不产生额外会话消息,不改 DSH 源码,不提 PR。

这个插件解决什么

DSH 自带的 @deepseek-ai/dsh-time-context 每次请求注入约 280 字符的元数据:

Time sampled while preparing turn 3, step 2: 2026-09-08T16:05:36+08:00[Asia/Shanghai]
Browser time zone for this request: Asia/Shanghai. Interpret otherwise-unqualified dates and times in this zone.
Elapsed since the preceding model-visible message: 2m 34s.

本插件把同样的信息压成一行 46 字符,并且换了一个落点 —— 不再往消息流里塞:

Current date: 2026-09-08 Asia/Shanghai Tuesday
维度 dsh-time-context dsh-date-wrapper
注入文本 ~280 字符 46 字符(↓84%),约 12 token
落点 每条 pre-step 消息(user/message) 平台运行上下文快照(systemPrompt.context)
频率 每个 eligible step 一条 文本变化时随快照重发(同一天内 0 条)
依赖 agents 服务 systemPrompt 服务
运行时依赖 — 零

版本适配与兼容性

项 结论
目标 DSH 版本 0.1.0-rc.7 → 0.1.7.x(0.1.x 线 — 产物 ≤ 0.2.0)与 0.2.0-rc.1 → 0.2.0.x(0.2.0 线,engines.dsh: >=0.2.0-rc.1 <0.2.1-0 — 产物 ≥ 0.3.0)
settings API 不适用:本插件不注册 settings,也不导出 schemastery Config
使用的契约点 只有一个 —— systemPrompt.context()
与原生功能冲突 @deepseek-ai/dsh-time-context 功能重叠,不要同时使用。本插件默认不安装 = 默认关闭
client 半 无:不涉及 slot / DOM / CSS 语义 token
DSH 包 import 零:不 import 任何 @deepseek-ai/*,比「运行时检测 + 双 API 回退」更保守
契约点 0.1.0-rc.7 0.1.1-rc.2 0.1.2-rc.1 0.1.3-alpha.2 0.1.7-rc.2 0.2.0-rc.1
systemPrompt.context(ctx): () => void ✅ ✅(本机实装验证) ✅ ✅ ✅ ✅(相对 0.1.7-rc.2 diff 仅版本号)
PromptContext = { name, order, text },无 complete 字段 ✅ ✅ ✅ ✅ ✅ ✅
includeRuntimeContext / suppressRuntimeContext ✅ ✅ ✅ ✅ ✅ ✅
agent-loop project() 按文本去重、surfaceOp: "append" ✅ ✅ ✅ 未比对 ✅ ✅
order: 116 无碰撞(110 / 115 / 120 已占用) ✅ ✅ ✅ ✅ ✅ ✅

验证方式:npm pack @deepseek-ai/dsh-system-prompt@<版本> 解包后比对 lib/types/index.d.ts 与 lib/index.js;@deepseek-ai/dsh-agent-loop 同法。 dsh-v0.1.7-rc.2 与 dsh-v0.2.0-rc.1 之间,packages/core/system-prompt 的 diff 仅版本号一行,110/115/120 的 systemPrompt.context 调用点原位未动,插件迁移指南无任何 systemPrompt 条目。 运行时只在本机 0.1.1-rc.2 上验证过;0.2.0-rc.1 的运行时冒烟记录见 HANDOVER.md §7。

为什么用运行上下文快照,而不是消息

最初的做法是学 dsh-time-context,在 agent/pre-step 里追加一条 user/message。实测下来太贵:每条 JSONL 事件 339 字节(文本只占 46 字节,content 与 sections 各存一份),而它每轮都会写一条。

改成注册运行上下文后,日期并入平台本来就有的那条快照消息:

  • 平台对快照按文本去重(dsh-agent-loop 的 RuntimeContextProjection.project():if (this.retained?.text === snapshot) return),所以日期不变时一条事件都不多;
  • 快照是追加新消息(surfaceOp: 'append'),不是原地改写,请求序列只增长 → 不破坏前缀缓存;
  • 我们的边际成本只有那 46 字节,且只在快照因文本变化而重发时才被带上。

本机实测(一个 10 轮 / 231 步的真实会话):

项 实测
平台运行上下文快照 2 条,1133 B/条,共 2.3 KB
真实用户消息 10 条,396 B/条
旧做法(每轮一条消息) 10 条 × 339 B ≈ 3.4 KB
本做法增量 0 条额外事件,日期约 46 B 并入已有快照

配置

cordis.patch.yml 里随行下发,改完需重启:

- insert:
    - id: date-wrapper
      name: dsh-date-wrapper
      config:
        timeZone: Asia/Shanghai   # IANA 时区;缺省用进程时区
  • timeZone 非法会在启动时直接抛错(不静默降级成 UTC)。
  • 文本里的时区名就是解析后的 IANA 名(timeZone 缺省时取进程时区名)。
  • 运行上下文条目的名字是 date-wrapper:date,排序位 116(已占用:110 sandbox、115 approval、120 subagent)。
  • 本插件不导出 schemastery Config,所以配置不走宿主的 schema 校验,校验全部在 validateConfig() 里手写(这也是「设置 → 插件」页没有本插件配置表单的原因)。

开关:靠插件激活,没有面板开关

本插件不提供设置面板开关,也没有 enabled 之类的 config 字段。原因:

  • 功能开关 = 插件行是否激活。插件未激活 → apply() 不跑 → 运行上下文条目不存在 → 一个字都不会注入。
  • 本插件没有 client 半(无 dsh.client),界面上没有任何属于它的控件。
  • DSH 自带的 设置 → 插件 页面已经会显示每个条目的 已启用 / 已停用(只读,不能点)。

怎么关

在你自己的 profile patch 层里按 id 覆盖即可 —— C:\Users\<你>\.dsh\profiles\web\cordis.patch.yml:

- id: date-wrapper
  disabled: true    # 停用;改回 false 即恢复
  • 热生效,无需重启:该文件被 Cordis HMR 监听,disabled: true 会直接 dispose 该行的 fiber。
  • 若 date-wrapper 行还不存在(未安装),这条 patch 只会打一条 entry "date-wrapper" not found 警告,不会让启动失败。
  • ⚠️ 该文件必须是顶层 YAML 数组;写坏了会启动失败(DSH 对用户 patch 层是 fail-loud)。

怎么彻底移除

dsh plugin --profile web remove dsh-date-wrapper

卸载走 bundle 层,需要重启 dsh web 才生效(bundle patch 不热重载)。

安装

dsh plugin --profile web add github:drscrewdriver/dsh-date-wrapper

重启 dsh web 并刷新页面。本地路径 / 软链安装与排错详见 INSTALL.zh.md。

验证

# 怎么验证 期望
A1 新开一个会话,发一句话 运行上下文快照里出现 Current date: YYYY-MM-DD <时区> <星期>(会话里显示为一条注入上下文行,来源含 system-prompt)
A2 看该行文本 ≤50 字符(实测 46;PRD 原阈值 30,因用户指定格式放宽)
A3 停用插件(profile patch 置 disabled: true) 后续会话快照里不再出现该行
A4 搜索会话日志 没有 Time sampled / Elapsed since / Browser time zone
A5 把 timeZone 改成 UTC 并重启 日期按 UTC 计算(跨时区边界会差一天)

实现要点

dsh-date-wrapper/
├── package.json          # name / type: module / main / exports["."] / dsh.bundle.patch / files
├── cordis.patch.yml      # 一行 insert(无 patch 级 id → 落在 profile 根 = 宿主面)
├── src/
│   ├── format.js         # 纯函数:resolveZone / renderDate / createDateContextText / validateConfig / TEXT_LABEL
│   └── index.js          # apply(ctx, config) → ctx.inject(['systemPrompt'], …) → systemPrompt.context(...)
└── tests/
    ├── format.test.mjs   # 11 项(时区投影、星期、格式与长度、降级、配置校验)
    └── context.test.mjs  # 7 项(伪 ctx 断言注册契约)
  • 宿主面行:ctx.inject(['systemPrompt'], …) 建立子 fiber;服务缺失时静默不注册,而不是让整个 boot 失败。
  • fail-soft 的文本 provider:prompt 组装期抛错会让每一次请求都失败,所以渲染失败时返回空串(平台会过滤掉空文本)。
  • 不设 complete:设了会顶掉整份系统提示词。
  • 去重交给平台:不维护任何 per-agent 状态,跨天时快照自动带上新日期。
  • 生命周期:注册归属 ctx.inject 的子 fiber,插件停用时随 fiber 回收。

开发:TDD + lint

npm install          # 只装 devDependencies(eslint / @eslint/js),运行时零依赖

npm run tdd          # 监听模式:改 src/ 或 tests/ 自动重跑(node --test --watch)
npm test             # 单次全量:node --test "tests/*.test.mjs"
node tests/format.test.mjs   # 单文件直接跑(沙箱里最稳,不派生子进程)

npm run lint         # eslint .(src + tests + eslint.config.mjs)
npm run lint:fix     # 自动修可修的
npm run verify       # lint + test,提交前跑这一条

红-绿-重构

测试用例直接对应验收项,流程是「先写一条会红的断言,再让它变绿」:

步骤 动作 命令
1 红 在 tests/*.test.mjs 里写一条按验收项命名的断言,断言当前行为不满足的期望 npm run tdd
2 绿 在 src/ 里写最小实现让它通过,不动其它断言 npm run tdd
3 重构 保持全绿的前提下整理命名/抽纯函数;src/format.js 承担全部纯逻辑,src/index.js 只做注册 npm run tdd
4 闸门 提交前跑 lint + 全量测试 npm run verify

现有 18 条断言:format.test.mjs(11 条)覆盖纯函数,context.test.mjs(7 条)用伪 ctx 断言注册契约。

lint 配置要点

  • ESLint 10 扁平配置(eslint.config.mjs),@eslint/js recommended 为基线。
  • 收紧项:eqeqeq、prefer-const、object-shorthand、no-unused-vars(_ 前缀豁免)。
  • 显式声明 Node 全局 crypto / console / process,否则 no-undef 会误报。

已知限制

  • fixed-prompt preset 下不生效:若某个 preset 的 persona 设了 includeRuntimeContext: false(官方 minimal 与本地 simple-reply 都是),assemble() 会返回 contexts: [],本插件的条目会被整段丢掉。这类 preset 的设计意图就是「不允许后续 listener 往提示词里加东西」。
  • 旧快照会留在历史里:日期变化时平台追加一条新快照(旧快照保留),靠快照自带的 "This snapshot supersedes earlier runtime-context snapshots" 声明让最新一条生效 —— 这与平台处理 cwd / sandbox / approval 策略变化的方式一致。
  • bundle patch 不热重载:改 cordis.patch.yml 或升级插件后必须重启 dsh web(改 profile patch 的 disabled 是热生效的)。
  • 不加载也不过滤 dsh-time-context:若你在某个 preset 里显式挂载它,它的 verbose 文本会照常出现。不要同时使用。
  • 契约点未做运行时探测:systemPrompt.context 目前是裸调用,若 DSH 未来改名,表现为插件加载失败而非静默降级(待办见 HANDOVER.md §7)。

License

MIT

内容来自项目 README(GitHub)↗

评论

评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。