better-dsh 0.2.3-e → 0.2.3-g

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 (270) hide show
  1. package/docs/50_test-reports/2026-09-13-preact-ui-shell/345/256/236/346/265/213/346/212/245/345/221/212.md +1 -1
  2. package/docs/50_test-reports/2026-09-14-4999-skill/346/270/205/345/215/225/344/270/216lsp-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +54 -0
  3. package/docs/specs/agent/spec.md +54 -0
  4. package/docs/specs/ast/spec.md +34 -0
  5. package/docs/specs/compaction-recall/spec.md +46 -0
  6. package/docs/specs/ctx/spec.md +107 -0
  7. package/docs/specs/dsh/spec.md +47 -0
  8. package/docs/specs/dvc/spec.md +87 -0
  9. package/docs/specs/escalation-guidance/spec.md +44 -0
  10. package/docs/specs/fs-scheme-resolution/spec.md +37 -0
  11. package/docs/specs/hash-edit/spec.md +41 -0
  12. package/docs/specs/http-read/spec.md +73 -0
  13. package/docs/specs/kernel-provisioning/spec.md +53 -0
  14. package/docs/specs/lsp/spec.md +121 -0
  15. package/docs/specs/mobile-layout/spec.md +108 -0
  16. package/docs/specs/model-failover/spec.md +20 -0
  17. package/docs/specs/preact-ui-shell/spec.md +22 -0
  18. package/docs/specs/repl-dispatch-resilience/spec.md +21 -0
  19. package/docs/specs/skill/spec.md +58 -0
  20. package/docs/specs/tool-surface/spec.md +222 -0
  21. package/docs/specs/url-schema/spec.md +148 -0
  22. package/docs/specs/web-trust-fence/spec.md +43 -0
  23. package/dsh-docs/AGENTS.md +75 -0
  24. package/dsh-docs/agent-lifecycle.md +84 -0
  25. package/dsh-docs/agent-lifecycle.zh.md +86 -0
  26. package/dsh-docs/api-gateway.md +164 -0
  27. package/dsh-docs/api-gateway.zh.md +164 -0
  28. package/dsh-docs/architecture.md +150 -0
  29. package/dsh-docs/architecture.zh.md +154 -0
  30. package/dsh-docs/capability-seams.md +543 -0
  31. package/dsh-docs/capability-seams.zh.md +545 -0
  32. package/dsh-docs/config-catalog.md +3473 -0
  33. package/dsh-docs/config-catalog.zh.md +3474 -0
  34. package/dsh-docs/cookbook/adding-a-package.md +117 -0
  35. package/dsh-docs/cookbook/adding-a-package.zh.md +119 -0
  36. package/dsh-docs/cookbook/adding-a-remote-api.md +197 -0
  37. package/dsh-docs/cookbook/adding-a-remote-api.zh.md +197 -0
  38. package/dsh-docs/cookbook/adding-a-settings-card.md +102 -0
  39. package/dsh-docs/cookbook/adding-a-settings-card.zh.md +102 -0
  40. package/dsh-docs/cookbook/adding-a-tool.md +101 -0
  41. package/dsh-docs/cookbook/adding-a-tool.zh.md +103 -0
  42. package/dsh-docs/cookbook/adding-a-vendored-package.md +59 -0
  43. package/dsh-docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  44. package/dsh-docs/cookbook/adding-an-llm-adapter.md +43 -0
  45. package/dsh-docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  46. package/dsh-docs/cookbook/extension-cookbook.md +132 -0
  47. package/dsh-docs/cookbook/extension-cookbook.zh.md +136 -0
  48. package/dsh-docs/cookbook/maintaining-dsh-code-review.md +64 -0
  49. package/dsh-docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  50. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  51. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  52. package/dsh-docs/cordis-api/context.md +364 -0
  53. package/dsh-docs/cordis-api/context.zh.md +366 -0
  54. package/dsh-docs/cordis-api/events.md +207 -0
  55. package/dsh-docs/cordis-api/events.zh.md +209 -0
  56. package/dsh-docs/cordis-api/fiber.md +375 -0
  57. package/dsh-docs/cordis-api/fiber.zh.md +377 -0
  58. package/dsh-docs/cordis-api/inherited.md +39 -0
  59. package/dsh-docs/cordis-api/registry.md +152 -0
  60. package/dsh-docs/cordis-api/registry.zh.md +154 -0
  61. package/dsh-docs/cordis-api/service.md +102 -0
  62. package/dsh-docs/cordis-api/service.zh.md +104 -0
  63. package/dsh-docs/cordis-primer.md +45 -0
  64. package/dsh-docs/cordis-primer.zh.md +51 -0
  65. package/dsh-docs/cordis-tutorial/01-first-plugin.md +95 -0
  66. package/dsh-docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  67. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  68. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  69. package/dsh-docs/cordis-tutorial/03-services.md +98 -0
  70. package/dsh-docs/cordis-tutorial/03-services.zh.md +98 -0
  71. package/dsh-docs/cordis-tutorial/04-events.md +144 -0
  72. package/dsh-docs/cordis-tutorial/04-events.zh.md +144 -0
  73. package/dsh-docs/cordis-tutorial/05-config.md +84 -0
  74. package/dsh-docs/cordis-tutorial/05-config.zh.md +84 -0
  75. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  76. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  77. package/dsh-docs/cordis-tutorial/07-into-the-harness.md +108 -0
  78. package/dsh-docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  79. package/dsh-docs/cordis-tutorial/index.md +60 -0
  80. package/dsh-docs/cordis-tutorial/index.zh.md +62 -0
  81. package/dsh-docs/deepseek-llm-api-wire-extensions.md +163 -0
  82. package/dsh-docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  83. package/dsh-docs/defensive-patterns.md +33 -0
  84. package/dsh-docs/defensive-patterns.zh.md +35 -0
  85. package/dsh-docs/development.md +167 -0
  86. package/dsh-docs/development.zh.md +173 -0
  87. package/dsh-docs/event-producer-consumer.md +86 -0
  88. package/dsh-docs/event-producer-consumer.zh.md +88 -0
  89. package/dsh-docs/glossary.md +45 -0
  90. package/dsh-docs/glossary.zh.md +45 -0
  91. package/dsh-docs/graph-atlas.md +22 -0
  92. package/dsh-docs/graph-atlas.zh.md +24 -0
  93. package/dsh-docs/i18n/README.md +60 -0
  94. package/dsh-docs/i18n/README.zh.md +62 -0
  95. package/dsh-docs/i18n/style-samples.md +87 -0
  96. package/dsh-docs/i18n/terminology.md +214 -0
  97. package/dsh-docs/i18n/translation-prompt.md +263 -0
  98. package/dsh-docs/i18n/translation-rules.md +69 -0
  99. package/dsh-docs/i18n/translation-rules.zh.md +69 -0
  100. package/dsh-docs/module-graph.md +1411 -0
  101. package/dsh-docs/module-graph.zh.md +1413 -0
  102. package/dsh-docs/persistence-catalog.md +1075 -0
  103. package/dsh-docs/persistence-catalog.zh.md +1077 -0
  104. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  105. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  106. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  107. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  108. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  109. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  110. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  111. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  112. package/dsh-docs/postmortem/README.md +18 -0
  113. package/dsh-docs/postmortem/README.zh.md +18 -0
  114. package/dsh-docs/rescope.md +53 -0
  115. package/dsh-docs/rescope.zh.md +53 -0
  116. package/dsh-docs/subsystems/README.md +61 -0
  117. package/dsh-docs/subsystems/README.zh.md +61 -0
  118. package/dsh-docs/subsystems/agent-team.md +207 -0
  119. package/dsh-docs/subsystems/agent-team.zh.md +207 -0
  120. package/dsh-docs/subsystems/approval.md +170 -0
  121. package/dsh-docs/subsystems/approval.zh.md +170 -0
  122. package/dsh-docs/subsystems/attachment.md +351 -0
  123. package/dsh-docs/subsystems/attachment.zh.md +351 -0
  124. package/dsh-docs/subsystems/client-modules.md +168 -0
  125. package/dsh-docs/subsystems/client-modules.zh.md +168 -0
  126. package/dsh-docs/subsystems/code-runtime.md +195 -0
  127. package/dsh-docs/subsystems/code-runtime.zh.md +195 -0
  128. package/dsh-docs/subsystems/commands.md +219 -0
  129. package/dsh-docs/subsystems/commands.zh.md +219 -0
  130. package/dsh-docs/subsystems/compaction.md +238 -0
  131. package/dsh-docs/subsystems/compaction.zh.md +238 -0
  132. package/dsh-docs/subsystems/conversation.md +258 -0
  133. package/dsh-docs/subsystems/conversation.zh.md +258 -0
  134. package/dsh-docs/subsystems/core.md +1209 -0
  135. package/dsh-docs/subsystems/core.zh.md +1219 -0
  136. package/dsh-docs/subsystems/credentials.md +329 -0
  137. package/dsh-docs/subsystems/credentials.zh.md +329 -0
  138. package/dsh-docs/subsystems/extensions.md +382 -0
  139. package/dsh-docs/subsystems/extensions.zh.md +382 -0
  140. package/dsh-docs/subsystems/feedback.md +266 -0
  141. package/dsh-docs/subsystems/feedback.zh.md +266 -0
  142. package/dsh-docs/subsystems/filesystem.md +505 -0
  143. package/dsh-docs/subsystems/filesystem.zh.md +505 -0
  144. package/dsh-docs/subsystems/goal.md +277 -0
  145. package/dsh-docs/subsystems/goal.zh.md +277 -0
  146. package/dsh-docs/subsystems/invariants.md +88 -0
  147. package/dsh-docs/subsystems/invariants.zh.md +88 -0
  148. package/dsh-docs/subsystems/jobs.md +290 -0
  149. package/dsh-docs/subsystems/jobs.zh.md +290 -0
  150. package/dsh-docs/subsystems/llm-streaming.md +1080 -0
  151. package/dsh-docs/subsystems/llm-streaming.zh.md +1086 -0
  152. package/dsh-docs/subsystems/lsp.md +202 -0
  153. package/dsh-docs/subsystems/lsp.zh.md +202 -0
  154. package/dsh-docs/subsystems/permission-presets.md +131 -0
  155. package/dsh-docs/subsystems/permission-presets.zh.md +131 -0
  156. package/dsh-docs/subsystems/persistence.md +395 -0
  157. package/dsh-docs/subsystems/persistence.zh.md +395 -0
  158. package/dsh-docs/subsystems/plan.md +87 -0
  159. package/dsh-docs/subsystems/plan.zh.md +87 -0
  160. package/dsh-docs/subsystems/sandbox.md +220 -0
  161. package/dsh-docs/subsystems/sandbox.zh.md +220 -0
  162. package/dsh-docs/subsystems/schedule.md +192 -0
  163. package/dsh-docs/subsystems/schedule.zh.md +192 -0
  164. package/dsh-docs/subsystems/scope.md +59 -0
  165. package/dsh-docs/subsystems/scope.zh.md +59 -0
  166. package/dsh-docs/subsystems/session-projection.md +354 -0
  167. package/dsh-docs/subsystems/session-projection.zh.md +354 -0
  168. package/dsh-docs/subsystems/session-query.md +509 -0
  169. package/dsh-docs/subsystems/session-query.zh.md +509 -0
  170. package/dsh-docs/subsystems/session-reference.md +219 -0
  171. package/dsh-docs/subsystems/session-reference.zh.md +219 -0
  172. package/dsh-docs/subsystems/session-telemetry.md +194 -0
  173. package/dsh-docs/subsystems/session-telemetry.zh.md +194 -0
  174. package/dsh-docs/subsystems/session-title.md +204 -0
  175. package/dsh-docs/subsystems/session-title.zh.md +204 -0
  176. package/dsh-docs/subsystems/session.md +1155 -0
  177. package/dsh-docs/subsystems/session.zh.md +1159 -0
  178. package/dsh-docs/subsystems/settings.md +405 -0
  179. package/dsh-docs/subsystems/settings.zh.md +405 -0
  180. package/dsh-docs/subsystems/shell.md +303 -0
  181. package/dsh-docs/subsystems/shell.zh.md +303 -0
  182. package/dsh-docs/subsystems/skills.md +354 -0
  183. package/dsh-docs/subsystems/skills.zh.md +354 -0
  184. package/dsh-docs/subsystems/slots.md +175 -0
  185. package/dsh-docs/subsystems/slots.zh.md +175 -0
  186. package/dsh-docs/subsystems/spill.md +117 -0
  187. package/dsh-docs/subsystems/spill.zh.md +117 -0
  188. package/dsh-docs/subsystems/storage.md +260 -0
  189. package/dsh-docs/subsystems/storage.zh.md +260 -0
  190. package/dsh-docs/subsystems/subagent.md +766 -0
  191. package/dsh-docs/subsystems/subagent.zh.md +770 -0
  192. package/dsh-docs/subsystems/subprocess.md +324 -0
  193. package/dsh-docs/subsystems/subprocess.zh.md +324 -0
  194. package/dsh-docs/subsystems/system-prompt.md +220 -0
  195. package/dsh-docs/subsystems/system-prompt.zh.md +220 -0
  196. package/dsh-docs/subsystems/terminal.md +184 -0
  197. package/dsh-docs/subsystems/terminal.zh.md +184 -0
  198. package/dsh-docs/subsystems/todo.md +32 -0
  199. package/dsh-docs/subsystems/todo.zh.md +32 -0
  200. package/dsh-docs/subsystems/token-meter.md +105 -0
  201. package/dsh-docs/subsystems/token-meter.zh.md +105 -0
  202. package/dsh-docs/subsystems/tools.md +720 -0
  203. package/dsh-docs/subsystems/tools.zh.md +720 -0
  204. package/dsh-docs/subsystems/typert.md +343 -0
  205. package/dsh-docs/subsystems/typert.zh.md +343 -0
  206. package/dsh-docs/subsystems/user-questions.md +178 -0
  207. package/dsh-docs/subsystems/user-questions.zh.md +178 -0
  208. package/dsh-docs/subsystems/web-client.md +95 -0
  209. package/dsh-docs/subsystems/web-client.zh.md +95 -0
  210. package/dsh-docs/subsystems/web-server.md +154 -0
  211. package/dsh-docs/subsystems/web-server.zh.md +154 -0
  212. package/dsh-docs/subsystems/web.md +206 -0
  213. package/dsh-docs/subsystems/web.zh.md +206 -0
  214. package/dsh-docs/subsystems/webhook.md +70 -0
  215. package/dsh-docs/subsystems/webhook.zh.md +70 -0
  216. package/dsh-docs/subsystems/workflow.md +278 -0
  217. package/dsh-docs/subsystems/workflow.zh.md +278 -0
  218. package/dsh-docs/subsystems/workspace.md +321 -0
  219. package/dsh-docs/subsystems/workspace.zh.md +321 -0
  220. package/dsh-docs/testing.md +54 -0
  221. package/dsh-docs/testing.zh.md +54 -0
  222. package/dsh-docs/tool-catalog.md +2225 -0
  223. package/dsh-docs/tool-catalog.zh.md +2233 -0
  224. package/dsh-docs/tool-execution-pipeline.md +62 -0
  225. package/dsh-docs/tool-execution-pipeline.zh.md +64 -0
  226. package/dsh-docs/user/develop/basic/config.md +106 -0
  227. package/dsh-docs/user/develop/basic/config.zh.md +106 -0
  228. package/dsh-docs/user/develop/basic/index.md +144 -0
  229. package/dsh-docs/user/develop/basic/index.zh.md +144 -0
  230. package/dsh-docs/user/develop/basic/publish.md +183 -0
  231. package/dsh-docs/user/develop/basic/publish.zh.md +183 -0
  232. package/dsh-docs/user/develop/basic/tool.md +52 -0
  233. package/dsh-docs/user/develop/basic/tool.zh.md +52 -0
  234. package/dsh-docs/user/develop/framework/events.md +143 -0
  235. package/dsh-docs/user/develop/framework/events.zh.md +143 -0
  236. package/dsh-docs/user/develop/framework/index.md +137 -0
  237. package/dsh-docs/user/develop/framework/index.zh.md +137 -0
  238. package/dsh-docs/user/develop/framework/service.md +148 -0
  239. package/dsh-docs/user/develop/framework/service.zh.md +150 -0
  240. package/dsh-docs/user/develop/practice/dynamic-cordis.md +15 -0
  241. package/dsh-docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  242. package/dsh-docs/user/develop/practice/index.md +155 -0
  243. package/dsh-docs/user/develop/practice/index.zh.md +155 -0
  244. package/dsh-docs/user/develop/practice/llm-adapter.md +189 -0
  245. package/dsh-docs/user/develop/practice/llm-adapter.zh.md +189 -0
  246. package/dsh-docs/user/guide/github-review.md +102 -0
  247. package/dsh-docs/user/guide/github-review.zh.md +102 -0
  248. package/dsh-docs/user/guide/index.md +30 -0
  249. package/dsh-docs/user/guide/index.zh.md +30 -0
  250. package/dsh-docs/user/guide/mcp-memory.md +101 -0
  251. package/dsh-docs/user/guide/mcp-memory.zh.md +101 -0
  252. package/dsh-docs/user/guide/network-proxy.md +85 -0
  253. package/dsh-docs/user/guide/network-proxy.zh.md +85 -0
  254. package/dsh-docs/user/guide/providers.md +190 -0
  255. package/dsh-docs/user/guide/providers.zh.md +190 -0
  256. package/dsh-docs/user/guide/python-sdk.md +150 -0
  257. package/dsh-docs/user/guide/python-sdk.zh.md +150 -0
  258. package/dsh-docs/user/guide/schedule.md +21 -0
  259. package/dsh-docs/user/guide/schedule.zh.md +21 -0
  260. package/dsh-docs/user/index.md +11 -0
  261. package/dsh-docs/user/index.zh.md +11 -0
  262. package/dsh-docs/web-styling.md +29 -0
  263. package/dsh-docs/web-styling.zh.md +29 -0
  264. package/lib/client/index.js +268 -38
  265. package/lib/fs-aware/sandbox-plugin.js +1 -1
  266. package/lib/index.js +1112 -1261
  267. package/lib/lsp-server-registry-B8DNonhS.js +3 -0
  268. package/lib/lsp-server-registry-BexQagaK.js +943 -0
  269. package/lib/{wrap-DC8O3SYz.js → wrap-JFjcWwZf.js} +42 -16
  270. package/package.json +2 -1
@@ -0,0 +1,194 @@
1
+ # 遥测(telemetry)
2
+
3
+ [English](session-telemetry.md) | 中文
4
+
5
+ 对外的会话上报拆分为一项[能力 seam](../capability-seams.zh.md):Service Definition 与捕获协调器([dsh-session-telemetry](../../packages/session/session-telemetry),`ctx.sessionTelemetry`)拥有完整的权威事件捕获、`session-telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service Provider([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.zh.md)中定案;捕获与游标约定见 [Service Definition README](../../packages/session/session-telemetry/README.zh.md)。
6
+
7
+ 源码:[`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts)
8
+
9
+ ## 逻辑记录
10
+
11
+ ```ts type-equiv
12
+ /**
13
+ * Severity of a telemetry record, pre-mapped at capture so a receiver can
14
+ * alert with zero configuration: `error` for events whose own outcome flag
15
+ * says so (the tool-result block's `isError`, `turn/end` error reasons) and for
16
+ * `agent-error` operational records. Captured events otherwise default to
17
+ * `info`; `warn` remains available to `session-telemetry/record` policies and
18
+ * backends.
19
+ */
20
+ type SessionTelemetrySeverity = 'info' | 'warn' | 'error'
21
+ ```
22
+
23
+ ```ts type-equiv
24
+ /**
25
+ * One logical record handed to a backend — the capture contract's whole outbound
26
+ * vocabulary. Ledger records mirror session-log events one-to-one;
27
+ * operational records (`channel: 'ops'`) carry the two signals with no log
28
+ * home (`agent-error`, `shutdown`) and deliberately omit `event.seq`-style
29
+ * identity so they can never be mistaken for ledger rows.
30
+ */
31
+ interface SessionTelemetryRecord {
32
+ /** Ledger (session-log mirror) or ops (operational signal) channel; backends keep the two under separate instrumentation scopes. */
33
+ channel: 'ledger' | 'ops'
34
+ /** Unix epoch milliseconds — the source event's append time for ledger records, the emission time for ops records. */
35
+ time: number
36
+ /** Pre-mapped alerting severity; see {@link SessionTelemetrySeverity}. */
37
+ severity: SessionTelemetrySeverity
38
+ /**
39
+ * Identity attributes, deliberately minimal: ledger records carry
40
+ * `session.id`, `session.format_version`, `event.type`, `event.seq`, plus optional
41
+ * `session.cwd` / `session.parent_id`; a seeded Session also carries
42
+ * `session.seed_length` from its exact inherited event count;
43
+ * ops records carry `telemetry.op`, `session.id`, and (for `agent-error`)
44
+ * `agent.id`, `turn`, `step`, `error.name`. Anything recoverable from the
45
+ * body is intentionally NOT duplicated here.
46
+ */
47
+ attributes: Record<string, string | number>
48
+ /**
49
+ * The complete payload: a deep copy of the session event's `data` for
50
+ * ledger records (JSON-serializable by `Session.append`'s own
51
+ * validation), or the op payload for ops records. Never mutated after
52
+ * handoff.
53
+ */
54
+ body: unknown
55
+ }
56
+ ```
57
+
58
+ 每条权威[会话事件](session.zh.md)都会完整透传为一条有序 ledger 记录,包括每个携带完整紧凑 stream 的 `assistant/message` 或 `assistant/attempt`,以及该 seam 从未听说过、由插件合并进来的类型。进程本地 `agent/assistant-stream` frame 不进入该持久 feed。新 Session 对象会从 seq 0 回放完整日志,包括构造 seed 历史;重新收养同一对象时会从 handoff 游标之后继续。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(新对象回放、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, session.format_version, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
59
+
60
+ ## 共享披露
61
+
62
+ 该 seam 的确认契约(归属 [Service Definition README 的共享披露段](../../packages/session/session-telemetry/README.zh.md#the-sharing-disclosure)):每个后端都通过 `ctx.sessionTelemetry` 上必需的抽象 `sharing` 成员披露其部署级共享策略,消费方只有在未挂载任何遥测服务时才渲染「未配置」。披露只陈述当前策略,绝不承诺投递或留存——交接是非阻塞入队,批处理、重试与丢失策略仍归上报 SDK。
63
+
64
+ ```ts type-equiv
65
+ /**
66
+ * Deployment-selected session-sharing policy disclosed by a mounted
67
+ * {@link SessionTelemetryBackend} backend to human-facing acknowledgement surfaces (the
68
+ * `/feedback` command's confirmation text). The Service Definition owns the
69
+ * vocabulary so consumers and backends do not depend on a specific provider.
70
+ */
71
+ type SessionTelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
72
+ ```
73
+
74
+ ## 后端约定
75
+
76
+ ```ts type-equiv
77
+ /**
78
+ * The minimum backend contract the coordinator requires. {@link SessionTelemetryBackend} is
79
+ * its service-registered form; tests compose the coordinator with a bare
80
+ * implementation of this interface.
81
+ */
82
+ interface SessionTelemetrySink {
83
+ /**
84
+ * Hand one record to the backend's pipeline. MUST be a non-blocking
85
+ * enqueue — the coordinator calls this synchronously from the
86
+ * `session/event` hot path or an explicit canonical-log capture, so anything
87
+ * slower than a queue push would tax the agent loop or feedback handling.
88
+ * Errors thrown here are contained by the coordinator and logged; they
89
+ * never reach the loop.
90
+ * @param record - the logical record to report; owned by the backend after the call.
91
+ */
92
+ emit(record: SessionTelemetryRecord): void
93
+ /**
94
+ * Optional hint that a turn ended. A backend may forward it to its SDK's
95
+ * flush so records are exported after each turn. Called
96
+ * fire-and-forget; implementations must not block and must not throw
97
+ * meaningfully (the coordinator contains exceptions). Most backends should
98
+ * leave this unimplemented and let their SDK's own batching cadence govern
99
+ * export timing: a backend that does implement it owns the interaction
100
+ * between its concurrent flushes and {@link shutdown}'s drain (the OTel
101
+ * backend leaves it unimplemented for exactly that hazard — see the
102
+ * revival Agent Note).
103
+ */
104
+ flush?(): void
105
+ /**
106
+ * Forward the fiber's disposal to the SDK: flush whatever is queued and
107
+ * reach quiescence, per the SDK's own shutdown contract. Everything
108
+ * emitted before this call must still be delivered — including records
109
+ * enqueued while a {@link flush} hint is in flight, so a backend whose SDK
110
+ * guards against concurrent flushes orders behind the outstanding one (the
111
+ * coordinator emits its dispose-time `shutdown` markers immediately before
112
+ * calling this). Awaited by the coordinator's dispose; a rejection is
113
+ * logged as a warning and never fails application teardown.
114
+ * The coordinator captures dispose-time shutdown markers immediately before
115
+ * this call for live capture; on-demand capture creates no ops records.
116
+ * @returns resolves when the backend's pipeline has quiesced.
117
+ */
118
+ shutdown(): Promise<void>
119
+ }
120
+ ```
121
+
122
+ `SessionTelemetryBackend`(`ctx.sessionTelemetry`,[签名](#ctxsessiontelemetry--sessiontelemetrybackend-abstract-seam))是该约定的可加载形态:每个上下文只允许一个实现,重复加载会抛出异常;后端在其构造函数中组合 seam 的 `SessionTelemetryCoordinator`,以此装配捕获侧。
123
+
124
+ ## 脱敏 waterfall:`session-telemetry/record`
125
+
126
+ 每条记录在权威事件副本与 `emit()` 之间都要经过 `session-telemetry/record` [waterfall](../cordis-primer.zh.md#cordis-waterfall-semantics)([事件条目](#session-telemetryrecord--waterfall))。seam 自身不带任何规则:未挂载监听器时,记录以捕获时的原样到达后端;导出数据能干净到什么程度,恰恰取决于部署方挂载了什么规则。监听器通过变换 `next()` 的返回值来堆叠;不调用 `next()` 就返回,即替换其下方的全部逻辑;抛出异常的监听器会在协调器的隔离范围内以 fail-closed 方式扣下这一条记录。脱敏只作用于导出副本;权威会话日志永不改写。
127
+
128
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
129
+
130
+ <a id="cordis-surface"></a>
131
+
132
+ ## Cordis API
133
+
134
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
135
+
136
+ <a id="ctxsessiontelemetry--sessiontelemetrybackend-abstract-seam"></a>
137
+
138
+ ### `ctx.sessionTelemetry` — `SessionTelemetryBackend` (abstract seam)
139
+
140
+ Loadable form of the backend contract: one implementation per context — the cordis `Service` registration under the `telemetry` key throws on a duplicate, cordis' standard behavior. A backend composes a SessionTelemetryCoordinator in its constructor to install the capture side.
141
+
142
+ ```ts cordis-catalog
143
+ /**
144
+ * See {@link SessionTelemetrySink.emit} — that declaration is the contract's one home.
145
+ * @param record - the logical record to report; owned by the backend after the call.
146
+ */
147
+ abstract emit(record: SessionTelemetryRecord): void
148
+
149
+ /** See {@link SessionTelemetrySink.flush}. */
150
+ flush?(): void
151
+
152
+ /**
153
+ * See {@link SessionTelemetrySink.shutdown}.
154
+ * @returns resolves when the backend's pipeline has quiesced.
155
+ */
156
+ abstract shutdown(): Promise<void>
157
+ ```
158
+
159
+ Source: [`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts)
160
+
161
+ <a id="session-telemetry-events"></a>
162
+
163
+ ### `session-telemetry/*` events
164
+
165
+ <a id="session-telemetryrecord--waterfall"></a>
166
+
167
+ #### `session-telemetry/record` — waterfall
168
+
169
+ Transform one outbound record before it reaches the backend. This waterfall is the Service Definition's redaction extension point. It ships NO rules of its own: the innermost `next()` passes the record through unchanged, and with no listener mounted records reach the backend as captured, so exported data is exactly as clean as the rules a deployment mounts. Listeners stack by transforming `next()`'s return value; returning without `next()` replaces everything beneath. Dispatched synchronously on the capture hot path inside the coordinator's containment: a throwing listener withholds that one record (fail-closed) and never reaches the agent loop. Live capture dispatches at append time; on-demand capture dispatches while reading the canonical log. Redaction applies to the exported copy only; the canonical session log is never rewritten.
170
+
171
+ ```ts cordis-catalog
172
+ /**
173
+ * Transform one outbound record before it reaches the backend. This
174
+ * waterfall is the Service Definition's redaction extension point. It ships NO rules
175
+ * of its own: the
176
+ * innermost `next()` passes the record through unchanged, and with no
177
+ * listener mounted records reach the backend as captured, so exported
178
+ * data is exactly as clean as the rules a deployment mounts. Listeners
179
+ * stack by transforming `next()`'s return value; returning without
180
+ * `next()` replaces everything beneath. Dispatched synchronously on the
181
+ * capture hot path inside the coordinator's containment: a throwing
182
+ * listener withholds that one record (fail-closed) and never reaches the
183
+ * agent loop. Live capture dispatches at append time; on-demand capture
184
+ * dispatches while reading the canonical log. Redaction applies to the
185
+ * exported copy only; the canonical session log is never rewritten.
186
+ * @param record - the candidate record, already the coordinator's own deep
187
+ * copy; listeners return a (possibly new) record and must not mutate it.
188
+ * @mode waterfall
189
+ */
190
+ 'session-telemetry/record'(record: SessionTelemetryRecord, next: () => SessionTelemetryRecord): SessionTelemetryRecord
191
+ ```
192
+
193
+ Source: [`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts)
194
+ <!-- END GENERATED cordis-surface -->
@@ -0,0 +1,204 @@
1
+ # Session Titles
2
+
3
+ English | [中文](session-title.zh.md)
4
+
5
+ Durable latest-wins title state and the optional asynchronous provider vocabulary owned by [`@deepseek-ai/dsh-session-title`](../../packages/session/session-title). The shared LLM helper owns the exact auxiliary request record. Package READMEs own timing, fallback, failure, and fork behavior; the generated [persistence catalog](../persistence-catalog.md) owns the complete event declarations.
6
+
7
+ Sources: [`packages/session/session-title/src/index.ts`](../../packages/session/session-title/src/index.ts), [`packages/session/session-title-llm/src/index.ts`](../../packages/session/session-title-llm/src/index.ts)
8
+
9
+ ## Durable title state
10
+
11
+ `SessionTitleProviderId` is recorded for provider-produced revisions. `SessionTitleEventData` lists the exact human-message seqs used for the title, while `SessionTitleSnapshot` adds the durable event envelope facts returned by `ctx.sessionTitle.get()` and `foldSessionTitle()`. The `title` projection keeps its version-1 state and client view as only the title string or `null`, so existing persisted cache rows remain readable.
12
+
13
+ ```ts type-equiv
14
+ /** Identifies one session-title provider registration. */
15
+ type SessionTitleProviderId = Branded<'SessionTitleProviderId'>
16
+ ```
17
+
18
+ ```ts type-equiv
19
+ /** Exact auxiliary model route that produced a title. */
20
+ interface SessionTitleModelProvenance {
21
+ /** Registered LLM provider route. */
22
+ readonly provider: string
23
+ /** Provider model id. */
24
+ readonly model: string
25
+ }
26
+ ```
27
+
28
+ ```ts type-equiv
29
+ /** Durable ownership record for an accepted session title. */
30
+ type SessionTitleSource =
31
+ | { readonly kind: 'fallback' }
32
+ | {
33
+ readonly kind: 'provider'
34
+ readonly provider: SessionTitleProviderId
35
+ readonly model?: SessionTitleModelProvenance
36
+ }
37
+ | {
38
+ /** Explicit user rename: pins the title — automatic generation stops scheduling. */
39
+ readonly kind: 'user'
40
+ }
41
+ ```
42
+
43
+ ```ts type-equiv
44
+ /** Payload of the log-only `session/title` event. */
45
+ interface SessionTitleEventData {
46
+ /** Normalized non-empty title text. */
47
+ readonly title: string
48
+ /** Exact human `user/message` seqs used to derive this title; empty for an explicit user rename. */
49
+ readonly messageSeqs: SessionSeq[]
50
+ /** Whether the built-in fallback, a registered provider, or the user supplied the title. */
51
+ readonly source: SessionTitleSource
52
+ }
53
+ ```
54
+
55
+ ```ts type-equiv
56
+ /** Latest folded title plus the title event's durable envelope facts. */
57
+ interface SessionTitleSnapshot extends SessionTitleEventData {
58
+ /** Seq of the latest `session/title` event. */
59
+ readonly eventSeq: SessionSeq
60
+ /** Timestamp of the latest `session/title` event. */
61
+ readonly updatedAt: number
62
+ }
63
+ ```
64
+
65
+ ## Auxiliary request record
66
+
67
+ The shared LLM helper records each validated, dispatchable title request before calling the model. The payload reproduces the model-visible system and message input, routing, output limit, provider ownership, and source-message attribution even when generation later fails.
68
+
69
+ ```ts type-equiv
70
+ /** Exact model-visible request recorded before one auxiliary title dispatch. */
71
+ interface SessionTitleLlmRequestEventData {
72
+ /** Registered title-provider identity responsible for the request. */
73
+ readonly titleProvider: SessionTitleProviderId
74
+ /** Exact human `user/message` seqs represented in `messages`. */
75
+ readonly messageSeqs: SessionSeq[]
76
+ /** Exact auxiliary LLM route. */
77
+ readonly route: SessionTitleModelProvenance
78
+ /** Exact auxiliary system prompt. */
79
+ readonly system: string
80
+ /** Exact auxiliary message list. */
81
+ readonly messages: Message[]
82
+ /** Exact auxiliary output-token cap. */
83
+ readonly maxTokens: number
84
+ }
85
+ ```
86
+
87
+ ## Provider input and output
88
+
89
+ The service snapshots eligible messages through one revision. A provider returns only seqs from that request; service-owned acceptance verifies ordering, normalizes the title, enforces the byte limit, and appends the title with its source-message seqs and source kind.
90
+
91
+ ```ts type-equiv
92
+ /** One eligible human text message exposed to title providers. */
93
+ interface SessionTitleUserMessage {
94
+ /** Source `user/message` event seq. */
95
+ readonly seq: SessionSeq
96
+ /** Exact concatenated text-block content. */
97
+ readonly text: string
98
+ }
99
+ ```
100
+
101
+ ```ts type-equiv
102
+ /** Automatic generation cadence owned by a registered provider. */
103
+ type SessionTitleAutomaticMode = 'first-prompt' | 'all-prompts'
104
+ ```
105
+
106
+ ```ts type-equiv
107
+ /** Immutable input supplied to one title-provider call. */
108
+ interface SessionTitleProviderRequest {
109
+ /** Live session being titled. */
110
+ readonly session: Session
111
+ /** All eligible human messages through this generation revision. */
112
+ readonly messages: readonly SessionTitleUserMessage[]
113
+ /** Exact current logged main-request route, when one has been recorded. */
114
+ readonly route?: SessionTitleModelProvenance
115
+ /** Cancellation for supersession, disposal, timeout composition, or the explicit caller. */
116
+ readonly signal: AbortSignal
117
+ }
118
+ ```
119
+
120
+ ```ts type-equiv
121
+ /** Provider output before service-owned normalization and log acceptance. */
122
+ interface SessionTitleProviderResult {
123
+ /** Proposed title text. */
124
+ readonly title: string
125
+ /** Exact seqs from `request.messages` used by this result. */
126
+ readonly messageSeqs: readonly SessionSeq[]
127
+ /** Auxiliary LLM route, when generation used a model. */
128
+ readonly model?: SessionTitleModelProvenance
129
+ }
130
+ ```
131
+
132
+ ```ts type-equiv
133
+ /** One optional asynchronous title implementation registered with the service. */
134
+ interface SessionTitleProvider {
135
+ /** Stable id of the provider recorded with the title. */
136
+ readonly id: SessionTitleProviderId
137
+ /** When new human prompts start automatic generation. */
138
+ readonly automatic: SessionTitleAutomaticMode
139
+ /**
140
+ * Produce one title revision.
141
+ * @param request - message snapshot, current route, session, and cancellation.
142
+ * @returns proposed title plus exact input seqs and the optional provider/model route used to generate it.
143
+ */
144
+ generate(request: SessionTitleProviderRequest): Promise<SessionTitleProviderResult>
145
+ }
146
+ ```
147
+
148
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
149
+
150
+ <a id="cordis-surface"></a>
151
+
152
+ ## Cordis API
153
+
154
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
155
+
156
+ <a id="ctxsessiontitle--sessiontitleservice"></a>
157
+
158
+ ### `ctx.sessionTitle` — `SessionTitleService`
159
+
160
+ Log-backed title fold plus asynchronous fallback generation.
161
+
162
+ ```ts cordis-catalog
163
+ /**
164
+ * Read the latest folded title from one live or replayed session.
165
+ * @param session - session whose log is the title source of truth.
166
+ * @returns latest title snapshot, or `undefined` before eligible input.
167
+ */
168
+ get(session: Session): SessionTitleSnapshot | undefined
169
+
170
+ /**
171
+ * Accept an explicit user title. Appends a `session/title` event with the
172
+ * `user` source, which pins the title: in-flight automatic generation is
173
+ * superseded and later user messages schedule none (an explicit
174
+ * {@link SessionTitleService.refresh} remains the deliberate unpin).
175
+ * @param session - exact live session to rename.
176
+ * @param title - raw user input; normalized before acceptance.
177
+ * @returns the accepted title snapshot.
178
+ * @throws {SessionTitleInvalidError} when the title normalizes to empty.
179
+ * @throws {Error} when the session is not live or the service is disposed.
180
+ */
181
+ rename(session: Session, title: string): SessionTitleSnapshot
182
+
183
+ /**
184
+ * Explicitly retry the registered provider, or materialize the built-in
185
+ * fallback when no provider is registered.
186
+ * @param session - exact live session to refresh.
187
+ * @param signal - optional caller cancellation.
188
+ * @returns latest accepted title, or `undefined` when no eligible text exists.
189
+ */
190
+ async refresh(session: Session, signal?: AbortSignal): Promise<SessionTitleSnapshot | undefined>
191
+
192
+ /**
193
+ * Register the sole optional title provider. Disposal aborts its pending and
194
+ * active work before another provider may register.
195
+ * @param provider - provider identity, cadence, and generation function.
196
+ * @returns exact Cordis effect disposer, which settles after active calls quiesce.
197
+ */
198
+ register(provider: SessionTitleProvider): () => Promise<void>
199
+ ```
200
+
201
+ Types: [Session](session.md)
202
+
203
+ Source: [`packages/session/session-title/src/index.ts`](../../packages/session/session-title/src/index.ts)
204
+ <!-- END GENERATED cordis-surface -->
@@ -0,0 +1,204 @@
1
+ # 会话标题
2
+
3
+ [English](session-title.md) | 中文
4
+
5
+ [`@deepseek-ai/dsh-session-title`](../../packages/session/session-title) 所拥有的持久、后写覆盖的标题状态与可选异步提供方词汇。共享 LLM(大语言模型)辅助组件负责精确的辅助请求记录。各包 README 负责时序、回退、失败与 fork 行为;生成的[持久化日志事件目录](../persistence-catalog.zh.md)负责完整的事件声明。
6
+
7
+ 源码:[`packages/session/session-title/src/index.ts`](../../packages/session/session-title/src/index.ts)、[`packages/session/session-title-llm/src/index.ts`](../../packages/session/session-title-llm/src/index.ts)
8
+
9
+ ## 持久标题状态
10
+
11
+ 提供方生成修订时会记录 `SessionTitleProviderId`。`SessionTitleEventData` 列出生成标题时使用的精确人类消息 seq,`SessionTitleSnapshot` 则加入 `ctx.sessionTitle.get()` 与 `foldSessionTitle()` 返回的持久事件封装信息。`title` 投影的版本 1 状态与客户端视图都只保留标题字符串或 `null`,因此既有持久化缓存行仍可读取。
12
+
13
+ ```ts type-equiv
14
+ /** Identifies one session-title provider registration. */
15
+ type SessionTitleProviderId = Branded<'SessionTitleProviderId'>
16
+ ```
17
+
18
+ ```ts type-equiv
19
+ /** Exact auxiliary model route that produced a title. */
20
+ interface SessionTitleModelProvenance {
21
+ /** Registered LLM provider route. */
22
+ readonly provider: string
23
+ /** Provider model id. */
24
+ readonly model: string
25
+ }
26
+ ```
27
+
28
+ ```ts type-equiv
29
+ /** Durable ownership record for an accepted session title. */
30
+ type SessionTitleSource =
31
+ | { readonly kind: 'fallback' }
32
+ | {
33
+ readonly kind: 'provider'
34
+ readonly provider: SessionTitleProviderId
35
+ readonly model?: SessionTitleModelProvenance
36
+ }
37
+ | {
38
+ /** Explicit user rename: pins the title — automatic generation stops scheduling. */
39
+ readonly kind: 'user'
40
+ }
41
+ ```
42
+
43
+ ```ts type-equiv
44
+ /** Payload of the log-only `session/title` event. */
45
+ interface SessionTitleEventData {
46
+ /** Normalized non-empty title text. */
47
+ readonly title: string
48
+ /** Exact human `user/message` seqs used to derive this title; empty for an explicit user rename. */
49
+ readonly messageSeqs: SessionSeq[]
50
+ /** Whether the built-in fallback, a registered provider, or the user supplied the title. */
51
+ readonly source: SessionTitleSource
52
+ }
53
+ ```
54
+
55
+ ```ts type-equiv
56
+ /** Latest folded title plus the title event's durable envelope facts. */
57
+ interface SessionTitleSnapshot extends SessionTitleEventData {
58
+ /** Seq of the latest `session/title` event. */
59
+ readonly eventSeq: SessionSeq
60
+ /** Timestamp of the latest `session/title` event. */
61
+ readonly updatedAt: number
62
+ }
63
+ ```
64
+
65
+ ## 辅助请求记录
66
+
67
+ 共享 LLM 辅助组件会在调用模型前,记录每一项已经过验证且可分发的标题请求。即使后续生成失败,载荷仍会复现模型可见的系统输入与消息输入、路由、输出上限、提供方归属和源消息归因。
68
+
69
+ ```ts type-equiv
70
+ /** Exact model-visible request recorded before one auxiliary title dispatch. */
71
+ interface SessionTitleLlmRequestEventData {
72
+ /** Registered title-provider identity responsible for the request. */
73
+ readonly titleProvider: SessionTitleProviderId
74
+ /** Exact human `user/message` seqs represented in `messages`. */
75
+ readonly messageSeqs: SessionSeq[]
76
+ /** Exact auxiliary LLM route. */
77
+ readonly route: SessionTitleModelProvenance
78
+ /** Exact auxiliary system prompt. */
79
+ readonly system: string
80
+ /** Exact auxiliary message list. */
81
+ readonly messages: Message[]
82
+ /** Exact auxiliary output-token cap. */
83
+ readonly maxTokens: number
84
+ }
85
+ ```
86
+
87
+ ## 提供方输入与输出
88
+
89
+ 服务会对截至某一修订的合格消息创建快照。提供方返回的 seq 仅可来自该请求;由服务负责的接纳流程会验证顺序、规范化标题、强制执行字节上限,并追加标题及其来源消息 seq 和来源类型。
90
+
91
+ ```ts type-equiv
92
+ /** One eligible human text message exposed to title providers. */
93
+ interface SessionTitleUserMessage {
94
+ /** Source `user/message` event seq. */
95
+ readonly seq: SessionSeq
96
+ /** Exact concatenated text-block content. */
97
+ readonly text: string
98
+ }
99
+ ```
100
+
101
+ ```ts type-equiv
102
+ /** Automatic generation cadence owned by a registered provider. */
103
+ type SessionTitleAutomaticMode = 'first-prompt' | 'all-prompts'
104
+ ```
105
+
106
+ ```ts type-equiv
107
+ /** Immutable input supplied to one title-provider call. */
108
+ interface SessionTitleProviderRequest {
109
+ /** Live session being titled. */
110
+ readonly session: Session
111
+ /** All eligible human messages through this generation revision. */
112
+ readonly messages: readonly SessionTitleUserMessage[]
113
+ /** Exact current logged main-request route, when one has been recorded. */
114
+ readonly route?: SessionTitleModelProvenance
115
+ /** Cancellation for supersession, disposal, timeout composition, or the explicit caller. */
116
+ readonly signal: AbortSignal
117
+ }
118
+ ```
119
+
120
+ ```ts type-equiv
121
+ /** Provider output before service-owned normalization and log acceptance. */
122
+ interface SessionTitleProviderResult {
123
+ /** Proposed title text. */
124
+ readonly title: string
125
+ /** Exact seqs from `request.messages` used by this result. */
126
+ readonly messageSeqs: readonly SessionSeq[]
127
+ /** Auxiliary LLM route, when generation used a model. */
128
+ readonly model?: SessionTitleModelProvenance
129
+ }
130
+ ```
131
+
132
+ ```ts type-equiv
133
+ /** One optional asynchronous title implementation registered with the service. */
134
+ interface SessionTitleProvider {
135
+ /** Stable id of the provider recorded with the title. */
136
+ readonly id: SessionTitleProviderId
137
+ /** When new human prompts start automatic generation. */
138
+ readonly automatic: SessionTitleAutomaticMode
139
+ /**
140
+ * Produce one title revision.
141
+ * @param request - message snapshot, current route, session, and cancellation.
142
+ * @returns proposed title plus exact input seqs and the optional provider/model route used to generate it.
143
+ */
144
+ generate(request: SessionTitleProviderRequest): Promise<SessionTitleProviderResult>
145
+ }
146
+ ```
147
+
148
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
149
+
150
+ <a id="cordis-surface"></a>
151
+
152
+ ## Cordis API
153
+
154
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
155
+
156
+ <a id="ctxsessiontitle--sessiontitleservice"></a>
157
+
158
+ ### `ctx.sessionTitle` — `SessionTitleService`
159
+
160
+ Log-backed title fold plus asynchronous fallback generation.
161
+
162
+ ```ts cordis-catalog
163
+ /**
164
+ * Read the latest folded title from one live or replayed session.
165
+ * @param session - session whose log is the title source of truth.
166
+ * @returns latest title snapshot, or `undefined` before eligible input.
167
+ */
168
+ get(session: Session): SessionTitleSnapshot | undefined
169
+
170
+ /**
171
+ * Accept an explicit user title. Appends a `session/title` event with the
172
+ * `user` source, which pins the title: in-flight automatic generation is
173
+ * superseded and later user messages schedule none (an explicit
174
+ * {@link SessionTitleService.refresh} remains the deliberate unpin).
175
+ * @param session - exact live session to rename.
176
+ * @param title - raw user input; normalized before acceptance.
177
+ * @returns the accepted title snapshot.
178
+ * @throws {SessionTitleInvalidError} when the title normalizes to empty.
179
+ * @throws {Error} when the session is not live or the service is disposed.
180
+ */
181
+ rename(session: Session, title: string): SessionTitleSnapshot
182
+
183
+ /**
184
+ * Explicitly retry the registered provider, or materialize the built-in
185
+ * fallback when no provider is registered.
186
+ * @param session - exact live session to refresh.
187
+ * @param signal - optional caller cancellation.
188
+ * @returns latest accepted title, or `undefined` when no eligible text exists.
189
+ */
190
+ async refresh(session: Session, signal?: AbortSignal): Promise<SessionTitleSnapshot | undefined>
191
+
192
+ /**
193
+ * Register the sole optional title provider. Disposal aborts its pending and
194
+ * active work before another provider may register.
195
+ * @param provider - provider identity, cadence, and generation function.
196
+ * @returns exact Cordis effect disposer, which settles after active calls quiesce.
197
+ */
198
+ register(provider: SessionTitleProvider): () => Promise<void>
199
+ ```
200
+
201
+ Types: [Session](session.zh.md)
202
+
203
+ Source: [`packages/session/session-title/src/index.ts`](../../packages/session/session-title/src/index.ts)
204
+ <!-- END GENERATED cordis-surface -->