@deepseek-ai/dsh-session-title-llm 0.2.1-alpha.1 → 0.2.1-alpha.2

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
@@ -3,44 +3,44 @@
3
3
  # After editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/session/session-title-llm/README.md
5
5
  /:
6
- en: da5040a980850a60
7
- zh: 0a1c0f6afbfa6c9e
6
+ en: 129d1901a10435e8
7
+ zh: ac0143c8ea8b82ee
8
8
  /deepseek-ai-dsh-session-title-llm:
9
9
  en: 7ef6dbec913fd508
10
10
  zh: 87c2448be60fb88e
11
11
  /deepseek-ai-dsh-session-title-llm/summary:
12
- en: 741cd917e857bd99
13
- zh: 43c290b6baf222e6
12
+ en: 6cc16d88b07242a4
13
+ zh: 76208dee63c2fcda
14
14
  /deepseek-ai-dsh-session-title-llm/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-session-title-llm/use-this-package:
18
- en: fa90841c0783ae27
19
- zh: 8fbd293f8050d345
20
- /deepseek-ai-dsh-session-title-llm/use-this-package/registering-a-provider:
21
- en: cf61c021b1bdb52f
22
- zh: dac17588e4143815
18
+ en: 1a4681db86d285e2
19
+ zh: 7a95a65b85afdb52
20
+ /deepseek-ai-dsh-session-title-llm/use-this-package/executing-a-provider-request:
21
+ en: d50165ad16f078f4
22
+ zh: b22c2bd7964c05a2
23
23
  /deepseek-ai-dsh-session-title-llm/use-this-package/route-and-failure-contract:
24
- en: 400a69851b523f0b
25
- zh: 90c147838ba38f82
24
+ en: 9b9251b3acc75bcf
25
+ zh: a508ebd71ec9c227
26
26
  /deepseek-ai-dsh-session-title-llm/use-this-package/configuration:
27
- en: 3c53156bd151068b
28
- zh: 2bf03f0831025e78
27
+ en: b317338d2d5335c6
28
+ zh: b21543c2f97c7694
29
29
  /deepseek-ai-dsh-session-title-llm/understand-the-implementation:
30
30
  en: aa0fd15305df90bb
31
31
  zh: d28e3a28bb324167
32
32
  /deepseek-ai-dsh-session-title-llm/understand-the-implementation/design-concept:
33
- en: be8c34c44b1a8a90
34
- zh: 2a308143c209b5d2
33
+ en: c7bb70f9f785bfca
34
+ zh: ad0b375fb2de6dfa
35
35
  /deepseek-ai-dsh-session-title-llm/understand-the-implementation/source-map:
36
- en: 0fdc928704abdd3a
37
- zh: bd4c0a7dd47578cf
36
+ en: ee1ac7a50e65d430
37
+ zh: 2c97dd5cc71e8f22
38
38
  /deepseek-ai-dsh-session-title-llm/understand-the-implementation/request-flow:
39
- en: 4a4ca58e3ae2e075
40
- zh: daf4a642d815833b
39
+ en: b3f23a8c2c8b38e3
40
+ zh: de612ea07796fe9d
41
41
  /deepseek-ai-dsh-session-title-llm/further-exploration:
42
- en: 641f31c35c48916b
43
- zh: 8e809fbdfef61b61
42
+ en: d9844c0fc3e16c5c
43
+ zh: 1e0c0b4b5d566972
44
44
  /deepseek-ai-dsh-session-title-llm/model-experience:
45
45
  en: 215e7ba838619b7b
46
46
  zh: a311da3843709f90
@@ -48,17 +48,17 @@
48
48
  en: 7dcc6f74474f78e7
49
49
  zh: 64cffa0b4d94c69d
50
50
  /deepseek-ai-dsh-session-title-llm/model-experience/auxiliary-title-request/what-the-model-sees:
51
- en: d3f50a8dab65c53f
52
- zh: 6d4f2e4183564e84
51
+ en: 7295cce9bf6e7008
52
+ zh: 40d63f0f772f15ad
53
53
  /deepseek-ai-dsh-session-title-llm/model-experience/auxiliary-title-request/token-effect:
54
- en: 4d59f31ebbff4d31
55
- zh: 6104f3b7a4c690af
54
+ en: 37b7841dcd3d25e9
55
+ zh: 1ad3050728315b49
56
56
  /deepseek-ai-dsh-session-title-llm/model-experience/auxiliary-title-request/kv-cache-effect:
57
- en: 5d3b5b7c8d8b4b67
58
- zh: 1b231d96bf6ca545
57
+ en: ebf780cb08ebf13d
58
+ zh: 0b92c06fb1ca0640
59
59
  /deepseek-ai-dsh-session-title-llm/known-limitations-and-deferred-work:
60
- en: 8510fb2c4ed03011
61
- zh: 29fb15ec84dccf56
60
+ en: 892839ae7a4a0d99
61
+ zh: a10c8cfdc300c178
62
62
  /deepseek-ai-dsh-session-title-llm/known-limitations-and-deferred-work/dev-note:
63
63
  en: e67f633dc6fe7773
64
64
  zh: 3bb0c20c93f16f98
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Shared model-backed title generation policy for users and maintainers configuring title providers or debugging auxiliary LLM requests."
2
+ description: "Shared model-execution policy for session-title providers: route, bounds, cancellation, request logging, and stream assembly."
3
3
  kind: "package-library"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- `dsh-session-title-llm` generates concise session titles from selected human messages with a consistent model request policy. Callers choose which messages contribute to each revision and may either supply a provider and model route together or use the route recorded for the current session. Required limits cap the framed input, generated output, and end-to-end duration, while caller cancellation remains effective throughout streaming. Invalid, empty, late, tool-call, or otherwise non-text results are rejected before they can replace a title.
12
+ `dsh-session-title-llm` executes one prepared auxiliary title request under consistent execution controls. Each provider supplies its own system instruction, user input, source-message attribution, reasoning selection, and output interpretation. This package resolves the route, caps the input, output, and end-to-end duration, keeps caller cancellation effective throughout streaming, records the exact model-visible request, and assembles the stream. Invalid or late operational results reject before a title can be replaced.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -25,28 +25,28 @@ English | [中文](README.zh.md)
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
- As a deployment, configure this policy through the [first-prompt](../session-title-first-prompt-llm/README.md) or [all-prompts](../session-title-all-prompts-llm/README.md) provider plugin. As a provider author, register through the shared helper instead of hand-rolling generation.
28
+ As a deployment, configure this policy through the [first-prompt](../session-title-first-prompt-llm/README.md) or [all-prompts](../../experimental/session-title-all-prompts-llm/README.md) provider plugin. As a provider author, build your own prepared input and execute it through the shared function.
29
29
 
30
- ### Registering a provider
30
+ ### Executing a provider request
31
31
 
32
- A provider plugin calls `registerSessionTitleLlmProvider(ctx, config, id, automatic, selectMessages)`; the helper validates the shared config, registers the provider on `ctx.sessionTitle`, and runs every generation through the shared policy. The two shipped plugins register the `first-prompt` and `all-prompts` cadences with their message selectors, and a second registration on the service throws.
32
+ A provider plugin registers directly on `ctx.sessionTitle` and, inside its `generate(request)`, passes `{ system, input, messageSeqs, selectReasoningEffort }` to `executeSessionTitleLlm`. The provider owns the system instruction, input framing, its reasoning selection, and output interpretation; the function owns route preparation, bounds, cancellation, request logging, and stream assembly. A second registration on the service throws.
33
+
34
+ Every request carries `currentTitle`, the latest accepted title snapshot the service captured for the call, including an accepted fallback. A provider decides whether to use it: the all-prompts provider anchors only a provider-sourced title, including one inherited from a different provider, and treats fallback, user, and absent titles as initial generation. The first-prompt provider ignores `currentTitle`.
33
35
 
34
36
  ### Route and failure contract
35
37
 
36
- `provider` and `model` overrides are optional but must be supplied together as non-empty strings. Without that pair, the helper uses the exact provider/model route captured from the current session's logged `request/header`, so an explicit refresh before any route exists needs overrides. The helper measures the final JSON-framed user prompt against `maxInputBytes` before logging or dispatch instead of truncating it, and rechecks timeout and caller cancellation while consuming the stream and after it completes, so a late successful result cannot be accepted even if an interceptor or adapter ignores abort. Malformed or empty output, tool calls, and non-stop finish reasons reject; the session-title service decides whether that rejection is an automatic warning or an explicit caller failure.
38
+ `provider` and `model` overrides are optional but must be supplied together as non-empty strings. Without that pair, the function uses the exact provider/model route captured from the current session's logged `request/header`, so an explicit refresh before any route exists needs overrides. It measures the final prepared user input against `maxInputBytes` before logging or dispatch instead of truncating it, and rechecks timeout and caller cancellation while consuming the stream and after it completes, so a late successful result cannot be accepted even if an interceptor or adapter ignores abort. It records the exact request in `session/title-llm-request` and returns the assembled content blocks plus the terminal finish and the used model identity. Operational errors, aborts, and unsupported finish reasons reject; `stop`, `tool-calls`, and `max-tokens` return to the provider for its own acceptance decision. The title request uses `maxOutputTokens` independently of the conversation's cap. Its route must have a registered adapter so preparation can resolve the request before it is recorded.
37
39
 
38
40
  ### Configuration
39
41
 
40
42
  <a id="configuration"></a>
41
43
 
42
- Every field is required except the paired route override; there are no library defaults.
44
+ Every execution field is required except the paired route override; there are no library defaults. Each provider adds its own title-length target settings, which that provider's README documents.
43
45
 
44
46
  | Key | Default | Meaning |
45
47
  |---|---|---|
46
- | `targetWords` | required | Target word count for non-CJK titles |
47
- | `targetCjkCharacters` | required | Target character count for Chinese, Japanese, or Korean titles |
48
- | `maxInputBytes` | required | UTF-8 byte ceiling for the final JSON-framed user prompt |
49
- | `maxOutputTokens` | required | Auxiliary generation token cap |
48
+ | `maxInputBytes` | required | UTF-8 byte ceiling for the prepared user input |
49
+ | `maxOutputTokens` | required | Title output-token cap, independent of conversation requests |
50
50
  | `timeoutMs` | required | End-to-end deadline within the runtime timer limit |
51
51
  | `provider`, `model` | optional | Explicit route; both or neither |
52
52
 
@@ -62,17 +62,17 @@ This section explains the generation path; the observable behavior is fully cove
62
62
 
63
63
  ### Design concept
64
64
 
65
- One shared policy so provider plugins cannot drift: config validation, route resolution, prompt framing, budget enforcement, cancellation, and output validation all live here, parameterized only by the provider's cadence and message selector.
65
+ One small shared execution policy so operational behavior cannot drift: execution-control validation, route resolution, budget enforcement, cancellation, request logging, and stream assembly live here. Prompt wording, title-length targets, reasoning selection, and output interpretation stay with each provider.
66
66
 
67
67
  ### Source map
68
68
 
69
69
  | File | Role |
70
70
  |---|---|
71
- | [`src/index.ts`](src/index.ts) | Config schema and validation, provider registration helper, request framing, dispatch, and output validation |
71
+ | [`src/index.ts`](src/index.ts) | Config schema and validation, route resolution, request bounds, dispatch, logging, and stream assembly |
72
72
 
73
73
  ### Request flow
74
74
 
75
- A generation validates the config once at registration; each revision frames the selected messages as JSON, measures the framed prompt's UTF-8 bytes against `maxInputBytes`, resolves the route (the explicit pair or the logged `request/header`), appends a log-only `session/title-llm-request` event carrying the exact dispatchable request, then streams through `ctx.llm` under a composed timeout and cancellation deadline. The dispatched envelope carries `purpose: 'session-title'` and deliberately lacks the agent loop's process-local request identity; the DeepSeek adapter maps that purpose to thinking-disabled so the small output budget is reserved for visible title text, and other adapters own their purpose-specific behavior. Output assembles into text blocks only; tool calls, malformed or empty output, and non-stop finish reasons reject, and a later model failure leaves the request record intact.
75
+ The caller builds the prepared input and frames it; the function checks the complete input against `maxInputBytes`. The provider's reasoning selector chooses at most one effort during `ctx.llm.prepareCall()`. The function records the exact input, output cap, and resolved effort in `session/title-llm-request`, then dispatches through the same captured adapter generation under the shared deadline. `purpose: 'session-title'` supplies attribution only. The request has no agent-loop identity and does not enter conversation history. Generation failures preserve the request record.
76
76
 
77
77
  </details>
78
78
 
@@ -86,7 +86,7 @@ Read these pages when the generation policy is not enough. They move from the se
86
86
  - [Session title service](../session-title/README.md) — the title service, fallback behavior, and provider registration contract.
87
87
  - [Session title subsystem](../../../docs/subsystems/session-title.md) — durable title state and the auxiliary request record.
88
88
  - [First-message title provider](../session-title-first-prompt-llm/README.md) — titles from the first eligible human message.
89
- - [All-messages title provider](../session-title-all-prompts-llm/README.md) — titles from every eligible human message.
89
+ - [All-messages title provider](../../experimental/session-title-all-prompts-llm/README.md) — titles from every eligible human message.
90
90
  - [Session package map](../README.md) — adjacent persistence, projection, title, and telemetry packages.
91
91
 
92
92
  -----
@@ -98,15 +98,15 @@ Read these pages when the generation policy is not enough. They move from the se
98
98
 
99
99
  #### What the model sees
100
100
 
101
- The title model receives a fixed system instruction to return one concise unadorned title in the input language, including the configured word and CJK-character targets. Its one user message contains a JSON array of the exact selected human messages and their seqs.
101
+ The title model receives the provider-owned system instruction and one user message containing the provider-owned input. The executor records and dispatches those exact values without reconstruction; the framing and the output instruction belong to each provider, which the [first-prompt](../session-title-first-prompt-llm/README.md) and [all-prompts](../../experimental/session-title-all-prompts-llm/README.md) READMEs document.
102
102
 
103
103
  #### Token effect
104
104
 
105
- The auxiliary request consumes tokens according to selected input size and `maxOutputTokens`. It is separate from the main agent request and does not add title text or framing to agent history. DeepSeek title calls disable thinking; the main conversation retains its configured thinking mode.
105
+ The auxiliary request consumes tokens according to the provider-prepared input size and `maxOutputTokens`. It is separate from the main agent request and does not add title text or framing to agent history. The executor applies the provider's selected reasoning effort, or the route's normal default when the selector returns `undefined`; a model that still reasons spends part of `maxOutputTokens` on it. The main conversation retains its configured thinking mode.
106
106
 
107
107
  #### KV Cache effect
108
108
 
109
- No main-request invalidation. Auxiliary cache reuse is provider-specific; the fixed instruction is reusable while the JSON message array changes with each revision.
109
+ No main-request invalidation. Auxiliary cache reuse is provider-specific: this executor dispatches the provider's exact system prompt and input, so reuse depends on how each provider frames successive revisions.
110
110
 
111
111
  ## Known Limitations and Deferred Work
112
112
 
@@ -115,8 +115,9 @@ No main-request invalidation. Auxiliary cache reuse is provider-specific; the fi
115
115
 
116
116
  These limits define the accepted generation shapes. They are current package constraints.
117
117
 
118
- - **Text output only** — the helper accepts text output and rejects tool calls; structured-output adapters and provider-specific prompt variants are not exposed.
119
- - **Whole-prompt byte ceiling** — it enforces a byte ceiling for the whole framed user prompt rather than clipping individual messages or applying a retention policy.
118
+ - **Provider-interpreted output** — the executor returns assembled content blocks and the terminal finish and does not accept or reject them; each shipped provider's README owns its acceptance policy.
119
+ - **Whole-input byte ceiling** — it rejects prepared input over `maxInputBytes` rather than truncating it.
120
+ - **Reasoning is provider-selected** — the executor applies the effort the provider returns and never chooses one; when the selector returns `undefined`, the route's normal default applies.
120
121
 
121
122
  <a id="dev-note"></a>
122
123
  ### Dev Note
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "面向用户与维护者的共享模型标题生成策略说明,用于配置标题提供方或排查辅助 LLM 请求。"
2
+ description: "面向会话标题提供方的共享模型执行策略:路由、上限、取消、请求记录与流式组装。"
3
3
  kind: "package-library"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ kind: "package-library"
9
9
 
10
10
  ## 概述
11
11
 
12
- `dsh-session-title-llm` 使用一致的模型请求策略,根据选中的用户消息生成简洁的会话标题。调用方选择每次修订包含哪些消息,以及成对提供 `provider`/`model` 路由,还是使用当前会话记录的路由。必填上限约束封装后的输入、生成输出与端到端时长,调用方取消在整个流式处理期间持续生效。无效、空、迟到、包含工具调用或其他非纯文本的结果会在替换标题前被拒绝。
12
+ `dsh-session-title-llm` 在一致且固定的执行控制下执行一次准备好的辅助标题请求。每个提供方提供自己的系统指令、用户输入、源消息归因、推理选择与输出解释。本包负责解析路由、限制输入、输出与端到端时长,在整个流式处理期间保持调用方取消有效,记录模型可见的确切请求,并组装流。无效或迟到的操作结果在替换标题前被拒绝。
13
13
 
14
14
  ## 目录
15
15
 
@@ -25,28 +25,28 @@ kind: "package-library"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 作为部署方,通过[首消息](../session-title-first-prompt-llm/README.zh.md)或[全消息](../session-title-all-prompts-llm/README.zh.md)提供方插件配置此策略。作为提供方作者,通过共享辅助函数注册,而不是手写生成逻辑。
28
+ 作为部署方,通过[首消息](../session-title-first-prompt-llm/README.zh.md)或[全消息](../../experimental/session-title-all-prompts-llm/README.zh.md)提供方插件配置此策略。作为提供方作者,构建自己的准备输入,并通过共享函数执行。
29
29
 
30
- ### 注册提供方
30
+ ### 执行提供方请求
31
31
 
32
- 提供方插件调用 `registerSessionTitleLlmProvider(ctx, config, id, automatic, selectMessages)`;辅助函数验证共享配置、在 `ctx.sessionTitle` 上注册提供方,并让每次生成都经过共享策略。两个随附插件以各自的 `first-prompt` 与 `all-prompts` 节奏和消息选择器注册;服务上的第二次注册会立即抛出。
32
+ 提供方插件直接注册到 `ctx.sessionTitle`,并在其 `generate(request)` 中把 `{ system, input, messageSeqs, selectReasoningEffort }` 传给 `executeSessionTitleLlm`。提供方负责系统指令、输入封装、自己的推理选择与输出解释;该函数负责路由准备、上限、取消、请求记录与流式组装。服务上的第二次注册会立即抛出。
33
+
34
+ 每个请求都带有 `currentTitle`,即服务在调用时捕获的最新已接纳标题快照,包括已接纳的回退标题。提供方自行决定是否使用它:全消息提供方只锚定来源为提供方的标题(包括继承自不同提供方的标题),并把回退、用户与不存在的标题视为初始生成。首消息提供方忽略 `currentTitle`。
33
35
 
34
36
  ### 路由与失败约定
35
37
 
36
- `provider` 与 `model` 覆盖项都是可选的,但必须同时作为非空字符串提供。如果没有这一对取值,辅助函数使用当前会话已记录 `request/header` 中捕获的确切提供方/模型路由,因此在任何路由出现前显式刷新时必须提供覆盖项。辅助函数在记录或分发前,依据 `maxInputBytes` 检查最终 JSON 封装用户提示词的大小,而不是将其截断,并在消费流期间与完成后重新检查超时与调用方取消,因此即使拦截器或适配器忽略 abort,也不能接受迟到的成功结果。格式错误或空输出、工具调用与非 stop 结束原因都会拒绝;会话标题服务决定该拒绝属于自动警告还是显式调用方失败。
38
+ `provider` 与 `model` 覆盖项都是可选的,但必须同时作为非空字符串提供。如果没有这一对取值,函数使用当前会话已记录 `request/header` 中捕获的确切提供方/模型路由,因此在任何路由出现前显式刷新时必须提供覆盖项。函数在记录或分发前,依据 `maxInputBytes` 检查准备好的最终用户输入的大小,而不是将其截断,并在消费流期间与完成后重新检查超时与调用方取消,因此即使拦截器或适配器忽略 abort,也不能接受迟到的成功结果。函数把确切请求记录到 `session/title-llm-request`,并返回组装后的内容块、终止结束原因与所用模型身份。操作性错误、中止与不支持的结束原因都会拒绝;`stop`、`tool-calls` 与 `max-tokens` 会返回提供方,由其自行决定是否接受。标题请求独立使用 `maxOutputTokens`,不继承对话请求的上限。其路由必须注册适配器,以便在记录前完成请求准备。
37
39
 
38
40
  ### 配置
39
41
 
40
42
  <a id="configuration"></a>
41
43
 
42
- 除成对的路由覆盖项外,每个字段都必填;库不提供默认值。
44
+ 除成对的路由覆盖项外,每个执行字段都必填;库不提供默认值。每个提供方各自添加标题长度目标设置,并由该提供方的 README 记录。
43
45
 
44
46
  | 键 | 默认值 | 含义 |
45
47
  |---|---|---|
46
- | `targetWords` | 必填 | 非 CJK 标题的目标词数 |
47
- | `targetCjkCharacters` | 必填 | 中文、日文或韩文标题的目标字符数 |
48
- | `maxInputBytes` | 必填 | 最终 JSON 封装用户提示词的 UTF-8 字节上限 |
49
- | `maxOutputTokens` | 必填 | 辅助生成的 token 上限 |
48
+ | `maxInputBytes` | 必填 | 准备好的用户输入的 UTF-8 字节上限 |
49
+ | `maxOutputTokens` | 必填 | 标题输出 token 上限,独立于对话请求 |
50
50
  | `timeoutMs` | 必填 | 运行时定时器限制内的端到端时限 |
51
51
  | `provider`, `model` | 可选 | 显式路由;二者同时提供或同时省略 |
52
52
 
@@ -62,17 +62,17 @@ kind: "package-library"
62
62
 
63
63
  ### 设计理念
64
64
 
65
- 一份共享策略让提供方插件无法漂移:配置校验、路由解析、提示词封装、预算执行、取消与输出校验都在这里,只以提供方的节奏与消息选择器为参数。
65
+ 一份小型共享执行策略,使操作行为无法漂移:执行控制校验、路由解析、预算执行、取消、请求记录与流式组装都在这里。提示词措辞、标题长度目标、推理选择与输出解释仍归各提供方所有。
66
66
 
67
67
  ### 源码地图
68
68
 
69
69
  | 文件 | 职责 |
70
70
  |---|---|
71
- | [`src/index.ts`](src/index.ts) | 配置 schema 与校验、提供方注册辅助、请求封装、分发与输出校验 |
71
+ | [`src/index.ts`](src/index.ts) | 配置 schema 与校验、路由解析、请求上限、分发、记录与流式组装 |
72
72
 
73
73
  ### 请求流程
74
74
 
75
- 生成在注册时校验一次配置;每次修订把选中的消息封装为 JSON,依据 `maxInputBytes` 检查封装提示词的 UTF-8 字节数,解析路由(显式对或已记录 `request/header`),追加一条携带确切可分发请求的仅日志 `session/title-llm-request` 事件,然后在组合的超时与取消截止时间内通过 `ctx.llm` 流式生成。分发的封套携带 `purpose: 'session-title'`,且有意不包含 agent loop 的进程本地请求身份;DeepSeek 适配器根据该用途禁用思考,使少量输出预算全部用于可见标题文本,其他适配器负责自身用途专用行为。输出只组装为文本块;工具调用、格式错误或空输出与非 stop 结束原因都会拒绝,后续模型失败会保留请求记录。
75
+ 调用方构建准备好的输入并进行封装;函数依据 `maxInputBytes` 检查完整输入。提供方的推理选择器在 `ctx.llm.prepareCall()` 期间最多选择一个强度。函数把确切输入、输出上限与解析后的强度记录到 `session/title-llm-request`,然后在共享截止时间内通过同一捕获的适配器代次分发。`purpose: 'session-title'` 仅提供归属标注。请求不带 agent loop 身份,也不进入对话历史。生成失败仍保留请求记录。
76
76
 
77
77
  </details>
78
78
 
@@ -86,7 +86,7 @@ kind: "package-library"
86
86
  - [会话标题服务](../session-title/README.zh.md)——标题服务、回退行为与提供方注册约定。
87
87
  - [会话标题子系统](../../../docs/subsystems/session-title.zh.md)——持久标题状态与辅助请求记录。
88
88
  - [首消息标题提供方](../session-title-first-prompt-llm/README.zh.md)——根据第一条符合条件的用户消息生成标题。
89
- - [全消息标题提供方](../session-title-all-prompts-llm/README.zh.md)——根据所有符合条件的用户消息生成标题。
89
+ - [全消息标题提供方](../../experimental/session-title-all-prompts-llm/README.zh.md)——根据所有符合条件的用户消息生成标题。
90
90
  - [会话包映射](../README.zh.md)——相邻的持久化、投影、标题与遥测包。
91
91
 
92
92
  -----
@@ -98,15 +98,15 @@ kind: "package-library"
98
98
 
99
99
  #### 模型看到什么
100
100
 
101
- 标题模型会收到固定系统指令,要求以输入语言返回一个简洁且无装饰的标题;该指令包含所配置的词数与 CJK 字符数目标。它唯一的用户消息包含一个 JSON 数组,其中是精确选中的用户消息及其 seq。
101
+ 标题模型会收到由提供方拥有的系统指令,以及一条包含提供方所拥有输入的用户消息。执行器记录并分发这些确切取值,不做重建;封装方式与输出指令都归提供方所有,并由[首消息](../session-title-first-prompt-llm/README.zh.md)与[全消息](../../experimental/session-title-all-prompts-llm/README.zh.md) README 记录。
102
102
 
103
103
  #### Token 影响
104
104
 
105
- 辅助请求根据所选输入大小与 `maxOutputTokens` 消耗 token。它与主 agent 请求相互独立,不会向 agent 历史增加标题文本或封装内容。DeepSeek 标题调用会关闭思考;主对话保留自身配置的思考模式。
105
+ 辅助请求根据提供方准备好的输入大小与 `maxOutputTokens` 消耗 token。它与主 agent 请求相互独立,不会向 agent 历史增加标题文本或封装内容。执行器应用提供方选定的推理强度;选择器返回 `undefined` 时使用路由的正常默认值。仍在推理的模型会把部分 `maxOutputTokens` 用于推理。主对话保留自身配置的思考模式。
106
106
 
107
107
  #### KV Cache 影响
108
108
 
109
- 不会使主请求的 KV Cache 失效。辅助缓存复用由提供方决定;固定指令可复用,而 JSON 消息数组会随每次修订变化。
109
+ 不会使主请求的 KV Cache 失效。辅助缓存复用由提供方决定:此执行器分发提供方确切的系统提示词与输入,因此复用取决于各提供方对各次修订的封装方式。
110
110
 
111
111
  ## 已知限制与延期工作
112
112
 
@@ -115,8 +115,9 @@ kind: "package-library"
115
115
 
116
116
  这些限制定义被接受的生成形态。它们是当前包约束。
117
117
 
118
- - **仅文本输出**——辅助函数只接受文本输出并拒绝工具调用;不公开结构化输出适配器或提供方专用提示词变体。
119
- - **整体提示词字节上限**——它对整个封装用户提示词强制执行字节上限,而不是剪裁单条消息或应用保留策略。
118
+ - **输出由提供方解释**——执行器返回组装后的内容块与终止结束原因,不决定接受或拒绝;各随附提供方的 README 记录其接纳策略。
119
+ - **整体输入字节上限**——它对超过 `maxInputBytes` 的准备输入直接拒绝,而不是将其截断。
120
+ - **推理由提供方选择**——执行器只应用提供方返回的强度,绝不自行选择;选择器返回 `undefined` 时使用路由的正常默认值。
120
121
 
121
122
  <a id="dev-note"></a>
122
123
  ### 开发备注
package/lib/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
2
  import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
3
3
  import { MAX_TIMER_DELAY_MS, deadline } from "@deepseek-ai/dsh-timeout";
4
- import { deepFreeze } from "@deepseek-ai/dsh-util-values";
5
- import { SessionTitleProviderId, normalizeSessionTitle } from "@deepseek-ai/dsh-session-title";
4
+ import { assertNever, deepFreeze } from "@deepseek-ai/dsh-util-values";
6
5
  //#region lib/types/index.js
7
6
  /**
8
- * Shared route, framing, timeout, assembly, and validation policy for
9
- * model-backed session-title providers.
7
+ * Shared execution policy for model-backed session-title providers: route
8
+ * preparation, input/token/time bounds, cancellation, exact auxiliary request
9
+ * logging, and stream assembly. Title wording, length targets, reasoning
10
+ * selection, and output interpretation belong to each provider.
10
11
  * @module @deepseek-ai/dsh-session-title-llm
11
12
  */
12
13
  var __addDisposableResource = function(env, value, async) {
@@ -71,8 +72,6 @@ var __disposeResources = (function(SuppressedError) {
71
72
  const SESSION_TITLE_TIMEOUT_CODE = "SESSION_TITLE_TIMEOUT";
72
73
  /** Shared Loader field schemas with no library defaults. */
73
74
  const SessionTitleLlmConfigFields = {
74
- targetWords: z.number().step(1).min(1).required(),
75
- targetCjkCharacters: z.number().step(1).min(1).required(),
76
75
  maxInputBytes: z.number().step(1).min(1).required(),
77
76
  maxOutputTokens: z.number().step(1).min(1).required(),
78
77
  timeoutMs: z.number().step(1).min(1).max(MAX_TIMER_DELAY_MS).required(),
@@ -81,10 +80,8 @@ const SessionTitleLlmConfigFields = {
81
80
  };
82
81
  /** Shared Loader schema with no library defaults. */
83
82
  const SessionTitleLlmConfigSchema = z.object(SessionTitleLlmConfigFields);
84
- /** Complete configuration key set for direct construction validation. */
83
+ /** Complete execution-control key set for direct construction validation. */
85
84
  const CONFIG_KEYS = new Set([
86
- "targetWords",
87
- "targetCjkCharacters",
88
85
  "maxInputBytes",
89
86
  "maxOutputTokens",
90
87
  "timeoutMs",
@@ -96,17 +93,15 @@ function assertPositiveInteger(name, value) {
96
93
  if (!Number.isInteger(value) || value <= 0) throw new Error(`session-title-llm: ${name} must be a positive integer`);
97
94
  }
98
95
  /**
99
- * Validate and detach required model-provider configuration.
100
- * @param config - untrusted plugin configuration.
101
- * @returns immutable policy with optional route absence preserved.
96
+ * Validate and detach required execution controls.
97
+ * @param config - untrusted execution configuration.
98
+ * @returns immutable controls with optional route absence preserved.
102
99
  */
103
100
  function resolveSessionTitleLlmConfig(config) {
104
101
  const candidate = config;
105
102
  if (candidate === null || typeof candidate !== "object") throw new Error("session-title-llm: configuration is required");
106
103
  const value = candidate;
107
104
  for (const key of Object.keys(value)) if (!CONFIG_KEYS.has(key)) throw new Error(`session-title-llm: unknown config key "${key}"`);
108
- assertPositiveInteger("targetWords", value.targetWords);
109
- assertPositiveInteger("targetCjkCharacters", value.targetCjkCharacters);
110
105
  assertPositiveInteger("maxInputBytes", value.maxInputBytes);
111
106
  assertPositiveInteger("maxOutputTokens", value.maxOutputTokens);
112
107
  assertPositiveInteger("timeoutMs", value.timeoutMs);
@@ -116,25 +111,6 @@ function resolveSessionTitleLlmConfig(config) {
116
111
  if (hasProvider && (typeof value.provider !== "string" || value.provider.length === 0 || typeof value.model !== "string" || value.model.length === 0)) throw new Error("session-title-llm: provider and model overrides must be non-empty strings");
117
112
  return deepFreeze({ ...value });
118
113
  }
119
- /**
120
- * Register one model-backed provider through the shared configuration and call policy.
121
- * @param ctx - context exposing the title and LLM services.
122
- * @param config - untrusted required deployment policy.
123
- * @param id - stable plugin id recorded with generated titles.
124
- * @param automatic - provider-owned automatic generation cadence.
125
- * @param selectMessages - exact source-message selection for one revision.
126
- */
127
- function registerSessionTitleLlmProvider(ctx, config, id, automatic, selectMessages) {
128
- const resolved = resolveSessionTitleLlmConfig(config);
129
- const titleProvider = SessionTitleProviderId(id);
130
- ctx.sessionTitle.register({
131
- id: titleProvider,
132
- automatic,
133
- async generate(request) {
134
- return generateSessionTitleWithLlm(ctx, resolved, request, selectMessages(request.messages), titleProvider);
135
- }
136
- });
137
- }
138
114
  /** Resolve the explicit pair or the exact route captured from `request/header`. */
139
115
  function resolveRoute(config, request) {
140
116
  if (config.provider !== void 0 && config.model !== void 0) return {
@@ -144,44 +120,44 @@ function resolveRoute(config, request) {
144
120
  if (request.route === void 0) throw new Error("session-title-llm: no logged request route is available; configure provider and model together");
145
121
  return request.route;
146
122
  }
147
- /** Stable language-aware system instruction shared by both provider plugins. */
148
- function systemPrompt(config) {
149
- return [
150
- "Create a concise title for an AI coding-assistant session from the supplied human messages.",
151
- "Return only the title on one line, **in plain text of natural language**, with no quotes, prefix, explanation, Markdown, XML, or terminal control codes. No code is allowed.",
152
- "Use the language of the messages.",
153
- `Aim for about ${config.targetWords} words in non-CJK languages or ${config.targetCjkCharacters} CJK characters.`
154
- ].join("\n");
155
- }
156
- /** Frame exact messages as JSON so user text cannot break structural delimiters. */
157
- function frameMessages(messages) {
158
- return `Generate the session title from this JSON array of human messages:\n${JSON.stringify(messages)}`;
159
- }
160
- /** Translate terminal finish reasons into an auxiliary-call failure. */
161
- function finishError(finish) {
123
+ /**
124
+ * Classify one terminal finish reason. Operational failures throw; every other
125
+ * terminal kind is returned for the provider to accept or reject.
126
+ * @param finish - terminal finish reason from the assembled stream.
127
+ * @returns the provider-facing finish reason.
128
+ * @throws {Error} on a provider or caller abort, or an impossible finish variant.
129
+ */
130
+ function terminalFinish(finish) {
162
131
  switch (finish.kind) {
163
- case "stop": return;
132
+ case "stop":
133
+ case "tool-calls":
134
+ case "max-tokens": return finish;
164
135
  case "error":
165
136
  case "aborted": {
166
137
  const error = new Error(finish.failure.message);
167
138
  error.code = finish.failure.code;
168
- return error;
139
+ throw error;
169
140
  }
170
- case "max-tokens": return /* @__PURE__ */ new Error("session-title-llm: title output reached maxOutputTokens");
171
- case "tool-calls": return /* @__PURE__ */ new Error("session-title-llm: title model unexpectedly requested a tool");
172
- default: return /* @__PURE__ */ new Error(`session-title-llm: unsupported finish reason "${String(finish.kind)}"`);
141
+ /* v8 ignore next -- closed FinishReason union exhaustiveness guard */
142
+ default: return assertNever(finish, "FinishReason");
173
143
  }
174
144
  }
175
145
  /**
176
- * Generate one title through the shared auxiliary LLM call.
146
+ * Execute one prepared auxiliary title request.
147
+ *
148
+ * The provider owns the system prompt, user input, reasoning selection, and
149
+ * output interpretation. This function owns route preparation, the final input
150
+ * byte limit, the output-token cap, the end-to-end deadline, cancellation, the
151
+ * exact `session/title-llm-request` record, and stream assembly.
177
152
  * @param ctx - context exposing the registered LLM service.
178
- * @param config - validated model-provider policy.
179
- * @param request - service-owned session, route, message snapshot, and cancellation.
180
- * @param selectedMessages - exact provider-selected subset to frame and attribute.
153
+ * @param config - validated execution controls.
154
+ * @param request - service-owned session, route, message snapshot, current title, and cancellation.
181
155
  * @param titleProvider - registered title-provider identity recorded with the request.
182
- * @returns normalized non-empty title, exact source seqs, and used model route.
156
+ * @param prepared - provider system prompt, input, source-message seqs, and reasoning selector.
157
+ * @returns assembled response blocks, terminal finish, and the exact route used.
158
+ * @throws {Error} when input bounds, route preparation, the deadline, cancellation, or an operational finish failure occurs.
183
159
  */
184
- async function generateSessionTitleWithLlm(ctx, config, request, selectedMessages, titleProvider) {
160
+ async function executeSessionTitleLlm(ctx, config, request, titleProvider, prepared) {
185
161
  const env_1 = {
186
162
  stack: [],
187
163
  error: void 0,
@@ -189,54 +165,57 @@ async function generateSessionTitleWithLlm(ctx, config, request, selectedMessage
189
165
  };
190
166
  try {
191
167
  request.signal.throwIfAborted();
192
- if (selectedMessages.length === 0) throw new Error("session-title-llm: at least one source message is required");
193
- const framedInput = frameMessages(selectedMessages);
194
- const inputBytes = Buffer.byteLength(framedInput, "utf8");
168
+ if (prepared.messageSeqs.length === 0) throw new Error("session-title-llm: at least one source message is required");
169
+ const inputBytes = Buffer.byteLength(prepared.input, "utf8");
195
170
  if (inputBytes > config.maxInputBytes) throw new Error(`session-title-llm: input is ${inputBytes} bytes, exceeding maxInputBytes ${config.maxInputBytes}`);
196
171
  const route = resolveRoute(config, request);
197
172
  const messages = [createUserMessage({
198
173
  content: [{
199
174
  type: "text",
200
- text: framedInput
175
+ text: prepared.input
201
176
  }],
202
177
  source: { kind: "dsh-session-title-llm" }
203
178
  })];
204
- const system = systemPrompt(config);
205
179
  const callDeadline = __addDisposableResource(env_1, deadline(request.signal, config.timeoutMs, SESSION_TITLE_TIMEOUT_CODE), false);
180
+ const maxTokens = config.maxOutputTokens;
181
+ const call = await ctx.llm.prepareCall({
182
+ ...route,
183
+ maxTokens
184
+ }, callDeadline.signal, (controls, model) => {
185
+ const effort = prepared.selectReasoningEffort(model);
186
+ return {
187
+ ...controls,
188
+ ...effort === void 0 ? {} : { reasoningEffort: effort }
189
+ };
190
+ });
206
191
  const options = deepFreeze({
207
- provider: route.provider,
208
- model: route.model,
192
+ ...call.config,
209
193
  messages,
210
- system,
211
- maxTokens: config.maxOutputTokens,
194
+ system: prepared.system,
212
195
  sessionId: request.session.id,
213
196
  purpose: "session-title",
214
197
  signal: callDeadline.signal
215
198
  });
216
199
  request.session.append("session/title-llm-request", {
217
200
  titleProvider,
218
- messageSeqs: selectedMessages.map((message) => message.seq),
201
+ messageSeqs: [...prepared.messageSeqs],
219
202
  route,
220
- system,
203
+ system: prepared.system,
221
204
  messages,
222
- maxTokens: config.maxOutputTokens
205
+ maxTokens,
206
+ ...call.config.reasoningEffort === void 0 ? {} : { reasoningEffort: call.config.reasoningEffort }
223
207
  });
224
208
  callDeadline.signal.throwIfAborted();
225
209
  const assembler = new BlockAssembler();
226
- for await (const chunk of ctx.llm.stream(options)) {
210
+ for await (const chunk of call.stream(options)) {
227
211
  callDeadline.signal.throwIfAborted();
228
212
  assembler.push(chunk);
229
213
  }
230
214
  callDeadline.signal.throwIfAborted();
231
- const terminalError = finishError(assembler.finish);
232
- if (terminalError !== void 0) throw terminalError;
233
- const blocks = assembler.blocks();
234
- if (blocks.some((block) => block.type === "tool-call")) throw new Error("session-title-llm: title output must contain text only");
235
- const title = normalizeSessionTitle(blocks.filter((block) => block.type === "text").map((block) => block.text).join(" "), Number.MAX_SAFE_INTEGER);
236
- if (title.length === 0) throw new Error("session-title-llm: title model produced no text");
215
+ const finish = terminalFinish(assembler.finish);
237
216
  return {
238
- title,
239
- messageSeqs: selectedMessages.map((message) => message.seq),
217
+ blocks: assembler.blocks(),
218
+ finish,
240
219
  model: route
241
220
  };
242
221
  } catch (e_1) {
@@ -247,4 +226,4 @@ async function generateSessionTitleWithLlm(ctx, config, request, selectedMessage
247
226
  }
248
227
  }
249
228
  //#endregion
250
- export { SESSION_TITLE_TIMEOUT_CODE, SessionTitleLlmConfigFields, SessionTitleLlmConfigSchema, generateSessionTitleWithLlm, registerSessionTitleLlmProvider, resolveSessionTitleLlmConfig };
229
+ export { SESSION_TITLE_TIMEOUT_CODE, SessionTitleLlmConfigFields, SessionTitleLlmConfigSchema, executeSessionTitleLlm, resolveSessionTitleLlmConfig };
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Shared route, framing, timeout, assembly, and validation policy for
3
- * model-backed session-title providers.
2
+ * Shared execution policy for model-backed session-title providers: route
3
+ * preparation, input/token/time bounds, cancellation, exact auxiliary request
4
+ * logging, and stream assembly. Title wording, length targets, reasoning
5
+ * selection, and output interpretation belong to each provider.
4
6
  * @module @deepseek-ai/dsh-session-title-llm
5
7
  */
6
8
  import type { Context } from '@deepseek-ai/cordis';
@@ -13,10 +15,10 @@ declare module '@deepseek-ai/dsh-llm' {
13
15
  } & ContextFormed;
14
16
  }
15
17
  }
16
- import type { Message } from '@deepseek-ai/dsh-llm';
18
+ import type { ContentBlock, FinishReason, LlmResolvedModelInfo, Message, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
17
19
  import type { SessionSeq } from '@deepseek-ai/dsh-session';
18
20
  import { SessionTitleProviderId } from '@deepseek-ai/dsh-session-title';
19
- import type { SessionTitleAutomaticMode, SessionTitleModelIdentity, SessionTitleProviderRequest, SessionTitleProviderResult, SessionTitleUserMessage } from '@deepseek-ai/dsh-session-title';
21
+ import type { SessionTitleModelIdentity, SessionTitleProviderRequest } from '@deepseek-ai/dsh-session-title';
20
22
  /** Exact model-visible request recorded before one auxiliary title dispatch. */
21
23
  export interface SessionTitleLlmRequestEventData {
22
24
  /** Registered title-provider identity responsible for the request. */
@@ -31,6 +33,8 @@ export interface SessionTitleLlmRequestEventData {
31
33
  readonly messages: Message[];
32
34
  /** Exact auxiliary output-token cap. */
33
35
  readonly maxTokens: number;
36
+ /** Resolved reasoning effort when recorded; older requests can omit it. */
37
+ readonly reasoningEffort?: ReasoningEffortId;
34
38
  }
35
39
  declare module '@deepseek-ai/dsh-session/types' {
36
40
  interface SessionEventMap {
@@ -40,15 +44,11 @@ declare module '@deepseek-ai/dsh-session/types' {
40
44
  }
41
45
  /** Capability-owned timeout reason code for auxiliary title requests. */
42
46
  export declare const SESSION_TITLE_TIMEOUT_CODE = "SESSION_TITLE_TIMEOUT";
43
- /** Required deployment policy for one model-backed title plugin. */
47
+ /** Required execution controls for one model-backed title request. */
44
48
  export interface SessionTitleLlmConfig {
45
- /** Target word count for non-CJK titles. */
46
- readonly targetWords: number;
47
- /** Target character count for Chinese, Japanese, or Korean titles. */
48
- readonly targetCjkCharacters: number;
49
- /** Maximum UTF-8 bytes in the final JSON-framed user prompt. */
49
+ /** Maximum UTF-8 bytes in the provider-prepared user input. */
50
50
  readonly maxInputBytes: number;
51
- /** Auxiliary generation output-token cap. */
51
+ /** Output-token cap for the title request, independent of conversation requests. */
52
52
  readonly maxOutputTokens: number;
53
53
  /** End-to-end auxiliary request deadline in milliseconds. */
54
54
  readonly timeoutMs: number;
@@ -57,13 +57,11 @@ export interface SessionTitleLlmConfig {
57
57
  /** Optional explicit model id; must be paired with `provider`. */
58
58
  readonly model?: string;
59
59
  }
60
- /** Validated immutable model-provider policy. */
60
+ /** Validated immutable execution controls. */
61
61
  export interface ResolvedSessionTitleLlmConfig extends SessionTitleLlmConfig {
62
62
  }
63
63
  /** Shared Loader field schemas with no library defaults. */
64
64
  export declare const SessionTitleLlmConfigFields: {
65
- targetWords: z<number, number, "defined">;
66
- targetCjkCharacters: z<number, number, "defined">;
67
65
  maxInputBytes: z<number, number, "defined">;
68
66
  maxOutputTokens: z<number, number, "defined">;
69
67
  timeoutMs: z<number, number, "defined">;
@@ -73,30 +71,57 @@ export declare const SessionTitleLlmConfigFields: {
73
71
  /** Shared Loader schema with no library defaults. */
74
72
  export declare const SessionTitleLlmConfigSchema: z<SessionTitleLlmConfig>;
75
73
  /**
76
- * Validate and detach required model-provider configuration.
77
- * @param config - untrusted plugin configuration.
78
- * @returns immutable policy with optional route absence preserved.
74
+ * Validate and detach required execution controls.
75
+ * @param config - untrusted execution configuration.
76
+ * @returns immutable controls with optional route absence preserved.
79
77
  */
80
78
  export declare function resolveSessionTitleLlmConfig(config: SessionTitleLlmConfig): ResolvedSessionTitleLlmConfig;
81
- /** Select the provider-owned message subset from one fixed service revision. */
82
- export type SessionTitleLlmMessageSelector = (messages: readonly SessionTitleUserMessage[]) => readonly SessionTitleUserMessage[];
83
79
  /**
84
- * Register one model-backed provider through the shared configuration and call policy.
85
- * @param ctx - context exposing the title and LLM services.
86
- * @param config - untrusted required deployment policy.
87
- * @param id - stable plugin id recorded with generated titles.
88
- * @param automatic - provider-owned automatic generation cadence.
89
- * @param selectMessages - exact source-message selection for one revision.
80
+ * Provider-prepared model input, source-message attribution, and the
81
+ * provider-owned reasoning selector forwarded to `ctx.llm.prepareCall`.
90
82
  */
91
- export declare function registerSessionTitleLlmProvider(ctx: Context, config: SessionTitleLlmConfig, id: string, automatic: SessionTitleAutomaticMode, selectMessages: SessionTitleLlmMessageSelector): void;
83
+ export interface SessionTitleLlmPreparedRequest {
84
+ /** Exact system prompt supplied by the provider. */
85
+ readonly system: string;
86
+ /** Exact user message text supplied by the provider, including any framing. */
87
+ readonly input: string;
88
+ /** Exact human `user/message` seqs represented by `input`, in log order. */
89
+ readonly messageSeqs: readonly SessionSeq[];
90
+ /**
91
+ * Provider-owned reasoning selection for the captured route. The execution
92
+ * module combines only the returned effort with its fixed output-token cap.
93
+ * @param model - detached, deeply frozen metadata from the captured adapter generation.
94
+ * @returns a supported effort id, or `undefined` to use the route's normal default.
95
+ */
96
+ readonly selectReasoningEffort: (model: Readonly<LlmResolvedModelInfo>) => ReasoningEffortId | undefined;
97
+ }
98
+ /** Terminal finish kinds forwarded to a provider for its own interpretation. */
99
+ export type SessionTitleLlmFinish = Extract<FinishReason, {
100
+ kind: 'stop' | 'tool-calls' | 'max-tokens';
101
+ }>;
102
+ /** Assembled auxiliary model response for one provider to interpret. */
103
+ export interface SessionTitleLlmResponse {
104
+ /** Assembled content blocks in stream order; the provider rejects unwanted block types. */
105
+ readonly blocks: readonly ContentBlock[];
106
+ /** Terminal finish reason forwarded without title-output interpretation. */
107
+ readonly finish: SessionTitleLlmFinish;
108
+ /** Exact auxiliary model route that produced the response. */
109
+ readonly model: SessionTitleModelIdentity;
110
+ }
92
111
  /**
93
- * Generate one title through the shared auxiliary LLM call.
112
+ * Execute one prepared auxiliary title request.
113
+ *
114
+ * The provider owns the system prompt, user input, reasoning selection, and
115
+ * output interpretation. This function owns route preparation, the final input
116
+ * byte limit, the output-token cap, the end-to-end deadline, cancellation, the
117
+ * exact `session/title-llm-request` record, and stream assembly.
94
118
  * @param ctx - context exposing the registered LLM service.
95
- * @param config - validated model-provider policy.
96
- * @param request - service-owned session, route, message snapshot, and cancellation.
97
- * @param selectedMessages - exact provider-selected subset to frame and attribute.
119
+ * @param config - validated execution controls.
120
+ * @param request - service-owned session, route, message snapshot, current title, and cancellation.
98
121
  * @param titleProvider - registered title-provider identity recorded with the request.
99
- * @returns normalized non-empty title, exact source seqs, and used model route.
122
+ * @param prepared - provider system prompt, input, source-message seqs, and reasoning selector.
123
+ * @returns assembled response blocks, terminal finish, and the exact route used.
124
+ * @throws {Error} when input bounds, route preparation, the deadline, cancellation, or an operational finish failure occurs.
100
125
  */
101
- export declare function generateSessionTitleWithLlm(ctx: Context, config: ResolvedSessionTitleLlmConfig, request: SessionTitleProviderRequest, selectedMessages: readonly SessionTitleUserMessage[], titleProvider: SessionTitleProviderId): Promise<SessionTitleProviderResult>;
126
+ export declare function executeSessionTitleLlm(ctx: Context, config: ResolvedSessionTitleLlmConfig, request: SessionTitleProviderRequest, titleProvider: SessionTitleProviderId, prepared: SessionTitleLlmPreparedRequest): Promise<SessionTitleLlmResponse>;
102
127
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-session-title-llm",
3
3
  "description": "Shared LLM generation policy for DeepSeek Harness session-title providers",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -28,20 +28,20 @@
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
30
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
31
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
32
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
33
- "@deepseek-ai/dsh-session-title": "0.2.1-alpha.1",
34
- "@deepseek-ai/dsh-timeout": "0.2.1-alpha.1"
31
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
32
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
33
+ "@deepseek-ai/dsh-session-title": "0.2.1-alpha.2",
34
+ "@deepseek-ai/dsh-timeout": "0.2.1-alpha.2"
35
35
  },
36
36
  "dependencies": {
37
- "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
37
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.2",
38
38
  "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
42
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
43
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
44
- "@deepseek-ai/dsh-session-title": "0.2.1-alpha.1",
45
- "@deepseek-ai/dsh-timeout": "0.2.1-alpha.1"
42
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
43
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
44
+ "@deepseek-ai/dsh-session-title": "0.2.1-alpha.2",
45
+ "@deepseek-ai/dsh-timeout": "0.2.1-alpha.2"
46
46
  }
47
47
  }