@deepseek-ai/dsh-tool-session-query 0.1.1-rc.2 → 0.1.2-alpha.3

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.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/session-query/tool-session-query/README.md
5
- README.md: d973daf1124c4be05f7335b18661d431d45be39f
6
- README.zh.md: 71c1c74addf8cb2b29773933a36f3368b1c81bf5
5
+ README.md: 6066c8466b0d161e80f96d1e667902ef30aa1d00
6
+ README.zh.md: e509e2e8546cc535c56ddf5a6a4a1d608276a252
package/README.md CHANGED
@@ -1,24 +1,115 @@
1
+ ---
2
+ description: "Workspace-authorized model-facing session history tools for agent developers and maintainers choosing, configuring, or debugging prior-session search, tracing, and event reads."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-tool-session-query
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Workspace-authorized model tools over `ctx.sessionQuery`. The opt-in package depends only on the unified interface and registers `session_search`, `session_event_search`, `session_trace`, `session_event_trace`, and `session_event_read`; shipped host compositions do not mount it by default.
10
+ ## Summary
11
+
12
+ `dsh-tool-session-query` gives the model five read-only tools over session history: `session_search`, `session_event_search`, `session_trace`, `session_event_trace`, and `session_event_read`. The tools are workspace-authorized — a model can only reach sessions whose `cwd` exactly matches its own caller session — and results are cursor-free plain text, so the model can search prior work and follow a useful hit into its lineage or exact event data. The package is opt-in and not mounted by shipped host compositions: mounting it adds one concise guidance section and the five schemas to every request. Configuration and usage come first; the implementation internals live in a collapsible developer section below.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
6
24
 
7
- ## Configuration
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
8
27
 
9
- | Key | Default | Meaning |
10
- |---|---:|---|
11
- | `maxSearchResults` | `100` | Maximum authorized non-self hits collected across internal provider pages |
28
+ Mount this package when the agent should be able to search its own prior sessions and inspect their relationships and events. The common path is explicit: mount the plugin over `ctx.sessionQuery` (backed by `dsh-session-query-sqlite`), then let the model call the tools.
29
+
30
+ ### When to choose it
31
+
32
+ Choose it when a deployment wants model-driven retrieval of prior work — for example a coding agent that searches what it did in earlier sessions before starting a task. Avoid it when only programmatic retrieval is needed: `ctx.sessionQuery` itself serves code callers without the model-facing schema, prompt, and authorization layer.
33
+
34
+ ### Configuration
35
+
36
+ | Field | Default | Meaning |
37
+ |---|---|---|
38
+ | `maxSearchResults` | `100` | Maximum authorized hits returned by one search call |
12
39
  | `searchTimeoutMs` | `30000` | Cooperative deadline attached to both full-text search tools |
13
40
 
14
- The caller comes exclusively from `ToolExecution.exec.agent`. Cross-session access requires exact equality between the target and caller session `cwd` values; a caller without `cwd` can inspect only itself. Search never exposes provider cursors, offsets, page sizes, or a model-controlled limit. Because one search consumes generation-bound provider cursors internally, both search tools execute exclusively with sibling tool calls; the three exact trace/read tools opt into parallel execution. Every exact executor passes its unchanged execution signal through authorization and the service trace/read, so cancellation waits for cooperative persistence cleanup and retains the signal's exact reason. Timestamps at the tool boundary require an explicit `Z` or numeric offset and become inclusive epoch-millisecond filters.
41
+ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-tool-session-query) is the exhaustive source for every accepted field and its JSDoc.
42
+
43
+ ### What the model can do
44
+
45
+ | Tool | What the model gets |
46
+ |---|---|
47
+ | `session_search` | Sessions matching a literal query, ranked, with title and best-match excerpt; always omits the caller session |
48
+ | `session_event_search` | Events matching a literal query inside one authorized session; for the current session it stops before the step that invoked it |
49
+ | `session_trace` | The authorized ancestor chain and descendant tree of one session; unauthorized boundaries appear as markers without hidden ids |
50
+ | `session_event_trace` | One event's positional replacements and cited source-event relationships |
51
+ | `session_event_read` | One full unabridged event as JSON, plus optional neighboring event summaries |
52
+
53
+ Workspace authority is conservative: cross-session access requires exact `cwd` equality between target and caller session, and a caller without `cwd` can inspect only itself. Requested parent ids are deduplicated and authority-checked before search; missing and cross-workspace guesses behave identically. Search results are cursor-free: a capped result asks the model to narrow its query, and never exposes provider cursors, offsets, page sizes, or a model-controlled limit. Timestamps at the tool boundary are timezone-qualified ISO 8601 and become inclusive epoch-millisecond filters.
54
+
55
+ ### Failures and recovery
56
+
57
+ Every trusted query-service call crosses one error sanitizer: caller cancellation is preserved exactly, corpus and provider diagnostics go to the internal log, and unsafe or unprintable failures fall back to the fixed `SESSION_QUERY_TOOL_FAILED` code and message. Local argument-validation and authorization errors keep their precise tool-owned messages (`SESSION_QUERY_TOOL_UNAUTHORIZED` for a target outside the caller workspace). The package performs no byte or character truncation and does not import a spill backend; deployments that need bounded inline output mount `@deepseek-ai/dsh-spill-policy`, which can replace oversized rendered text while retaining the complete result.
58
+
59
+ -----
60
+
61
+ <a id="understand-the-implementation"></a>
62
+ ## Understand the implementation
63
+
64
+ <details>
65
+ <summary>Implementation internals — click to expand</summary>
66
+
67
+ This section explains the design decisions behind the tools and points at the code that realizes them; the observable behavior is fully covered in [Use this package](#use-this-package).
68
+
69
+ ### Design philosophy
15
70
 
16
- `session_search` always omits the caller session. Requested parent ids are deduplicated and checked against caller-workspace authority before FTS; only authorized ids reach the provider, while missing and cross-workspace guesses behave identically and the root marker remains independently ORed. A current-session `session_event_search` stops immediately before the step that invoked it, so the active assistant output and logged tool call cannot match themselves. Direct targets are authorized before trace, event, or title reads. Lineage output replaces unauthorized ancestor and descendant boundaries with markers that contain no hidden session id.
71
+ The consumer is built on one separation and three commitments:
17
72
 
18
- Every trusted `ctx.sessionQuery` call crosses one model-boundary sanitizer. Caller cancellation is checked first and preserved exactly. Available corpus and provider diagnostics, including safely inspectable nested causes, are logged internally on a best-effort basis; unprintable failures use a fixed log placeholder. Diagnostic formatting and error classification are independently guarded, so an unprintable cause cannot escape or prevent a safely classified outer error, while unsafe classification or logging falls back to the fixed `SESSION_QUERY_TOOL_FAILED` code and message. Local argument-validation and authorization errors retain their precise tool-owned messages.
73
+ - **Narrow read-only tools.** Five tools with flat snake-case schemas, each teaching one follow-up step; no cursor, offset, page-size, or model-controlled limit ever reaches the model.
74
+ - **Authority derived from the caller, never the model.** Caller identity comes from `ToolExecution.exec.agent`; workspace is exact-string `cwd` equality, re-checked against the header observed with each result.
75
+ - **One model-boundary sanitizer.** Every trusted `ctx.sessionQuery` call goes through the service boundary, which preserves cancellation and contains diagnostic and classification failures.
76
+ - **No second truncation format.** Results stay complete; the generic spill policy owns bounded inline output.
19
77
 
20
- The package deliberately performs no byte or character truncation and does not import a spill backend. Deployments that need bounded inline output mount `@deepseek-ai/dsh-spill-policy`, which can replace the rendered text after execution while retaining the complete result.
78
+ The design history lives in the [model-facing session query tools note](../../../.agents/notes/implemented/feature/2026-07-24-model-facing-session-query-tools.md) and the [session-search-not-shipped-default note](../../../.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md).
21
79
 
80
+ ### Source map
81
+
82
+ | File | Role |
83
+ |---|---|
84
+ | [`src/index.ts`](src/index.ts) | Plugin entry: config, prompt section, five tool registrations |
85
+ | [`src/input.ts`](src/input.ts) | Model schemas, argument normalization, filter construction |
86
+ | [`src/workspace-access.ts`](src/workspace-access.ts) | Caller identity, workspace authorization, title access, lineage projection |
87
+ | [`src/service-boundary.ts`](src/service-boundary.ts) | Trusted calls and model-safe error translation |
88
+ | [`src/operations.ts`](src/operations.ts) | The five operation workflows |
89
+ | [`src/presentation.ts`](src/presentation.ts) | Text result rendering and tool-call cards |
90
+
91
+ ### Operation flow
92
+
93
+ Each executor derives the caller, normalizes the model's arguments into service filters, authorizes the target (or the requested parent ids) against the caller workspace, and collects results through the service boundary. Both search tools page internally through provider cursors while the observed generation stays valid, stopping at `maxSearchResults`; because one search consumes generation-bound provider cursors, the two search tools execute exclusively with sibling tool calls, while the three exact trace/read tools opt into parallel execution. Lineage output replaces unauthorized ancestor and descendant boundaries with markers containing no hidden session id.
94
+
95
+ </details>
96
+
97
+ -----
98
+
99
+ <a id="further-exploration"></a>
100
+ ## Further Exploration
101
+
102
+ Read these pages when the package-level contract is not enough. They move from the tool surface to the underlying service, the schema catalog, and the design evidence.
103
+
104
+ - [Generated tool catalog](../../../docs/tool-catalog.md#deepseek-aidsh-tool-session-query) — the five tool schemas as the model sees them.
105
+ - [dsh-session-query](../session-query/README.md) — the service these tools call.
106
+ - [dsh-session-query-sqlite](../session-query-sqlite/README.md) — the full-text backend behind the two search tools.
107
+ - [Session Query subsystem reference](../../../docs/subsystems/session-query.md) — the type-level contract under the tools.
108
+ - [Model-facing session query tools](../../../.agents/notes/implemented/feature/2026-07-24-model-facing-session-query-tools.md) — workspace authority, cursor-free results, and spill decisions.
109
+
110
+ -----
111
+
112
+ <a id="model-experience"></a>
22
113
  ## Model Experience
23
114
 
24
115
  ### System prompt
@@ -71,6 +162,25 @@ Append-only result text follows the reusable request prefix and does not invalid
71
162
 
72
163
  ## Known Limitations and Deferred Work
73
164
 
74
- - Search returns at most the deployment cap and asks the model to narrow its query when more matches exist; it offers no continuation token.
75
- - Workspace identity is conservative exact-string `cwd` equality, so symlink-equivalent paths do not share authority.
76
- - Custom compositions without the generic spill policy accept complete trace and event payloads inline.
165
+ <a id="known-limitations-and-deferred-work"></a>
166
+
167
+
168
+ These limits define when this package is a poor fit or needs special operational care. They are current package constraints, not a task backlog.
169
+
170
+ - **Search caps without continuation** — search returns at most the deployment cap and asks the model to narrow its query when more matches exist; there is no continuation token.
171
+ - **Conservative workspace identity** — workspace identity is exact-string `cwd` equality, so symlink-equivalent paths do not share authority.
172
+ - **Inline payloads without the spill policy** — custom compositions without the generic spill policy accept complete trace and event payloads inline.
173
+
174
+ <a id="dev-note"></a>
175
+ ### Dev Note
176
+
177
+ <details>
178
+ <summary>Working context for maintainers — click to expand</summary>
179
+
180
+ This Dev Note is working context for maintainers: open design questions and directions that are not decided. It is explicitly non-authoritative — shipped behavior, limits, and accepted rationale live in the sections above, the package code, and the linked Agent Notes.
181
+
182
+ #### Future: broader workspace semantics
183
+
184
+ Exact-string `cwd` equality is deliberately conservative; symlink-aware or canonical-path workspace identity would change which sessions share authority and is undecided.
185
+
186
+ </details>
package/README.zh.md CHANGED
@@ -1,29 +1,120 @@
1
+ ---
2
+ description: "面向 agent 开发者与维护者的工作区授权模型会话历史工具,用于选择、配置或排查既往会话搜索、追踪与事件读取。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-tool-session-query
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 位于 `ctx.sessionQuery` 之上、经工作区授权的模型工具。该 opt-in 包只依赖统一接口,并注册 `session_search`、`session_event_search`、`session_trace`、`session_event_trace` 和 `session_event_read`;已发布的宿主组合默认不挂载它。
10
+ ## 概述
11
+
12
+ `dsh-tool-session-query` 给模型提供五个会话历史只读工具:`session_search`、`session_event_search`、`session_trace`、`session_event_trace` 与 `session_event_read`。工具经工作区授权——模型只能访问 `cwd` 与其自身调用方会话完全相同的会话——结果是无游标的纯文本,因此模型可以搜索既往工作,并顺着有用命中进入其血缘或精确事件数据。本包是 opt-in,已发布宿主组合默认不挂载:挂载后每次请求都会增加一个精简指引章节与五个 schema。配置与用法在前;实现内部细节放在下方可折叠的开发者章节中。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
6
24
 
7
- ## 配置
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
8
27
 
9
- | 键 | 默认值 | 含义 |
10
- |---|---:|---|
11
- | `maxSearchResults` | `100` | 在内部提供方分页中收集的最大已授权非自身命中数 |
28
+ 当 agent 应该能搜索自己的既往会话并检查其关系与事件时挂载本包。常用路径是显式的:在 `ctx.sessionQuery`(由 `dsh-session-query-sqlite` 支撑)之上挂载插件,然后让模型调用这些工具。
29
+
30
+ ### 何时选择
31
+
32
+ 当部署需要模型驱动的既往工作检索时选择它——例如编程 agent 在开始任务前搜索更早会话中做过的事。只需要程序化检索时避免使用:`ctx.sessionQuery` 本身服务代码调用方,无需面向模型的 schema、提示词与授权层。
33
+
34
+ ### 配置
35
+
36
+ | 字段 | 默认值 | 含义 |
37
+ |---|---|---|
38
+ | `maxSearchResults` | `100` | 一次搜索调用返回的最大已授权命中数 |
12
39
  | `searchTimeoutMs` | `30000` | 附加到两个全文搜索工具的协作式截止时间 |
13
40
 
14
- 调用方只能来自 `ToolExecution.exec.agent`。跨会话访问要求目标和调用方会话的 `cwd` 值严格相等;没有 `cwd` 的调用方只能检查自己。搜索绝不公开提供方游标、偏移、分页大小或模型可控上限。由于一次搜索会在内部消费与世代绑定的提供方游标,两个搜索工具都与同级工具调用排他执行;三个精确跟踪/读取工具选择并行执行。每个精确执行器都将未更改的执行信号传递给授权和服务跟踪/读取,因此取消会等待协作式持久化清理,并保留信号的精确原因。工具边界上的时间戳要求显式 `Z` 或数字偏移,并转换为包含端点的 epoch 毫秒过滤器。
41
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-tool-session-query)是每个受支持字段及其 JSDoc 的穷尽式真源。
42
+
43
+ ### 模型可以做什么
44
+
45
+ | 工具 | 模型得到什么 |
46
+ |---|---|
47
+ | `session_search` | 匹配字面查询的会话,经排序,带标题与最佳匹配摘录;始终省略调用方会话 |
48
+ | `session_event_search` | 一个已授权会话内匹配字面查询的事件;针对当前会话时,在调用它的步骤之前停止 |
49
+ | `session_trace` | 一个会话的已授权祖先链与后代树;未授权边界以不含隐藏 id 的标记出现 |
50
+ | `session_event_trace` | 一个事件的位置替换与被引用源事件关系 |
51
+ | `session_event_read` | 一个完整未删节事件(JSON),加可选的事件邻接摘要 |
52
+
53
+ 工作区授权是保守的:跨会话访问要求目标与调用方会话的 `cwd` 严格相等,没有 `cwd` 的调用方只能检查自己。请求的父 id 会在搜索前去重并按权限检查;缺失与跨工作区猜测行为完全相同。搜索结果无游标:结果达到上限时请模型缩小查询,绝不暴露提供方游标、偏移、分页大小或模型可控上限。工具边界的时间戳是带时区限定的 ISO 8601,并转换为包含端点的 epoch 毫秒过滤器。
54
+
55
+ ### 失败与恢复
56
+
57
+ 每个可信查询服务调用都经过一个错误净化器:调用方取消被精确保留,语料库与提供方诊断进入内部日志,不安全或不可打印的失败回退到固定 `SESSION_QUERY_TOOL_FAILED` 代码与消息。本地参数校验与授权错误保留精确的工具自有消息(目标在调用方工作区之外时为 `SESSION_QUERY_TOOL_UNAUTHORIZED`)。本包不执行字节或字符截断,也不导入 spill 后端;需要限制内联输出的部署应挂载 `@deepseek-ai/dsh-spill-policy`,它可以在保留完整结果的同时替换过大的已渲染文本。
58
+
59
+ -----
60
+
61
+ <a id="understand-the-implementation"></a>
62
+ ## 理解实现
63
+
64
+ <details>
65
+ <summary>实现细节——点击展开</summary>
66
+
67
+ 本节解释工具背后的设计决策,并指出实现它们的代码位置;可观察行为已在[使用本包](#use-this-package)中完整说明。
68
+
69
+ ### 设计理念
15
70
 
16
- `session_search` 始终省略调用方会话。请求的父 id 会被去重,并在 FTS 前根据调用方工作区权限检查;只有已授权 id 会到达提供方,而缺失猜测和跨工作区猜测的行为完全相同,root 标记仍独立使用 OR。当前会话中的 `session_event_search` 会在调用它的步骤之前立即停止,因此当前 assistant 输出和已记录工具调用无法匹配自身。直接目标在跟踪、事件或标题读取前完成授权。血缘输出会用不含隐藏会话 id 的标记替换未授权祖先和后代边界。
71
+ 本消费方建立在一个分离与三项承诺之上:
17
72
 
18
- 每个可信 `ctx.sessionQuery` 调用都会经过一个模型边界净化器。首先检查调用方取消,并精确保留。可获取的语料库诊断信息和提供方诊断信息(包括可安全检查的嵌套原因)会尽力记录到内部日志;不可打印的失败使用固定日志占位符。诊断格式化和错误分类各自独立受保护,因此不可打印的原因无法逃逸,也无法阻止已安全分类的外层错误;不安全的分类或日志记录则回退到固定 `SESSION_QUERY_TOOL_FAILED` 代码和消息。本地参数验证和授权错误保留精确的工具自有消息。
73
+ - **窄而只读的工具。** 五个带扁平 snake-case schema 的工具,每个都引导一个后续步骤;游标、偏移、分页大小或模型可控上限永远不会到达模型。
74
+ - **授权来自调用方,绝不由模型提供。** 调用方身份来自 `ToolExecution.exec.agent`;工作区是字符串精确 `cwd` 相等,并对照每次结果观察到的 header 重新校验。
75
+ - **一个模型边界净化器。** 每个可信 `ctx.sessionQuery` 调用都经过服务边界,它保留取消并包含诊断与分类失败。
76
+ - **不引入第二种截断格式。** 结果保持完整;通用 spill 策略负责有界内联输出。
19
77
 
20
- 该包刻意不执行字节或字符截断,也不导入 spill 后端。需要限制内联输出的部署应挂载 `@deepseek-ai/dsh-spill-policy`,它可在执行后替换已渲染文本,同时保留完整结果。
78
+ 设计历史记录在[面向模型的会话查询工具笔记](../../../.agents/notes/implemented/feature/2026-07-24-model-facing-session-query-tools.zh.md)与 [session-search-not-shipped-default 笔记](../../../.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md)中。
21
79
 
80
+ ### 源码地图
81
+
82
+ | 文件 | 职责 |
83
+ |---|---|
84
+ | [`src/index.ts`](src/index.ts) | 插件入口:配置、提示词章节、五个工具注册 |
85
+ | [`src/input.ts`](src/input.ts) | 模型 schema、参数规范化、过滤器构造 |
86
+ | [`src/workspace-access.ts`](src/workspace-access.ts) | 调用方身份、工作区授权、标题访问、血缘投影 |
87
+ | [`src/service-boundary.ts`](src/service-boundary.ts) | 可信调用与模型安全错误转换 |
88
+ | [`src/operations.ts`](src/operations.ts) | 五个操作工作流 |
89
+ | [`src/presentation.ts`](src/presentation.ts) | 文本结果渲染与工具调用卡片 |
90
+
91
+ ### 操作流程
92
+
93
+ 每个执行器先派生调用方,把模型的参数规范化为服务过滤器,对照调用方工作区授权目标(或请求的父 id),然后通过服务边界收集结果。两个搜索工具在观察世代仍有效时内部翻页消费提供方游标,停在 `maxSearchResults`;由于一次搜索会消费与世代绑定的提供方游标,两个搜索工具与同级工具调用排他执行,而三个精确追踪/读取工具选择并行执行。血缘输出用不含隐藏会话 id 的标记替换未授权祖先与后代边界。
94
+
95
+ </details>
96
+
97
+ -----
98
+
99
+ <a id="further-exploration"></a>
100
+ ## 进一步探索
101
+
102
+ 当包级约定不够用时阅读以下页面。它们从工具表面逐步进入底层服务、schema 目录与设计证据。
103
+
104
+ - [生成的工具目录](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-session-query)——模型看到的五个工具 schema。
105
+ - [dsh-session-query](../session-query/README.zh.md)——这些工具调用的服务。
106
+ - [dsh-session-query-sqlite](../session-query-sqlite/README.zh.md)——两个搜索工具背后的全文后端。
107
+ - [会话查询子系统参考](../../../docs/subsystems/session-query.zh.md)——工具之下的类型级约定。
108
+ - [面向模型的会话查询工具](../../../.agents/notes/implemented/feature/2026-07-24-model-facing-session-query-tools.zh.md)——工作区授权、无游标结果与 spill 决策。
109
+
110
+ -----
111
+
112
+ <a id="model-experience"></a>
22
113
  ## 模型体验
23
114
 
24
115
  ### 系统提示词
25
116
 
26
- #### 模型看到的内容
117
+ #### 模型看到什么
27
118
 
28
119
  模型会收到一个固定的既往历史指引章节。
29
120
 
@@ -39,27 +130,27 @@ Use session_search to find relevant work from prior sessions, or session_event_s
39
130
 
40
131
  #### KV Cache 影响
41
132
 
42
- 插件和指引文本不变时,前缀稳定。
133
+ 插件与指引文本不变时,前缀稳定。
43
134
 
44
135
  ### 工具 schema
45
136
 
46
- #### 模型看到的内容
137
+ #### 模型看到什么
47
138
 
48
- 模型会看到生成的 [`session_search`、`session_event_search`、`session_trace`、`session_event_trace` 和 `session_event_read` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-session-query)。搜索过滤器会增加固定 schema token,而游标、工作区路径、输出分页和模型可控结果上限仍不存在。
139
+ 模型会看到生成的 [`session_search`、`session_event_search`、`session_trace`、`session_event_trace` 与 `session_event_read` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-session-query)。搜索过滤器会增加固定 schema token,而游标、工作区路径、输出分页与模型可控结果上限仍不存在。
49
140
 
50
141
  #### Token 影响
51
142
 
52
- 可见期间,每次请求都会发送 5 个固定只读 schema。
143
+ 可见期间,每次请求都会发送五个固定只读 schema。
53
144
 
54
145
  #### KV Cache 影响
55
146
 
56
- 工具可见性和定义不变时,前缀稳定。
147
+ 工具可见性与定义不变时,前缀稳定。
57
148
 
58
149
  ### 工具结果
59
150
 
60
- #### 模型看到的内容
151
+ #### 模型看到什么
61
152
 
62
- 每次成功调用都会发出一个纯文本块。搜索结果包含标题和最佳匹配摘录;跟踪包含全部已授权关系;事件读取包含未经删节的目标 JSON。通用 spill 策略可以将过大的内联文本替换为预览、不透明定位信息和取回指引。
153
+ 每次成功调用都会发出一个纯文本块。搜索结果包含标题与最佳匹配摘录;追踪包含全部已授权关系;事件读取包含未经删节的目标 JSON。通用 spill 策略可以用其预览、不透明定位信息与取回指引替换过大的内联文本。
63
154
 
64
155
  #### Token 影响
65
156
 
@@ -69,8 +160,27 @@ Use session_search to find relevant work from prior sessions, or session_event_s
69
160
 
70
161
  仅追加的结果文本位于可重用请求前缀之后,不会使较早的缓存条目失效。
71
162
 
72
- ## 已知限制与暂缓事项
163
+ ## 已知限制与延期工作
164
+
165
+ <a id="known-limitations-and-deferred-work"></a>
166
+
167
+
168
+ 这些限制说明本包何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是任务积压。
169
+
170
+ - **搜索有上限且无延续**——搜索最多返回部署上限,匹配更多时会请模型缩小查询;不提供延续 token。
171
+ - **保守的工作区身份**——工作区身份是字符串精确 `cwd` 相等,因此符号链接等价的路径不共享权限。
172
+ - **无 spill 策略时内联载荷**——未挂载通用 spill 策略的自定义组合会以内联方式接收完整追踪与事件载荷。
173
+
174
+ <a id="dev-note"></a>
175
+ ### 开发备注
176
+
177
+ <details>
178
+ <summary>维护者的工作上下文——点击展开</summary>
179
+
180
+ 本开发备注是维护者的工作上下文:开放设计问题与尚未决定的探索方向。它明确不具权威性——已交付的行为、限制与既定理由以上文、包代码和相关 Agent Note 为准。
181
+
182
+ #### 未来:更宽泛的工作区语义
183
+
184
+ 字符串精确 `cwd` 相等是刻意保守的选择;符号链接感知或规范路径的工作区身份会改变哪些会话共享权限,尚未决定。
73
185
 
74
- - 搜索最多返回部署上限,匹配更多时会请模型缩小查询;不提供延续 token。
75
- - 工作区身份使用保守的字符串精确 `cwd` 相等性,因此符号链接等价的路径不共享权限。
76
- - 未挂载通用 spill 策略的自定义组合会以内联方式接收完整跟踪和事件载荷。
186
+ </details>
package/lib/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
2
  import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
3
3
  import { defineTool } from "@deepseek-ai/dsh-tools";
4
- import { SessionId } from "@deepseek-ai/dsh-session";
4
+ import { brandString } from "@deepseek-ai/dsh-brand";
5
5
  import { SessionQueryError, extractSessionEventText } from "@deepseek-ai/dsh-session-query";
6
6
  import { HarnessError } from "@deepseek-ai/dsh-llm";
7
7
  //#region lib/types/input.js
@@ -134,7 +134,7 @@ function buildSessionFilters(args) {
134
134
  assertNonEmptyArray("session_ids", args.session_ids);
135
135
  filters.push({
136
136
  kind: "id",
137
- values: args.session_ids.map(SessionId)
137
+ values: args.session_ids.map((value) => brandString(value))
138
138
  });
139
139
  }
140
140
  const created = timestampRange("created_at", args.created_at_from, args.created_at_to);
@@ -154,7 +154,7 @@ function buildSessionFilters(args) {
154
154
  function materializeParentSessionIds(values) {
155
155
  if (values === void 0) return void 0;
156
156
  assertNonEmptyArray("parent_session_ids", values);
157
- return [...new Set(values.map(SessionId))];
157
+ return [...new Set(values.map((value) => brandString(value)))];
158
158
  }
159
159
  function buildEventFilters(input) {
160
160
  const filters = [];
@@ -440,17 +440,18 @@ const serviceBoundary = {
440
440
  *
441
441
  * @module @deepseek-ai/dsh-tool-session-query/workspace-access
442
442
  */
443
- function callerOf(exec) {
443
+ function callerOf(exec, ctx) {
444
444
  const agent = exec.agent;
445
445
  if (agent === void 0) throw new HarnessError("session query tools require an agent-bound caller", "SESSION_QUERY_TOOL_MISSING_AGENT");
446
446
  return {
447
447
  id: agent.session.id,
448
448
  header: agent.session.header,
449
- events: agent.session.events
449
+ events: agent.session.events,
450
+ boundary: ctx.sessionProjections.stateOf(agent.session, "turnBoundary")
450
451
  };
451
452
  }
452
453
  function targetId(args, caller) {
453
- return args.session_id === void 0 ? caller.id : SessionId(args.session_id);
454
+ return args.session_id === void 0 ? caller.id : brandString(args.session_id);
454
455
  }
455
456
  async function authorizeTarget(ctx, caller, target, signal) {
456
457
  if (target === caller.id) return;
@@ -745,7 +746,7 @@ const presentation = {
745
746
  * @module @deepseek-ai/dsh-tool-session-query/operations
746
747
  */
747
748
  async function executeSessionSearch(ctx, args, exec, maxResults) {
748
- const caller = workspaceAccess.callerOf(exec);
749
+ const caller = workspaceAccess.callerOf(exec, ctx);
749
750
  const cwd = caller.header.cwd;
750
751
  if (cwd === void 0) throw new HarnessError("cross-session search is unavailable because the caller session has no workspace", "SESSION_QUERY_TOOL_UNAUTHORIZED");
751
752
  const query = toolInput.normalizeQuery(args.query);
@@ -785,15 +786,15 @@ async function executeSessionSearch(ctx, args, exec, maxResults) {
785
786
  return presentation.formatSessionSearch(collected, titles, authorizedParents);
786
787
  }
787
788
  async function executeEventSearch(ctx, args, exec, maxResults) {
788
- const caller = workspaceAccess.callerOf(exec);
789
+ const caller = workspaceAccess.callerOf(exec, ctx);
789
790
  const sessionId = workspaceAccess.targetId(args, caller);
790
791
  await workspaceAccess.authorizeTarget(ctx, caller, sessionId, exec.signal);
791
792
  const query = toolInput.normalizeQuery(args.query);
792
793
  const range = toolInput.sequenceRange(args.seq_from, args.seq_to);
793
794
  if (sessionId === caller.id) {
794
- const stepStart = caller.events.findLast((event) => event.type === "step/start");
795
- if (stepStart === void 0) throw new HarnessError("current-session search requires an active step boundary", "SESSION_QUERY_TOOL_NO_CURRENT_STEP");
796
- range.to = Math.min(range.to ?? Number.MAX_SAFE_INTEGER, stepStart.seq - 1);
795
+ const stepStartSeq = caller.boundary?.lastStepStartSeq;
796
+ if (stepStartSeq === void 0) throw new HarnessError("current-session search requires an active step boundary", "SESSION_QUERY_TOOL_NO_CURRENT_STEP");
797
+ range.to = Math.min(range.to ?? Number.MAX_SAFE_INTEGER, (stepStartSeq ?? 0) - 1);
797
798
  }
798
799
  const title = await workspaceAccess.readTitle(ctx, caller, sessionId, exec.signal);
799
800
  if (range.from !== void 0 && range.to !== void 0 && range.from > range.to) return presentation.formatEventSearch(sessionId, title, {
@@ -821,7 +822,7 @@ async function executeEventSearch(ctx, args, exec, maxResults) {
821
822
  return presentation.formatEventSearch(sessionId, title, collected);
822
823
  }
823
824
  async function executeSessionTrace(ctx, args, exec) {
824
- const caller = workspaceAccess.callerOf(exec);
825
+ const caller = workspaceAccess.callerOf(exec, ctx);
825
826
  const sessionId = workspaceAccess.targetId(args, caller);
826
827
  await workspaceAccess.authorizeTarget(ctx, caller, sessionId, exec.signal);
827
828
  const trace = await serviceBoundary.call(ctx, exec.signal, "session lineage trace", () => ctx.sessionQuery.traceSession(sessionId, exec.signal));
@@ -847,7 +848,7 @@ async function executeSessionTrace(ctx, args, exec) {
847
848
  }
848
849
  async function executeEventTrace(ctx, args, exec) {
849
850
  toolInput.assertNonNegativeSafeInteger("seq", args.seq);
850
- const caller = workspaceAccess.callerOf(exec);
851
+ const caller = workspaceAccess.callerOf(exec, ctx);
851
852
  const sessionId = workspaceAccess.targetId(args, caller);
852
853
  await workspaceAccess.authorizeTarget(ctx, caller, sessionId, exec.signal);
853
854
  const trace = await serviceBoundary.call(ctx, exec.signal, "event trace", () => ctx.sessionQuery.traceEvent({
@@ -862,7 +863,7 @@ async function executeEventRead(ctx, args, exec) {
862
863
  toolInput.assertNonNegativeSafeInteger("seq", args.seq);
863
864
  if (args.before !== void 0) toolInput.assertNonNegativeSafeInteger("before", args.before);
864
865
  if (args.after !== void 0) toolInput.assertNonNegativeSafeInteger("after", args.after);
865
- const caller = workspaceAccess.callerOf(exec);
866
+ const caller = workspaceAccess.callerOf(exec, ctx);
866
867
  const sessionId = workspaceAccess.targetId(args, caller);
867
868
  await workspaceAccess.authorizeTarget(ctx, caller, sessionId, exec.signal);
868
869
  const window = await serviceBoundary.call(ctx, exec.signal, "event read", () => ctx.sessionQuery.readEvent({
@@ -921,7 +922,8 @@ const name = "tool-session-query";
921
922
  const inject = [
922
923
  "tools",
923
924
  "systemPrompt",
924
- "sessionQuery"
925
+ "sessionQuery",
926
+ "sessionProjections"
925
927
  ];
926
928
  /** Default maximum number of authorized search hits returned by one call. */
927
929
  const DEFAULT_MAX_SEARCH_RESULTS = 100;
@@ -945,7 +947,7 @@ function apply(ctx, config) {
945
947
  const resolved = resolveConfig(config);
946
948
  ctx.systemPrompt.section({
947
949
  name: "tool:session-query",
948
- order: 113,
950
+ order: ctx.systemPrompt.getSectionOrder("TOOL_SESSION_QUERY"),
949
951
  text: PROMPT_TEXT
950
952
  });
951
953
  ctx.tools.register(defineTool({
@@ -5,12 +5,15 @@
5
5
  */
6
6
  import type { Context } from '@deepseek-ai/cordis';
7
7
  import { type SessionEvent, type SessionHeader, type SessionId as SessionIdValue } from '@deepseek-ai/dsh-session';
8
+ import type { TurnBoundaryProjection } from '@deepseek-ai/dsh-agent';
8
9
  import type { SessionLineageNode, SessionRecord } from '@deepseek-ai/dsh-session-query';
9
10
  import type { ToolRunContext } from '@deepseek-ai/dsh-tools';
10
11
  interface Caller {
11
12
  readonly id: SessionIdValue;
12
13
  readonly header: SessionHeader;
13
14
  readonly events: readonly SessionEvent[];
15
+ /** The caller's own-session boundary fold (the `turnBoundary` projection). */
16
+ readonly boundary: TurnBoundaryProjection | undefined;
14
17
  }
15
18
  interface TitleView {
16
19
  readonly text: string;
@@ -28,7 +31,7 @@ interface DescendantVisit {
28
31
  readonly depth: number;
29
32
  readonly next: DescendantVisit | undefined;
30
33
  }
31
- declare function callerOf(exec: ToolRunContext): Caller;
34
+ declare function callerOf(exec: ToolRunContext, ctx: Context): Caller;
32
35
  declare function targetId(args: {
33
36
  readonly session_id?: string;
34
37
  }, caller: Caller): SessionIdValue;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-tool-session-query",
3
3
  "description": "Workspace-authorized model-facing session history search, trace, and event read tools",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,32 +32,37 @@
32
32
  ],
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
36
- "@deepseek-ai/dsh-session-query": "^0.1.1-rc.2",
37
- "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
38
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
39
- "@deepseek-ai/dsh-timeout": "^0.1.1-rc.2",
40
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
41
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
42
- "@deepseek-ai/cordis": "^4.0.1"
35
+ "@deepseek-ai/dsh-agent": "^0.1.2-alpha.3",
36
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
37
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.3",
38
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.3",
39
+ "@deepseek-ai/dsh-session-query": "^0.1.2-alpha.3",
40
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.3",
41
+ "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.3",
42
+ "@deepseek-ai/dsh-tools": "^0.1.2-alpha.3",
43
+ "@deepseek-ai/dsh-session": "^0.1.2-alpha.3",
44
+ "@deepseek-ai/cordis": "^4.0.2"
43
45
  },
44
46
  "dependencies": {
45
- "@deepseek-ai/schemastery": "^3.18.1"
47
+ "@deepseek-ai/schemastery": "^3.18.2",
48
+ "@deepseek-ai/dsh-brand": "^0.1.2-alpha.3"
46
49
  },
47
50
  "devDependencies": {
48
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
51
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
52
- "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2",
53
- "@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.1-rc.2",
54
- "@deepseek-ai/dsh-session-query": "^0.1.1-rc.2",
55
- "@deepseek-ai/dsh-session-query-sqlite": "^0.1.1-rc.2",
56
- "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
57
- "@deepseek-ai/dsh-session-title": "^0.1.1-rc.2",
58
- "@deepseek-ai/dsh-timeout": "^0.1.1-rc.2",
59
- "@deepseek-ai/dsh-tool-call-timeout-policy": "^0.1.1-rc.2",
60
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
61
- "@deepseek-ai/cordis": "^4.0.1"
51
+ "@deepseek-ai/cordis": "^4.0.2",
52
+ "@deepseek-ai/dsh-agent-loop": "^0.1.2-alpha.3",
53
+ "@deepseek-ai/dsh-agent": "^0.1.2-alpha.3",
54
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
55
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.3",
56
+ "@deepseek-ai/dsh-session": "^0.1.2-alpha.3",
57
+ "@deepseek-ai/dsh-session-persistence": "^0.1.2-alpha.3",
58
+ "@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.2-alpha.3",
59
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.3",
60
+ "@deepseek-ai/dsh-session-query": "^0.1.2-alpha.3",
61
+ "@deepseek-ai/dsh-session-query-sqlite": "^0.1.2-alpha.3",
62
+ "@deepseek-ai/dsh-session-title": "^0.1.2-alpha.3",
63
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.3",
64
+ "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.3",
65
+ "@deepseek-ai/dsh-tool-call-timeout-policy": "^0.1.2-alpha.3",
66
+ "@deepseek-ai/dsh-tools": "^0.1.2-alpha.3"
62
67
  }
63
68
  }