dsh-session-clock

sessionnpmMIT

Per-session clock injection with durable idle-gap tracking: tells the agent how long it has been since this particular conversation last spoke, which the host's time context (last message only) cannot.

下载量 / Downloads
471

Install

dsh plugin --profile web add dsh-session-clock

Sandbox test

This plugin has not been tested yet. Submit a test →

README

dsh-session-clock

给 DeepSeek Harness 的「会话时钟」插件——按会话授时,并给出跨轮、跨会话的空闲间隔。
定位是宿主内置 @deepseek-ai/dsh-time-context 的补充插件,不是替代品。

[English](README.en.md) | 中文

dsh-hot-reloader — 改完插件源码不用重启

dsh-session-clock — 按会话授时与空闲间隔(本仓库)

dsh-second-opinion — 卡住时把问题交给另一个独立会话,要一份第二意见

dsh-onebot-companion — QQ 通道一体化:出站沉默守卫 / 行为规则 / 对话节奏 / 人设 / 语音


一句话说明

DSH 内置的 time-context 已经很擅长「告诉模型现在几点、距上一条消息过了多久」。

本插件不重复它,只补三件它结构上做不到的事:

能力 · dsh-time-context(内置) · dsh-session-clock(本插件)

当前时间戳 · ✅ 每轮首步 · ➖ 不重复(full 模式下才复刻)

浏览器时区 · ✅ · ➖ 不重复

距上一条模型可见消息多久 · ✅ · ➖ 不重复

只给「指定会话」授时 · ❌ 对所有 agent 一视同仁 · ✅ sessions / exceptSessions 白名单

**/正则/、* 通配匹配会话** · ❌ · ✅

跨会话指针(任何会话上次活跃多久前) · ❌ 不感知会话边界 · ✅

距上一次「用户主动说话」多久 · ❌ 只算模型可见消息 · ✅ 排除定时/主动/工具触发的轮次

重启后间隔依然成立 · ⚠️ 依赖会话内事件 · ✅ 持久化到 $DSH_HOME/session-clock/activity.json

agent 主动查询(session_clock 工具) · ❌ · ✅

HTTP 状态观测面 · ❌ · ✅


为什么需要它

DSH 内置的 @deepseek-ai/dsh-time-context 每个 turn 的首步都会注入一条三行消息:

Time sampled while preparing turn 8, step 1: 2026-10-13T10:14:10+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: 2h 15m 3s.

第三行在每轮第一步其实已经等于「距上次对话过去多久」——因为 step 1 执行时本轮的

user/message 还没提交,基线落在上一轮最后一条模型可见消息上。这一点本插件承认并且

不去动它(这也是本插件默认 mode: supplement 的原因)。

但它有两个结构性缺口:

1. 它是全局的。 所有 agent、所有会话一视同仁,没法做到「只给这几个会话授时」。

在 QQ 群、定时任务、子代理混跑的场景里,token 花在了不需要的会话上。

2. 它感知不到会话边界。 它知道「距上一条消息」,但不知道「距别的会话上次活跃」,

也不知道「用户上次主动开口是多久前」(定时唤醒、主动搭话也会产生模型可见消息,

把这条基线冲掉)。

本插件就补这两点。注入格式刻意沿用与 time-context 完全一致的时间戳/时长写法

(2026-10-13T10:14:10+08:00[Asia/Shanghai]、1d 2h 3m 4s),两条注入放在一起不打架。


功能详解

1. 按会话授时

sessions: ['onebot-*', 'session-*']      # 白名单,支持 * 通配与 /正则/
exceptSessions: ['/^onebot-group-.*$/']  # 黑名单,优先级高于白名单
  • '*'(默认)等于全部会话。
  • 'onebot-' 匹配所有 QQ 通道会话;'/^session-36f4./' 走正则。
  • 非法正则自动退化为字面量匹配,不会让插件崩掉。

2. 跨轮与跨会话间隔

每条注入一行,形如:

Session clock for onebot-group-2000000002-mv40ioj5: previous user message 3d 4h 12m 9s ago; any session last active 12m 3s ago (session-36f403a5-...), turn 42.
  • previous user message ... ago:距上一次用户主动发言(不含注入消息、不含定时唤醒)。
  • any session last active ... ago:跨会话指针——任何一个被跟踪的会话上次动过是多久前,

括号里是那个会话 id。用来回答「我是不是刚在另一个窗口问过你」。

  • turn 42:本会话累计轮次数。
  • 各子句可用 includeUserGap / includeGlobalIdle / includeTurnCount 逐个关掉。

3. 持久化

状态写到 $DSH_HOME/session-clock/activity.json(默认 ~/.dsh/session-clock/activity.json)。

DSH 重启后内存里的会话对象是新的,但文件里的间隔基线还在,所以「距上次对话多久」

在重启后依然算得对——这是内置插件做不到的。写盘是延迟合并 + 原子替换

(tmp 文件 → renameSync),不会因为断电留下半个 JSON。

4. agent 可主动查询

注册了一个 session_clock 工具:

action · 作用

now · 本会话(或 session_id 指定)当前时间 + 各类空闲时长

list · 最近活跃的会话及空闲时长(limit 控制条数)

模型可以直接回答「我多久没来了」,而不必依赖注入。

5. HTTP 观测面

只在 loopback(127.x.x.x / localhost / ::1 / *.localhost)可访问,非本机一律 403:

方法 · 路径 · 作用

GET · /session-clock · 当前状态(enabled / mode / 计数 / 上次决策原因)

GET · /session-clock/list · 已跟踪会话及空闲时长

GET · /session-clock/logs · 环形日志缓冲(最近 300 条)

POST · /session-clock/toggle · 开/关注入

POST · /session-clock/flush · 立即落盘

POST · /session-clock/forget · 忘掉某个会话(body {"session": "<id>"})

/session-clock 里的 lastDecision 会告诉你上一次为什么没注入(例如

mode=supplement 只在首步注入)——这个插件每轮只补一条,错过首步就整轮静默,

没有这个字段会很难区分「没轮到」和「坏了」。


环境要求

前置插件

插件 · 版本 · 说明

@deepseek-ai/dsh-time-context · 0.2.0-rc.2 · 宿主内置。必须存在但不要改动它——本插件默认 supplement 模式与它并存(见「与 time-context 共存」)

time-context 由 @deepseek-ai/dsh-base 组合包提供,你不需要单独安装。

本插件不 import 它,只在语义上补它结构上给不出的维度。

注意:dsh-experimental-schedule-bundle 也会随包插入同一个 dsh-time-context。
profile patch 里请保持单点挂载,插第二份会导致每 turn 首步注入两条逐字相同的消息。

DSH 宿主

项 · 版本

DSH · 0.2.0-rc.2(实测于该版本)

Electron · 44.0.0

Node(宿主内嵌) · 24.18.1

V8 · 15.2

Cordis · 4.0.4

依赖的宿主服务与接口

依赖 · 必需 · 说明

ctx.sessions · ✅ · inject = ['sessions']。取当前会话、读事件流

ctx.sessions.snapshotEvents() · ✅ · 重建「距上次对话多久」的基线

ctx.on('session/event') · ✅ · 追踪每条消息的 time 字段

@deepseek-ai/dsh-llm 的 createUserMessage · ⭕ 可选 · 受控动态 import:try { ... } catch { undefined },拿不到就退回本地 deepFreeze({ id: randomUUID(), role: 'user', ... }) 等价物

webServer · ⭕ 可选 · 没有它插件照常注入,只是看不到 HTTP 观测面

ctx.reflect.provide('sessionClock') · ⭕ 可选 · 已用 try/catch 包裹,宿主没这个服务也不影响

零运行时依赖:只用 node:crypto / node:fs / node:path / node:url,

外加 ./time.js 与 ./store.js 两个自带模块。

状态文件

$DSH_HOME/session-clock/activity.json     # 默认;DSH_HOME 缺省时退回 ~/.dsh
  • 原子写(tmp + renameSync),格式 { version: 1, sessions: {...}, global: {...} }
  • MAX_RECORDS = 5000,超出时按 lastSeenAt 裁剪最旧的
  • 删掉这个文件 = 清空所有间隔记录(重启后间隔从零开始)

安装

支持的 DSH 版本:>=0.2.0-rc.2 <0.3.0-0(开发与验证所用为 0.2.1-rc.2)。

1. npm / 插件管理器(推荐)

dsh plugin --profile <你的profile> add dsh-session-clock

2. 从源码挂链接

git clone https://github.com/xfgil/dsh-session-clock.git D:\Plugins\dsh-session-clock
dsh plugin --profile <你的profile> add link:/绝对路径/dsh-session-clock

link: 方式的好处是改完源码不用重新安装。

3. 下载 Release 附件

在 Releases 页面下载对应版本的

源码压缩包,解压到任意目录,再用上面的 link: 命令挂进 profile。

装好后通常无需重启:宿主内置的 HMR 会监听到 profile 清单变化并自动

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::3,最后更新 2026-11-01

Links

GitHub · Homepage · npm

Same category