dsh-session-recall 0.7.5 → 0.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +53 -47
  2. package/README.zh.md +53 -36
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@ English | [中文](https://github.com/kittimzhe/dsh-session-recall/blob/main/REA
6
6
 
7
7
  Deterministic cross-session full-text retrieval for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): the model-facing `recall` tool lets the agent **search its own past session transcripts** — "that bug we fixed last week", "the font we chose for my resume" — through the trusted `ctx.sessionQuery` seam.
8
8
 
9
- ## Quick Start
9
+ ## Install
10
10
 
11
11
  **Requirements**: Node.js 20 or 22 · a DeepSeek Harness profile that mounts the `tools` and `sessionQuery` services (the shipped `web` / `agent` profiles qualify).
12
12
 
@@ -14,42 +14,61 @@ Deterministic cross-session full-text retrieval for [DeepSeek Harness](https://g
14
14
  dsh plugin --profile web add dsh-session-recall
15
15
  ```
16
16
 
17
+ ## Try it once
18
+
17
19
  The first search builds a persistent FTS5 index automatically — no extra setup. In a session, just ask naturally:
18
20
 
19
21
  ```text
20
22
  recall: which font did we pick for the resume last week?
21
23
  ```
22
24
 
23
- Full details — GitHub install route, `cordis.patch.yml` snippet, configuration — in [Install](#install-out-of-tree-plugin) below.
25
+ The tool surfaces the best-matching event per session — each hit carries the session id, a best-effort title, the date, and a match snippet, rendered as a native search card in the Web UI.
24
26
 
25
- ## Positioning
27
+ ## The session toolchain
26
28
 
27
- `dsh-session-recall` is a **transcript retrieval layer** focused on correctness and control.
29
+ | Plugin | Layer | Answers |
30
+ |---|---|---|
31
+ | [`dsh-session-export`](https://www.npmjs.com/package/dsh-session-export) | Evidence | "What exactly happened in this session?" |
32
+ | **`dsh-session-recall`** | **Memory** | **"What did I do before, and where is it?"** |
33
+ | [`dsh-session-eval`](https://www.npmjs.com/package/dsh-session-eval) | Measurement | "Was that session good? Is the trend improving?" |
28
34
 
29
- - It returns evidence from original session logs, not synthesized summaries.
30
- - It enforces explicit retrieval scope (cwd by default, opt-in widening).
31
- - It favors deterministic behavior over "smart" but lossy memory extraction.
35
+ All three read through the same trusted `ctx.sessionQuery` seam.
32
36
 
33
- If you need agent memory orchestration, use a memory framework; if you need bounded, auditable lookup over historical transcripts, use this plugin.
37
+ ## Contributing
34
38
 
35
- ## Competitive context
39
+ - **Local dev**: `npm ci && npm run typecheck && npm test && npm run bundle` (Node 20 or 22).
40
+ - **Start in the source**: [`src/tool.ts`](src/tool.ts) (tool contract), [`src/rank.ts`](src/rank.ts) (recency re-ranking, pinned cwds), [`src/redact.ts`](src/redact.ts) (redaction patterns), [`src/resilient.ts`](src/resilient.ts) (degraded raw-scan). The full source map is in [CONTRIBUTING.md](CONTRIBUTING.md).
41
+ - **Open gaps**: [#6](https://github.com/kittimzhe/dsh-session-recall/issues/6) (redaction patterns), [#7](https://github.com/kittimzhe/dsh-session-recall/issues/7) (tie-break order) — or browse [issues labeled `good first issue`](https://github.com/kittimzhe/dsh-session-recall/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
42
+ - **Roadmap**: [P2: evidence handoff — expose `sessionId` + transcript path from recall hits (#8)](https://github.com/kittimzhe/dsh-session-recall/issues/8), acceptance criteria in the issue; post a comment before starting so effort is not duplicated.
43
+ - **Rules**: behavior changes need tests; doc changes must update `README.md` and `README.zh.md` in sync; releases belong to the maintainer. Details: [CONTRIBUTING.md](CONTRIBUTING.md).
36
44
 
37
- | Capability focus | Memory frameworks | Generic transcript search | `dsh-session-recall` |
38
- |---|---|---|---|
39
- | Retrieval target | Derived memory objects | Varies by implementation | **Original session transcript events** |
40
- | Scope control | Framework-specific | Often coarse | **cwd-scoped default + explicit `all_projects`, `since_days`, `tools`, `errors_only` gate** |
41
- | CJK behavior | Framework-specific | Often tokenizer-limited | **FTS + CJK zero-hit substring fallback** |
42
- | Output contract | Usually framework-native | Varies | **Typed `recall` result with stable fields/hints** |
45
+ ## What the model gets
43
46
 
44
- Name & scope notes (2026-09):
47
+ ```
48
+ recall({ query }) → best-matching event per session, current project only
49
+ recall({ query, all_projects: true }) → search every session on the machine
50
+ recall({ query, session_id }) → search the events of one session
51
+ recall({ query, limit, cursor }) → page through results
52
+ ```
45
53
 
46
- - This plugin is **unrelated to `dsh-recall-plugin`** — that plugin is message undo/rewind (restoring workspace and conversation to before a message was sent).
47
- - It **succeeds `dsh-recall`** — an earlier transcript-search plugin (last release 2026-08-21) with a similar goal; this plugin continues the line with persistent FTS5 indexing, CJK fallback, approval gates, and lineage-scoped authorization.
48
- - It **complements memory frameworks** such as `dsh-mnemon` (write-side memory orchestration): this plugin stays a read-only retrieval layer over original session logs and makes no writes to any memory store.
54
+ Each hit carries the session id, title (best-effort), date, and a match snippet; the result renders as a native search card in the Web UI (`SearchMatchesResultView`). Because the FTS `unicode61` tokenizer indexes an uninterrupted CJK run as a single token, a short Chinese phrase inside a longer sentence would otherwise never match the index — so a zero-hit CJK query automatically falls back to a substring scan over session text (the `sessionQuery.filterEvents` literal text clause). Every whitespace-separated term must match, so `简历 模板` still recovers `简历模板`; the hint reports when that path matched.
49
55
 
50
- ## Roadmap
56
+ ## Scoping (the authorization gap)
57
+
58
+ `sessionQuery` is trusted infrastructure — it can read every session. This tool therefore constrains each call itself:
51
59
 
52
- - **P2: evidence handoff** — one-click bridge to session export for matched sessions.
60
+ - by default, `sessionFilters: [{ kind: 'cwd', values: [<calling agent's cwd>] }]` — only sessions started in the same project directory;
61
+ - `all_projects: true` widens the scope, and only if the deployment allows it (`allowAllProjects: false` disables the argument).
62
+
63
+ ## Positioning
64
+
65
+ `dsh-session-recall` is a **transcript retrieval layer** focused on correctness and control.
66
+
67
+ - It returns evidence from original session logs, not synthesized summaries.
68
+ - It enforces explicit retrieval scope (cwd by default, opt-in widening).
69
+ - It favors deterministic behavior over "smart" but lossy memory extraction.
70
+
71
+ If you need agent memory orchestration, use a memory framework; if you need bounded, auditable lookup over historical transcripts, use this plugin.
53
72
 
54
73
  ## Why
55
74
 
@@ -69,23 +88,20 @@ And the shipped web profile mounts its SQLite FTS5 backend with `openAt: never`
69
88
 
70
89
  Memory plugins extract structured notes with an LLM (lossy, costs tokens); `recall` searches the **original transcripts** — zero extraction, zero loss, works retroactively on day one.
71
90
 
72
- ## What the model gets
73
-
74
- ```
75
- recall({ query }) → best-matching event per session, current project only
76
- recall({ query, all_projects: true }) → search every session on the machine
77
- recall({ query, session_id }) → search the events of one session
78
- recall({ query, limit, cursor }) → page through results
79
- ```
80
-
81
- Each hit carries the session id, title (best-effort), date, and a match snippet; the result renders as a native search card in the Web UI (`SearchMatchesResultView`). Because the FTS `unicode61` tokenizer indexes an uninterrupted CJK run as a single token, a short Chinese phrase inside a longer sentence would otherwise never match the index — so a zero-hit CJK query automatically falls back to a substring scan over session text (the `sessionQuery.filterEvents` literal text clause). Every whitespace-separated term must match, so `简历 模板` still recovers `简历模板`; the hint reports when that path matched.
91
+ ## Competitive context
82
92
 
83
- ## Scoping (the authorization gap)
93
+ | Capability focus | Memory frameworks | Generic transcript search | `dsh-session-recall` |
94
+ |---|---|---|---|
95
+ | Retrieval target | Derived memory objects | Varies by implementation | **Original session transcript events** |
96
+ | Scope control | Framework-specific | Often coarse | **cwd-scoped default + explicit `all_projects`, `since_days`, `tools`, `errors_only` gate** |
97
+ | CJK behavior | Framework-specific | Often tokenizer-limited | **FTS + CJK zero-hit substring fallback** |
98
+ | Output contract | Usually framework-native | Varies | **Typed `recall` result with stable fields/hints** |
84
99
 
85
- `sessionQuery` is trusted infrastructure — it can read every session. This tool therefore constrains each call itself:
100
+ Name & scope notes (2026-09):
86
101
 
87
- - by default, `sessionFilters: [{ kind: 'cwd', values: [<calling agent's cwd>] }]` — only sessions started in the same project directory;
88
- - `all_projects: true` widens the scope, and only if the deployment allows it (`allowAllProjects: false` disables the argument).
102
+ - This plugin is **unrelated to `dsh-recall-plugin`** — that plugin is message undo/rewind (restoring workspace and conversation to before a message was sent).
103
+ - It **succeeds `dsh-recall`** — an earlier transcript-search plugin (last release 2026-08-21) with a similar goal; this plugin continues the line with persistent FTS5 indexing, CJK fallback, approval gates, and lineage-scoped authorization.
104
+ - It **complements memory frameworks** such as `dsh-mnemon` (write-side memory orchestration): this plugin stays a read-only retrieval layer over original session logs and makes no writes to any memory store.
89
105
 
90
106
  ## Install (out-of-tree plugin)
91
107
 
@@ -171,7 +187,7 @@ Every result also carries a `diagnostics` object (v0.5): which engine produced t
171
187
 
172
188
  ## Benchmark
173
189
 
174
- Measured on a real headless profile (Node 25, Apple Silicon, warm filesystem cache).
190
+ Measured on a real headless profile on the machine at hand (Node 25, Apple Silicon, warm filesystem cache) — indicative numbers, not a CI gate. Supported and CI-tested Node versions remain 20 and 22.
175
191
 
176
192
  | Corpus | |
177
193
  |---|---|
@@ -192,22 +208,12 @@ Warm searches run sub-millisecond to ~1.5 ms against the on-disk index. Cold sta
192
208
  ## Development
193
209
 
194
210
  ```sh
195
- npm install
211
+ npm ci
196
212
  npm run typecheck # tsc --noEmit
197
213
  npm test # vitest run
198
214
  npm run bundle # tsdown → lib/
199
215
  ```
200
216
 
201
- ## Session toolchain
202
-
203
- This plugin is one of three layers over the same trusted `ctx.sessionQuery` seam:
204
-
205
- | Plugin | Layer | Answers |
206
- |---|---|---|
207
- | [`dsh-session-export`](https://www.npmjs.com/package/dsh-session-export) | Evidence | "What exactly happened in this session?" |
208
- | `dsh-session-recall` | Memory | "What did I do before, and where is it?" |
209
- | [`dsh-session-eval`](https://www.npmjs.com/package/dsh-session-eval) | Measurement | "Was that session good? Is the trend improving?" |
210
-
211
217
  ## License
212
218
 
213
219
  [MIT](https://github.com/kittimzhe/dsh-session-recall/blob/main/LICENSE)
package/README.zh.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  DeepSeek Harness 的**确定性跨会话全文检索**插件:注册模型可调用的 `recall` 工具,让 agent 能**检索自己过往的会话原文**——"上周修的那个 bug"、"简历选的什么字体"——全部通过可信的 `ctx.sessionQuery` 缝完成。
8
8
 
9
- ## 快速开始
9
+ ## 安装
10
10
 
11
11
  **环境要求**:Node.js 20 或 22 · 挂载了 `tools` 与 `sessionQuery` 服务的 DeepSeek Harness profile(官方 `web` / `agent` profile 均满足)。
12
12
 
@@ -14,13 +14,51 @@ DeepSeek Harness 的**确定性跨会话全文检索**插件:注册模型可
14
14
  dsh plugin --profile web add dsh-session-recall
15
15
  ```
16
16
 
17
+ ## 试一次
18
+
17
19
  首次搜索会自动构建持久化 FTS5 索引——无需额外步骤。会话里直接问:
18
20
 
19
21
  ```text
20
22
  recall:上周给简历选的什么字体来着?
21
23
  ```
22
24
 
23
- 完整细节(GitHub 安装方式、`cordis.patch.yml` 片段、配置项)见下文「安装」一节。
25
+ 工具会按会话返回最强命中——每条带会话 id、尽力补全的标题、日期与命中摘录,在 Web UI 里渲染成原生搜索卡片。
26
+
27
+ ## 会话工具链
28
+
29
+ | 插件 | 层 | 回答的问题 |
30
+ |---|---|---|
31
+ | [`dsh-session-export`](https://www.npmjs.com/package/dsh-session-export) | 证据层 | "这个会话到底发生了什么?" |
32
+ | **`dsh-session-recall`** | **记忆层** | **"我以前做过什么,在哪?"** |
33
+ | [`dsh-session-eval`](https://www.npmjs.com/package/dsh-session-eval) | 评测层 | "刚才的会话好不好?趋势在变好吗?" |
34
+
35
+ 三者都通过同一个受信的 `ctx.sessionQuery` 接缝读取。
36
+
37
+ ## 贡献
38
+
39
+ - **本地开发**:`npm ci && npm run typecheck && npm test && npm run bundle`(Node 20 或 22)。
40
+ - **源码入口**:[`src/tool.ts`](src/tool.ts)(工具契约)、[`src/rank.ts`](src/rank.ts)(新近度重排、置顶项目)、[`src/redact.ts`](src/redact.ts)(脱敏规则)、[`src/resilient.ts`](src/resilient.ts)(降级直扫)。完整源码地图见 [CONTRIBUTING.md](CONTRIBUTING.md)。
41
+ - **当前缺口**:[#6](https://github.com/kittimzhe/dsh-session-recall/issues/6)(脱敏规则扩展)、[#7](https://github.com/kittimzhe/dsh-session-recall/issues/7)(同分排序钉死)——或浏览 [`good first issue` 标签](https://github.com/kittimzhe/dsh-session-recall/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)。
42
+ - **路线图**:[P2:证据联动——recall 命中携带 sessionId + 转录路径(#8)](https://github.com/kittimzhe/dsh-session-recall/issues/8),验收标准见 issue;认领前请先留言避免撞车。
43
+ - **规矩**:行为变更必须带测试;文档必须 `README.md` 与 `README.zh.md` 同步改;版本发布由维护者执行。详见 [CONTRIBUTING.md](CONTRIBUTING.md)。
44
+
45
+ ## 模型看到什么
46
+
47
+ ```
48
+ recall({ query }) → 每个会话返回最强命中事件,默认只搜当前项目
49
+ recall({ query, all_projects: true }) → 搜索本机全部会话
50
+ recall({ query, session_id }) → 只搜指定会话内的事件
51
+ recall({ query, limit, cursor }) → 翻页
52
+ ```
53
+
54
+ 每条命中带会话 id、标题(尽力补全)、日期、命中摘录;结果在 Web UI 里渲染成原生搜索卡片(`SearchMatchesResultView`)。因为 FTS 的 `unicode61` 分词器会把连续中文当成一个 token,短中文短语一旦嵌在长句里就匹配不到索引——所以 CJK 查询零命中时会自动回退到对会话文本的子串扫描(走 `sessionQuery.filterEvents` 的字面文本子句),空格拆出的每个词都必须命中,因此 `简历 模板` 也能找回 `简历模板`;hint 会说明这条回退路径是否命中。
55
+
56
+ ## 授权边界(官方明确留给工具层的责任)
57
+
58
+ `sessionQuery` 是可信基础设施——它能读所有会话。所以本工具自己约束每一次调用:
59
+
60
+ - 默认注入 `sessionFilters: [{ kind: 'cwd', values: [<调用方 agent 的 cwd>] }]`——只搜同一项目目录下开始的会话;
61
+ - `all_projects: true` 才放宽到全机,且部署方可以用 `allowAllProjects: false` 直接禁用该参数。
24
62
 
25
63
  ## 项目定位
26
64
 
@@ -32,24 +70,6 @@ recall:上周给简历选的什么字体来着?
32
70
 
33
71
  如果你要做长期记忆编排,请用记忆框架;如果你要做可审计、有权限边界的历史检索,请用本插件。
34
72
 
35
- ## 竞品视角
36
-
37
- | 能力重心 | 记忆框架类插件 | 通用检索类插件 | `dsh-session-recall` |
38
- |---|---|---|---|
39
- | 检索对象 | 推导后的记忆结构 | 视实现而定 | **原始会话事件文本** |
40
- | 范围控制 | 框架内约束 | 常较粗粒度 | **默认 cwd + 显式 `all_projects` 闸门** |
41
- | CJK 体验 | 视实现而定 | 常受分词限制 | **FTS + CJK 零命中子串回退** |
42
- | 输出契约 | 框架内部格式 | 不统一 | **类型化 `recall` 结果 + 稳定 hint** |
43
-
44
- 命名与边界说明(2026-09):
45
-
46
- - 本插件与 **`dsh-recall-plugin` 无关**——那是"撤回消息"插件(把工作区与对话回退到某条消息发出之前)。
47
- - 本插件是 **`dsh-recall` 的后继者**——后者是更早的会话检索插件(最后更新 2026-08-21);本插件在其方向上续写:持久 FTS5 索引、中文回退、审批闸门、谱系鉴权。
48
- - 本插件与 **`dsh-mnemon` 等记忆框架互补**:它们做写入侧的记忆编排;本插件保持只读检索层,只读原始会话日志,不写任何记忆存储。
49
- ## 路线图
50
-
51
- - **P2:证据联动导出** —— 命中后可一键触发对应会话导出。
52
-
53
73
  ## 为什么做这个
54
74
 
55
75
  官方 `@deepseek-ai/dsh-session-query` 的 README 自己列出了缺口:
@@ -68,23 +88,20 @@ recall:上周给简历选的什么字体来着?
68
88
 
69
89
  记忆类插件用 LLM 提取结构化笔记(有损、费 token);`recall` 检索的是**原始对话记录**——零提取、零损失、装完当天就能搜全部历史。
70
90
 
71
- ## 模型看到什么
72
-
73
- ```
74
- recall({ query }) → 每个会话返回最强命中事件,默认只搜当前项目
75
- recall({ query, all_projects: true }) → 搜索本机全部会话
76
- recall({ query, session_id }) → 只搜指定会话内的事件
77
- recall({ query, limit, cursor }) → 翻页
78
- ```
79
-
80
- 每条命中带会话 id、标题(尽力补全)、日期、命中摘录;结果在 Web UI 里渲染成原生搜索卡片(`SearchMatchesResultView`)。因为 FTS 的 `unicode61` 分词器会把连续中文当成一个 token,短中文短语一旦嵌在长句里就匹配不到索引——所以 CJK 查询零命中时会自动回退到对会话文本的子串扫描(走 `sessionQuery.filterEvents` 的字面文本子句),空格拆出的每个词都必须命中,因此 `简历 模板` 也能找回 `简历模板`;hint 会说明这条回退路径是否命中。
91
+ ## 竞品视角
81
92
 
82
- ## 授权边界(官方明确留给工具层的责任)
93
+ | 能力重心 | 记忆框架类插件 | 通用检索类插件 | `dsh-session-recall` |
94
+ |---|---|---|---|
95
+ | 检索对象 | 推导后的记忆结构 | 视实现而定 | **原始会话事件文本** |
96
+ | 范围控制 | 框架内约束 | 常较粗粒度 | **默认 cwd + 显式 `all_projects` 闸门** |
97
+ | CJK 体验 | 视实现而定 | 常受分词限制 | **FTS + CJK 零命中子串回退** |
98
+ | 输出契约 | 框架内部格式 | 不统一 | **类型化 `recall` 结果 + 稳定 hint** |
83
99
 
84
- `sessionQuery` 是可信基础设施——它能读所有会话。所以本工具自己约束每一次调用:
100
+ 命名与边界说明(2026-09):
85
101
 
86
- - 默认注入 `sessionFilters: [{ kind: 'cwd', values: [<调用方 agent 的 cwd>] }]`——只搜同一项目目录下开始的会话;
87
- - `all_projects: true` 才放宽到全机,且部署方可以用 `allowAllProjects: false` 直接禁用该参数。
102
+ - 本插件与 **`dsh-recall-plugin` 无关**——那是"撤回消息"插件(把工作区与对话回退到某条消息发出之前)。
103
+ - 本插件是 **`dsh-recall` 的后继者**——后者是更早的会话检索插件(最后更新 2026-08-21);本插件在其方向上续写:持久 FTS5 索引、中文回退、审批闸门、谱系鉴权。
104
+ - 本插件与 **`dsh-mnemon` 等记忆框架互补**:它们做写入侧的记忆编排;本插件保持只读检索层,只读原始会话日志,不写任何记忆存储。
88
105
 
89
106
  ## 安装(out-of-tree 插件)
90
107
 
@@ -170,7 +187,7 @@ dsh plugin --profile web add github:kittimzhe/dsh-session-recall
170
187
 
171
188
  ## 基准
172
189
 
173
- 真机 headless profile 实测(Node 25,Apple Silicon,暖文件缓存)。
190
+ 真机 headless profile 实测(手头机器为 Node 25、Apple Silicon、暖文件缓存)——数字仅供参考,不是 CI 门槛;受支持并经 CI 测试的版本仍是 Node 20 与 22。
174
191
 
175
192
  | 语料 | |
176
193
  |---|---|
@@ -191,7 +208,7 @@ dsh plugin --profile web add github:kittimzhe/dsh-session-recall
191
208
  ## 开发
192
209
 
193
210
  ```sh
194
- npm install
211
+ npm ci
195
212
  npm run typecheck # tsc --noEmit
196
213
  npm test # vitest run
197
214
  npm run bundle # tsdown → lib/
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-session-recall",
3
3
  "description": "Deterministic cross-session transcript retrieval for DeepSeek Harness: the model-facing `recall` tool searches past session logs with explicit scope control",
4
- "version": "0.7.5",
4
+ "version": "0.7.7",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },