DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

jonah791 /

jonah791/dsh-session-handoff

Verified

This plugin has no description yet.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: master@b22e77b2

dsh-session-handoff

version license TypeScript tests

会话自动衔接:新建会话时,自动把「上一场会话」的尾部对话注入为一段交接材料,使新会话不必从头解释上下文。

快速开始

1) 装依赖(在目标 profile 的 package.json 加 link 依赖):

"dsh-session-handoff": "link:E:/alice/self-plugins/dsh-session-handoff"

2) 挂组合:

- id: dsh-session-handoff
  name: dsh-session-handoff

3) 30 秒验证:新建会话 → 首轮上下文里应出现上一场的尾部对话(仅在存在新鲜对话时注入)

解决的问题

一场会话卡住/中断/上下文过载后,新开一场就丢失了「刚在做什么、卡在哪、下一步是什么」。手工复述既费时又容易漏。本插件把这件事变成自动的、可核查的一行注入。

它做什么

  • 监听 session/created({ global: true }),只对真正的新会话生效:子代理会话、fork 子会话、重启时恢复的历史会话一律跳过。
  • 取该会话的 scope key(carrierKeyOf(this)——事件的 this 是 routing-only 载体,没有 Context API),找到同工作目录、窗口内最近的一场有真实对话的会话。
  • 摘录它尾部的若干条 user/assistant 文本(不调模型、不做摘要生成,成本为 0 且可复现),渲染成一段交接块。
  • 交接块经 systemPrompt.context 落为动态上下文快照:全局注册一次,text 按本次装配的 AssembleContext.scope 查表返回——未命中的会话拿到空串,而「空文本不贡献任何内容」是 PromptContext 的既定语义 ⇒ 只影响被衔接的那一场会话。

交接块首行显式声明它是历史材料、不是新指令——衔接内容来自上一场会话,绝不能变成可执行的命令。

它不做什么

不做 归属
fork(全量继承历史) sessions.fork
生成式摘要(调模型压缩) 模型侧 or 人工
改系统提示词 / 工具面 section / 工具注册
跨会话记忆 dsh-agent-memory

配置

字段 默认 说明
enabled true 总开关
maxAgeMinutes 720 新鲜度窗口:上一场会话最后活动早于此则不衔接
maxChars 3000 交接块字符预算
messageChars 400 单条消息字符上限
maxMessages 8 最多引用多少条消息
sameWorkspaceOnly true 只衔接同一工作目录的会话
maxCandidates 3 最多向前探查几个候选(每个都要读日志,故设上限)
order 850 动态上下文排序位

观测(机制自证)

每次注入/跳过/出错都落一行侧车:

tail -f "$DSH_HOME/session-handoff-trace.jsonl"

stage 取值:injected(注入成功,带来源会话/字符数/消息数)、skip(无合格对话)、filtered(被判据跳过,带 reason)、error / candidate-error(读日志失败)。

判据(可证伪):开一场新会话后,该文件应出现一行 "stage":"injected",且其中的 session 等于新会话 id;未产生注入时会看到 filtered/skip 并附原因——不会静默什么都不写。

已知边界

  • 不作为的注入:交接文本进入模型历史(动态上下文快照默认进历史),因此只摘录 user/assistant 文本,不摘录工具结果与文件内容。
  • 只认「最近一场」:不跨多场会话合并,不猜测话题相关性;判据是时间 + 工作目录,不含语义相似度。
  • 读日志有成本:候选逐个 observeSession(读完整事件流)。maxCandidates 就是这个成本的闸门;projectionMode: 'none' 已关闭投影计算。
  • sessionQuery 是硬依赖:写在 inject 里(不是 ctx.get() 探测)。用探测会与加载顺序赛跑,失败时插件静默变成空转(实测:装了、mounted、却零轨迹)。
  • 「新会话」按内容判,不按创建时间判:判据是该会话自身还没有真实对话(见下「实践修订记录」)。

测试

pnpm build && pnpm test   # 10 个用例,含 4 条尸体样本(子代理/fork/过期/无对话/异目录/自身)

纯决策层(src/handoff.ts)与 IO 壳层(src/index.ts)分层:判据与渲染可离线验证,壳层只做搬运。

实践修订记录

两处判据都是被真实运行打回来才改对的,留档以免重犯:

  1. 2026-09-30 · ctx.get('sessionQuery') 探测 → 静态 inject 首版用 ctx.get() 探测服务,探测失败就打一条 warn 后返回。结果:插件 mounted、built: true、进程也重启了,却零轨迹——外部完全看不出「没加载」与「加载了但空转」的区别。改为 inject = ['systemPrompt', 'sessionQuery'] 声明式依赖,并加一行启动自报 stage: 'ready'。教训:机制必须自证,否则「装了」和「在工作」在观测上是同一张脸。

  2. 2026-09-30 · 按 createdAt 判「新会话」 → 按「自身有无真实对话」判 首版用「创建时间在 N 分钟内」识别新会话。实测:GUI 点「新会话」复用的是既有空白会话的 id(21:28 建的空会话,22:05 点「新会话」时仍用它),于是被误判为「恢复的老会话」而拒绝注入(轨迹里留下 "reason":"not-new")。改为内容判据:extractMessages(session.snapshotEvents()).length === 0 才算新会话。判据要贴语义(「还没有对话」),不要贴代理量(「创建时间新」)。

相关文档

  • ⚠ 本插件暂无 semantic.md(未建语义文档)——契约以 README 各节与源码为准;补文档是待办。
  • 中心仓:alice-digital-life
—/ 5

No ratings yet

Verified DSH bundle

Commit b22e77b29efb

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout