@code-yeongyu/senpi 2026.9.7 → 2026.9.8

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 (323) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/core/agent-session.d.ts +40 -3
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +159 -40
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/compaction/compaction.d.ts.map +1 -1
  7. package/dist/core/compaction/compaction.js +2 -1
  8. package/dist/core/compaction/compaction.js.map +1 -1
  9. package/dist/core/dynamic-prompt/working-task.js +1 -1
  10. package/dist/core/dynamic-prompt/working-task.js.map +1 -1
  11. package/dist/core/extensions/builtin/cache-keepalive/index.d.ts.map +1 -1
  12. package/dist/core/extensions/builtin/cache-keepalive/index.js +4 -21
  13. package/dist/core/extensions/builtin/cache-keepalive/index.js.map +1 -1
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts +2 -0
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts.map +1 -1
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js +10 -25
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js.map +1 -1
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +36 -19
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js +21 -10
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +4 -17
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +23 -33
  27. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
  28. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  29. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +1 -0
  30. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js +5 -3
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js.map +1 -1
  34. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +8 -3
  36. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js.map +1 -1
  37. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts +6 -5
  38. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js +6 -5
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/circuit-breaker.d.ts +8 -0
  42. package/dist/core/extensions/builtin/compaction/circuit-breaker.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/compaction/circuit-breaker.js +8 -0
  44. package/dist/core/extensions/builtin/compaction/circuit-breaker.js.map +1 -1
  45. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -0
  46. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +125 -20
  48. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  49. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.d.ts +18 -0
  50. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.d.ts.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.js +20 -0
  52. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.js.map +1 -0
  53. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/compaction/index.js +54 -11
  55. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  56. package/dist/core/extensions/builtin/compaction/lane-policy.d.ts +3 -0
  57. package/dist/core/extensions/builtin/compaction/lane-policy.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/compaction/lane-policy.js +47 -23
  59. package/dist/core/extensions/builtin/compaction/lane-policy.js.map +1 -1
  60. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +11 -0
  62. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  63. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js +6 -4
  64. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js.map +1 -1
  65. package/dist/core/extensions/builtin/goal/cache-warm.d.ts +25 -1
  66. package/dist/core/extensions/builtin/goal/cache-warm.d.ts.map +1 -1
  67. package/dist/core/extensions/builtin/goal/cache-warm.js +29 -10
  68. package/dist/core/extensions/builtin/goal/cache-warm.js.map +1 -1
  69. package/dist/core/extensions/builtin/goal/continuation.d.ts +3 -1
  70. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/goal/continuation.js +17 -2
  72. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  73. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +1 -0
  75. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  76. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +1 -1
  77. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/goal/monitor-continuation.js +8 -3
  79. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  80. package/dist/core/extensions/builtin/gpt-account.d.ts +5 -1
  81. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -1
  82. package/dist/core/extensions/builtin/gpt-account.js +9 -26
  83. package/dist/core/extensions/builtin/gpt-account.js.map +1 -1
  84. package/dist/core/extensions/builtin/hooks/plugin-manifest.js +2 -2
  85. package/dist/core/extensions/builtin/hooks/plugin-manifest.js.map +1 -1
  86. package/dist/core/extensions/builtin/hooks/safety.js +2 -2
  87. package/dist/core/extensions/builtin/hooks/safety.js.map +1 -1
  88. package/dist/core/extensions/builtin/monitor-state-event.d.ts +18 -0
  89. package/dist/core/extensions/builtin/monitor-state-event.d.ts.map +1 -1
  90. package/dist/core/extensions/builtin/monitor-state-event.js +23 -0
  91. package/dist/core/extensions/builtin/monitor-state-event.js.map +1 -1
  92. package/dist/core/extensions/builtin/oauth-login-interaction.d.ts +24 -0
  93. package/dist/core/extensions/builtin/oauth-login-interaction.d.ts.map +1 -0
  94. package/dist/core/extensions/builtin/oauth-login-interaction.js +77 -0
  95. package/dist/core/extensions/builtin/oauth-login-interaction.js.map +1 -0
  96. package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
  97. package/dist/core/extensions/builtin/permission-system/external-dir.js +5 -51
  98. package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
  99. package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
  100. package/dist/core/extensions/builtin/permission-system/parsers.js +5 -7
  101. package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
  102. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +1 -1
  103. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -1
  104. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +1 -1
  105. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  106. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +14 -7
  107. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts.map +1 -1
  108. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +34 -13
  109. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js.map +1 -1
  110. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +6 -10
  111. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  112. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +14 -9
  113. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  114. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +15 -15
  115. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
  116. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +49 -21
  117. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
  118. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +1 -1
  119. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  120. package/dist/core/extensions/builtin/service-tier.d.ts +2 -0
  121. package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
  122. package/dist/core/extensions/builtin/service-tier.js +17 -1
  123. package/dist/core/extensions/builtin/service-tier.js.map +1 -1
  124. package/dist/core/extensions/builtin/terminal/durable-command.d.ts.map +1 -1
  125. package/dist/core/extensions/builtin/terminal/durable-command.js +3 -0
  126. package/dist/core/extensions/builtin/terminal/durable-command.js.map +1 -1
  127. package/dist/core/extensions/builtin/terminal/durable-file.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/terminal/durable-file.js +2 -0
  129. package/dist/core/extensions/builtin/terminal/durable-file.js.map +1 -1
  130. package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/terminal/extension.js +14 -2
  132. package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
  133. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  134. package/dist/core/extensions/builtin/terminal/monitor-notify.js +27 -5
  135. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  136. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +17 -0
  137. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
  138. package/dist/core/extensions/builtin/terminal/monitor-registry.js +76 -14
  139. package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
  140. package/dist/core/extensions/builtin/terminal/notify.d.ts +2 -0
  141. package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
  142. package/dist/core/extensions/builtin/terminal/notify.js +6 -1
  143. package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
  144. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +3 -1
  145. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/terminal/session-bundle.js +13 -0
  147. package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
  148. package/dist/core/extensions/builtin/terminal/shared.d.ts +13 -2
  149. package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/terminal/shared.js +15 -2
  151. package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
  152. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
  153. package/dist/core/extensions/builtin/terminal/tools/monitor.js +8 -1
  154. package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
  155. package/dist/core/extensions/builtin/tool-search/index.d.ts.map +1 -1
  156. package/dist/core/extensions/builtin/tool-search/index.js +1 -0
  157. package/dist/core/extensions/builtin/tool-search/index.js.map +1 -1
  158. package/dist/core/extensions/builtin/tool-search/service.d.ts +4 -0
  159. package/dist/core/extensions/builtin/tool-search/service.d.ts.map +1 -1
  160. package/dist/core/extensions/builtin/tool-search/service.js +11 -0
  161. package/dist/core/extensions/builtin/tool-search/service.js.map +1 -1
  162. package/dist/core/extensions/runner.d.ts +1 -0
  163. package/dist/core/extensions/runner.d.ts.map +1 -1
  164. package/dist/core/extensions/runner.js +8 -1
  165. package/dist/core/extensions/runner.js.map +1 -1
  166. package/dist/core/extensions/types.d.ts +9 -0
  167. package/dist/core/extensions/types.d.ts.map +1 -1
  168. package/dist/core/extensions/types.js.map +1 -1
  169. package/dist/core/high-reasoning-warning.d.ts.map +1 -1
  170. package/dist/core/high-reasoning-warning.js +4 -6
  171. package/dist/core/high-reasoning-warning.js.map +1 -1
  172. package/dist/core/sdk.d.ts +1 -1
  173. package/dist/core/sdk.d.ts.map +1 -1
  174. package/dist/core/sdk.js +25 -6
  175. package/dist/core/sdk.js.map +1 -1
  176. package/dist/core/settings-manager.js +1 -1
  177. package/dist/core/settings-manager.js.map +1 -1
  178. package/dist/core/settings-shapes.js.map +1 -1
  179. package/dist/core/tools/bounded-realpath.d.ts +28 -0
  180. package/dist/core/tools/bounded-realpath.d.ts.map +1 -0
  181. package/dist/core/tools/bounded-realpath.js +53 -0
  182. package/dist/core/tools/bounded-realpath.js.map +1 -0
  183. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  184. package/dist/core/tools/file-mutation-queue.js +15 -13
  185. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  186. package/dist/core/tools/filesystem-policy.d.ts +7 -0
  187. package/dist/core/tools/filesystem-policy.d.ts.map +1 -1
  188. package/dist/core/tools/filesystem-policy.js +25 -15
  189. package/dist/core/tools/filesystem-policy.js.map +1 -1
  190. package/dist/core/trust-manager.d.ts.map +1 -1
  191. package/dist/core/trust-manager.js +13 -2
  192. package/dist/core/trust-manager.js.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  194. package/dist/modes/interactive/interactive-mode.js +1 -0
  195. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  196. package/dist/modes/interactive/tips/catalog/memory-tips.d.ts.map +1 -1
  197. package/dist/modes/interactive/tips/catalog/memory-tips.js +6 -0
  198. package/dist/modes/interactive/tips/catalog/memory-tips.js.map +1 -1
  199. package/dist/modes/interactive/tips/catalog/subagent-tips.d.ts.map +1 -1
  200. package/dist/modes/interactive/tips/catalog/subagent-tips.js +6 -0
  201. package/dist/modes/interactive/tips/catalog/subagent-tips.js.map +1 -1
  202. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  203. package/dist/modes/rpc/host-lifecycle.js +31 -5
  204. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  205. package/dist/modes/rpc/host-watchdog.d.ts +11 -0
  206. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  207. package/dist/modes/rpc/host-watchdog.js +16 -2
  208. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  209. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  210. package/dist/modes/rpc/multi-session-host.js +54 -16
  211. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  212. package/dist/modes/rpc/socket-ownership.d.ts +46 -0
  213. package/dist/modes/rpc/socket-ownership.d.ts.map +1 -0
  214. package/dist/modes/rpc/socket-ownership.js +178 -0
  215. package/dist/modes/rpc/socket-ownership.js.map +1 -0
  216. package/dist/utils/fs-watch.d.ts +17 -0
  217. package/dist/utils/fs-watch.d.ts.map +1 -1
  218. package/dist/utils/fs-watch.js +38 -10
  219. package/dist/utils/fs-watch.js.map +1 -1
  220. package/dist/utils/paths.d.ts +33 -0
  221. package/dist/utils/paths.d.ts.map +1 -1
  222. package/dist/utils/paths.js +109 -3
  223. package/dist/utils/paths.js.map +1 -1
  224. package/docs/development.md +3 -2
  225. package/docs/providers.md +5 -1
  226. package/docs/settings.md +1 -0
  227. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +31 -0
  228. package/node_modules/@code-yeongyu/senpi-codemode/README.md +14 -1
  229. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  230. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +1 -0
  231. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/runtime-factory.ts +3 -0
  232. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +7 -0
  233. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +7 -0
  234. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/kernel.ts +4 -0
  235. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +3 -0
  236. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +29 -0
  237. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +10 -6
  238. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.d.ts +16 -0
  239. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.js +44 -8
  240. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-startup.ts +1 -0
  241. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel-contract.ts +3 -0
  242. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +9 -1
  243. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/kernel.ts +4 -0
  244. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/session-env.ts +56 -0
  245. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-contract.ts +3 -0
  246. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +9 -1
  247. package/node_modules/@code-yeongyu/senpi-codemode/src/output/output-meta.ts +26 -2
  248. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +17 -24
  249. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image.ts +12 -3
  250. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  251. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
  252. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  253. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +7 -0
  254. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
  255. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +19 -0
  256. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
  257. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -1
  258. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +24 -16
  259. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -1
  260. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +1 -1
  261. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  262. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +1 -1
  263. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  265. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +47 -178
  267. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.d.ts +3 -0
  269. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.d.ts.map +1 -0
  270. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js +260 -0
  271. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js.map +1 -0
  272. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +1 -0
  274. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +1 -0
  277. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.d.ts +40 -0
  279. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.d.ts.map +1 -0
  280. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.js +138 -0
  281. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.js.map +1 -0
  282. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts +2 -3
  283. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts.map +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js +42 -139
  285. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.d.ts +6 -0
  287. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.d.ts.map +1 -0
  288. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.js +29 -0
  289. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.js.map +1 -0
  290. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.d.ts +3 -0
  291. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.d.ts.map +1 -0
  292. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.js +20 -0
  293. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.js.map +1 -0
  294. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  295. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -1
  297. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  298. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  299. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  301. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  303. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  304. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  305. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js +16 -1
  307. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +7 -0
  309. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +14 -3
  314. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  315. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts +2 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts.map +1 -1
  317. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js +16 -0
  318. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js.map +1 -1
  319. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  320. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  321. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  322. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  323. package/package.json +7 -7
@@ -2,11 +2,44 @@ import { estimateTokens } from "../../../compaction/index.js";
2
2
  import { StreamDurationBudgetError, StreamIdleTimeoutError } from "../../../compaction/stream-watchdog.js";
3
3
  import { filterContextExcludedMessages } from "../../../messages.js";
4
4
  import { buildSessionContext, getSessionContextEntryId, } from "../../../session-manager.js";
5
+ import { markFailedTurnFragments } from "./fallback-failed-turn-normalization.js";
5
6
  import { SummarizationOverflowExhaustedError } from "./overflow-retry.js";
6
7
  import { resolveEffectiveReserveTokens } from "./policy.js";
7
8
  import { hasUnsafeRetainedContent } from "./retained-message-safety.js";
8
9
  import { SummaryGenerationError, SummaryRequestError } from "./speculative.js";
9
10
  import { capUtf8Bytes } from "./task-intent.js";
11
+ export function formatRequiredCompactionFallbackRejection(diagnostics) {
12
+ const candidate = diagnostics.candidateRejections?.at(-1);
13
+ const reason = diagnostics.rejectionReason ?? "context-reconstruction-failed";
14
+ const recovery = {
15
+ "retained-token-budget-exceeded": "The retained turn exceeds the usable context. Select a model with a larger context and run /compact, or start a new session with an explicit checkpoint.",
16
+ "atomic-tool-chain-cut": "The retained tool calls and results do not form complete pairs. Finish the pending tool operation before /compact; if the transcript is damaged, start a new session with an explicit checkpoint.",
17
+ "unsafe-retained-content": "The retained message cannot be replayed safely. Inspect the identified entry; start a new session with an explicit checkpoint if it cannot be repaired.",
18
+ "missing-preparation-boundary": "The prepared boundary is absent from the branch. Reload the session and run /compact.",
19
+ "context-reconstruction-failed": "The retained context could not be reconstructed. Reload the session and run /compact.",
20
+ };
21
+ const diagnostic = {
22
+ rejectionReason: reason,
23
+ contextWindow: diagnostics.contextWindow,
24
+ reserveTokens: diagnostics.reserveTokens,
25
+ budgetTokens: diagnostics.budgetTokens,
26
+ budgetExceeded: diagnostics.budgetExceeded ?? false,
27
+ candidatesChecked: diagnostics.candidatesChecked ?? 0,
28
+ ...(candidate
29
+ ? {
30
+ candidate: {
31
+ ...candidate,
32
+ firstKeptEntryId: capUtf8Bytes(candidate.firstKeptEntryId, 128),
33
+ ...(candidate.unsafeEntryId ? { unsafeEntryId: capUtf8Bytes(candidate.unsafeEntryId, 128) } : {}),
34
+ ...(candidate.unsafeMessageRole
35
+ ? { unsafeMessageRole: capUtf8Bytes(candidate.unsafeMessageRole, 32) }
36
+ : {}),
37
+ },
38
+ }
39
+ : {}),
40
+ };
41
+ return `deterministic compaction fallback could not retain a safe suffix\n${JSON.stringify(diagnostic)}\n${recovery[reason]} The original transcript has not been changed.`;
42
+ }
10
43
  const NON_VISIBLE_USER_TEXT = /[\p{White_Space}\p{Default_Ignorable_Code_Point}]/gu;
11
44
  function isRecord(value) {
12
45
  return typeof value === "object" && value !== null;
@@ -76,10 +109,18 @@ export function classifyRequiredCompactionFallbackFailure(error) {
76
109
  return undefined;
77
110
  }
78
111
  export function createRequiredCompactionFallback(preparation, contextWindow, failureKind, metadata, branchEntries = [], diagnostics) {
112
+ const reserveTokens = resolveEffectiveReserveTokens(contextWindow, preparation.settings);
113
+ const budget = contextWindow - reserveTokens;
79
114
  const preparedBoundaryIndex = branchEntries.findIndex((entry) => entry.id === preparation.firstKeptEntryId);
80
115
  if (!preparation.firstKeptEntryId || preparedBoundaryIndex === -1) {
81
- if (diagnostics)
82
- diagnostics.rejectionReason = "missing-preparation-boundary";
116
+ if (diagnostics) {
117
+ Object.assign(diagnostics, {
118
+ rejectionReason: "missing-preparation-boundary",
119
+ contextWindow,
120
+ reserveTokens,
121
+ budgetTokens: budget,
122
+ });
123
+ }
83
124
  return undefined;
84
125
  }
85
126
  const marker = [
@@ -123,10 +164,22 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
123
164
  projectedMessages = filterContextExcludedMessages(buildSessionContext([...branchEntries, syntheticCompaction]).messages);
124
165
  }
125
166
  catch {
126
- if (diagnostics)
127
- diagnostics.rejectionReason = "context-reconstruction-failed";
167
+ if (diagnostics) {
168
+ Object.assign(diagnostics, {
169
+ rejectionReason: "context-reconstruction-failed",
170
+ contextWindow,
171
+ reserveTokens,
172
+ budgetTokens: budget,
173
+ });
174
+ }
128
175
  return undefined;
129
176
  }
177
+ // Evaluate the candidate the provider would actually receive: `convertToLlm`
178
+ // drops failed/aborted assistant turns (and their orphaned tool results) before
179
+ // every request, so their dangling toolCall blocks are neither incomplete calls
180
+ // nor retained tokens here. Raw session history stays untouched - this mask is
181
+ // local to the fallback projection (code-yeongyu/oh-my-openagent#7921).
182
+ const droppedByFailedTurnNormalization = markFailedTurnFragments(projectedMessages);
130
183
  const messageIndexesByEntryId = new Map();
131
184
  for (const [index, message] of projectedMessages.entries()) {
132
185
  const entryId = getSessionContextEntryId(message);
@@ -135,27 +188,51 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
135
188
  }
136
189
  const summaryIndex = messageIndexesByEntryId.get(syntheticCompaction.id);
137
190
  const unsafeSuffix = new Array(projectedMessages.length + 1).fill(false);
191
+ const unsafeIndexSuffix = new Int32Array(projectedMessages.length + 1).fill(-1);
138
192
  const tokenSuffix = new Array(projectedMessages.length + 1).fill(0);
139
193
  const toolCalls = new Map();
140
194
  const toolResults = new Map();
141
195
  for (let index = projectedMessages.length - 1; index >= 0; index--) {
142
196
  const message = projectedMessages[index];
143
197
  tokenSuffix[index] = tokenSuffix[index + 1];
198
+ unsafeIndexSuffix[index] = unsafeIndexSuffix[index + 1];
199
+ if (droppedByFailedTurnNormalization[index]) {
200
+ unsafeSuffix[index] = unsafeSuffix[index + 1];
201
+ continue;
202
+ }
144
203
  let messageUnsafe = false;
145
204
  let serialized;
146
205
  try {
147
206
  messageUnsafe = hasUnsafeRetainedContent([message]);
148
- serialized = isSafeBoundedValue(message) ? JSON.stringify(message) : undefined;
207
+ const bounded = isSafeBoundedValue(message);
208
+ messageUnsafe ||= !bounded;
209
+ let imageTokens = 0;
210
+ if (!messageUnsafe && message.role === "toolResult") {
211
+ const content = message.content.map((block) => {
212
+ if (block.type !== "image")
213
+ return block;
214
+ imageTokens += estimateTokens({ ...message, content: [block] });
215
+ return { ...block, data: "" };
216
+ });
217
+ serialized = JSON.stringify({ ...message, content });
218
+ }
219
+ else {
220
+ serialized = bounded ? JSON.stringify(message) : undefined;
221
+ }
222
+ // Apply the shared weighted chars/4 estimator to the envelope too.
223
+ // Storage bytes are not tokens; opaque text and image costs still count.
149
224
  tokenSuffix[index] +=
150
225
  serialized === undefined
151
226
  ? Number.POSITIVE_INFINITY
152
- : Math.max(estimateTokens(message), Buffer.byteLength(serialized));
227
+ : Math.max(estimateTokens(message), estimateTokens({ role: "user", content: serialized, timestamp: 0 }) + imageTokens);
153
228
  }
154
229
  catch {
155
230
  messageUnsafe = true;
156
231
  tokenSuffix[index] = Number.POSITIVE_INFINITY;
157
232
  }
158
233
  unsafeSuffix[index] = unsafeSuffix[index + 1] || messageUnsafe;
234
+ if (messageUnsafe)
235
+ unsafeIndexSuffix[index] = index;
159
236
  if (!isRecord(message))
160
237
  continue;
161
238
  if (message.role === "toolResult" && typeof message.toolCallId === "string") {
@@ -167,9 +244,8 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
167
244
  for (const block of message.content) {
168
245
  if (!isRecord(block) || block.type !== "toolCall" || typeof block.id !== "string")
169
246
  continue;
170
- const call = toolCalls.get(block.id) ?? { indexes: [], incomplete: false };
247
+ const call = toolCalls.get(block.id) ?? { indexes: [], newestIncomplete: block.incomplete === true };
171
248
  call.indexes.push(index);
172
- call.incomplete ||= block.incomplete === true;
173
249
  toolCalls.set(block.id, call);
174
250
  }
175
251
  }
@@ -185,18 +261,21 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
185
261
  };
186
262
  for (const [id, call] of toolCalls) {
187
263
  const results = toolResults.get(id) ?? [];
188
- if (call.indexes.length !== 1 || results.length !== 1) {
264
+ if (results.length === 0) {
189
265
  markInvalidRange(0, Math.max(call.indexes[0] ?? -1, results[0] ?? -1) + 1);
190
266
  continue;
191
267
  }
192
268
  const callIndex = call.indexes[0];
193
269
  const resultIndex = results[0];
194
- if (call.incomplete)
270
+ // Indexes are newest-first. Older duplicate IDs matter only while retained;
271
+ // dropping an entire historical pair leaves the newest pair valid.
272
+ markInvalidRange(0, Math.max(call.indexes[1] ?? -1, results[1] ?? -1) + 1);
273
+ if (call.newestIncomplete || callIndex >= resultIndex) {
195
274
  markInvalidRange(0, Math.max(callIndex, resultIndex) + 1);
196
- else if (callIndex < resultIndex)
275
+ }
276
+ else {
197
277
  markInvalidRange(callIndex + 1, resultIndex + 1);
198
- else
199
- markInvalidRange(0, Math.max(callIndex, resultIndex) + 1);
278
+ }
200
279
  }
201
280
  for (const [id, results] of toolResults) {
202
281
  if (toolCalls.has(id))
@@ -212,11 +291,14 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
212
291
  const projectCandidate = (firstKeptEntryId, retainedSuffix) => {
213
292
  candidateCount++;
214
293
  const details = { ...baseDetails, retainedSuffix };
215
- const reject = (rejectionReason) => {
294
+ const reject = (rejectionReason, detail = {}) => {
216
295
  if (diagnostics) {
217
296
  diagnostics.rejectionReason = rejectionReason;
297
+ diagnostics.contextWindow = contextWindow;
298
+ diagnostics.reserveTokens = reserveTokens;
299
+ diagnostics.budgetTokens = budget;
218
300
  diagnostics.candidateRejections ??= [];
219
- diagnostics.candidateRejections.push({ firstKeptEntryId, rejectionReason });
301
+ diagnostics.candidateRejections.push({ firstKeptEntryId, rejectionReason, ...detail });
220
302
  }
221
303
  return undefined;
222
304
  };
@@ -230,21 +312,31 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
230
312
  if (startIndex === undefined)
231
313
  return reject("context-reconstruction-failed");
232
314
  const retainedStart = Math.min(startIndex, projectedMessages.length);
233
- if (unsafeSuffix[retainedStart])
234
- return reject("unsafe-retained-content");
315
+ if (unsafeSuffix[retainedStart]) {
316
+ const unsafeMessageIndex = unsafeIndexSuffix[retainedStart];
317
+ const unsafeMessage = projectedMessages[unsafeMessageIndex];
318
+ return reject("unsafe-retained-content", {
319
+ unsafeMessageIndex,
320
+ unsafeEntryId: getSessionContextEntryId(unsafeMessage),
321
+ unsafeMessageRole: unsafeMessage.role,
322
+ });
323
+ }
235
324
  if (!toolChainValidAt[retainedStart])
236
325
  return reject("atomic-tool-chain-cut");
237
326
  // The hard-limit valve reserves the scaled budget, so accepting against the raw
238
327
  // configured reserve would admit a context that valve immediately compacts again.
239
- const budget = contextWindow - resolveEffectiveReserveTokens(contextWindow, preparation.settings);
240
328
  const summaryTokens = summaryIndex === undefined
241
329
  ? Number.POSITIVE_INFINITY
242
- : Math.max(estimateTokens(projectedMessages[summaryIndex]), Buffer.byteLength(JSON.stringify(projectedMessages[summaryIndex])));
330
+ : Math.max(estimateTokens(projectedMessages[summaryIndex]), estimateTokens({
331
+ role: "user",
332
+ content: JSON.stringify(projectedMessages[summaryIndex]),
333
+ timestamp: 0,
334
+ }));
243
335
  const retainedTokens = (tokenSuffix[retainedStart] ?? Number.POSITIVE_INFINITY) + summaryTokens;
244
336
  if (retainedTokens > budget) {
245
337
  if (diagnostics)
246
338
  diagnostics.budgetExceeded = true;
247
- return reject("retained-token-budget-exceeded");
339
+ return reject("retained-token-budget-exceeded", { estimatedTokens: retainedTokens });
248
340
  }
249
341
  return { ...result, estimatedTokensAfter: retainedTokens };
250
342
  };
@@ -280,6 +372,19 @@ export function createRequiredCompactionFallback(preparation, contextWindow, fai
280
372
  diagnostics.candidatesChecked = candidateCount;
281
373
  return latestUser;
282
374
  }
375
+ // A steering user message can occur inside a tool chain. Keep that request
376
+ // and walk back to its declaring assistant instead of orphaning the result.
377
+ for (let earlierIndex = index - 1; earlierIndex > preparedBoundaryIndex; earlierIndex--) {
378
+ const earlierEntry = branchEntries[earlierIndex];
379
+ if (earlierEntry.type === "compaction")
380
+ break;
381
+ const earlier = projectCandidate(earlierEntry.id, "earlier-safe-boundary");
382
+ if (earlier) {
383
+ if (diagnostics)
384
+ diagnostics.candidatesChecked = candidateCount;
385
+ return earlier;
386
+ }
387
+ }
283
388
  break;
284
389
  }
285
390
  if (diagnostics)
@@ -1 +1 @@
1
- {"version":3,"file":"deterministic-fallback.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/deterministic-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CompactionPreparation, type CompactionResult, estimateTokens } from \"../../../compaction/index.ts\";\nimport { StreamDurationBudgetError, StreamIdleTimeoutError } from \"../../../compaction/stream-watchdog.ts\";\nimport { filterContextExcludedMessages } from \"../../../messages.ts\";\nimport {\n\tbuildSessionContext,\n\ttype CompactionEntry,\n\tgetSessionContextEntryId,\n\ttype SessionEntry,\n} from \"../../../session-manager.ts\";\nimport { SummarizationOverflowExhaustedError } from \"./overflow-retry.ts\";\nimport { resolveEffectiveReserveTokens } from \"./policy.ts\";\nimport { hasUnsafeRetainedContent } from \"./retained-message-safety.ts\";\nimport { SummaryGenerationError, SummaryRequestError } from \"./speculative.ts\";\nimport { capUtf8Bytes } from \"./task-intent.ts\";\n\nexport type RequiredCompactionFallbackFailure =\n\t| \"summarization-timeout\"\n\t| \"upstream-stream-truncated\"\n\t| \"summarization-overflow-exhausted\"\n\t| \"summarization-empty-summary\";\n\ninterface RecoveryMetadata {\n\ttaskIntent?: string;\n\ttodoSnapshot?: unknown;\n\tcheckpoint?: unknown;\n}\n\nexport type DeterministicFallbackRejectionReason =\n\t| \"missing-preparation-boundary\"\n\t| \"unsafe-retained-content\"\n\t| \"retained-token-budget-exceeded\"\n\t| \"atomic-tool-chain-cut\"\n\t| \"context-reconstruction-failed\";\n\ninterface DeterministicFallbackDetails {\n\tschema: \"senpi.compaction.deterministic-fallback.v1\";\n\torigin: \"required-compaction-recovery\";\n\tfailureKind: RequiredCompactionFallbackFailure;\n\ttaskIntent?: string;\n\tretainedSuffix?: \"prepared\" | \"latest-user-turn\" | \"earlier-safe-boundary\";\n}\n\nexport interface DeterministicFallbackDiagnostic {\n\trejectionReason?: DeterministicFallbackRejectionReason;\n\tcandidateRejections?: Array<{\n\t\tfirstKeptEntryId: string;\n\t\trejectionReason: DeterministicFallbackRejectionReason;\n\t}>;\n\tcandidatesChecked?: number;\n\tbudgetExceeded?: boolean;\n}\n\nconst NON_VISIBLE_USER_TEXT = /[\\p{White_Space}\\p{Default_Ignorable_Code_Point}]/gu;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction hasMeaningfulUserText(entry: SessionEntry): boolean {\n\tif (entry.type !== \"message\" || !isRecord(entry.message) || entry.message.role !== \"user\") return false;\n\tconst content = entry.message.content;\n\tconst hasVisibleText = (text: unknown): boolean =>\n\t\ttypeof text === \"string\" && text.normalize(\"NFKC\").replace(NON_VISIBLE_USER_TEXT, \"\").length > 0;\n\tif (typeof content === \"string\") return hasVisibleText(content);\n\tif (!Array.isArray(content)) return false;\n\treturn content.some((block) => isRecord(block) && block.type === \"text\" && hasVisibleText(block.text));\n}\n\n/**\n * Bound a value graph that came from persisted, potentially hostile session data.\n * Returns false when the graph contains anything we must not read (accessors,\n * non-plain prototypes, cycles, functions, symbols) so callers fail closed\n * instead of executing persisted code or walking unbounded structures.\n */\nfunction isSafeBoundedValue(value: unknown, seen = new Set<object>(), depth = 0): boolean {\n\tif (depth > 32) return false;\n\tif (value === null || value === undefined) return true;\n\tconst kind = typeof value;\n\tif (kind === \"string\" || kind === \"number\" || kind === \"boolean\") return true;\n\tif (kind !== \"object\") return false;\n\tif (seen.has(value as object)) return false;\n\tseen.add(value as object);\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) if (!isSafeBoundedValue(item, seen, depth + 1)) return false;\n\t\treturn true;\n\t}\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto !== Object.prototype && proto !== null) return false;\n\tfor (const descriptor of Object.values(Object.getOwnPropertyDescriptors(value))) {\n\t\tif (descriptor.get !== undefined || descriptor.set !== undefined) return false;\n\t\tif (typeof descriptor.value === \"function\" || typeof descriptor.value === \"symbol\") return false;\n\t\tif (!isSafeBoundedValue(descriptor.value, seen, depth + 1)) return false;\n\t}\n\treturn true;\n}\n\nexport function classifyRequiredCompactionFallbackFailure(\n\terror: unknown,\n): RequiredCompactionFallbackFailure | undefined {\n\tif (error instanceof StreamDurationBudgetError || error instanceof StreamIdleTimeoutError) {\n\t\treturn \"summarization-timeout\";\n\t}\n\tif (error instanceof SummaryRequestError && error.transient && error.failureKind === \"upstream-stream-truncated\") {\n\t\treturn \"upstream-stream-truncated\";\n\t}\n\tif (error instanceof SummarizationOverflowExhaustedError) {\n\t\treturn \"summarization-overflow-exhausted\";\n\t}\n\tif (error instanceof SummaryGenerationError && error.kind === \"empty-summary\") {\n\t\treturn \"summarization-empty-summary\";\n\t}\n\treturn undefined;\n}\n\nexport function createRequiredCompactionFallback(\n\tpreparation: CompactionPreparation,\n\tcontextWindow: number,\n\tfailureKind: RequiredCompactionFallbackFailure,\n\tmetadata: RecoveryMetadata,\n\tbranchEntries: SessionEntry[] = [],\n\tdiagnostics?: DeterministicFallbackDiagnostic,\n): CompactionResult<DeterministicFallbackDetails> | undefined {\n\tconst preparedBoundaryIndex = branchEntries.findIndex((entry) => entry.id === preparation.firstKeptEntryId);\n\tif (!preparation.firstKeptEntryId || preparedBoundaryIndex === -1) {\n\t\tif (diagnostics) diagnostics.rejectionReason = \"missing-preparation-boundary\";\n\t\treturn undefined;\n\t}\n\n\tconst marker = [\n\t\t\"[Deterministic compaction recovery checkpoint]\",\n\t\t\"Generated summarization did not complete, so older context was reduced without another provider request.\",\n\t\t\"Continue from the retained messages after this checkpoint. Treat omitted transcript details as unknown.\",\n\t].join(\"\\n\");\n\tconst taskIntent = metadata.taskIntent?.trim();\n\tconst fixedText = taskIntent ? `${marker}\\n\\nTask intent:\\n${taskIntent}` : marker;\n\tconst maxSummaryBytes = Math.max(1_024, Math.floor(contextWindow * 0.4));\n\tconst previousSummary = preparation.previousSummary?.trim();\n\tlet summary = fixedText;\n\tif (previousSummary) {\n\t\tconst availableBytes = Math.max(0, maxSummaryBytes - Buffer.byteLength(`${fixedText}\\n\\nPrevious checkpoint:\\n`));\n\t\tconst truncationMarker = \"\\n[Older checkpoint truncated]\";\n\t\tconst boundedPrevious =\n\t\t\tBuffer.byteLength(previousSummary) <= availableBytes\n\t\t\t\t? previousSummary\n\t\t\t\t: `${capUtf8Bytes(previousSummary, Math.max(0, availableBytes - Buffer.byteLength(truncationMarker)))}${truncationMarker}`;\n\t\tsummary = `${fixedText}\\n\\nPrevious checkpoint:\\n${boundedPrevious}`;\n\t}\n\n\tconst baseDetails: DeterministicFallbackDetails = {\n\t\tschema: \"senpi.compaction.deterministic-fallback.v1\",\n\t\torigin: \"required-compaction-recovery\",\n\t\tfailureKind,\n\t\t...(taskIntent ? { taskIntent } : {}),\n\t};\n\tlet candidateCount = 0;\n\n\tconst syntheticCompaction: CompactionEntry = {\n\t\ttype: \"compaction\",\n\t\tid: \"__senpi_deterministic_fallback_preview__\",\n\t\tparentId: branchEntries.at(-1)?.id ?? null,\n\t\ttimestamp: new Date(0).toISOString(),\n\t\tsummary,\n\t\tfirstKeptEntryId: branchEntries[0]?.id ?? preparation.firstKeptEntryId,\n\t\ttokensBefore: preparation.tokensBefore,\n\t\tdetails: { ...baseDetails, retainedSuffix: \"prepared\" },\n\t\tfromHook: true,\n\t};\n\n\tlet projectedMessages: ReturnType<typeof filterContextExcludedMessages>;\n\ttry {\n\t\tprojectedMessages = filterContextExcludedMessages(\n\t\t\tbuildSessionContext([...branchEntries, syntheticCompaction]).messages,\n\t\t);\n\t} catch {\n\t\tif (diagnostics) diagnostics.rejectionReason = \"context-reconstruction-failed\";\n\t\treturn undefined;\n\t}\n\n\tconst messageIndexesByEntryId = new Map<string, number>();\n\tfor (const [index, message] of projectedMessages.entries()) {\n\t\tconst entryId = getSessionContextEntryId(message);\n\t\tif (entryId !== undefined) messageIndexesByEntryId.set(entryId, index);\n\t}\n\tconst summaryIndex = messageIndexesByEntryId.get(syntheticCompaction.id);\n\tconst unsafeSuffix = new Array(projectedMessages.length + 1).fill(false);\n\tconst tokenSuffix = new Array(projectedMessages.length + 1).fill(0);\n\tconst toolCalls = new Map<string, { indexes: number[]; incomplete: boolean }>();\n\tconst toolResults = new Map<string, number[]>();\n\tfor (let index = projectedMessages.length - 1; index >= 0; index--) {\n\t\tconst message = projectedMessages[index];\n\t\ttokenSuffix[index] = tokenSuffix[index + 1];\n\t\tlet messageUnsafe = false;\n\t\tlet serialized: string | undefined;\n\t\ttry {\n\t\t\tmessageUnsafe = hasUnsafeRetainedContent([message]);\n\t\t\tserialized = isSafeBoundedValue(message) ? JSON.stringify(message) : undefined;\n\t\t\ttokenSuffix[index] +=\n\t\t\t\tserialized === undefined\n\t\t\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t\t\t: Math.max(estimateTokens(message), Buffer.byteLength(serialized));\n\t\t} catch {\n\t\t\tmessageUnsafe = true;\n\t\t\ttokenSuffix[index] = Number.POSITIVE_INFINITY;\n\t\t}\n\t\tunsafeSuffix[index] = unsafeSuffix[index + 1] || messageUnsafe;\n\t\tif (!isRecord(message)) continue;\n\t\tif (message.role === \"toolResult\" && typeof message.toolCallId === \"string\") {\n\t\t\tconst indexes = toolResults.get(message.toolCallId) ?? [];\n\t\t\tindexes.push(index);\n\t\t\ttoolResults.set(message.toolCallId, indexes);\n\t\t} else if (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\tfor (const block of message.content) {\n\t\t\t\tif (!isRecord(block) || block.type !== \"toolCall\" || typeof block.id !== \"string\") continue;\n\t\t\t\tconst call = toolCalls.get(block.id) ?? { indexes: [], incomplete: false };\n\t\t\t\tcall.indexes.push(index);\n\t\t\t\tcall.incomplete ||= block.incomplete === true;\n\t\t\t\ttoolCalls.set(block.id, call);\n\t\t\t}\n\t\t}\n\t}\n\tconst invalidToolChainDiff = new Int32Array(projectedMessages.length + 2);\n\tconst markInvalidRange = (start: number, endExclusive: number) => {\n\t\tconst boundedStart = Math.max(0, start);\n\t\tconst boundedEnd = Math.min(projectedMessages.length + 1, endExclusive);\n\t\tif (boundedStart >= boundedEnd) return;\n\t\tinvalidToolChainDiff[boundedStart]++;\n\t\tinvalidToolChainDiff[boundedEnd]--;\n\t};\n\tfor (const [id, call] of toolCalls) {\n\t\tconst results = toolResults.get(id) ?? [];\n\t\tif (call.indexes.length !== 1 || results.length !== 1) {\n\t\t\tmarkInvalidRange(0, Math.max(call.indexes[0] ?? -1, results[0] ?? -1) + 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst callIndex = call.indexes[0];\n\t\tconst resultIndex = results[0];\n\t\tif (call.incomplete) markInvalidRange(0, Math.max(callIndex, resultIndex) + 1);\n\t\telse if (callIndex < resultIndex) markInvalidRange(callIndex + 1, resultIndex + 1);\n\t\telse markInvalidRange(0, Math.max(callIndex, resultIndex) + 1);\n\t}\n\tfor (const [id, results] of toolResults) {\n\t\tif (toolCalls.has(id)) continue;\n\t\tmarkInvalidRange(0, results[0] + 1);\n\t}\n\tconst toolChainValidAt = new Array(projectedMessages.length + 1).fill(true);\n\tlet invalidToolChainCount = 0;\n\tfor (let index = 0; index < toolChainValidAt.length; index++) {\n\t\tinvalidToolChainCount += invalidToolChainDiff[index];\n\t\ttoolChainValidAt[index] = invalidToolChainCount === 0;\n\t}\n\n\tconst projectCandidate = (\n\t\tfirstKeptEntryId: string,\n\t\tretainedSuffix: NonNullable<DeterministicFallbackDetails[\"retainedSuffix\"]>,\n\t): CompactionResult<DeterministicFallbackDetails> | undefined => {\n\t\tcandidateCount++;\n\t\tconst details = { ...baseDetails, retainedSuffix };\n\t\tconst reject = (rejectionReason: DeterministicFallbackRejectionReason): undefined => {\n\t\t\tif (diagnostics) {\n\t\t\t\tdiagnostics.rejectionReason = rejectionReason;\n\t\t\t\tdiagnostics.candidateRejections ??= [];\n\t\t\t\tdiagnostics.candidateRejections.push({ firstKeptEntryId, rejectionReason });\n\t\t\t}\n\t\t\treturn undefined;\n\t\t};\n\t\tconst result: CompactionResult<DeterministicFallbackDetails> = {\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore: preparation.tokensBefore,\n\t\t\tdetails,\n\t\t};\n\t\tconst startIndex = messageIndexesByEntryId.get(firstKeptEntryId);\n\t\tif (startIndex === undefined) return reject(\"context-reconstruction-failed\");\n\t\tconst retainedStart = Math.min(startIndex, projectedMessages.length);\n\t\tif (unsafeSuffix[retainedStart]) return reject(\"unsafe-retained-content\");\n\t\tif (!toolChainValidAt[retainedStart]) return reject(\"atomic-tool-chain-cut\");\n\t\t// The hard-limit valve reserves the scaled budget, so accepting against the raw\n\t\t// configured reserve would admit a context that valve immediately compacts again.\n\t\tconst budget = contextWindow - resolveEffectiveReserveTokens(contextWindow, preparation.settings);\n\t\tconst summaryTokens =\n\t\t\tsummaryIndex === undefined\n\t\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t\t: Math.max(\n\t\t\t\t\t\testimateTokens(projectedMessages[summaryIndex]),\n\t\t\t\t\t\tBuffer.byteLength(JSON.stringify(projectedMessages[summaryIndex])),\n\t\t\t\t\t);\n\t\tconst retainedTokens = (tokenSuffix[retainedStart] ?? Number.POSITIVE_INFINITY) + summaryTokens;\n\t\tif (retainedTokens > budget) {\n\t\t\tif (diagnostics) diagnostics.budgetExceeded = true;\n\t\t\treturn reject(\"retained-token-budget-exceeded\");\n\t\t}\n\t\treturn { ...result, estimatedTokensAfter: retainedTokens };\n\t};\n\n\t// 1. Try prepared boundary\n\tconst prepared = projectCandidate(preparation.firstKeptEntryId, \"prepared\");\n\tif (prepared) {\n\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\treturn prepared;\n\t}\n\n\t// 2. If prepared boundary cut an atomic signed chain or was rejected, walk backward\n\t// to the actual chain boundary. The chain length is determined by the session.\n\tfor (let index = preparedBoundaryIndex - 1; index >= 0; index--) {\n\t\tconst entry = branchEntries[index];\n\t\tif (entry.type === \"compaction\") break;\n\t\t// Only consider message turn starts or assistant call starts\n\t\tconst earlier = projectCandidate(entry.id, \"earlier-safe-boundary\");\n\t\tif (earlier) {\n\t\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\t\treturn earlier;\n\t\t}\n\t}\n\n\t// 3. Try latest meaningful user turn\n\tfor (let index = branchEntries.length - 1; index > preparedBoundaryIndex; index--) {\n\t\tconst entry = branchEntries[index];\n\t\tif (!hasMeaningfulUserText(entry)) continue;\n\t\tconst latestUser = projectCandidate(entry.id, \"latest-user-turn\");\n\t\tif (latestUser) {\n\t\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\t\treturn latestUser;\n\t\t}\n\t\tbreak;\n\t}\n\n\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"deterministic-fallback.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/deterministic-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CompactionPreparation, type CompactionResult, estimateTokens } from \"../../../compaction/index.ts\";\nimport { StreamDurationBudgetError, StreamIdleTimeoutError } from \"../../../compaction/stream-watchdog.ts\";\nimport { filterContextExcludedMessages } from \"../../../messages.ts\";\nimport {\n\tbuildSessionContext,\n\ttype CompactionEntry,\n\tgetSessionContextEntryId,\n\ttype SessionEntry,\n} from \"../../../session-manager.ts\";\nimport { markFailedTurnFragments } from \"./fallback-failed-turn-normalization.ts\";\nimport { SummarizationOverflowExhaustedError } from \"./overflow-retry.ts\";\nimport { resolveEffectiveReserveTokens } from \"./policy.ts\";\nimport { hasUnsafeRetainedContent } from \"./retained-message-safety.ts\";\nimport { SummaryGenerationError, SummaryRequestError } from \"./speculative.ts\";\nimport { capUtf8Bytes } from \"./task-intent.ts\";\n\nexport type RequiredCompactionFallbackFailure =\n\t| \"summarization-timeout\"\n\t| \"upstream-stream-truncated\"\n\t| \"summarization-overflow-exhausted\"\n\t| \"summarization-empty-summary\";\n\ninterface RecoveryMetadata {\n\ttaskIntent?: string;\n\ttodoSnapshot?: unknown;\n\tcheckpoint?: unknown;\n}\n\nexport type DeterministicFallbackRejectionReason =\n\t| \"missing-preparation-boundary\"\n\t| \"unsafe-retained-content\"\n\t| \"retained-token-budget-exceeded\"\n\t| \"atomic-tool-chain-cut\"\n\t| \"context-reconstruction-failed\";\n\ninterface DeterministicFallbackDetails {\n\tschema: \"senpi.compaction.deterministic-fallback.v1\";\n\torigin: \"required-compaction-recovery\";\n\tfailureKind: RequiredCompactionFallbackFailure;\n\ttaskIntent?: string;\n\tretainedSuffix?: \"prepared\" | \"latest-user-turn\" | \"earlier-safe-boundary\";\n}\n\nexport interface DeterministicFallbackDiagnostic {\n\trejectionReason?: DeterministicFallbackRejectionReason;\n\tcandidateRejections?: Array<{\n\t\tfirstKeptEntryId: string;\n\t\trejectionReason: DeterministicFallbackRejectionReason;\n\t\testimatedTokens?: number;\n\t\tunsafeMessageIndex?: number;\n\t\tunsafeEntryId?: string;\n\t\tunsafeMessageRole?: string;\n\t}>;\n\tcandidatesChecked?: number;\n\tbudgetExceeded?: boolean;\n\tcontextWindow?: number;\n\treserveTokens?: number;\n\tbudgetTokens?: number;\n}\n\nexport function formatRequiredCompactionFallbackRejection(diagnostics: DeterministicFallbackDiagnostic): string {\n\tconst candidate = diagnostics.candidateRejections?.at(-1);\n\tconst reason = diagnostics.rejectionReason ?? \"context-reconstruction-failed\";\n\tconst recovery: Record<DeterministicFallbackRejectionReason, string> = {\n\t\t\"retained-token-budget-exceeded\":\n\t\t\t\"The retained turn exceeds the usable context. Select a model with a larger context and run /compact, or start a new session with an explicit checkpoint.\",\n\t\t\"atomic-tool-chain-cut\":\n\t\t\t\"The retained tool calls and results do not form complete pairs. Finish the pending tool operation before /compact; if the transcript is damaged, start a new session with an explicit checkpoint.\",\n\t\t\"unsafe-retained-content\":\n\t\t\t\"The retained message cannot be replayed safely. Inspect the identified entry; start a new session with an explicit checkpoint if it cannot be repaired.\",\n\t\t\"missing-preparation-boundary\":\n\t\t\t\"The prepared boundary is absent from the branch. Reload the session and run /compact.\",\n\t\t\"context-reconstruction-failed\":\n\t\t\t\"The retained context could not be reconstructed. Reload the session and run /compact.\",\n\t};\n\tconst diagnostic = {\n\t\trejectionReason: reason,\n\t\tcontextWindow: diagnostics.contextWindow,\n\t\treserveTokens: diagnostics.reserveTokens,\n\t\tbudgetTokens: diagnostics.budgetTokens,\n\t\tbudgetExceeded: diagnostics.budgetExceeded ?? false,\n\t\tcandidatesChecked: diagnostics.candidatesChecked ?? 0,\n\t\t...(candidate\n\t\t\t? {\n\t\t\t\t\tcandidate: {\n\t\t\t\t\t\t...candidate,\n\t\t\t\t\t\tfirstKeptEntryId: capUtf8Bytes(candidate.firstKeptEntryId, 128),\n\t\t\t\t\t\t...(candidate.unsafeEntryId ? { unsafeEntryId: capUtf8Bytes(candidate.unsafeEntryId, 128) } : {}),\n\t\t\t\t\t\t...(candidate.unsafeMessageRole\n\t\t\t\t\t\t\t? { unsafeMessageRole: capUtf8Bytes(candidate.unsafeMessageRole, 32) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n\treturn `deterministic compaction fallback could not retain a safe suffix\\n${JSON.stringify(diagnostic)}\\n${recovery[reason]} The original transcript has not been changed.`;\n}\n\nconst NON_VISIBLE_USER_TEXT = /[\\p{White_Space}\\p{Default_Ignorable_Code_Point}]/gu;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction hasMeaningfulUserText(entry: SessionEntry): boolean {\n\tif (entry.type !== \"message\" || !isRecord(entry.message) || entry.message.role !== \"user\") return false;\n\tconst content = entry.message.content;\n\tconst hasVisibleText = (text: unknown): boolean =>\n\t\ttypeof text === \"string\" && text.normalize(\"NFKC\").replace(NON_VISIBLE_USER_TEXT, \"\").length > 0;\n\tif (typeof content === \"string\") return hasVisibleText(content);\n\tif (!Array.isArray(content)) return false;\n\treturn content.some((block) => isRecord(block) && block.type === \"text\" && hasVisibleText(block.text));\n}\n\n/**\n * Bound a value graph that came from persisted, potentially hostile session data.\n * Returns false when the graph contains anything we must not read (accessors,\n * non-plain prototypes, cycles, functions, symbols) so callers fail closed\n * instead of executing persisted code or walking unbounded structures.\n */\nfunction isSafeBoundedValue(value: unknown, seen = new Set<object>(), depth = 0): boolean {\n\tif (depth > 32) return false;\n\tif (value === null || value === undefined) return true;\n\tconst kind = typeof value;\n\tif (kind === \"string\" || kind === \"number\" || kind === \"boolean\") return true;\n\tif (kind !== \"object\") return false;\n\tif (seen.has(value as object)) return false;\n\tseen.add(value as object);\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) if (!isSafeBoundedValue(item, seen, depth + 1)) return false;\n\t\treturn true;\n\t}\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto !== Object.prototype && proto !== null) return false;\n\tfor (const descriptor of Object.values(Object.getOwnPropertyDescriptors(value))) {\n\t\tif (descriptor.get !== undefined || descriptor.set !== undefined) return false;\n\t\tif (typeof descriptor.value === \"function\" || typeof descriptor.value === \"symbol\") return false;\n\t\tif (!isSafeBoundedValue(descriptor.value, seen, depth + 1)) return false;\n\t}\n\treturn true;\n}\n\nexport function classifyRequiredCompactionFallbackFailure(\n\terror: unknown,\n): RequiredCompactionFallbackFailure | undefined {\n\tif (error instanceof StreamDurationBudgetError || error instanceof StreamIdleTimeoutError) {\n\t\treturn \"summarization-timeout\";\n\t}\n\tif (error instanceof SummaryRequestError && error.transient && error.failureKind === \"upstream-stream-truncated\") {\n\t\treturn \"upstream-stream-truncated\";\n\t}\n\tif (error instanceof SummarizationOverflowExhaustedError) {\n\t\treturn \"summarization-overflow-exhausted\";\n\t}\n\tif (error instanceof SummaryGenerationError && error.kind === \"empty-summary\") {\n\t\treturn \"summarization-empty-summary\";\n\t}\n\treturn undefined;\n}\n\nexport function createRequiredCompactionFallback(\n\tpreparation: CompactionPreparation,\n\tcontextWindow: number,\n\tfailureKind: RequiredCompactionFallbackFailure,\n\tmetadata: RecoveryMetadata,\n\tbranchEntries: SessionEntry[] = [],\n\tdiagnostics?: DeterministicFallbackDiagnostic,\n): CompactionResult<DeterministicFallbackDetails> | undefined {\n\tconst reserveTokens = resolveEffectiveReserveTokens(contextWindow, preparation.settings);\n\tconst budget = contextWindow - reserveTokens;\n\tconst preparedBoundaryIndex = branchEntries.findIndex((entry) => entry.id === preparation.firstKeptEntryId);\n\tif (!preparation.firstKeptEntryId || preparedBoundaryIndex === -1) {\n\t\tif (diagnostics) {\n\t\t\tObject.assign(diagnostics, {\n\t\t\t\trejectionReason: \"missing-preparation-boundary\",\n\t\t\t\tcontextWindow,\n\t\t\t\treserveTokens,\n\t\t\t\tbudgetTokens: budget,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tconst marker = [\n\t\t\"[Deterministic compaction recovery checkpoint]\",\n\t\t\"Generated summarization did not complete, so older context was reduced without another provider request.\",\n\t\t\"Continue from the retained messages after this checkpoint. Treat omitted transcript details as unknown.\",\n\t].join(\"\\n\");\n\tconst taskIntent = metadata.taskIntent?.trim();\n\tconst fixedText = taskIntent ? `${marker}\\n\\nTask intent:\\n${taskIntent}` : marker;\n\tconst maxSummaryBytes = Math.max(1_024, Math.floor(contextWindow * 0.4));\n\tconst previousSummary = preparation.previousSummary?.trim();\n\tlet summary = fixedText;\n\tif (previousSummary) {\n\t\tconst availableBytes = Math.max(0, maxSummaryBytes - Buffer.byteLength(`${fixedText}\\n\\nPrevious checkpoint:\\n`));\n\t\tconst truncationMarker = \"\\n[Older checkpoint truncated]\";\n\t\tconst boundedPrevious =\n\t\t\tBuffer.byteLength(previousSummary) <= availableBytes\n\t\t\t\t? previousSummary\n\t\t\t\t: `${capUtf8Bytes(previousSummary, Math.max(0, availableBytes - Buffer.byteLength(truncationMarker)))}${truncationMarker}`;\n\t\tsummary = `${fixedText}\\n\\nPrevious checkpoint:\\n${boundedPrevious}`;\n\t}\n\n\tconst baseDetails: DeterministicFallbackDetails = {\n\t\tschema: \"senpi.compaction.deterministic-fallback.v1\",\n\t\torigin: \"required-compaction-recovery\",\n\t\tfailureKind,\n\t\t...(taskIntent ? { taskIntent } : {}),\n\t};\n\tlet candidateCount = 0;\n\n\tconst syntheticCompaction: CompactionEntry = {\n\t\ttype: \"compaction\",\n\t\tid: \"__senpi_deterministic_fallback_preview__\",\n\t\tparentId: branchEntries.at(-1)?.id ?? null,\n\t\ttimestamp: new Date(0).toISOString(),\n\t\tsummary,\n\t\tfirstKeptEntryId: branchEntries[0]?.id ?? preparation.firstKeptEntryId,\n\t\ttokensBefore: preparation.tokensBefore,\n\t\tdetails: { ...baseDetails, retainedSuffix: \"prepared\" },\n\t\tfromHook: true,\n\t};\n\n\tlet projectedMessages: ReturnType<typeof filterContextExcludedMessages>;\n\ttry {\n\t\tprojectedMessages = filterContextExcludedMessages(\n\t\t\tbuildSessionContext([...branchEntries, syntheticCompaction]).messages,\n\t\t);\n\t} catch {\n\t\tif (diagnostics) {\n\t\t\tObject.assign(diagnostics, {\n\t\t\t\trejectionReason: \"context-reconstruction-failed\",\n\t\t\t\tcontextWindow,\n\t\t\t\treserveTokens,\n\t\t\t\tbudgetTokens: budget,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Evaluate the candidate the provider would actually receive: `convertToLlm`\n\t// drops failed/aborted assistant turns (and their orphaned tool results) before\n\t// every request, so their dangling toolCall blocks are neither incomplete calls\n\t// nor retained tokens here. Raw session history stays untouched - this mask is\n\t// local to the fallback projection (code-yeongyu/oh-my-openagent#7921).\n\tconst droppedByFailedTurnNormalization = markFailedTurnFragments(projectedMessages);\n\n\tconst messageIndexesByEntryId = new Map<string, number>();\n\tfor (const [index, message] of projectedMessages.entries()) {\n\t\tconst entryId = getSessionContextEntryId(message);\n\t\tif (entryId !== undefined) messageIndexesByEntryId.set(entryId, index);\n\t}\n\tconst summaryIndex = messageIndexesByEntryId.get(syntheticCompaction.id);\n\tconst unsafeSuffix = new Array(projectedMessages.length + 1).fill(false);\n\tconst unsafeIndexSuffix = new Int32Array(projectedMessages.length + 1).fill(-1);\n\tconst tokenSuffix = new Array(projectedMessages.length + 1).fill(0);\n\tconst toolCalls = new Map<string, { indexes: number[]; newestIncomplete: boolean }>();\n\tconst toolResults = new Map<string, number[]>();\n\tfor (let index = projectedMessages.length - 1; index >= 0; index--) {\n\t\tconst message = projectedMessages[index];\n\t\ttokenSuffix[index] = tokenSuffix[index + 1];\n\t\tunsafeIndexSuffix[index] = unsafeIndexSuffix[index + 1];\n\t\tif (droppedByFailedTurnNormalization[index]) {\n\t\t\tunsafeSuffix[index] = unsafeSuffix[index + 1];\n\t\t\tcontinue;\n\t\t}\n\t\tlet messageUnsafe = false;\n\t\tlet serialized: string | undefined;\n\t\ttry {\n\t\t\tmessageUnsafe = hasUnsafeRetainedContent([message]);\n\t\t\tconst bounded = isSafeBoundedValue(message);\n\t\t\tmessageUnsafe ||= !bounded;\n\t\t\tlet imageTokens = 0;\n\t\t\tif (!messageUnsafe && message.role === \"toolResult\") {\n\t\t\t\tconst content = message.content.map((block) => {\n\t\t\t\t\tif (block.type !== \"image\") return block;\n\t\t\t\t\timageTokens += estimateTokens({ ...message, content: [block] });\n\t\t\t\t\treturn { ...block, data: \"\" };\n\t\t\t\t});\n\t\t\t\tserialized = JSON.stringify({ ...message, content });\n\t\t\t} else {\n\t\t\t\tserialized = bounded ? JSON.stringify(message) : undefined;\n\t\t\t}\n\t\t\t// Apply the shared weighted chars/4 estimator to the envelope too.\n\t\t\t// Storage bytes are not tokens; opaque text and image costs still count.\n\t\t\ttokenSuffix[index] +=\n\t\t\t\tserialized === undefined\n\t\t\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t\t\t: Math.max(\n\t\t\t\t\t\t\testimateTokens(message),\n\t\t\t\t\t\t\testimateTokens({ role: \"user\", content: serialized, timestamp: 0 }) + imageTokens,\n\t\t\t\t\t\t);\n\t\t} catch {\n\t\t\tmessageUnsafe = true;\n\t\t\ttokenSuffix[index] = Number.POSITIVE_INFINITY;\n\t\t}\n\t\tunsafeSuffix[index] = unsafeSuffix[index + 1] || messageUnsafe;\n\t\tif (messageUnsafe) unsafeIndexSuffix[index] = index;\n\t\tif (!isRecord(message)) continue;\n\t\tif (message.role === \"toolResult\" && typeof message.toolCallId === \"string\") {\n\t\t\tconst indexes = toolResults.get(message.toolCallId) ?? [];\n\t\t\tindexes.push(index);\n\t\t\ttoolResults.set(message.toolCallId, indexes);\n\t\t} else if (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\tfor (const block of message.content) {\n\t\t\t\tif (!isRecord(block) || block.type !== \"toolCall\" || typeof block.id !== \"string\") continue;\n\t\t\t\tconst call = toolCalls.get(block.id) ?? { indexes: [], newestIncomplete: block.incomplete === true };\n\t\t\t\tcall.indexes.push(index);\n\t\t\t\ttoolCalls.set(block.id, call);\n\t\t\t}\n\t\t}\n\t}\n\tconst invalidToolChainDiff = new Int32Array(projectedMessages.length + 2);\n\tconst markInvalidRange = (start: number, endExclusive: number) => {\n\t\tconst boundedStart = Math.max(0, start);\n\t\tconst boundedEnd = Math.min(projectedMessages.length + 1, endExclusive);\n\t\tif (boundedStart >= boundedEnd) return;\n\t\tinvalidToolChainDiff[boundedStart]++;\n\t\tinvalidToolChainDiff[boundedEnd]--;\n\t};\n\tfor (const [id, call] of toolCalls) {\n\t\tconst results = toolResults.get(id) ?? [];\n\t\tif (results.length === 0) {\n\t\t\tmarkInvalidRange(0, Math.max(call.indexes[0] ?? -1, results[0] ?? -1) + 1);\n\t\t\tcontinue;\n\t\t}\n\t\tconst callIndex = call.indexes[0];\n\t\tconst resultIndex = results[0];\n\t\t// Indexes are newest-first. Older duplicate IDs matter only while retained;\n\t\t// dropping an entire historical pair leaves the newest pair valid.\n\t\tmarkInvalidRange(0, Math.max(call.indexes[1] ?? -1, results[1] ?? -1) + 1);\n\t\tif (call.newestIncomplete || callIndex >= resultIndex) {\n\t\t\tmarkInvalidRange(0, Math.max(callIndex, resultIndex) + 1);\n\t\t} else {\n\t\t\tmarkInvalidRange(callIndex + 1, resultIndex + 1);\n\t\t}\n\t}\n\tfor (const [id, results] of toolResults) {\n\t\tif (toolCalls.has(id)) continue;\n\t\tmarkInvalidRange(0, results[0] + 1);\n\t}\n\tconst toolChainValidAt = new Array(projectedMessages.length + 1).fill(true);\n\tlet invalidToolChainCount = 0;\n\tfor (let index = 0; index < toolChainValidAt.length; index++) {\n\t\tinvalidToolChainCount += invalidToolChainDiff[index];\n\t\ttoolChainValidAt[index] = invalidToolChainCount === 0;\n\t}\n\n\tconst projectCandidate = (\n\t\tfirstKeptEntryId: string,\n\t\tretainedSuffix: NonNullable<DeterministicFallbackDetails[\"retainedSuffix\"]>,\n\t): CompactionResult<DeterministicFallbackDetails> | undefined => {\n\t\tcandidateCount++;\n\t\tconst details = { ...baseDetails, retainedSuffix };\n\t\tconst reject = (\n\t\t\trejectionReason: DeterministicFallbackRejectionReason,\n\t\t\tdetail: Omit<\n\t\t\t\tNonNullable<DeterministicFallbackDiagnostic[\"candidateRejections\"]>[number],\n\t\t\t\t\"firstKeptEntryId\" | \"rejectionReason\"\n\t\t\t> = {},\n\t\t): undefined => {\n\t\t\tif (diagnostics) {\n\t\t\t\tdiagnostics.rejectionReason = rejectionReason;\n\t\t\t\tdiagnostics.contextWindow = contextWindow;\n\t\t\t\tdiagnostics.reserveTokens = reserveTokens;\n\t\t\t\tdiagnostics.budgetTokens = budget;\n\t\t\t\tdiagnostics.candidateRejections ??= [];\n\t\t\t\tdiagnostics.candidateRejections.push({ firstKeptEntryId, rejectionReason, ...detail });\n\t\t\t}\n\t\t\treturn undefined;\n\t\t};\n\t\tconst result: CompactionResult<DeterministicFallbackDetails> = {\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore: preparation.tokensBefore,\n\t\t\tdetails,\n\t\t};\n\t\tconst startIndex = messageIndexesByEntryId.get(firstKeptEntryId);\n\t\tif (startIndex === undefined) return reject(\"context-reconstruction-failed\");\n\t\tconst retainedStart = Math.min(startIndex, projectedMessages.length);\n\t\tif (unsafeSuffix[retainedStart]) {\n\t\t\tconst unsafeMessageIndex = unsafeIndexSuffix[retainedStart];\n\t\t\tconst unsafeMessage = projectedMessages[unsafeMessageIndex];\n\t\t\treturn reject(\"unsafe-retained-content\", {\n\t\t\t\tunsafeMessageIndex,\n\t\t\t\tunsafeEntryId: getSessionContextEntryId(unsafeMessage),\n\t\t\t\tunsafeMessageRole: unsafeMessage.role,\n\t\t\t});\n\t\t}\n\t\tif (!toolChainValidAt[retainedStart]) return reject(\"atomic-tool-chain-cut\");\n\t\t// The hard-limit valve reserves the scaled budget, so accepting against the raw\n\t\t// configured reserve would admit a context that valve immediately compacts again.\n\t\tconst summaryTokens =\n\t\t\tsummaryIndex === undefined\n\t\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t\t: Math.max(\n\t\t\t\t\t\testimateTokens(projectedMessages[summaryIndex]),\n\t\t\t\t\t\testimateTokens({\n\t\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\t\tcontent: JSON.stringify(projectedMessages[summaryIndex]),\n\t\t\t\t\t\t\ttimestamp: 0,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\tconst retainedTokens = (tokenSuffix[retainedStart] ?? Number.POSITIVE_INFINITY) + summaryTokens;\n\t\tif (retainedTokens > budget) {\n\t\t\tif (diagnostics) diagnostics.budgetExceeded = true;\n\t\t\treturn reject(\"retained-token-budget-exceeded\", { estimatedTokens: retainedTokens });\n\t\t}\n\t\treturn { ...result, estimatedTokensAfter: retainedTokens };\n\t};\n\n\t// 1. Try prepared boundary\n\tconst prepared = projectCandidate(preparation.firstKeptEntryId, \"prepared\");\n\tif (prepared) {\n\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\treturn prepared;\n\t}\n\n\t// 2. If prepared boundary cut an atomic signed chain or was rejected, walk backward\n\t// to the actual chain boundary. The chain length is determined by the session.\n\tfor (let index = preparedBoundaryIndex - 1; index >= 0; index--) {\n\t\tconst entry = branchEntries[index];\n\t\tif (entry.type === \"compaction\") break;\n\t\t// Only consider message turn starts or assistant call starts\n\t\tconst earlier = projectCandidate(entry.id, \"earlier-safe-boundary\");\n\t\tif (earlier) {\n\t\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\t\treturn earlier;\n\t\t}\n\t}\n\n\t// 3. Try latest meaningful user turn\n\tfor (let index = branchEntries.length - 1; index > preparedBoundaryIndex; index--) {\n\t\tconst entry = branchEntries[index];\n\t\tif (!hasMeaningfulUserText(entry)) continue;\n\t\tconst latestUser = projectCandidate(entry.id, \"latest-user-turn\");\n\t\tif (latestUser) {\n\t\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\t\treturn latestUser;\n\t\t}\n\t\t// A steering user message can occur inside a tool chain. Keep that request\n\t\t// and walk back to its declaring assistant instead of orphaning the result.\n\t\tfor (let earlierIndex = index - 1; earlierIndex > preparedBoundaryIndex; earlierIndex--) {\n\t\t\tconst earlierEntry = branchEntries[earlierIndex];\n\t\t\tif (earlierEntry.type === \"compaction\") break;\n\t\t\tconst earlier = projectCandidate(earlierEntry.id, \"earlier-safe-boundary\");\n\t\t\tif (earlier) {\n\t\t\t\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\t\t\t\treturn earlier;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\n\tif (diagnostics) diagnostics.candidatesChecked = candidateCount;\n\treturn undefined;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Mark the messages that the transport's canonical failed-turn normalization
3
+ * removes before a provider request.
4
+ *
5
+ * `convertToLlm` (`core/messages.ts`) ends with `dropFailedAssistantTurns`, so an
6
+ * assistant turn that stopped with `error` or `aborted` - together with every tool
7
+ * result orphaned by that drop - never reaches the provider. The deterministic
8
+ * compaction fallback evaluates the same projection, so those fragments must not be
9
+ * counted as incomplete tool calls or charged against the retained budget.
10
+ *
11
+ * The shared function is reused directly (no rule mirroring) and the input array is
12
+ * never mutated: the result is a positional mask over the caller's own messages.
13
+ * Index `i` is `true` when message `i` is dropped by that normalization.
14
+ */
15
+ export declare function markFailedTurnFragments<T extends {
16
+ role: string;
17
+ }>(messages: readonly T[]): boolean[];
18
+ //# sourceMappingURL=fallback-failed-turn-normalization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-failed-turn-normalization.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/fallback-failed-turn-normalization.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,CAGrG"}
@@ -0,0 +1,20 @@
1
+ import { dropFailedAssistantTurns } from "@earendil-works/pi-ai";
2
+ /**
3
+ * Mark the messages that the transport's canonical failed-turn normalization
4
+ * removes before a provider request.
5
+ *
6
+ * `convertToLlm` (`core/messages.ts`) ends with `dropFailedAssistantTurns`, so an
7
+ * assistant turn that stopped with `error` or `aborted` - together with every tool
8
+ * result orphaned by that drop - never reaches the provider. The deterministic
9
+ * compaction fallback evaluates the same projection, so those fragments must not be
10
+ * counted as incomplete tool calls or charged against the retained budget.
11
+ *
12
+ * The shared function is reused directly (no rule mirroring) and the input array is
13
+ * never mutated: the result is a positional mask over the caller's own messages.
14
+ * Index `i` is `true` when message `i` is dropped by that normalization.
15
+ */
16
+ export function markFailedTurnFragments(messages) {
17
+ const retained = new Set(dropFailedAssistantTurns(messages));
18
+ return messages.map((message) => !retained.has(message));
19
+ }
20
+ //# sourceMappingURL=fallback-failed-turn-normalization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-failed-turn-normalization.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/fallback-failed-turn-normalization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAA6B,QAAsB;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAI,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import { dropFailedAssistantTurns } from \"@earendil-works/pi-ai\";\n\n/**\n * Mark the messages that the transport's canonical failed-turn normalization\n * removes before a provider request.\n *\n * `convertToLlm` (`core/messages.ts`) ends with `dropFailedAssistantTurns`, so an\n * assistant turn that stopped with `error` or `aborted` - together with every tool\n * result orphaned by that drop - never reaches the provider. The deterministic\n * compaction fallback evaluates the same projection, so those fragments must not be\n * counted as incomplete tool calls or charged against the retained budget.\n *\n * The shared function is reused directly (no rule mirroring) and the input array is\n * never mutated: the result is a positional mask over the caller's own messages.\n * Index `i` is `true` when message `i` is dropped by that normalization.\n */\nexport function markFailedTurnFragments<T extends { role: string }>(messages: readonly T[]): boolean[] {\n\tconst retained = new Set<T>(dropFailedAssistantTurns(messages));\n\treturn messages.map((message) => !retained.has(message));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoE,MAAM,gBAAgB,CAAC;AAyBrH,OAAO,EACN,KAAK,kCAAkC,EAIvC,MAAM,oBAAoB,CAAC;AAqC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AA2B/D,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAC1C,EAAE,EAAE,YAAY,EAChB,4BAA4B,GAAE,kCAAuC,GACnE,IAAI,CAo6BN"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoE,MAAM,gBAAgB,CAAC;AA4BrH,OAAO,EACN,KAAK,kCAAkC,EAIvC,MAAM,oBAAoB,CAAC;AAqC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AA2B/D,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAC1C,EAAE,EAAE,YAAY,EAChB,4BAA4B,GAAE,kCAAuC,GACnE,IAAI,CAu9BN"}
@@ -3,7 +3,7 @@ import * as checkpointState from "./checkpoint-state.js";
3
3
  import * as breaker from "./circuit-breaker.js";
4
4
  import { buildCompactionContext } from "./context-pipeline.js";
5
5
  import { createDegradationMonitorState, handleMessageEnd, handleTurnEnd, RECOVERY_INSTRUCTIONS, resetOnSessionCompact, } from "./degradation-monitor.js";
6
- import { classifyRequiredCompactionFallbackFailure, createRequiredCompactionFallback, } from "./deterministic-fallback.js";
6
+ import { classifyRequiredCompactionFallbackFailure, createRequiredCompactionFallback, formatRequiredCompactionFallbackRejection, } from "./deterministic-fallback.js";
7
7
  import * as idle from "./idle.js";
8
8
  import * as idleRetry from "./idle-retry.js";
9
9
  import { CLAUDE_SDK_OAUTH_COMPACT_ENTRY_TYPE, collectCompactBoundaryEntries, createCompactionLanePolicy, SDK_NATIVE_LANE_REJECTION_REASON, } from "./lane-policy.js";
@@ -295,6 +295,11 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
295
295
  checkpointState.persistCheckpoint(pi, metadata.checkpoint);
296
296
  todoBridge.persistTodoSnapshot(pi, metadata.todoSnapshot);
297
297
  }
298
+ function recoverRequiredCompaction(snapshot, failureKind) {
299
+ const diagnostics = {};
300
+ const compaction = createRequiredCompactionFallback(snapshot.preparation, snapshot.contextWindow, failureKind, { taskIntent: resolveInheritedTaskIntent(snapshot.branchEntries ?? []) }, snapshot.branchEntries, diagnostics);
301
+ return compaction ? { compaction } : { rejectionReason: formatRequiredCompactionFallbackRejection(diagnostics) };
302
+ }
298
303
  async function applyBlockingCompaction(ctx, customInstructions) {
299
304
  const provider = ctx.model?.provider;
300
305
  if ((provider === "cursor" || provider === "cursor-cli-oauth") && !ctx.isIdle()) {
@@ -361,7 +366,21 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
361
366
  }
362
367
  if (inheritedFailure !== undefined) {
363
368
  speculativeJob = undefined;
364
- if (isTransientSummarizationFailure(inheritedFailure, inheritedFailure.message)) {
369
+ const failureKind = classifyRequiredCompactionFallbackFailure(inheritedFailure);
370
+ if (failureKind !== undefined &&
371
+ !feedbackSignal?.aborted &&
372
+ pendingJob.snapshot.generation === speculativeGeneration &&
373
+ pendingJob.snapshot.expectedRevision === ctx.getMessageRevision()) {
374
+ const recovery = recoverRequiredCompaction(pendingJob.snapshot, failureKind);
375
+ compaction = recovery.compaction;
376
+ if (!compaction) {
377
+ const result = { applied: false, reason: "failed" };
378
+ endCompactionFeedback(ctx, feedbackSignal, result, recovery.rejectionReason);
379
+ return result;
380
+ }
381
+ }
382
+ else if (failureKind === undefined &&
383
+ isTransientSummarizationFailure(inheritedFailure, inheritedFailure.message)) {
365
384
  ctx.endCompaction?.({
366
385
  reason: "extension",
367
386
  signal: feedbackSignal,
@@ -412,9 +431,21 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
412
431
  }));
413
432
  }
414
433
  catch (error) {
415
- if (!(error instanceof SummaryGenerationError))
416
- throw error;
417
- getLogger(ctx).debug("summary_failed", { reason: error.kind });
434
+ const failureKind = classifyRequiredCompactionFallbackFailure(error);
435
+ if (failureKind !== undefined && !feedbackSignal?.aborted) {
436
+ const recovery = recoverRequiredCompaction(snapshot, failureKind);
437
+ compaction = recovery.compaction;
438
+ if (!compaction) {
439
+ const result = { applied: false, reason: "failed" };
440
+ endCompactionFeedback(ctx, feedbackSignal, result, recovery.rejectionReason);
441
+ return result;
442
+ }
443
+ }
444
+ else {
445
+ if (!(error instanceof SummaryGenerationError))
446
+ throw error;
447
+ getLogger(ctx).debug("summary_failed", { reason: error.kind });
448
+ }
418
449
  }
419
450
  const result = await applyGeneratedCompaction(ctx, snapshot, () => speculativeGeneration, compaction, feedbackSignal);
420
451
  endCompactionFeedback(ctx, feedbackSignal, result, remoteFallbackReason);
@@ -457,8 +488,9 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
457
488
  // keeps streaming for a result nobody will read.
458
489
  let warmJobConsumed = false;
459
490
  invalidateSpeculativeCompaction(ctx);
491
+ const claimedGeneration = speculativeGeneration;
460
492
  try {
461
- if (lanePolicy.disablesSenpiCompaction(ctx)) {
493
+ if (!lanePolicy.ownsCompaction(ctx, event.reason)) {
462
494
  return {
463
495
  cancel: true,
464
496
  rejectionCause: "external-owner",
@@ -505,6 +537,7 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
505
537
  getLogger(ctx).debug("core_route_generated", { route: "core-route", requestId: event.requestId });
506
538
  return { compaction: remoteCompaction };
507
539
  }
540
+ let inheritedWarmFailure;
508
541
  if (claimedWarmJob) {
509
542
  const unlinkAbort = linkAbortSignal(event.signal, claimedWarmJob.controller);
510
543
  let warmCompaction;
@@ -521,6 +554,14 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
521
554
  warmJobConsumed = true;
522
555
  return { compaction: warmCompaction };
523
556
  }
557
+ if (warmFailure !== undefined &&
558
+ isRequiredCompactionFallbackReason(event.reason) &&
559
+ classifyRequiredCompactionFallbackFailure(warmFailure) !== undefined &&
560
+ !event.signal.aborted &&
561
+ speculativeGeneration === claimedGeneration &&
562
+ claimedWarmJob.snapshot.expectedRevision === ctx.getMessageRevision()) {
563
+ inheritedWarmFailure = warmFailure;
564
+ }
524
565
  }
525
566
  const snapshot = {
526
567
  generation: ++speculativeGeneration,
@@ -537,6 +578,8 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
537
578
  };
538
579
  let compaction;
539
580
  try {
581
+ if (inheritedWarmFailure)
582
+ throw inheritedWarmFailure;
540
583
  compaction = await runExtensionCompaction(ctx, snapshot, event.signal, (delta) => ctx.updateCompaction?.({ reason: event.reason, signal: event.signal, delta }));
541
584
  }
542
585
  catch (error) {
@@ -545,13 +588,13 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
545
588
  if (isRequiredCompactionFallbackReason(event.reason) &&
546
589
  failureKind !== undefined &&
547
590
  !event.signal.aborted) {
548
- const fallback = createRequiredCompactionFallback(snapshot.preparation, snapshot.contextWindow, failureKind, { taskIntent: resolveInheritedTaskIntent(event.branchEntries) }, event.branchEntries);
549
- if (fallback)
550
- return { compaction: fallback };
591
+ const recovery = recoverRequiredCompaction(snapshot, failureKind);
592
+ if (recovery.compaction)
593
+ return { compaction: recovery.compaction };
551
594
  pendingMetadata.delete(event.requestId);
552
595
  return {
553
596
  cancel: true,
554
- reason: "deterministic compaction fallback cannot retain the prepared suffix",
597
+ reason: recovery.rejectionReason,
555
598
  };
556
599
  }
557
600
  pendingMetadata.delete(event.requestId);
@@ -641,7 +684,7 @@ export default function compactionExtension(pi, remoteCompactionDependencies = {
641
684
  }
642
685
  if (compactEvent.rejectionCause === "external-owner")
643
686
  return;
644
- if (!lanePolicy.disablesSenpiCompaction(ctx)) {
687
+ if (lanePolicy.ownsCompaction(ctx, compactEvent.reason)) {
645
688
  state = breaker.recordFailure(state, Date.now(), { route: compactEvent.reason });
646
689
  }
647
690
  });