kiokuko-dsh 0.1.34 → 0.1.36

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 (228) hide show
  1. package/PERMISSIONS.md +10 -0
  2. package/README.ja.md +6 -1
  3. package/README.ko.md +1 -1
  4. package/README.md +6 -1
  5. package/README.zh-CN.md +1 -1
  6. package/dist/client.cjs +170 -23
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/context/delivery.d.ts +2 -0
  9. package/dist/context/delivery.d.ts.map +1 -1
  10. package/dist/context/delivery.js +34 -9
  11. package/dist/context/delivery.js.map +1 -1
  12. package/dist/context/memory-projection.d.ts +41 -0
  13. package/dist/context/memory-projection.d.ts.map +1 -0
  14. package/dist/context/memory-projection.js +97 -0
  15. package/dist/context/memory-projection.js.map +1 -0
  16. package/dist/context/read-snapshot.d.ts +5 -0
  17. package/dist/context/read-snapshot.d.ts.map +1 -0
  18. package/dist/context/read-snapshot.js +45 -0
  19. package/dist/context/read-snapshot.js.map +1 -0
  20. package/dist/context/scoped-broker.d.ts +7 -1
  21. package/dist/context/scoped-broker.d.ts.map +1 -1
  22. package/dist/context/scoped-broker.js +57 -9
  23. package/dist/context/scoped-broker.js.map +1 -1
  24. package/dist/context/selection-state.d.ts +6 -0
  25. package/dist/context/selection-state.d.ts.map +1 -1
  26. package/dist/context/selection-state.js +7 -0
  27. package/dist/context/selection-state.js.map +1 -1
  28. package/dist/deep-thinker/abortable-stream.d.ts +4 -0
  29. package/dist/deep-thinker/abortable-stream.d.ts.map +1 -0
  30. package/dist/deep-thinker/abortable-stream.js +35 -0
  31. package/dist/deep-thinker/abortable-stream.js.map +1 -0
  32. package/dist/deep-thinker/commands.d.ts +9 -0
  33. package/dist/deep-thinker/commands.d.ts.map +1 -0
  34. package/dist/deep-thinker/commands.js +19 -0
  35. package/dist/deep-thinker/commands.js.map +1 -0
  36. package/dist/deep-thinker/configuration.d.ts +25 -0
  37. package/dist/deep-thinker/configuration.d.ts.map +1 -0
  38. package/dist/deep-thinker/configuration.js +156 -0
  39. package/dist/deep-thinker/configuration.js.map +1 -0
  40. package/dist/deep-thinker/controller.d.ts +55 -0
  41. package/dist/deep-thinker/controller.d.ts.map +1 -0
  42. package/dist/deep-thinker/controller.js +473 -0
  43. package/dist/deep-thinker/controller.js.map +1 -0
  44. package/dist/deep-thinker/core/budget.d.ts +7 -0
  45. package/dist/deep-thinker/core/budget.d.ts.map +1 -0
  46. package/dist/deep-thinker/core/budget.js +23 -0
  47. package/dist/deep-thinker/core/budget.js.map +1 -0
  48. package/dist/deep-thinker/core/contracts.d.ts +517 -0
  49. package/dist/deep-thinker/core/contracts.d.ts.map +1 -0
  50. package/dist/deep-thinker/core/contracts.js +83 -0
  51. package/dist/deep-thinker/core/contracts.js.map +1 -0
  52. package/dist/deep-thinker/core/graph.d.ts +15 -0
  53. package/dist/deep-thinker/core/graph.d.ts.map +1 -0
  54. package/dist/deep-thinker/core/graph.js +208 -0
  55. package/dist/deep-thinker/core/graph.js.map +1 -0
  56. package/dist/deep-thinker/current-model.d.ts +5 -0
  57. package/dist/deep-thinker/current-model.d.ts.map +1 -0
  58. package/dist/deep-thinker/current-model.js +24 -0
  59. package/dist/deep-thinker/current-model.js.map +1 -0
  60. package/dist/deep-thinker/evidence.d.ts +7 -0
  61. package/dist/deep-thinker/evidence.d.ts.map +1 -0
  62. package/dist/deep-thinker/evidence.js +44 -0
  63. package/dist/deep-thinker/evidence.js.map +1 -0
  64. package/dist/deep-thinker/failures.d.ts +3 -0
  65. package/dist/deep-thinker/failures.d.ts.map +1 -0
  66. package/dist/deep-thinker/failures.js +3 -0
  67. package/dist/deep-thinker/failures.js.map +1 -0
  68. package/dist/deep-thinker/initial-state.d.ts +4 -0
  69. package/dist/deep-thinker/initial-state.d.ts.map +1 -0
  70. package/dist/deep-thinker/initial-state.js +11 -0
  71. package/dist/deep-thinker/initial-state.js.map +1 -0
  72. package/dist/deep-thinker/memory-finalizer.d.ts +111 -0
  73. package/dist/deep-thinker/memory-finalizer.d.ts.map +1 -0
  74. package/dist/deep-thinker/memory-finalizer.js +132 -0
  75. package/dist/deep-thinker/memory-finalizer.js.map +1 -0
  76. package/dist/deep-thinker/memory-request.d.ts +10 -0
  77. package/dist/deep-thinker/memory-request.d.ts.map +1 -0
  78. package/dist/deep-thinker/memory-request.js +3 -0
  79. package/dist/deep-thinker/memory-request.js.map +1 -0
  80. package/dist/deep-thinker/native-executor.d.ts +50 -0
  81. package/dist/deep-thinker/native-executor.d.ts.map +1 -0
  82. package/dist/deep-thinker/native-executor.js +179 -0
  83. package/dist/deep-thinker/native-executor.js.map +1 -0
  84. package/dist/deep-thinker/prompts.d.ts +41 -0
  85. package/dist/deep-thinker/prompts.d.ts.map +1 -0
  86. package/dist/deep-thinker/prompts.js +41 -0
  87. package/dist/deep-thinker/prompts.js.map +1 -0
  88. package/dist/deep-thinker/read-port.d.ts +57 -0
  89. package/dist/deep-thinker/read-port.d.ts.map +1 -0
  90. package/dist/deep-thinker/read-port.js +141 -0
  91. package/dist/deep-thinker/read-port.js.map +1 -0
  92. package/dist/deep-thinker/report-port.d.ts +35 -0
  93. package/dist/deep-thinker/report-port.d.ts.map +1 -0
  94. package/dist/deep-thinker/report-port.js +68 -0
  95. package/dist/deep-thinker/report-port.js.map +1 -0
  96. package/dist/deep-thinker/report-surface.d.ts +6 -0
  97. package/dist/deep-thinker/report-surface.d.ts.map +1 -0
  98. package/dist/deep-thinker/report-surface.js +46 -0
  99. package/dist/deep-thinker/report-surface.js.map +1 -0
  100. package/dist/deep-thinker/report.d.ts +23 -0
  101. package/dist/deep-thinker/report.d.ts.map +1 -0
  102. package/dist/deep-thinker/report.js +27 -0
  103. package/dist/deep-thinker/report.js.map +1 -0
  104. package/dist/deep-thinker/scheduler.d.ts +24 -0
  105. package/dist/deep-thinker/scheduler.d.ts.map +1 -0
  106. package/dist/deep-thinker/scheduler.js +313 -0
  107. package/dist/deep-thinker/scheduler.js.map +1 -0
  108. package/dist/deep-thinker/slots.d.ts +7 -0
  109. package/dist/deep-thinker/slots.d.ts.map +1 -0
  110. package/dist/deep-thinker/slots.js +58 -0
  111. package/dist/deep-thinker/slots.js.map +1 -0
  112. package/dist/deep-thinker/store.d.ts +155 -0
  113. package/dist/deep-thinker/store.d.ts.map +1 -0
  114. package/dist/deep-thinker/store.js +231 -0
  115. package/dist/deep-thinker/store.js.map +1 -0
  116. package/dist/dsh/commands.d.ts +4 -0
  117. package/dist/dsh/commands.d.ts.map +1 -1
  118. package/dist/dsh/commands.js.map +1 -1
  119. package/dist/dsh/composition.d.ts +1 -0
  120. package/dist/dsh/composition.d.ts.map +1 -1
  121. package/dist/dsh/composition.js +13 -2
  122. package/dist/dsh/composition.js.map +1 -1
  123. package/dist/dsh/config.d.ts +16 -0
  124. package/dist/dsh/config.d.ts.map +1 -1
  125. package/dist/dsh/config.js +2 -0
  126. package/dist/dsh/config.js.map +1 -1
  127. package/dist/dsh/context-projection.d.ts +2 -0
  128. package/dist/dsh/context-projection.d.ts.map +1 -1
  129. package/dist/dsh/context-projection.js +3 -2
  130. package/dist/dsh/context-projection.js.map +1 -1
  131. package/dist/dsh/enno-delegation.d.ts +2 -24
  132. package/dist/dsh/enno-delegation.d.ts.map +1 -1
  133. package/dist/dsh/enno-delegation.js +27 -35
  134. package/dist/dsh/enno-delegation.js.map +1 -1
  135. package/dist/dsh/evidence-selection.d.ts +17 -0
  136. package/dist/dsh/evidence-selection.d.ts.map +1 -0
  137. package/dist/dsh/evidence-selection.js +43 -0
  138. package/dist/dsh/evidence-selection.js.map +1 -0
  139. package/dist/dsh/execution-selection.d.ts +60 -0
  140. package/dist/dsh/execution-selection.d.ts.map +1 -1
  141. package/dist/dsh/execution-selection.js +9 -1
  142. package/dist/dsh/execution-selection.js.map +1 -1
  143. package/dist/dsh/host-adapter.d.ts +1 -0
  144. package/dist/dsh/host-adapter.d.ts.map +1 -1
  145. package/dist/dsh/host-adapter.js +72 -6
  146. package/dist/dsh/host-adapter.js.map +1 -1
  147. package/dist/dsh/index.js +1 -1
  148. package/dist/dsh/index.js.map +1 -1
  149. package/dist/dsh/intake-gate.d.ts.map +1 -1
  150. package/dist/dsh/intake-gate.js +1 -0
  151. package/dist/dsh/intake-gate.js.map +1 -1
  152. package/dist/dsh/japanese-output-skill.d.ts +22 -0
  153. package/dist/dsh/japanese-output-skill.d.ts.map +1 -0
  154. package/dist/dsh/japanese-output-skill.js +47 -0
  155. package/dist/dsh/japanese-output-skill.js.map +1 -0
  156. package/dist/dsh/message-sources.d.ts +1 -1
  157. package/dist/dsh/message-sources.d.ts.map +1 -1
  158. package/dist/dsh/message-sources.js +13 -21
  159. package/dist/dsh/message-sources.js.map +1 -1
  160. package/dist/dsh/model-configuration.d.ts +6 -0
  161. package/dist/dsh/model-configuration.d.ts.map +1 -1
  162. package/dist/dsh/model-configuration.js +10 -4
  163. package/dist/dsh/model-configuration.js.map +1 -1
  164. package/dist/dsh/model-routing.d.ts.map +1 -1
  165. package/dist/dsh/model-routing.js +2 -1
  166. package/dist/dsh/model-routing.js.map +1 -1
  167. package/dist/dsh/model-selection-ui.d.ts.map +1 -1
  168. package/dist/dsh/model-selection-ui.js +207 -102
  169. package/dist/dsh/model-selection-ui.js.map +1 -1
  170. package/dist/dsh/orca-host.d.ts +5 -0
  171. package/dist/dsh/orca-host.d.ts.map +1 -1
  172. package/dist/dsh/orca-host.js +11 -4
  173. package/dist/dsh/orca-host.js.map +1 -1
  174. package/dist/dsh/orchestration/execution-owner.d.ts +18 -0
  175. package/dist/dsh/orchestration/execution-owner.d.ts.map +1 -0
  176. package/dist/dsh/orchestration/execution-owner.js +18 -0
  177. package/dist/dsh/orchestration/execution-owner.js.map +1 -0
  178. package/dist/dsh/orchestration/managed-agent-executor.d.ts +37 -0
  179. package/dist/dsh/orchestration/managed-agent-executor.d.ts.map +1 -0
  180. package/dist/dsh/orchestration/managed-agent-executor.js +38 -0
  181. package/dist/dsh/orchestration/managed-agent-executor.js.map +1 -0
  182. package/dist/dsh/request-memory.d.ts +13 -0
  183. package/dist/dsh/request-memory.d.ts.map +1 -0
  184. package/dist/dsh/request-memory.js +64 -0
  185. package/dist/dsh/request-memory.js.map +1 -0
  186. package/dist/dsh/session-log-surface.d.ts.map +1 -1
  187. package/dist/dsh/session-log-surface.js +1 -0
  188. package/dist/dsh/session-log-surface.js.map +1 -1
  189. package/dist/dsh/session-memory-finalizer.d.ts +4 -6
  190. package/dist/dsh/session-memory-finalizer.d.ts.map +1 -1
  191. package/dist/dsh/session-memory-finalizer.js +81 -15
  192. package/dist/dsh/session-memory-finalizer.js.map +1 -1
  193. package/dist/dsh/standard-skill-provider.d.ts +3 -0
  194. package/dist/dsh/standard-skill-provider.d.ts.map +1 -1
  195. package/dist/dsh/standard-skill-provider.js +17 -8
  196. package/dist/dsh/standard-skill-provider.js.map +1 -1
  197. package/dist/dsh/surface-range.d.ts +15 -0
  198. package/dist/dsh/surface-range.d.ts.map +1 -0
  199. package/dist/dsh/surface-range.js +10 -0
  200. package/dist/dsh/surface-range.js.map +1 -0
  201. package/dist/dsh/task-intake.d.ts +5 -0
  202. package/dist/dsh/task-intake.d.ts.map +1 -1
  203. package/dist/dsh/task-intake.js +11 -1
  204. package/dist/dsh/task-intake.js.map +1 -1
  205. package/dist/enno-oduno/schemas.d.ts +7 -7
  206. package/dist/memory/checkpoint-contract.d.ts +6 -6
  207. package/dist/memory/evolution/contracts.d.ts +4 -0
  208. package/dist/memory/evolution/contracts.d.ts.map +1 -1
  209. package/dist/memory/evolution/contracts.js +14 -3
  210. package/dist/memory/evolution/contracts.js.map +1 -1
  211. package/dist/memory/evolution/store.d.ts +1 -1
  212. package/dist/memory/evolution/store.d.ts.map +1 -1
  213. package/dist/memory/evolution/store.js +2 -2
  214. package/dist/memory/evolution/store.js.map +1 -1
  215. package/dist/memory/evolution/worker.js +4 -4
  216. package/dist/memory/evolution/worker.js.map +1 -1
  217. package/dist/model-tools/contracts.d.ts +4 -4
  218. package/docs/deep-planning-verification.md +65 -0
  219. package/docs/deep-planning.md +143 -0
  220. package/docs/dependency-security.md +54 -0
  221. package/docs/japanese-output.md +48 -0
  222. package/docs/memory-lifecycle-verification.md +57 -0
  223. package/docs/model-selection.ja.md +28 -2
  224. package/docs/model-selection.md +27 -2
  225. package/migrations/013_dsh_deep_thinker.sql +90 -0
  226. package/migrations/014_memory_projection_evidence.sql +20 -0
  227. package/package.json +8 -6
  228. package/skills/japanese-translation-for-oss-models/SKILL.md +663 -0
package/PERMISSIONS.md CHANGED
@@ -51,6 +51,16 @@ with pnpm `allowBuilds`; the npm tarball already contains `dist/`.
51
51
 
52
52
  ## Failure boundaries
53
53
 
54
+ `/deep-planning` creates native read-only child agents using explicitly selected
55
+ DSH model connections. It stores input, configuration snapshots, bounded source
56
+ excerpts, attempts, estimated usage and answers in the configured database.
57
+ Source excerpts and the problem are sent to those configured model providers.
58
+ It offers no shell, mutation, arbitrary MCP or further child-spawn capability.
59
+ Deep memory extraction shares the request budget. Unknown Deep calls and memory
60
+ extractions are not automatically resent after a crash. Deep children inherit
61
+ only their exact parent's existing Orca recording choice. See
62
+ [Deep planning](docs/deep-planning.md) for limits and recovery behavior.
63
+
54
64
  Missing optional dependencies, unavailable external services, stale or
55
65
  ambiguous run state, failed verifier processes, and integrity or ownership
56
66
  conflicts are reported as failures or unavailable states. They are never
package/README.ja.md CHANGED
@@ -7,9 +7,14 @@ OrcaReplay でモデル・ツールの動作を記録し、内容の確認と HT
7
7
 
8
8
 
9
9
  新しい変更作業では、通常実行か役小角(enno-oduno)を選べます。役小角ではおすすめテンプレート、またはDSH設定済みモデルから役割ごとの構成を選択します。[モデル選択と接続上の制約](docs/model-selection.ja.md)
10
+
11
+ `/deep-planning <問題>` は、四つの役割による読み取り専用の調査・分析・計画作成です。入力を保持し、一時停止・復旧に対応します。推定予算に達した場合も部分回答を返します。[操作・予算・復旧の仕様](docs/deep-planning.md)
12
+
13
+ DeepSeek・Kimi・GLM・Qwen・HY/Hunyuan・MiMo・MiniMaxのAgentには、日本語を自然に整える同梱Skillを自動で渡します。[適用条件とモデル判定](docs/japanese-output.md)
14
+
10
15
  ## 導入と使い方
11
16
 
12
- 対応 DSH: `0.1.2-rc.1` / [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) / [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)。
17
+ 対応 DSH: [0.1.5-rc.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.5-rc.1) / [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) / [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)。
13
18
  Node.js **24.16.0 以上**と pnpm が必要です。
14
19
  DSH のソースディレクトリで、公開済み npm パッケージを導入して起動します。
15
20
 
package/README.ko.md CHANGED
@@ -9,7 +9,7 @@ OrcaReplay로 모델과 도구의 동작을 기록하고, 기록을 확인하거
9
9
  새 변경 작업에서는 일반 실행 또는 役小角(enno-oduno)를 선택할 수 있습니다. 역할별 모델은 추천 템플릿이나 DSH에 설정된 모델에서 선택합니다. [모델 선택과 연결 제한](docs/model-selection.md).
10
10
  ## 설치 및 사용
11
11
 
12
- DSH `0.1.2-rc.1`, [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)를 지원합니다.
12
+ DSH [0.1.5-rc.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.5-rc.1), [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)를 지원합니다.
13
13
  Node.js **24.16.0 이상**과 pnpm이 필요합니다.
14
14
  DSH 소스 디렉터리에서 다음 명령으로 공개된 npm 패키지를 설치하고 시작합니다.
15
15
 
package/README.md CHANGED
@@ -8,9 +8,14 @@ OrcaReplay records model/tool activity for inspection and HTML export.
8
8
 
9
9
 
10
10
  For new coding tasks, choose normal execution or 役小角(enno-oduno). Enno offers model templates and role assignments from configured DSH models. [Model selection and connection limits](docs/model-selection.md).
11
+
12
+ Use `/deep-planning <problem>` for bounded, read-only investigation and planning with four agent roles. It preserves inputs, supports pause/recovery, and returns partial answers when its estimated budget is exhausted. [Commands, budgets and recovery](docs/deep-planning.md).
13
+
14
+ DeepSeek, Kimi, GLM, Qwen, HY/Hunyuan, MiMo and MiniMax agents automatically receive the bundled Japanese writing Skill. [Application rules and model identification](docs/japanese-output.md).
15
+
11
16
  ## Install and use
12
17
 
13
- Supports DSH `0.1.2-rc.1`, [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), and [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2).
18
+ Supports DSH [0.1.5-rc.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.5-rc.1), [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), and [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2).
14
19
  Requires Node.js **24.16.0+** and pnpm.
15
20
  Run these commands from the DSH source directory to install the published npm package and start:
16
21
 
package/README.zh-CN.md CHANGED
@@ -9,7 +9,7 @@ OrcaReplay 可记录模型和工具活动,查看记录并导出 HTML。
9
9
  新的修改任务可以选择普通执行或役小角(enno-oduno)。役小角支持推荐模板,也可从DSH已配置的模型中为各角色选择模型。[模型选择与连接限制](docs/model-selection.md)。
10
10
  ## 安装与使用
11
11
 
12
- 支持 DSH `0.1.2-rc.1`、[0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) 和 [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)。
12
+ 支持 DSH [0.1.5-rc.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.5-rc.1)、[0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) 和 [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)。
13
13
  需要 Node.js **24.16.0 以上**和 pnpm。
14
14
  在 DSH 源码目录中运行以下命令,安装已发布的 npm 包并启动:
15
15
 
package/dist/client.cjs CHANGED
@@ -203,28 +203,156 @@ window.__ModuleLoader__.load({
203
203
  /** A plugin-owned result in chat, never forged as a model assistant message. */
204
204
  const completionReportDefinition = {
205
205
  kind: 'kiokuko-completion-report', target: 'chat',
206
- match: (event) => (event.type === 'kiokuko/completion-report' || event.type === 'kiokuko/execution-status') && typeof event.data.reportId === 'string' && typeof event.data.text === 'string'
206
+ match: (event) => ['kiokuko/completion-report', 'kiokuko/execution-status', 'kiokuko/deep-report', 'kiokuko/deep-status'].includes(event.type) && typeof event.data.reportId === 'string' && typeof event.data.text === 'string'
207
207
  ? { id: event.data.reportId, role: 'start' } : null,
208
- start: (_context, match) => ({ seq: match.event.seq, text: match.event.data.text }),
208
+ start: (_context, match) => ({ seq: match.event.seq, text: match.event.data.text, status: match.event.type.endsWith('status') }),
209
209
  update: (context) => context.state,
210
210
  buildViewNode: (context) => context.state === undefined ? null : {
211
211
  key: context.key, id: context.id, kind: 'kiokuko-completion-report', target: 'chat',
212
212
  anchorSeq: context.state.seq, location: context.start?.location ?? { kind: 'session' },
213
- visibility: 'visible', data: { text: context.state.text },
213
+ visibility: 'visible', data: { text: context.state.text, status: context.state.status },
214
214
  },
215
215
  };
216
216
  function CompletionReport(props) {
217
217
  const node = props.node;
218
- return jsx('section', { role: 'status', 'aria-live': 'polite',
219
- style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', padding: '12px 0' }, children: node.data.text });
218
+ return jsx('section', { ...(node.data.status ? { role: 'status', 'aria-live': 'polite', 'aria-atomic': true } : { 'aria-label': '保存済みの回答', tabIndex: 0 }),
219
+ style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', maxWidth: '100%', minWidth: 0, padding: '12px 0', lineHeight: 1.65 }, children: node.data.text });
220
+ }
221
+ /** Read-only, Session-bound display with explicit delivery acknowledgement after render. */
222
+ function DeepSessionReports(props) {
223
+ const sessionId = String(props.sessionId);
224
+ const [items, setItems] = useState([]);
225
+ const [open, setOpen] = useState(false);
226
+ const [error, setError] = useState('');
227
+ const seen = useRef(new Set());
228
+ const dialog = useRef(null);
229
+ const trigger = useRef(null);
230
+ useEffect(() => {
231
+ if (open && dialog.current && !dialog.current.open)
232
+ dialog.current.showModal();
233
+ else if (!open && dialog.current?.open) {
234
+ dialog.current.close();
235
+ trigger.current?.focus();
236
+ }
237
+ }, [open]);
238
+ useEffect(() => {
239
+ const controller = new AbortController();
240
+ let timer;
241
+ let etag = '';
242
+ setItems([]);
243
+ setOpen(false);
244
+ seen.current = new Set();
245
+ const refresh = async () => {
246
+ try {
247
+ const url = new URL('/api/kiokuko.deep', hostBase());
248
+ url.searchParams.set('sessionId', sessionId);
249
+ const response = await fetch(url, { signal: controller.signal, headers: etag ? { 'if-none-match': etag } : {} });
250
+ if (response.status === 304) {
251
+ setError('');
252
+ return;
253
+ }
254
+ if (!response.ok)
255
+ throw new Error('Deepの状態を再確認できません。接続を確認してください。');
256
+ etag = response.headers.get('etag') ?? '';
257
+ const data = await response.json();
258
+ if (!Array.isArray(data.items) || data.items.some(item => typeof item.id !== 'string' || typeof item.text !== 'string'))
259
+ throw new Error('Deepの応答を読み取れません。');
260
+ if (controller.signal.aborted)
261
+ return;
262
+ setItems(data.items);
263
+ setError('');
264
+ for (const item of data.items)
265
+ if (item.kind === 'report' && !item.delivered && !seen.current.has(item.id)) {
266
+ seen.current.add(item.id);
267
+ setOpen(true);
268
+ }
269
+ }
270
+ catch (failure) {
271
+ if (!controller.signal.aborted)
272
+ setError(messageOf(failure));
273
+ }
274
+ finally {
275
+ if (!controller.signal.aborted)
276
+ timer = setTimeout(() => void refresh(), document.hidden ? 10_000 : 2_000);
277
+ }
278
+ };
279
+ void refresh();
280
+ return () => { controller.abort(); clearTimeout(timer); };
281
+ }, [sessionId]);
282
+ useEffect(() => {
283
+ const unread = items.filter(item => !item.delivered && (item.kind === 'status' || open));
284
+ if (!unread.length)
285
+ return;
286
+ const controller = new AbortController();
287
+ const url = new URL('/api/kiokuko.deep', hostBase());
288
+ url.searchParams.set('sessionId', sessionId);
289
+ for (const item of unread)
290
+ url.searchParams.append('id', item.id);
291
+ let timer;
292
+ const acknowledge = async () => {
293
+ try {
294
+ const response = await fetch(url, { method: 'POST', signal: controller.signal });
295
+ if (!response.ok)
296
+ throw new Error('Deepの受領確認を再試行しています。回答は保持されています。');
297
+ }
298
+ catch (failure) {
299
+ if (!controller.signal.aborted) {
300
+ setError(messageOf(failure));
301
+ timer = setTimeout(() => void acknowledge(), 5_000);
302
+ }
303
+ }
304
+ };
305
+ void acknowledge();
306
+ return () => { controller.abort(); clearTimeout(timer); };
307
+ }, [sessionId, items, open]);
308
+ if (!items.length && !error)
309
+ return null;
310
+ const status = items.find(item => item.kind === 'status')?.text ?? 'Deepの保存済み回答';
311
+ return jsxs(Fragment, { children: [
312
+ jsx('button', { ref: trigger, type: 'button', className: 'kiokuko-session-log-button', onClick: () => setOpen(true), 'aria-label': `Deep planning: ${status}`, children: items.some(item => item.kind === 'report') ? 'Deepの回答' : 'Deepの状態' }),
313
+ jsx('span', { role: 'status', 'aria-live': 'polite', style: { position: 'absolute', width: 1, height: 1, overflow: 'hidden', clipPath: 'inset(50%)' }, children: error || status.slice(0, 200) }),
314
+ jsxs('dialog', { ref: dialog, 'aria-label': 'Deep planning', onCancel: () => setOpen(false), onClose: () => { setOpen(false); trigger.current?.focus(); },
315
+ style: { width: 'min(48rem, calc(100vw - 2rem))', maxHeight: 'calc(100dvh - 2rem)', boxSizing: 'border-box', margin: 'auto', padding: '20px', border: '1px solid var(--dsw-alias-border-l4, #ddd)', borderRadius: '16px', background: 'var(--dsw-alias-background-primary, Canvas)', color: 'var(--dsw-alias-label-primary, CanvasText)', overflow: 'auto' },
316
+ children: [jsxs('div', { style: { display: 'flex', justifyContent: 'space-between', gap: '16px', alignItems: 'center' }, children: [jsx('h2', { style: { fontSize: '20px', margin: 0 }, children: 'Deep planning' }), jsx('button', { type: 'button', className: 'kiokuko-session-log-button', onClick: () => setOpen(false), children: '閉じる' })] }),
317
+ jsx('p', { style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' }, children: error || status }),
318
+ ...items.filter(item => item.kind === 'report').map(item => jsx('section', { key: item.id, 'aria-label': '保存済みの回答', tabIndex: 0, style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', maxWidth: '100%', padding: '12px 0', lineHeight: 1.65 }, children: item.text }))] }),
319
+ ] });
220
320
  }
221
321
  const intakeDrafts = new WeakMap();
322
+ /**
323
+ * Small intake questions this plugin renders as a numbered option card. The identity
324
+ * pair is matched exactly: another plugin's question that happens to share one
325
+ * half falls through to the native composer. `supported` keeps the option count
326
+ * inside the 1-9 range the number-key shortcut can address.
327
+ */
328
+ const INTAKE_QUESTIONS = [
329
+ { id: 'taskType', header: 'Kiokuko · 作業の選択' },
330
+ { id: 'kioku-orca-recording', header: 'OrcaReplay · 詳細ログ' },
331
+ ];
332
+ const ENNO_SELECTION_QUESTIONS = [
333
+ 'enno-execution-mode', 'enno-model-source', 'enno-template', 'enno-template-provider',
334
+ 'enno-template-unavailable', 'enno-bind-provider', 'enno-model-review', 'enno-catalog-retry',
335
+ 'enno-route-provider', 'enno-route-family', 'enno-route-auth', 'enno-route-protocol',
336
+ ];
337
+ function isEnnoSearchQuestion(question) {
338
+ return question.header === '実行方式とモデル' && /^enno-(?:provider|model)-(?:ideal|zenki|goki|worker|check)$/u.test(question.id);
339
+ }
340
+ function isSupportedQuestion(question) {
341
+ if (question === undefined || question.multiSelect === true)
342
+ return false;
343
+ const options = question.options?.length ?? 0;
344
+ if (options < 1)
345
+ return false;
346
+ if (question.header === '実行方式とモデル' && (ENNO_SELECTION_QUESTIONS.includes(question.id) || isEnnoSearchQuestion(question)))
347
+ return true;
348
+ if (options > 9)
349
+ return false;
350
+ return INTAKE_QUESTIONS.some(kind => kind.id === question.id && kind.header === question.header);
351
+ }
222
352
  function intakePending(props) {
223
353
  const pending = props.pendingInteraction;
224
- const question = pending?.questions?.[0];
225
354
  return pending?.kind === 'question' && pending.questions.length === 1
226
- && question?.id === 'taskType' && question.header === 'Kiokuko · 作業の選択'
227
- && question.multiSelect !== true && question.options?.length > 0 && question.options.length <= 9
355
+ && isSupportedQuestion(pending.questions[0])
228
356
  && typeof pending.answer === 'function' && typeof pending.cancel === 'function'
229
357
  ? pending : null;
230
358
  }
@@ -236,6 +364,7 @@ window.__ModuleLoader__.load({
236
364
  function IntakeQuestionCard(props) {
237
365
  const pending = props.pending;
238
366
  const question = pending.questions[0];
367
+ const searchable = isEnnoSearchQuestion(question);
239
368
  const [draft, setDraft] = useState(() => intakeDrafts.get(pending) ?? { selected: null, custom: '' });
240
369
  const [busy, setBusy] = useState(false);
241
370
  const [error, setError] = useState('');
@@ -253,6 +382,8 @@ window.__ModuleLoader__.load({
253
382
  optionElements.current[draft.selected]?.scrollIntoView({ block: 'nearest' });
254
383
  }, [draft.selected]);
255
384
  const update = (value) => {
385
+ if (inFlight.current)
386
+ return;
256
387
  intakeDrafts.set(pending, value);
257
388
  setDraft(value);
258
389
  setError('');
@@ -260,17 +391,22 @@ window.__ModuleLoader__.load({
260
391
  const settle = (cancel = false) => {
261
392
  if (inFlight.current)
262
393
  return;
263
- const custom = draft.custom.trim();
264
- if (!cancel && draft.selected === null && custom === '') {
394
+ // Read the synchronous draft: a digit and Enter can arrive before React rerenders.
395
+ const current = intakeDrafts.get(pending) ?? draft;
396
+ let custom = current.custom.trim();
397
+ let selected = current.selected;
398
+ if (!cancel && selected === null && custom === '') {
265
399
  setError('選択肢を選ぶか、自由入力してください。');
266
400
  return;
267
401
  }
268
- if (!cancel && /^[0-90-9]+$/u.test(custom)) {
402
+ if (!cancel && !searchable && /^[0-90-9]+$/u.test(custom)) {
269
403
  const ordinal = Number(custom.normalize('NFKC'));
270
404
  if (ordinal < 1 || ordinal > question.options.length) {
271
405
  setError(`番号は1〜${question.options.length}で入力してください。`);
272
406
  return;
273
407
  }
408
+ selected = ordinal - 1;
409
+ custom = '';
274
410
  }
275
411
  inFlight.current = true;
276
412
  setBusy(true);
@@ -278,7 +414,7 @@ window.__ModuleLoader__.load({
278
414
  // Enter is a separate confirmation. Typing, key-repeat and IME cannot submit twice.
279
415
  void Promise.resolve().then(() => cancel ? pending.cancel() : pending.answer({ answers: [{
280
416
  id: question.id,
281
- selected: draft.selected === null ? [] : [question.options[draft.selected].label],
417
+ selected: selected === null ? [] : [question.options[selected].label],
282
418
  ...(custom ? { custom } : {}),
283
419
  }] })).then(() => { intakeDrafts.delete(pending); }).catch(cause => {
284
420
  if (!mounted.current)
@@ -289,20 +425,26 @@ window.__ModuleLoader__.load({
289
425
  });
290
426
  };
291
427
  const keyDown = (event) => {
292
- if (busy || event.repeat || event.nativeEvent?.isComposing || event.nativeEvent?.keyCode === 229
428
+ if (busy || inFlight.current || event.repeat || event.nativeEvent?.isComposing || event.nativeEvent?.keyCode === 229
293
429
  || event.ctrlKey || event.altKey || event.metaKey || event.shiftKey)
294
430
  return;
295
431
  const editing = event.target?.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(event.target?.tagName ?? '');
296
- if (!editing && /^[1-9]$/u.test(event.key)) {
297
- const index = Number(event.key) - 1;
298
- if (index >= question.options.length)
432
+ const current = intakeDrafts.get(pending) ?? draft;
433
+ if (!editing && (/^[0-9]$/u.test(event.key) || (event.key === 'Backspace' && current.ordinal))) {
434
+ const multipleDigits = question.options.length > 9;
435
+ if (!multipleDigits && (!/^[1-9]$/u.test(event.key) || Number(event.key) > question.options.length))
299
436
  return;
300
437
  event.preventDefault();
301
438
  event.stopPropagation();
302
- update({ selected: index, custom: '' });
439
+ const ordinal = event.key === 'Backspace' ? current.ordinal.slice(0, -1) : multipleDigits ? (current.ordinal ?? '') + event.key : event.key;
440
+ const index = Number(ordinal) - 1;
441
+ const valid = ordinal !== '' && index >= 0 && index < question.options.length;
442
+ update({ selected: valid ? index : null, custom: '', ordinal });
443
+ if (ordinal && !valid)
444
+ setError(`番号「${ordinal}」は範囲外です。1〜${question.options.length}で入力してください。Backspaceで訂正できます。`);
303
445
  card.current?.focus();
304
446
  }
305
- else if (event.key === 'Enter' && event.target?.tagName !== 'BUTTON') {
447
+ else if (event.key === 'Enter' && event.target?.tagName !== 'BUTTON' && !event.target?.isContentEditable) {
306
448
  event.preventDefault();
307
449
  event.stopPropagation();
308
450
  settle();
@@ -317,14 +459,16 @@ window.__ModuleLoader__.load({
317
459
  jsx('button', { type: 'button', disabled: busy, onClick: () => settle(true), 'aria-label': '質問を閉じる', children: '閉じる' })] }),
318
460
  jsxs('div', { className: 'kiokuko-intake-body', children: [
319
461
  question.detail ? jsx('p', { children: question.detail }) : null,
320
- jsx('p', { children: `1〜${question.options.length}キーで選択、Enterで確定。` }),
321
- jsx('div', { 'aria-label': '作業の選択肢', children: question.options.map((option, index) => jsxs('button', {
462
+ jsx('p', { children: question.options.length > 9
463
+ ? `番号(1〜${question.options.length})を入力し、Enterで確定。10以上は数字を続けて入力、Backspaceで訂正できます。`
464
+ : `1〜${question.options.length}キーで選択、Enterで確定。` }),
465
+ jsx('div', { 'aria-label': '選択肢', children: question.options.map((option, index) => jsxs('button', {
322
466
  key: option.label, type: 'button', className: 'kiokuko-intake-option', disabled: busy,
323
467
  ref: (element) => { optionElements.current[index] = element; },
324
- 'aria-pressed': draft.selected === index, 'aria-keyshortcuts': String(index + 1),
468
+ 'aria-pressed': draft.selected === index, ...(question.options.length <= 9 ? { 'aria-keyshortcuts': String(index + 1) } : {}),
325
469
  onClick: () => update({ selected: index, custom: '' }),
326
470
  onKeyDown: (event) => {
327
- if (event.key !== 'Enter' || event.repeat || event.shiftKey || event.ctrlKey || event.altKey || event.metaKey || event.nativeEvent?.isComposing || event.nativeEvent?.keyCode === 229 || draft.selected !== index)
471
+ if (event.key !== 'Enter' || event.repeat || event.shiftKey || event.ctrlKey || event.altKey || event.metaKey || event.nativeEvent?.isComposing || event.nativeEvent?.keyCode === 229 || (intakeDrafts.get(pending) ?? draft).selected !== index)
328
472
  return;
329
473
  event.preventDefault();
330
474
  event.stopPropagation();
@@ -332,7 +476,7 @@ window.__ModuleLoader__.load({
332
476
  },
333
477
  children: [jsx('strong', { children: `${index + 1}. ${option.label}` }), option.description ? jsx('span', { children: option.description }) : null],
334
478
  })) }),
335
- jsx('label', { htmlFor: `${titleId}-custom`, children: '自由入力(任意)' }),
479
+ jsx('label', { htmlFor: `${titleId}-custom`, children: searchable ? '検索(Enterで検索・数字も検索語として入力できます)' : '自由入力(任意)' }),
336
480
  jsx('textarea', { id: `${titleId}-custom`, rows: 1, disabled: busy, value: draft.custom,
337
481
  onChange: (event) => update({ selected: null, custom: event.target.value }),
338
482
  }),
@@ -374,6 +518,9 @@ window.__ModuleLoader__.load({
374
518
  name: 'conversation.composer', priority: -10, select: intakePending, locale: LOCALE_NAMESPACE,
375
519
  }, IntakeQuestion));
376
520
  ctx.effect(installIntakeStyle, 'kiokuko-dsh: intake style');
521
+ ctx.slots.inject('conversation.session.header.utilities', () => ctx.slots.register({
522
+ name: 'conversation.session.header.utilities', id: 'kiokuko-deep-reports', locale: LOCALE_NAMESPACE,
523
+ }, DeepSessionReports));
377
524
  ctx.uiConversation.events.register(completionReportDefinition);
378
525
  ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({
379
526
  name: 'conversation.chat.node', key: 'kiokuko-completion-report', locale: LOCALE_NAMESPACE,
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC7G,QAAQ,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAYD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAA;KAC3F,CAAA;IACD,QAAQ,CAAC,KAAK,EAAE;QACd,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAA;QACtD,QAAQ,CACN,UAAU,EAAE;YACV,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;YACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;YAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;YAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;YACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAChD,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACrD,OAAO,CAAA;KACX,CAAA;IACD,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChF,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAA;CACtI;AA0ED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAqBjH;AAuHD,eAAO,MAAM,MAAM,gDAAiD,CAAA;AAoLpE,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CA0BjD"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC7G,QAAQ,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAYD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAA;KAC3F,CAAA;IACD,QAAQ,CAAC,KAAK,EAAE;QACd,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAA;QACtD,QAAQ,CACN,UAAU,EAAE;YACV,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;YACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;YAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;YAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;YACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAChD,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACrD,OAAO,CAAA;KACX,CAAA;IACD,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChF,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAA;CACtI;AA0ED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAqBjH;AAuHD,eAAO,MAAM,MAAM,gDAAiD,CAAA;AAgSpE,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CA6BjD"}
@@ -1,6 +1,7 @@
1
1
  import type { SqliteDatabase } from '../db/adapter.js';
2
2
  import { type ContextRankingV2Component } from './ranking.js';
3
3
  import { type ContextEntryOrigin } from './origin.js';
4
+ import { MemoryProjectionReceipt } from './memory-projection.js';
4
5
  export type ContextDeliveryScoreComponents = {
5
6
  [Component in ContextRankingV2Component]: number;
6
7
  };
@@ -12,6 +13,7 @@ export interface ContextDeliveryItemInput {
12
13
  selectionReasons: string[];
13
14
  /** Set only for v2 cross-scope deliveries; project remains the v1 default. */
14
15
  origin?: ContextEntryOrigin;
16
+ projection?: MemoryProjectionReceipt;
15
17
  }
16
18
  export interface ContextDeliveryInput {
17
19
  workspace: string;
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/context/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAqD,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAoBzG,MAAM,MAAM,8BAA8B,GAAG;KAAG,SAAS,IAAI,yBAAyB,GAAG,MAAM;CAAE,CAAC;AAElG,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,8BAA8B,CAAC;IAChD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,wBAAwB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAC9E,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,2GAA2G;IAC3G,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA4cD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,YAAY,CAAC,GAAG,MAAM,CAwBxF;AA2QD,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,2BAAgC,GACxC,mBAAmB,CAQrB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAOjG;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CA8CnG"}
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/context/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAqD,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGzG,OAAO,EAAE,uBAAuB,EAAsB,MAAM,wBAAwB,CAAC;AAkBrF,MAAM,MAAM,8BAA8B,GAAG;KAAG,SAAS,IAAI,yBAAyB,GAAG,MAAM;CAAE,CAAC;AAElG,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,8BAA8B,CAAC;IAChD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,wBAAwB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAC9E,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,2GAA2G;IAC3G,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAidD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,YAAY,CAAC,GAAG,MAAM,CAyBxF;AAoRD,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,2BAAgC,GACxC,mBAAmB,CAQrB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAOjG;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CA8CnG"}
@@ -7,6 +7,7 @@ import { isRetrievableEntry } from '../memory/hybrid-retrieval.js';
7
7
  import { entryOriginMatchesWorkspace, isContextEntryOrigin } from './origin.js';
8
8
  import { RUN_STATUSES } from '../ledger/types.js';
9
9
  import { readContextRunProfileBinding } from './run-state.js';
10
+ import { MemoryProjectionReceipt, projectMemoryEntry } from './memory-projection.js';
10
11
  const MAX_IDENTIFIER_BYTES = 256;
11
12
  const MAX_ITEMS = 100;
12
13
  const MAX_SCORE_COMPONENT = 1_000_000;
@@ -14,7 +15,7 @@ const MAX_CHAR_BUDGET = 100_000;
14
15
  const MAX_LIMIT = 100;
15
16
  const DEFAULT_LIMIT = 100;
16
17
  const DELIVERY_CURSOR_VERSION = 1;
17
- const SCOPED_DELIVERY_POLICY_VERSION = 'context-ranking-v6';
18
+ const SCOPED_DELIVERY_POLICY_VERSION = 'context-ranking-v7';
18
19
  const DELIVERY_SCORE_SCHEMA_VERSION = 2;
19
20
  const VALIDATION_MESSAGE = 'Context delivery input is invalid';
20
21
  const NOT_FOUND_MESSAGE = 'Context delivery target was not found';
@@ -195,7 +196,7 @@ function deliveryPolicyVersion() {
195
196
  return SCOPED_DELIVERY_POLICY_VERSION;
196
197
  }
197
198
  function storedDeliveryPolicyMatches(policyVersion) {
198
- return policyVersion === deliveryPolicyVersion();
199
+ return policyVersion === deliveryPolicyVersion() || policyVersion === 'context-ranking-v6';
199
200
  }
200
201
  function storedNonNegativeSafeInteger(value) {
201
202
  if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)
@@ -297,7 +298,7 @@ function validateDeliveryItems(value) {
297
298
  validation();
298
299
  const entries = new Set();
299
300
  return array.map((item, index) => {
300
- const object = objectInput(item, ['entryId', 'entryRevision', 'rank', 'scoreComponents', 'selectionReasons', 'origin'], false);
301
+ const object = objectInput(item, ['entryId', 'entryRevision', 'rank', 'scoreComponents', 'selectionReasons', 'origin', 'projection'], false);
301
302
  const entryId = boundedIdentifier(readField(object, 'entryId'));
302
303
  if (entries.has(entryId))
303
304
  validation();
@@ -314,6 +315,7 @@ function validateDeliveryItems(value) {
314
315
  scoreComponents: scoreComponentsForVersion(readField(object, 'scoreComponents')),
315
316
  selectionReasons: selectionReasons(readField(object, 'selectionReasons')),
316
317
  ...(origin === undefined ? {} : { origin }),
318
+ ...(object.projection === undefined ? {} : { projection: MemoryProjectionReceipt.parse(object.projection) }),
317
319
  };
318
320
  });
319
321
  }
@@ -345,9 +347,13 @@ function validateContextDeliveryInput(value) {
345
347
  validation();
346
348
  const truncated = booleanValue(readField(object, 'truncated'));
347
349
  const createdAt = timestamp(readField(object, 'createdAt'));
348
- if (policyVersion !== deliveryPolicyVersion())
350
+ if (!storedDeliveryPolicyMatches(policyVersion))
349
351
  validation();
350
352
  const items = validateDeliveryItems(readField(object, 'items'));
353
+ if (policyVersion === deliveryPolicyVersion() && (items.some(item => !item.projection || item.projection.sourceRevision !== item.entryRevision) || items.reduce((sum, item) => sum + item.projection.characters, 0) !== charCount))
354
+ validation();
355
+ if (policyVersion === 'context-ranking-v6' && items.some(item => item.projection !== undefined))
356
+ validation();
351
357
  return {
352
358
  workspace,
353
359
  deliveryId,
@@ -450,6 +456,7 @@ function canonicalDeliveryBody(input) {
450
456
  scoreComponents: item.scoreComponents,
451
457
  selectionReasons: item.selectionReasons,
452
458
  ...(item.origin === undefined ? {} : { origin: item.origin }),
459
+ ...(item.projection === undefined ? {} : { projection: item.projection }),
453
460
  })),
454
461
  scoreSchemaVersion: DELIVERY_SCORE_SCHEMA_VERSION,
455
462
  });
@@ -476,6 +483,7 @@ export function scopedDeliveryId(input) {
476
483
  scoreComponents: item.scoreComponents,
477
484
  selectionReasons: item.selectionReasons,
478
485
  ...(item.origin === undefined ? {} : { origin: item.origin }),
486
+ ...(item.projection === undefined ? {} : { projection: item.projection }),
479
487
  })),
480
488
  })}`;
481
489
  }
@@ -548,6 +556,8 @@ function assertRunForWrite(database, input) {
548
556
  const entry = strictCurrentEntry(database, entryWorkspace, item.entryId, origin !== 'project');
549
557
  if (entry.revision !== item.entryRevision)
550
558
  conflict();
559
+ if (input.policyVersion === deliveryPolicyVersion() && canonicalJson(projectMemoryEntry(database, entry)?.projection ?? null) !== canonicalJson(item.projection ?? null))
560
+ conflict();
551
561
  if (!isRetrievableEntry(database, entry) || entry.status === 'superseded')
552
562
  conflict();
553
563
  if (!entryOriginMatchesWorkspace({ origin, runWorkspace: input.workspace, entryWorkspace: entry.workspace }))
@@ -634,7 +644,7 @@ function validateStoredHeader(row, workspace) {
634
644
  function selectDeliveryEntries(database, deliveryId) {
635
645
  return database.prepare(`
636
646
  SELECT cde.delivery_id, cde.entry_id, cde.entry_revision, cde.rank,
637
- cde.score_components_json, cde.selection_reason_json, cde.origin_scope,
647
+ cde.score_components_json, cde.selection_reason_json, cde.origin_scope, cde.projection_json,
638
648
  e.workspace AS entry_workspace, r.workspace AS revision_workspace
639
649
  FROM context_delivery_entries AS cde
640
650
  LEFT JOIN entry_revisions AS r
@@ -674,7 +684,20 @@ function validateStoredEntries(database, header) {
674
684
  const reasons = storedSelectionReasons(reasonValue);
675
685
  if (canonicalJson(score) !== row.score_components_json || canonicalJson(reasons) !== row.selection_reason_json)
676
686
  integrity();
677
- return { entryId, entryRevision, rank, scoreComponents: score, selectionReasons: reasons, ...(origin === 'project' ? {} : { origin }) };
687
+ let projection;
688
+ if (row.projection_json !== null) {
689
+ try {
690
+ projection = MemoryProjectionReceipt.parse(validateStoredJson(row.projection_json));
691
+ }
692
+ catch {
693
+ integrity();
694
+ }
695
+ }
696
+ if (header.policyVersion === deliveryPolicyVersion() && (!projection || projection.sourceRevision !== entryRevision))
697
+ integrity();
698
+ if (header.policyVersion === 'context-ranking-v6' && projection !== undefined)
699
+ integrity();
700
+ return { entryId, entryRevision, rank, scoreComponents: score, selectionReasons: reasons, ...(origin === 'project' ? {} : { origin }), ...(projection === undefined ? {} : { projection }) };
678
701
  });
679
702
  }
680
703
  function assertStoredProfileBinding(database, header) {
@@ -706,6 +729,8 @@ function readStoredDelivery(database, workspace, deliveryId) {
706
729
  const header = validateStoredHeader(row, workspace);
707
730
  assertStoredDeliveryBinding(database, header);
708
731
  const items = validateStoredEntries(database, header);
732
+ if (header.policyVersion === deliveryPolicyVersion() && items.reduce((sum, item) => sum + item.projection.characters, 0) !== header.charCount)
733
+ integrity();
709
734
  const complete = { ...header, items };
710
735
  if (!storedScopedDeliveryIdentityMatches(complete))
711
736
  scopedIdentityIntegrity();
@@ -741,9 +766,9 @@ function writeContextDelivery(database, input, options = {}) {
741
766
  for (const item of input.items) {
742
767
  database.prepare(`
743
768
  INSERT INTO context_delivery_entries (
744
- delivery_id, entry_id, entry_revision, rank, score_components_json, selection_reason_json, origin_scope
745
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
746
- `).run(input.deliveryId, item.entryId, item.entryRevision, item.rank, canonicalJson(item.scoreComponents), canonicalJson(item.selectionReasons), item.origin ?? 'project');
769
+ delivery_id, entry_id, entry_revision, rank, score_components_json, selection_reason_json, origin_scope, projection_json
770
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
771
+ `).run(input.deliveryId, item.entryId, item.entryRevision, item.rank, canonicalJson(item.scoreComponents), canonicalJson(item.selectionReasons), item.origin ?? 'project', item.projection === undefined ? null : canonicalJson(item.projection));
747
772
  }
748
773
  return readStoredDelivery(database, input.workspace, input.deliveryId);
749
774
  }