@code-yeongyu/senpi 2026.8.28 → 2026.8.30-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/CHANGELOG.md +196 -0
  2. package/dist/cli/args.d.ts +2 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-session-services.d.ts.map +1 -1
  7. package/dist/core/agent-session-services.js +2 -0
  8. package/dist/core/agent-session-services.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +50 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +330 -29
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/auth-storage.d.ts +1 -0
  14. package/dist/core/auth-storage.d.ts.map +1 -1
  15. package/dist/core/auth-storage.js +3 -0
  16. package/dist/core/auth-storage.js.map +1 -1
  17. package/dist/core/bash-executor.d.ts.map +1 -1
  18. package/dist/core/bash-executor.js +155 -37
  19. package/dist/core/bash-executor.js.map +1 -1
  20. package/dist/core/compaction/compaction-execution.d.ts +14 -0
  21. package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
  22. package/dist/core/compaction/compaction-execution.js +121 -0
  23. package/dist/core/compaction/compaction-execution.js.map +1 -0
  24. package/dist/core/compaction/compaction-settings.d.ts +17 -0
  25. package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
  26. package/dist/core/compaction/compaction-settings.js +17 -0
  27. package/dist/core/compaction/compaction-settings.js.map +1 -0
  28. package/dist/core/compaction/compaction.d.ts +13 -26
  29. package/dist/core/compaction/compaction.d.ts.map +1 -1
  30. package/dist/core/compaction/compaction.js +7 -136
  31. package/dist/core/compaction/compaction.js.map +1 -1
  32. package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
  33. package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
  34. package/dist/core/compaction/ideal-compaction-settings.js +7 -0
  35. package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
  36. package/dist/core/compaction-settings-access.d.ts +19 -0
  37. package/dist/core/compaction-settings-access.d.ts.map +1 -0
  38. package/dist/core/compaction-settings-access.js +10 -0
  39. package/dist/core/compaction-settings-access.js.map +1 -0
  40. package/dist/core/compaction-settings-resolver.d.ts +22 -0
  41. package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
  42. package/dist/core/compaction-settings-resolver.js +46 -0
  43. package/dist/core/compaction-settings-resolver.js.map +1 -0
  44. package/dist/core/credential-accounts.d.ts.map +1 -1
  45. package/dist/core/credential-accounts.js +45 -21
  46. package/dist/core/credential-accounts.js.map +1 -1
  47. package/dist/core/credential-pool/classify.d.ts +6 -1
  48. package/dist/core/credential-pool/classify.d.ts.map +1 -1
  49. package/dist/core/credential-pool/classify.js +22 -5
  50. package/dist/core/credential-pool/classify.js.map +1 -1
  51. package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
  52. package/dist/core/credential-pool/env-slots.js +2 -0
  53. package/dist/core/credential-pool/env-slots.js.map +1 -1
  54. package/dist/core/credential-pool/failover.d.ts +8 -0
  55. package/dist/core/credential-pool/failover.d.ts.map +1 -1
  56. package/dist/core/credential-pool/failover.js +24 -6
  57. package/dist/core/credential-pool/failover.js.map +1 -1
  58. package/dist/core/credential-pool/rotation-stream.d.ts +13 -2
  59. package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
  60. package/dist/core/credential-pool/rotation-stream.js +97 -10
  61. package/dist/core/credential-pool/rotation-stream.js.map +1 -1
  62. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +17 -0
  63. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
  64. package/dist/core/extensions/builtin/compaction/context-pipeline.js +28 -0
  65. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
  66. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -2
  67. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +163 -48
  69. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  70. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
  71. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
  72. package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
  73. package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
  74. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
  75. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
  76. package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
  77. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
  78. package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
  79. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
  80. package/dist/core/extensions/builtin/compaction/idle.js +13 -2
  81. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
  82. package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
  83. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  84. package/dist/core/extensions/builtin/compaction/index.js +121 -147
  85. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  86. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  87. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  88. package/dist/core/extensions/builtin/compaction/log.js +2 -0
  89. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  90. package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
  91. package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
  92. package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
  93. package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
  94. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
  95. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
  96. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
  97. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
  98. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
  99. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  100. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  101. package/dist/core/extensions/builtin/compaction/orchestration.d.ts +56 -0
  102. package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
  103. package/dist/core/extensions/builtin/compaction/orchestration.js +136 -0
  104. package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
  105. package/dist/core/extensions/builtin/compaction/policy.d.ts +5 -2
  106. package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
  107. package/dist/core/extensions/builtin/compaction/policy.js +43 -26
  108. package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
  109. package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts.map +1 -1
  110. package/dist/core/extensions/builtin/compaction/retained-message-safety.js +31 -8
  111. package/dist/core/extensions/builtin/compaction/retained-message-safety.js.map +1 -1
  112. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
  113. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
  114. package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
  115. package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
  116. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
  117. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
  118. package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
  119. package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
  120. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +22 -0
  121. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
  122. package/dist/core/extensions/builtin/compaction/speculative-summary.js +131 -0
  123. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
  124. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
  125. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  126. package/dist/core/extensions/builtin/compaction/speculative.js +7 -196
  127. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  128. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +18 -0
  129. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
  130. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +18 -0
  131. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
  132. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +36 -0
  133. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
  134. package/dist/core/extensions/builtin/compaction/tool-admission.js +92 -0
  135. package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
  136. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.d.ts.map +1 -1
  137. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +8 -28
  138. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
  139. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/goal/index.js +7 -0
  141. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  142. package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
  144. package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
  145. package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
  147. package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
  148. package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
  149. package/dist/core/extensions/builtin/service-tier.js +13 -0
  150. package/dist/core/extensions/builtin/service-tier.js.map +1 -1
  151. package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
  152. package/dist/core/extensions/builtin/terminal/extension.js +4 -2
  153. package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
  154. package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
  155. package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
  156. package/dist/core/extensions/builtin/terminal/manager.js +31 -3
  157. package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
  158. package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
  159. package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
  160. package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
  161. package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
  162. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
  163. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
  164. package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
  165. package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
  166. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
  167. package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
  168. package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
  169. package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
  170. package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
  171. package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
  172. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
  173. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
  174. package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
  175. package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
  176. package/dist/core/model-config-schema.d.ts +4 -4
  177. package/dist/core/model-resolver.js +2 -2
  178. package/dist/core/model-resolver.js.map +1 -1
  179. package/dist/core/model-runtime.d.ts +2 -0
  180. package/dist/core/model-runtime.d.ts.map +1 -1
  181. package/dist/core/model-runtime.js +74 -37
  182. package/dist/core/model-runtime.js.map +1 -1
  183. package/dist/core/retry-fallback/chains.d.ts +23 -1
  184. package/dist/core/retry-fallback/chains.d.ts.map +1 -1
  185. package/dist/core/retry-fallback/chains.js +59 -3
  186. package/dist/core/retry-fallback/chains.js.map +1 -1
  187. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  188. package/dist/core/retry-fallback/controller.js +9 -2
  189. package/dist/core/retry-fallback/controller.js.map +1 -1
  190. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  191. package/dist/core/retry-fallback/settings.js +9 -0
  192. package/dist/core/retry-fallback/settings.js.map +1 -1
  193. package/dist/core/retry-fallback/validate.js +1 -1
  194. package/dist/core/retry-fallback/validate.js.map +1 -1
  195. package/dist/core/sdk.js +1 -1
  196. package/dist/core/sdk.js.map +1 -1
  197. package/dist/core/session-manager.d.ts +9 -0
  198. package/dist/core/session-manager.d.ts.map +1 -1
  199. package/dist/core/session-manager.js +40 -0
  200. package/dist/core/session-manager.js.map +1 -1
  201. package/dist/core/settings-manager.d.ts +15 -85
  202. package/dist/core/settings-manager.d.ts.map +1 -1
  203. package/dist/core/settings-manager.js +15 -17
  204. package/dist/core/settings-manager.js.map +1 -1
  205. package/dist/core/settings-public-types.d.ts +11 -0
  206. package/dist/core/settings-public-types.d.ts.map +1 -0
  207. package/dist/core/settings-public-types.js +2 -0
  208. package/dist/core/settings-public-types.js.map +1 -0
  209. package/dist/core/settings-shapes.d.ts +36 -0
  210. package/dist/core/settings-shapes.d.ts.map +1 -0
  211. package/dist/core/settings-shapes.js +2 -0
  212. package/dist/core/settings-shapes.js.map +1 -0
  213. package/dist/core/shared-host-policy.d.ts +6 -0
  214. package/dist/core/shared-host-policy.d.ts.map +1 -0
  215. package/dist/core/shared-host-policy.js +7 -0
  216. package/dist/core/shared-host-policy.js.map +1 -0
  217. package/dist/core/terminal-settings.d.ts +22 -0
  218. package/dist/core/terminal-settings.d.ts.map +1 -0
  219. package/dist/core/terminal-settings.js +2 -0
  220. package/dist/core/terminal-settings.js.map +1 -0
  221. package/dist/core/tools/bash.d.ts.map +1 -1
  222. package/dist/core/tools/bash.js +97 -15
  223. package/dist/core/tools/bash.js.map +1 -1
  224. package/dist/core/tools/index.d.ts +1 -0
  225. package/dist/core/tools/index.d.ts.map +1 -1
  226. package/dist/core/tools/index.js +8 -0
  227. package/dist/core/tools/index.js.map +1 -1
  228. package/dist/core/tools/output-accumulator.d.ts +1 -1
  229. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  230. package/dist/core/tools/output-accumulator.js +76 -34
  231. package/dist/core/tools/output-accumulator.js.map +1 -1
  232. package/dist/main.d.ts +7 -0
  233. package/dist/main.d.ts.map +1 -1
  234. package/dist/main.js +27 -6
  235. package/dist/main.js.map +1 -1
  236. package/dist/modes/interactive/components/favorite-models-selector.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/favorite-models-selector.js +2 -2
  238. package/dist/modes/interactive/components/favorite-models-selector.js.map +1 -1
  239. package/dist/modes/interactive/components/footer.d.ts +7 -0
  240. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  241. package/dist/modes/interactive/components/footer.js +34 -8
  242. package/dist/modes/interactive/components/footer.js.map +1 -1
  243. package/dist/modes/interactive/grok/chrome.d.ts +2 -0
  244. package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
  245. package/dist/modes/interactive/grok/chrome.js.map +1 -1
  246. package/dist/modes/interactive/interactive-host-runtime.d.ts +121 -1
  247. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  248. package/dist/modes/interactive/interactive-host-runtime.js +606 -45
  249. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  250. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  251. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  252. package/dist/modes/interactive/interactive-mode.js +390 -239
  253. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  254. package/dist/modes/rpc/connection-handler.d.ts +8 -1
  255. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  256. package/dist/modes/rpc/connection-handler.js +268 -63
  257. package/dist/modes/rpc/connection-handler.js.map +1 -1
  258. package/dist/modes/rpc/host-ensure.d.ts +19 -0
  259. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  260. package/dist/modes/rpc/host-ensure.js +79 -15
  261. package/dist/modes/rpc/host-ensure.js.map +1 -1
  262. package/dist/modes/rpc/host-lifecycle.d.ts +29 -0
  263. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  264. package/dist/modes/rpc/host-lifecycle.js +96 -25
  265. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  266. package/dist/modes/rpc/host-watchdog.d.ts +2 -0
  267. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  268. package/dist/modes/rpc/host-watchdog.js +23 -12
  269. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  270. package/dist/modes/rpc/multi-session-host.js +20 -8
  271. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  272. package/dist/modes/rpc/rpc-client.d.ts +91 -16
  273. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  274. package/dist/modes/rpc/rpc-client.js +131 -37
  275. package/dist/modes/rpc/rpc-client.js.map +1 -1
  276. package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
  277. package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
  278. package/dist/modes/rpc/rpc-input-validation.js +66 -0
  279. package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
  280. package/dist/modes/rpc/rpc-mode.d.ts +3 -1
  281. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  282. package/dist/modes/rpc/rpc-mode.js +3 -1
  283. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  284. package/dist/modes/rpc/rpc-types.d.ts +248 -3
  285. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  286. package/dist/modes/rpc/rpc-types.js.map +1 -1
  287. package/dist/modes/rpc/session-binding.d.ts +1 -0
  288. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  289. package/dist/modes/rpc/session-binding.js +21 -1
  290. package/dist/modes/rpc/session-binding.js.map +1 -1
  291. package/dist/modes/rpc/session-command-router.d.ts +22 -0
  292. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  293. package/dist/modes/rpc/session-command-router.js +148 -16
  294. package/dist/modes/rpc/session-command-router.js.map +1 -1
  295. package/dist/modes/rpc/session-event-writer.d.ts +4 -0
  296. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  297. package/dist/modes/rpc/session-event-writer.js +58 -7
  298. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  299. package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
  300. package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
  301. package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
  302. package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
  303. package/dist/modes/rpc/session-registry.d.ts +17 -2
  304. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  305. package/dist/modes/rpc/session-registry.js +67 -4
  306. package/dist/modes/rpc/session-registry.js.map +1 -1
  307. package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
  308. package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
  309. package/dist/modes/rpc/socket-event-fanout.js +84 -0
  310. package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
  311. package/docs/rpc.md +55 -2
  312. package/docs/settings.md +34 -0
  313. package/docs/windows.md +2 -0
  314. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +74 -0
  315. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  316. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
  317. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
  318. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  319. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +6 -3
  320. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  321. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  322. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
  323. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  324. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
  325. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  326. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
  327. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
  328. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
  330. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  332. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +67 -38
  334. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  335. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +20 -0
  336. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -0
  337. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +443 -0
  338. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -0
  339. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
  340. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  341. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +2 -0
  342. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  343. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  345. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  346. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  347. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  348. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  353. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  354. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  355. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  357. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  358. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  359. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  360. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  361. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  362. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  363. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  364. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  365. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  366. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  367. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +7 -0
  368. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  369. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -0
  370. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  371. package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +1 -1
  372. package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -1
  373. package/node_modules/@earendil-works/pi-tui/dist/mux.js +2 -2
  374. package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -1
  375. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
  376. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  377. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +19 -0
  378. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  379. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  380. package/package.json +7 -7
@@ -1,27 +1,31 @@
1
1
  const MIN_ADAPTIVE_THRESHOLD_RATIO = 0.4;
2
- const MAX_ADAPTIVE_THRESHOLD_RATIO = 0.7;
2
+ const MAX_ADAPTIVE_THRESHOLD_RATIO = 0.85;
3
3
  const HIGH_YIELD_SAVING_RATIO = 0.5;
4
4
  const LOW_YIELD_SAVING_RATIO = 0.1;
5
5
  const YIELD_ADJUSTMENT_RATIO = 0.05;
6
6
  const MIN_EFFECTIVE_KEEP_RECENT_TOKENS = 1024;
7
+ const RESERVE_WINDOW_FRACTION = 0.04;
8
+ const MAX_SCALED_RESERVE_TOKENS = 49_152;
9
+ const KEEP_RECENT_WINDOW_FRACTION = 0.05;
10
+ const MAX_SCALED_KEEP_RECENT_TOKENS = 60_000;
7
11
  export const SPECULATIVE_FRACTION = 0.75;
8
12
  function clampThresholdRatio(ratio) {
9
13
  return Math.min(MAX_ADAPTIVE_THRESHOLD_RATIO, Math.max(MIN_ADAPTIVE_THRESHOLD_RATIO, ratio));
10
14
  }
11
- function adjustThresholdRatio(ratio, savedTokens, tokensBefore) {
12
- if (tokensBefore <= 0) {
15
+ function adjustThresholdRatio(ratio, savedTokens, contextWindow) {
16
+ if (contextWindow <= 0) {
13
17
  return ratio;
14
18
  }
15
- const savedRatio = savedTokens / tokensBefore;
19
+ const savedRatio = savedTokens / contextWindow;
16
20
  if (savedRatio > HIGH_YIELD_SAVING_RATIO) {
17
21
  return clampThresholdRatio(ratio - YIELD_ADJUSTMENT_RATIO);
18
22
  }
19
23
  if (savedRatio < LOW_YIELD_SAVING_RATIO) {
20
- return clampThresholdRatio(ratio + YIELD_ADJUSTMENT_RATIO);
24
+ return Math.min(baseThresholdRatioForWindow(contextWindow), clampThresholdRatio(ratio + YIELD_ADJUSTMENT_RATIO));
21
25
  }
22
26
  return ratio;
23
27
  }
24
- function adjustEffectiveThresholdRatio(ratio, savedTokens, tokensBefore) {
28
+ function adjustEffectiveThresholdRatio(ratio, savedTokens, tokensBefore, contextWindow) {
25
29
  if (tokensBefore <= 0) {
26
30
  return ratio;
27
31
  }
@@ -30,56 +34,69 @@ function adjustEffectiveThresholdRatio(ratio, savedTokens, tokensBefore) {
30
34
  return ratio - YIELD_ADJUSTMENT_RATIO;
31
35
  }
32
36
  if (savedRatio < LOW_YIELD_SAVING_RATIO) {
33
- return ratio + YIELD_ADJUSTMENT_RATIO;
37
+ return Math.min(baseThresholdRatioForWindow(contextWindow), ratio + YIELD_ADJUSTMENT_RATIO);
34
38
  }
35
39
  return ratio;
36
40
  }
37
- export function computeAdaptiveThresholdRatio(contextWindow, priorCompactionSavedTokens) {
38
- let ratio;
41
+ export function baseThresholdRatioForWindow(contextWindow) {
39
42
  if (!(contextWindow > 0)) {
40
- ratio = 0.5;
43
+ return 0.5;
41
44
  }
42
- else if (contextWindow <= 16_000) {
43
- ratio = 0.45;
45
+ if (contextWindow <= 16_000) {
46
+ return 0.45;
44
47
  }
45
- else if (contextWindow <= 32_000) {
46
- ratio = 0.5;
48
+ if (contextWindow <= 32_000) {
49
+ return 0.5;
47
50
  }
48
- else if (contextWindow <= 64_000) {
49
- ratio = 0.55;
51
+ if (contextWindow <= 64_000) {
52
+ return 0.55;
50
53
  }
51
- else if (contextWindow <= 128_000) {
52
- ratio = 0.6;
54
+ if (contextWindow <= 128_000) {
55
+ return 0.6;
53
56
  }
54
- else {
55
- ratio = 0.65;
57
+ if (contextWindow <= 512_000) {
58
+ return 0.7;
56
59
  }
60
+ return 0.8;
61
+ }
62
+ export function resolveReserveTokens(contextWindow, configuredReserve) {
63
+ return Math.max(configuredReserve, Math.min(Math.floor(RESERVE_WINDOW_FRACTION * contextWindow), MAX_SCALED_RESERVE_TOKENS));
64
+ }
65
+ export function computeAdaptiveThresholdRatio(contextWindow, priorCompactionSavedTokens) {
66
+ const ratio = baseThresholdRatioForWindow(contextWindow);
57
67
  if (priorCompactionSavedTokens === undefined) {
58
68
  return ratio;
59
69
  }
60
70
  return adjustThresholdRatio(ratio, priorCompactionSavedTokens, contextWindow);
61
71
  }
62
72
  export function computeEffectiveThreshold(contextWindow, lastYield) {
63
- if (typeof lastYield === "number") {
64
- return Math.max(contextWindow, lastYield);
65
- }
66
73
  let ratio = computeAdaptiveThresholdRatio(contextWindow);
67
74
  if (lastYield) {
68
- ratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore);
75
+ ratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore, contextWindow);
69
76
  }
70
77
  return clampThresholdRatio(ratio);
71
78
  }
72
79
  export function computeEffectiveKeepRecentTokens(setting, contextWindow, thresholdRatio, margin = 0.05) {
80
+ const scaled = contextWindow > 409_600 && setting >= 10_000
81
+ ? Math.max(setting, Math.min(Math.floor(KEEP_RECENT_WINDOW_FRACTION * contextWindow), MAX_SCALED_KEEP_RECENT_TOKENS))
82
+ : setting;
73
83
  const capped = Math.floor(contextWindow * (1 - thresholdRatio - margin));
74
- return Math.min(setting, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));
84
+ return Math.min(scaled, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));
75
85
  }
76
- export function shouldStartSpeculativeCompaction(usage, contextWindow, settings, lastYield) {
86
+ export function shouldStartSpeculativeCompaction(usage, contextWindow, settings, lastYield, leadTokens) {
77
87
  if (settings.speculativeEnabled === false || usage.tokens === null || contextWindow <= 0) {
78
88
  return false;
79
89
  }
90
+ if (typeof leadTokens === "number" && Number.isFinite(leadTokens) && leadTokens > 0) {
91
+ const leadTrigger = Math.max(0, contextWindow * computeEffectiveThreshold(contextWindow, lastYield) - leadTokens);
92
+ return usage.tokens >= leadTrigger;
93
+ }
80
94
  const fraction = settings.speculativeFraction ?? SPECULATIVE_FRACTION;
81
95
  return usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield) * fraction;
82
96
  }
97
+ export function resolveEffectiveReserveTokens(contextWindow, configuredReserve, reserveScalingEnabled = true) {
98
+ return reserveScalingEnabled ? resolveReserveTokens(contextWindow, configuredReserve) : configuredReserve;
99
+ }
83
100
  export function isAtHardLimit(usage, contextWindow, reserveTokens, additionalTokens = 0) {
84
101
  return usage.tokens !== null && usage.tokens + additionalTokens + reserveTokens >= contextWindow;
85
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CompactionSettings } from \"../../../compaction/index.ts\";\nimport type { ContextUsage } from \"../../types.ts\";\n\nconst MIN_ADAPTIVE_THRESHOLD_RATIO = 0.4;\nconst MAX_ADAPTIVE_THRESHOLD_RATIO = 0.7;\nconst HIGH_YIELD_SAVING_RATIO = 0.5;\nconst LOW_YIELD_SAVING_RATIO = 0.1;\nconst YIELD_ADJUSTMENT_RATIO = 0.05;\nconst MIN_EFFECTIVE_KEEP_RECENT_TOKENS = 1024;\n\nexport const SPECULATIVE_FRACTION = 0.75;\n\nexport interface CompactionYield {\n\tsavedTokens: number;\n\ttokensBefore: number;\n}\n\nfunction clampThresholdRatio(ratio: number): number {\n\treturn Math.min(MAX_ADAPTIVE_THRESHOLD_RATIO, Math.max(MIN_ADAPTIVE_THRESHOLD_RATIO, ratio));\n}\n\nfunction adjustThresholdRatio(ratio: number, savedTokens: number, tokensBefore: number): number {\n\tif (tokensBefore <= 0) {\n\t\treturn ratio;\n\t}\n\n\tconst savedRatio = savedTokens / tokensBefore;\n\tif (savedRatio > HIGH_YIELD_SAVING_RATIO) {\n\t\treturn clampThresholdRatio(ratio - YIELD_ADJUSTMENT_RATIO);\n\t}\n\tif (savedRatio < LOW_YIELD_SAVING_RATIO) {\n\t\treturn clampThresholdRatio(ratio + YIELD_ADJUSTMENT_RATIO);\n\t}\n\treturn ratio;\n}\n\nfunction adjustEffectiveThresholdRatio(ratio: number, savedTokens: number, tokensBefore: number): number {\n\tif (tokensBefore <= 0) {\n\t\treturn ratio;\n\t}\n\n\tconst savedRatio = savedTokens / tokensBefore;\n\tif (savedRatio > HIGH_YIELD_SAVING_RATIO) {\n\t\treturn ratio - YIELD_ADJUSTMENT_RATIO;\n\t}\n\tif (savedRatio < LOW_YIELD_SAVING_RATIO) {\n\t\treturn ratio + YIELD_ADJUSTMENT_RATIO;\n\t}\n\treturn ratio;\n}\n\nexport function computeAdaptiveThresholdRatio(contextWindow: number, priorCompactionSavedTokens?: number): number {\n\tlet ratio: number;\n\tif (!(contextWindow > 0)) {\n\t\tratio = 0.5;\n\t} else if (contextWindow <= 16_000) {\n\t\tratio = 0.45;\n\t} else if (contextWindow <= 32_000) {\n\t\tratio = 0.5;\n\t} else if (contextWindow <= 64_000) {\n\t\tratio = 0.55;\n\t} else if (contextWindow <= 128_000) {\n\t\tratio = 0.6;\n\t} else {\n\t\tratio = 0.65;\n\t}\n\n\tif (priorCompactionSavedTokens === undefined) {\n\t\treturn ratio;\n\t}\n\n\treturn adjustThresholdRatio(ratio, priorCompactionSavedTokens, contextWindow);\n}\n\nexport function computeEffectiveThreshold(contextWindow: number, lastYield?: CompactionYield | number): number {\n\tif (typeof lastYield === \"number\") {\n\t\treturn Math.max(contextWindow, lastYield);\n\t}\n\n\tlet ratio = computeAdaptiveThresholdRatio(contextWindow);\n\tif (lastYield) {\n\t\tratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore);\n\t}\n\treturn clampThresholdRatio(ratio);\n}\n\nexport function computeEffectiveKeepRecentTokens(\n\tsetting: number,\n\tcontextWindow: number,\n\tthresholdRatio: number,\n\tmargin = 0.05,\n): number {\n\tconst capped = Math.floor(contextWindow * (1 - thresholdRatio - margin));\n\treturn Math.min(setting, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));\n}\n\nexport function shouldStartSpeculativeCompaction(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\tsettings: CompactionSettings,\n\tlastYield?: CompactionYield,\n): boolean {\n\tif (settings.speculativeEnabled === false || usage.tokens === null || contextWindow <= 0) {\n\t\treturn false;\n\t}\n\n\tconst fraction = settings.speculativeFraction ?? SPECULATIVE_FRACTION;\n\treturn usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield) * fraction;\n}\n\nexport function isAtHardLimit(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\treserveTokens: number,\n\tadditionalTokens = 0,\n): boolean {\n\treturn usage.tokens !== null && usage.tokens + additionalTokens + reserveTokens >= contextWindow;\n}\n\nexport function shouldTriggerCompaction(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\tsettings: CompactionSettings,\n\tlastYield?: CompactionYield,\n): boolean {\n\tif (!settings.enabled || usage.tokens === null || contextWindow <= 0) {\n\t\treturn false;\n\t}\n\n\treturn usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield);\n}\n"]}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/policy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CompactionSettings } from \"../../../compaction/index.ts\";\nimport type { ContextUsage } from \"../../types.ts\";\n\nconst MIN_ADAPTIVE_THRESHOLD_RATIO = 0.4;\nconst MAX_ADAPTIVE_THRESHOLD_RATIO = 0.85;\nconst HIGH_YIELD_SAVING_RATIO = 0.5;\nconst LOW_YIELD_SAVING_RATIO = 0.1;\nconst YIELD_ADJUSTMENT_RATIO = 0.05;\nconst MIN_EFFECTIVE_KEEP_RECENT_TOKENS = 1024;\nconst RESERVE_WINDOW_FRACTION = 0.04;\nconst MAX_SCALED_RESERVE_TOKENS = 49_152;\nconst KEEP_RECENT_WINDOW_FRACTION = 0.05;\nconst MAX_SCALED_KEEP_RECENT_TOKENS = 60_000;\n\nexport const SPECULATIVE_FRACTION = 0.75;\n\nexport interface CompactionYield {\n\tsavedTokens: number;\n\ttokensBefore: number;\n}\n\nfunction clampThresholdRatio(ratio: number): number {\n\treturn Math.min(MAX_ADAPTIVE_THRESHOLD_RATIO, Math.max(MIN_ADAPTIVE_THRESHOLD_RATIO, ratio));\n}\n\nfunction adjustThresholdRatio(ratio: number, savedTokens: number, contextWindow: number): number {\n\tif (contextWindow <= 0) {\n\t\treturn ratio;\n\t}\n\n\tconst savedRatio = savedTokens / contextWindow;\n\tif (savedRatio > HIGH_YIELD_SAVING_RATIO) {\n\t\treturn clampThresholdRatio(ratio - YIELD_ADJUSTMENT_RATIO);\n\t}\n\tif (savedRatio < LOW_YIELD_SAVING_RATIO) {\n\t\treturn Math.min(baseThresholdRatioForWindow(contextWindow), clampThresholdRatio(ratio + YIELD_ADJUSTMENT_RATIO));\n\t}\n\treturn ratio;\n}\n\nfunction adjustEffectiveThresholdRatio(\n\tratio: number,\n\tsavedTokens: number,\n\ttokensBefore: number,\n\tcontextWindow: number,\n): number {\n\tif (tokensBefore <= 0) {\n\t\treturn ratio;\n\t}\n\n\tconst savedRatio = savedTokens / tokensBefore;\n\tif (savedRatio > HIGH_YIELD_SAVING_RATIO) {\n\t\treturn ratio - YIELD_ADJUSTMENT_RATIO;\n\t}\n\tif (savedRatio < LOW_YIELD_SAVING_RATIO) {\n\t\treturn Math.min(baseThresholdRatioForWindow(contextWindow), ratio + YIELD_ADJUSTMENT_RATIO);\n\t}\n\treturn ratio;\n}\n\nexport function baseThresholdRatioForWindow(contextWindow: number): number {\n\tif (!(contextWindow > 0)) {\n\t\treturn 0.5;\n\t}\n\tif (contextWindow <= 16_000) {\n\t\treturn 0.45;\n\t}\n\tif (contextWindow <= 32_000) {\n\t\treturn 0.5;\n\t}\n\tif (contextWindow <= 64_000) {\n\t\treturn 0.55;\n\t}\n\tif (contextWindow <= 128_000) {\n\t\treturn 0.6;\n\t}\n\tif (contextWindow <= 512_000) {\n\t\treturn 0.7;\n\t}\n\treturn 0.8;\n}\n\nexport function resolveReserveTokens(contextWindow: number, configuredReserve: number): number {\n\treturn Math.max(\n\t\tconfiguredReserve,\n\t\tMath.min(Math.floor(RESERVE_WINDOW_FRACTION * contextWindow), MAX_SCALED_RESERVE_TOKENS),\n\t);\n}\n\nexport function computeAdaptiveThresholdRatio(contextWindow: number, priorCompactionSavedTokens?: number): number {\n\tconst ratio = baseThresholdRatioForWindow(contextWindow);\n\n\tif (priorCompactionSavedTokens === undefined) {\n\t\treturn ratio;\n\t}\n\n\treturn adjustThresholdRatio(ratio, priorCompactionSavedTokens, contextWindow);\n}\n\nexport function computeEffectiveThreshold(contextWindow: number, lastYield?: CompactionYield): number {\n\tlet ratio = computeAdaptiveThresholdRatio(contextWindow);\n\tif (lastYield) {\n\t\tratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore, contextWindow);\n\t}\n\treturn clampThresholdRatio(ratio);\n}\n\nexport function computeEffectiveKeepRecentTokens(\n\tsetting: number,\n\tcontextWindow: number,\n\tthresholdRatio: number,\n\tmargin = 0.05,\n): number {\n\tconst scaled =\n\t\tcontextWindow > 409_600 && setting >= 10_000\n\t\t\t? Math.max(\n\t\t\t\t\tsetting,\n\t\t\t\t\tMath.min(Math.floor(KEEP_RECENT_WINDOW_FRACTION * contextWindow), MAX_SCALED_KEEP_RECENT_TOKENS),\n\t\t\t\t)\n\t\t\t: setting;\n\tconst capped = Math.floor(contextWindow * (1 - thresholdRatio - margin));\n\treturn Math.min(scaled, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));\n}\n\nexport function shouldStartSpeculativeCompaction(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\tsettings: CompactionSettings,\n\tlastYield?: CompactionYield,\n\tleadTokens?: number,\n): boolean {\n\tif (settings.speculativeEnabled === false || usage.tokens === null || contextWindow <= 0) {\n\t\treturn false;\n\t}\n\n\tif (typeof leadTokens === \"number\" && Number.isFinite(leadTokens) && leadTokens > 0) {\n\t\tconst leadTrigger = Math.max(0, contextWindow * computeEffectiveThreshold(contextWindow, lastYield) - leadTokens);\n\t\treturn usage.tokens >= leadTrigger;\n\t}\n\n\tconst fraction = settings.speculativeFraction ?? SPECULATIVE_FRACTION;\n\treturn usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield) * fraction;\n}\n\nexport function resolveEffectiveReserveTokens(\n\tcontextWindow: number,\n\tconfiguredReserve: number,\n\treserveScalingEnabled = true,\n): number {\n\treturn reserveScalingEnabled ? resolveReserveTokens(contextWindow, configuredReserve) : configuredReserve;\n}\n\nexport function isAtHardLimit(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\treserveTokens: number,\n\tadditionalTokens = 0,\n): boolean {\n\treturn usage.tokens !== null && usage.tokens + additionalTokens + reserveTokens >= contextWindow;\n}\n\nexport function shouldTriggerCompaction(\n\tusage: ContextUsage,\n\tcontextWindow: number,\n\tsettings: CompactionSettings,\n\tlastYield?: CompactionYield,\n): boolean {\n\tif (!settings.enabled || usage.tokens === null || contextWindow <= 0) {\n\t\treturn false;\n\t}\n\n\treturn usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"retained-message-safety.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/retained-message-safety.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAmHlE,yGAAyG;AACzG,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAmD1E"}
1
+ {"version":3,"file":"retained-message-safety.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/retained-message-safety.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAgJlE,yGAAyG;AACzG,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAmD1E"}
@@ -25,7 +25,18 @@ function isUsage(value) {
25
25
  return ((value.cacheWrite1h === undefined || isFiniteNumber(value.cacheWrite1h)) &&
26
26
  (value.reasoning === undefined || isFiniteNumber(value.reasoning)));
27
27
  }
28
- function hasSafeAssistantContent(content) {
28
+ const base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
29
+ /** Validate an opaque provider signature without exposing or logging content. */
30
+ function isValidOpaqueSignature(sig) {
31
+ return typeof sig === "string" && sig.length > 0 && sig.length <= 65_536;
32
+ }
33
+ /** Gemini signatures are base64; other providers use bounded opaque strings. */
34
+ function isValidProviderSignature(sig, providerIsGoogle) {
35
+ if (!isValidOpaqueSignature(sig))
36
+ return false;
37
+ return !providerIsGoogle || (sig.length % 4 === 0 && base64SignaturePattern.test(sig));
38
+ }
39
+ function hasSafeAssistantContent(content, providerIsGoogle) {
29
40
  if (!Array.isArray(content))
30
41
  return false;
31
42
  for (const block of content) {
@@ -33,16 +44,23 @@ function hasSafeAssistantContent(content) {
33
44
  return false;
34
45
  switch (block.type) {
35
46
  case "text":
36
- if (typeof block.text !== "string" || block.textSignature !== undefined)
47
+ if (typeof block.text !== "string")
37
48
  return false;
49
+ if (block.textSignature !== undefined && !isValidProviderSignature(block.textSignature, providerIsGoogle)) {
50
+ return false;
51
+ }
38
52
  break;
39
53
  case "thinking":
40
54
  if (typeof block.thinking !== "string" ||
41
55
  (block.startedAt !== undefined && !isFiniteNumber(block.startedAt)) ||
42
56
  (block.endedAt !== undefined && !isFiniteNumber(block.endedAt)) ||
43
- (block.redacted !== undefined && typeof block.redacted !== "boolean") ||
44
- block.redacted === true ||
45
- block.thinkingSignature !== undefined) {
57
+ (block.redacted !== undefined && typeof block.redacted !== "boolean")) {
58
+ return false;
59
+ }
60
+ // Redacted thinking requires a bounded opaque signature for replay.
61
+ if ((block.thinkingSignature !== undefined &&
62
+ !isValidProviderSignature(block.thinkingSignature, providerIsGoogle)) ||
63
+ (block.redacted === true && !isValidOpaqueSignature(block.thinkingSignature))) {
46
64
  return false;
47
65
  }
48
66
  break;
@@ -51,8 +69,11 @@ function hasSafeAssistantContent(content) {
51
69
  typeof block.name !== "string" ||
52
70
  !isRecord(block.arguments) ||
53
71
  (block.incomplete !== undefined && block.incomplete !== true) ||
54
- (block.errorMessage !== undefined && typeof block.errorMessage !== "string") ||
55
- block.thoughtSignature !== undefined) {
72
+ (block.errorMessage !== undefined && typeof block.errorMessage !== "string")) {
73
+ return false;
74
+ }
75
+ if (block.thoughtSignature !== undefined &&
76
+ !isValidProviderSignature(block.thoughtSignature, providerIsGoogle)) {
56
77
  return false;
57
78
  }
58
79
  break;
@@ -63,6 +84,8 @@ function hasSafeAssistantContent(content) {
63
84
  return true;
64
85
  }
65
86
  function hasSafeAssistantEnvelope(message) {
87
+ const provider = typeof message.provider === "string" ? message.provider : "";
88
+ const providerIsGoogle = provider === "google" || provider === "google-vertex";
66
89
  const stopReason = message.stopReason;
67
90
  const stopDetails = message.stopDetails;
68
91
  const safeStopDetails = stopDetails === undefined ||
@@ -87,7 +110,7 @@ function hasSafeAssistantEnvelope(message) {
87
110
  (message.diagnostics === undefined || Array.isArray(message.diagnostics)) &&
88
111
  (message.errorMessage === undefined || typeof message.errorMessage === "string") &&
89
112
  (message.rawStopReason === undefined || typeof message.rawStopReason === "string") &&
90
- hasSafeAssistantContent(message.content));
113
+ hasSafeAssistantContent(message.content, providerIsGoogle));
91
114
  }
92
115
  function hasSafeToolResultEnvelope(message) {
93
116
  return (typeof message.toolCallId === "string" &&
@@ -1 +1 @@
1
- {"version":3,"file":"retained-message-safety.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/retained-message-safety.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction hasTextOnlyContent(content: unknown, allowString: boolean): boolean {\n\tif (typeof content === \"string\") return allowString;\n\tif (!Array.isArray(content)) return false;\n\treturn content.every((block) => isRecord(block) && block.type === \"text\" && typeof block.text === \"string\");\n}\n\nfunction isUsage(value: unknown): boolean {\n\tif (!isRecord(value) || !isRecord(value.cost)) return false;\n\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"totalTokens\"] as const) {\n\t\tif (!isFiniteNumber(value[field])) return false;\n\t}\n\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"total\"] as const) {\n\t\tif (!isFiniteNumber(value.cost[field])) return false;\n\t}\n\treturn (\n\t\t(value.cacheWrite1h === undefined || isFiniteNumber(value.cacheWrite1h)) &&\n\t\t(value.reasoning === undefined || isFiniteNumber(value.reasoning))\n\t);\n}\n\nfunction hasSafeAssistantContent(content: unknown): boolean {\n\tif (!Array.isArray(content)) return false;\n\tfor (const block of content) {\n\t\tif (!isRecord(block) || typeof block.type !== \"string\") return false;\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tif (typeof block.text !== \"string\" || block.textSignature !== undefined) return false;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof block.thinking !== \"string\" ||\n\t\t\t\t\t(block.startedAt !== undefined && !isFiniteNumber(block.startedAt)) ||\n\t\t\t\t\t(block.endedAt !== undefined && !isFiniteNumber(block.endedAt)) ||\n\t\t\t\t\t(block.redacted !== undefined && typeof block.redacted !== \"boolean\") ||\n\t\t\t\t\tblock.redacted === true ||\n\t\t\t\t\tblock.thinkingSignature !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"toolCall\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof block.id !== \"string\" ||\n\t\t\t\t\ttypeof block.name !== \"string\" ||\n\t\t\t\t\t!isRecord(block.arguments) ||\n\t\t\t\t\t(block.incomplete !== undefined && block.incomplete !== true) ||\n\t\t\t\t\t(block.errorMessage !== undefined && typeof block.errorMessage !== \"string\") ||\n\t\t\t\t\tblock.thoughtSignature !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction hasSafeAssistantEnvelope(message: Record<string, unknown>): boolean {\n\tconst stopReason = message.stopReason;\n\tconst stopDetails = message.stopDetails;\n\tconst safeStopDetails =\n\t\tstopDetails === undefined ||\n\t\t(isRecord(stopDetails) &&\n\t\t\t(stopDetails.type === \"sensitive\" ||\n\t\t\t\t(stopDetails.type === \"refusal\" &&\n\t\t\t\t\t(stopDetails.explanation === undefined || typeof stopDetails.explanation === \"string\"))));\n\treturn (\n\t\ttypeof message.api === \"string\" &&\n\t\ttypeof message.provider === \"string\" &&\n\t\ttypeof message.model === \"string\" &&\n\t\tisUsage(message.usage) &&\n\t\t(stopReason === \"pending\" ||\n\t\t\tstopReason === \"stop\" ||\n\t\t\tstopReason === \"length\" ||\n\t\t\tstopReason === \"toolUse\" ||\n\t\t\tstopReason === \"error\" ||\n\t\t\tstopReason === \"aborted\") &&\n\t\tsafeStopDetails &&\n\t\tisFiniteNumber(message.timestamp) &&\n\t\t(message.responseModel === undefined || typeof message.responseModel === \"string\") &&\n\t\t(message.responseId === undefined || typeof message.responseId === \"string\") &&\n\t\t(message.diagnostics === undefined || Array.isArray(message.diagnostics)) &&\n\t\t(message.errorMessage === undefined || typeof message.errorMessage === \"string\") &&\n\t\t(message.rawStopReason === undefined || typeof message.rawStopReason === \"string\") &&\n\t\thasSafeAssistantContent(message.content)\n\t);\n}\n\nfunction hasSafeToolResultEnvelope(message: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof message.toolCallId === \"string\" &&\n\t\tmessage.toolCallId.length > 0 &&\n\t\ttypeof message.toolName === \"string\" &&\n\t\tmessage.toolName.length > 0 &&\n\t\thasTextOnlyContent(message.content, false) &&\n\t\ttypeof message.isError === \"boolean\" &&\n\t\tisFiniteNumber(message.timestamp) &&\n\t\t(message.usage === undefined || isUsage(message.usage)) &&\n\t\t(message.addedToolNames === undefined ||\n\t\t\t(Array.isArray(message.addedToolNames) && message.addedToolNames.every((name) => typeof name === \"string\")))\n\t);\n}\n\n/** Reject any retained message that cannot be safely replayed through normalized provider conversion. */\nexport function hasUnsafeRetainedContent(messages: AgentMessage[]): boolean {\n\tfor (const value of messages as unknown[]) {\n\t\tif (!isRecord(value) || typeof value.role !== \"string\") return true;\n\t\tswitch (value.role) {\n\t\t\tcase \"user\":\n\t\t\t\tif (!isFiniteNumber(value.timestamp) || !hasTextOnlyContent(value.content, true)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"assistant\":\n\t\t\t\tif (!hasSafeAssistantEnvelope(value)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"toolResult\":\n\t\t\t\tif (!hasSafeToolResultEnvelope(value)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"custom\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.customType !== \"string\" ||\n\t\t\t\t\ttypeof value.display !== \"boolean\" ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp) ||\n\t\t\t\t\t!hasTextOnlyContent(value.content, true)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"bashExecution\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.command !== \"string\" ||\n\t\t\t\t\ttypeof value.output !== \"string\" ||\n\t\t\t\t\t(value.exitCode !== undefined && !isFiniteNumber(value.exitCode)) ||\n\t\t\t\t\ttypeof value.cancelled !== \"boolean\" ||\n\t\t\t\t\ttypeof value.truncated !== \"boolean\" ||\n\t\t\t\t\t(value.fullOutputPath !== undefined && typeof value.fullOutputPath !== \"string\") ||\n\t\t\t\t\t(value.excludeFromContext !== undefined && typeof value.excludeFromContext !== \"boolean\") ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"compactionSummary\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.summary !== \"string\" ||\n\t\t\t\t\t!isFiniteNumber(value.tokensBefore) ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n"]}
1
+ {"version":3,"file":"retained-message-safety.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/retained-message-safety.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction hasTextOnlyContent(content: unknown, allowString: boolean): boolean {\n\tif (typeof content === \"string\") return allowString;\n\tif (!Array.isArray(content)) return false;\n\treturn content.every((block) => isRecord(block) && block.type === \"text\" && typeof block.text === \"string\");\n}\n\nfunction isUsage(value: unknown): boolean {\n\tif (!isRecord(value) || !isRecord(value.cost)) return false;\n\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"totalTokens\"] as const) {\n\t\tif (!isFiniteNumber(value[field])) return false;\n\t}\n\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"total\"] as const) {\n\t\tif (!isFiniteNumber(value.cost[field])) return false;\n\t}\n\treturn (\n\t\t(value.cacheWrite1h === undefined || isFiniteNumber(value.cacheWrite1h)) &&\n\t\t(value.reasoning === undefined || isFiniteNumber(value.reasoning))\n\t);\n}\n\nconst base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;\n\n/** Validate an opaque provider signature without exposing or logging content. */\nfunction isValidOpaqueSignature(sig: unknown): sig is string {\n\treturn typeof sig === \"string\" && sig.length > 0 && sig.length <= 65_536;\n}\n\n/** Gemini signatures are base64; other providers use bounded opaque strings. */\nfunction isValidProviderSignature(sig: unknown, providerIsGoogle: boolean): sig is string {\n\tif (!isValidOpaqueSignature(sig)) return false;\n\treturn !providerIsGoogle || (sig.length % 4 === 0 && base64SignaturePattern.test(sig));\n}\n\nfunction hasSafeAssistantContent(content: unknown, providerIsGoogle: boolean): boolean {\n\tif (!Array.isArray(content)) return false;\n\tfor (const block of content) {\n\t\tif (!isRecord(block) || typeof block.type !== \"string\") return false;\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tif (typeof block.text !== \"string\") return false;\n\t\t\t\tif (block.textSignature !== undefined && !isValidProviderSignature(block.textSignature, providerIsGoogle)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"thinking\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof block.thinking !== \"string\" ||\n\t\t\t\t\t(block.startedAt !== undefined && !isFiniteNumber(block.startedAt)) ||\n\t\t\t\t\t(block.endedAt !== undefined && !isFiniteNumber(block.endedAt)) ||\n\t\t\t\t\t(block.redacted !== undefined && typeof block.redacted !== \"boolean\")\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Redacted thinking requires a bounded opaque signature for replay.\n\t\t\t\tif (\n\t\t\t\t\t(block.thinkingSignature !== undefined &&\n\t\t\t\t\t\t!isValidProviderSignature(block.thinkingSignature, providerIsGoogle)) ||\n\t\t\t\t\t(block.redacted === true && !isValidOpaqueSignature(block.thinkingSignature))\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"toolCall\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof block.id !== \"string\" ||\n\t\t\t\t\ttypeof block.name !== \"string\" ||\n\t\t\t\t\t!isRecord(block.arguments) ||\n\t\t\t\t\t(block.incomplete !== undefined && block.incomplete !== true) ||\n\t\t\t\t\t(block.errorMessage !== undefined && typeof block.errorMessage !== \"string\")\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tblock.thoughtSignature !== undefined &&\n\t\t\t\t\t!isValidProviderSignature(block.thoughtSignature, providerIsGoogle)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction hasSafeAssistantEnvelope(message: Record<string, unknown>): boolean {\n\tconst provider = typeof message.provider === \"string\" ? message.provider : \"\";\n\tconst providerIsGoogle = provider === \"google\" || provider === \"google-vertex\";\n\tconst stopReason = message.stopReason;\n\tconst stopDetails = message.stopDetails;\n\tconst safeStopDetails =\n\t\tstopDetails === undefined ||\n\t\t(isRecord(stopDetails) &&\n\t\t\t(stopDetails.type === \"sensitive\" ||\n\t\t\t\t(stopDetails.type === \"refusal\" &&\n\t\t\t\t\t(stopDetails.explanation === undefined || typeof stopDetails.explanation === \"string\"))));\n\treturn (\n\t\ttypeof message.api === \"string\" &&\n\t\ttypeof message.provider === \"string\" &&\n\t\ttypeof message.model === \"string\" &&\n\t\tisUsage(message.usage) &&\n\t\t(stopReason === \"pending\" ||\n\t\t\tstopReason === \"stop\" ||\n\t\t\tstopReason === \"length\" ||\n\t\t\tstopReason === \"toolUse\" ||\n\t\t\tstopReason === \"error\" ||\n\t\t\tstopReason === \"aborted\") &&\n\t\tsafeStopDetails &&\n\t\tisFiniteNumber(message.timestamp) &&\n\t\t(message.responseModel === undefined || typeof message.responseModel === \"string\") &&\n\t\t(message.responseId === undefined || typeof message.responseId === \"string\") &&\n\t\t(message.diagnostics === undefined || Array.isArray(message.diagnostics)) &&\n\t\t(message.errorMessage === undefined || typeof message.errorMessage === \"string\") &&\n\t\t(message.rawStopReason === undefined || typeof message.rawStopReason === \"string\") &&\n\t\thasSafeAssistantContent(message.content, providerIsGoogle)\n\t);\n}\n\nfunction hasSafeToolResultEnvelope(message: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof message.toolCallId === \"string\" &&\n\t\tmessage.toolCallId.length > 0 &&\n\t\ttypeof message.toolName === \"string\" &&\n\t\tmessage.toolName.length > 0 &&\n\t\thasTextOnlyContent(message.content, false) &&\n\t\ttypeof message.isError === \"boolean\" &&\n\t\tisFiniteNumber(message.timestamp) &&\n\t\t(message.usage === undefined || isUsage(message.usage)) &&\n\t\t(message.addedToolNames === undefined ||\n\t\t\t(Array.isArray(message.addedToolNames) && message.addedToolNames.every((name) => typeof name === \"string\")))\n\t);\n}\n\n/** Reject any retained message that cannot be safely replayed through normalized provider conversion. */\nexport function hasUnsafeRetainedContent(messages: AgentMessage[]): boolean {\n\tfor (const value of messages as unknown[]) {\n\t\tif (!isRecord(value) || typeof value.role !== \"string\") return true;\n\t\tswitch (value.role) {\n\t\t\tcase \"user\":\n\t\t\t\tif (!isFiniteNumber(value.timestamp) || !hasTextOnlyContent(value.content, true)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"assistant\":\n\t\t\t\tif (!hasSafeAssistantEnvelope(value)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"toolResult\":\n\t\t\t\tif (!hasSafeToolResultEnvelope(value)) return true;\n\t\t\t\tbreak;\n\t\t\tcase \"custom\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.customType !== \"string\" ||\n\t\t\t\t\ttypeof value.display !== \"boolean\" ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp) ||\n\t\t\t\t\t!hasTextOnlyContent(value.content, true)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"bashExecution\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.command !== \"string\" ||\n\t\t\t\t\ttypeof value.output !== \"string\" ||\n\t\t\t\t\t(value.exitCode !== undefined && !isFiniteNumber(value.exitCode)) ||\n\t\t\t\t\ttypeof value.cancelled !== \"boolean\" ||\n\t\t\t\t\ttypeof value.truncated !== \"boolean\" ||\n\t\t\t\t\t(value.fullOutputPath !== undefined && typeof value.fullOutputPath !== \"string\") ||\n\t\t\t\t\t(value.excludeFromContext !== undefined && typeof value.excludeFromContext !== \"boolean\") ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"compactionSummary\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof value.summary !== \"string\" ||\n\t\t\t\t\t!isFiniteNumber(value.tokensBefore) ||\n\t\t\t\t\t!isFiniteNumber(value.timestamp)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export declare const SPECULATION_LEAD_MIN_TOKENS = 8192;
2
+ export declare const SPECULATION_LEAD_MAX_TOKENS = 32768;
3
+ export declare function resolveSpeculationLeadTokens(thresholdTokens: number, configuredLeadTokens?: number): number;
4
+ export declare const WARM_GENERATION_FLOOR_RATIO = 0.5;
5
+ export declare function resolveGraceBandCapTokens(thresholdTokens: number, leadTokens: number, contextWindow: number, reserveTokens: number): number;
6
+ export declare function isWithinGraceBand(contextTokens: number, thresholdTokens: number, leadTokens: number, contextWindow: number, reserveTokens: number): boolean;
7
+ export declare function isWarmResultStale(armedAtTokens: number, currentTokens: number, keepRecentTokens: number): boolean;
8
+ //# sourceMappingURL=speculation-lead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculation-lead.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculation-lead.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAEjD,wBAAgB,4BAA4B,CAAC,eAAe,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3G;AAED,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACnB,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAChC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACnB,OAAO,CAET;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAEjH"}
@@ -0,0 +1,17 @@
1
+ export const SPECULATION_LEAD_MIN_TOKENS = 8192;
2
+ export const SPECULATION_LEAD_MAX_TOKENS = 32768;
3
+ export function resolveSpeculationLeadTokens(thresholdTokens, configuredLeadTokens) {
4
+ const requestedLeadTokens = configuredLeadTokens ?? Math.floor(thresholdTokens * 0.125);
5
+ return Math.min(SPECULATION_LEAD_MAX_TOKENS, Math.max(SPECULATION_LEAD_MIN_TOKENS, requestedLeadTokens));
6
+ }
7
+ export const WARM_GENERATION_FLOOR_RATIO = 0.5;
8
+ export function resolveGraceBandCapTokens(thresholdTokens, leadTokens, contextWindow, reserveTokens) {
9
+ return Math.min(thresholdTokens + leadTokens, contextWindow - reserveTokens);
10
+ }
11
+ export function isWithinGraceBand(contextTokens, thresholdTokens, leadTokens, contextWindow, reserveTokens) {
12
+ return contextTokens < resolveGraceBandCapTokens(thresholdTokens, leadTokens, contextWindow, reserveTokens);
13
+ }
14
+ export function isWarmResultStale(armedAtTokens, currentTokens, keepRecentTokens) {
15
+ return currentTokens - armedAtTokens > Math.max(keepRecentTokens, 8192);
16
+ }
17
+ //# sourceMappingURL=speculation-lead.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculation-lead.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculation-lead.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAChD,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEjD,MAAM,UAAU,4BAA4B,CAAC,eAAuB,EAAE,oBAA6B;IAClG,MAAM,mBAAmB,GAAG,oBAAoB,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAC1G,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C,MAAM,UAAU,yBAAyB,CACxC,eAAuB,EACvB,UAAkB,EAClB,aAAqB,EACrB,aAAqB;IAErB,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,UAAU,EAAE,aAAa,GAAG,aAAa,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,aAAqB,EACrB,eAAuB,EACvB,UAAkB,EAClB,aAAqB,EACrB,aAAqB;IAErB,OAAO,aAAa,GAAG,yBAAyB,CAAC,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAC7G,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,aAAqB,EAAE,aAAqB,EAAE,gBAAwB;IACvG,OAAO,aAAa,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;AACzE,CAAC","sourcesContent":["export const SPECULATION_LEAD_MIN_TOKENS = 8192;\nexport const SPECULATION_LEAD_MAX_TOKENS = 32768;\n\nexport function resolveSpeculationLeadTokens(thresholdTokens: number, configuredLeadTokens?: number): number {\n\tconst requestedLeadTokens = configuredLeadTokens ?? Math.floor(thresholdTokens * 0.125);\n\treturn Math.min(SPECULATION_LEAD_MAX_TOKENS, Math.max(SPECULATION_LEAD_MIN_TOKENS, requestedLeadTokens));\n}\n\nexport const WARM_GENERATION_FLOOR_RATIO = 0.5;\n\nexport function resolveGraceBandCapTokens(\n\tthresholdTokens: number,\n\tleadTokens: number,\n\tcontextWindow: number,\n\treserveTokens: number,\n): number {\n\treturn Math.min(thresholdTokens + leadTokens, contextWindow - reserveTokens);\n}\n\nexport function isWithinGraceBand(\n\tcontextTokens: number,\n\tthresholdTokens: number,\n\tleadTokens: number,\n\tcontextWindow: number,\n\treserveTokens: number,\n): boolean {\n\treturn contextTokens < resolveGraceBandCapTokens(thresholdTokens, leadTokens, contextWindow, reserveTokens);\n}\n\nexport function isWarmResultStale(armedAtTokens: number, currentTokens: number, keepRecentTokens: number): boolean {\n\treturn currentTokens - armedAtTokens > Math.max(keepRecentTokens, 8192);\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type { CompactionResult } from "../../../compaction/index.ts";
2
+ import type { SpeculativeCompactionSnapshot } from "./speculative.ts";
3
+ export interface SpeculativeJob {
4
+ generation: number;
5
+ snapshot: SpeculativeCompactionSnapshot;
6
+ controller: AbortController;
7
+ promise: Promise<CompactionResult | undefined>;
8
+ failure: Promise<Error | undefined>;
9
+ armedAtTokens: number;
10
+ completed: boolean;
11
+ }
12
+ export declare function trackSpeculativeJob(input: {
13
+ generation: number;
14
+ snapshot: SpeculativeCompactionSnapshot;
15
+ controller: AbortController;
16
+ settled: Promise<{
17
+ result: CompactionResult | undefined;
18
+ error: Error | undefined;
19
+ }>;
20
+ armedAtTokens: number;
21
+ }): SpeculativeJob;
22
+ //# sourceMappingURL=speculative-job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculative-job.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative-job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,6BAA6B,CAAC;IACxC,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,6BAA6B,CAAC;IACxC,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IACrF,aAAa,EAAE,MAAM,CAAC;CACtB,GAAG,cAAc,CAcjB"}
@@ -0,0 +1,16 @@
1
+ export function trackSpeculativeJob(input) {
2
+ const job = {
3
+ generation: input.generation,
4
+ snapshot: input.snapshot,
5
+ controller: input.controller,
6
+ promise: input.settled.then(({ result }) => result),
7
+ failure: input.settled.then(({ error }) => error),
8
+ armedAtTokens: input.armedAtTokens,
9
+ completed: false,
10
+ };
11
+ void input.settled.then(() => {
12
+ job.completed = true;
13
+ });
14
+ return job;
15
+ }
16
+ //# sourceMappingURL=speculative-job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculative-job.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative-job.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,mBAAmB,CAAC,KAMnC;IACA,MAAM,GAAG,GAAmB;QAC3B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC;QACnD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC;QACjD,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS,EAAE,KAAK;KAChB,CAAC;IACF,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;QAC5B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;IACtB,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACZ,CAAC","sourcesContent":["import type { CompactionResult } from \"../../../compaction/index.ts\";\nimport type { SpeculativeCompactionSnapshot } from \"./speculative.ts\";\n\nexport interface SpeculativeJob {\n\tgeneration: number;\n\tsnapshot: SpeculativeCompactionSnapshot;\n\tcontroller: AbortController;\n\tpromise: Promise<CompactionResult | undefined>;\n\tfailure: Promise<Error | undefined>;\n\tarmedAtTokens: number;\n\tcompleted: boolean;\n}\n\nexport function trackSpeculativeJob(input: {\n\tgeneration: number;\n\tsnapshot: SpeculativeCompactionSnapshot;\n\tcontroller: AbortController;\n\tsettled: Promise<{ result: CompactionResult | undefined; error: Error | undefined }>;\n\tarmedAtTokens: number;\n}): SpeculativeJob {\n\tconst job: SpeculativeJob = {\n\t\tgeneration: input.generation,\n\t\tsnapshot: input.snapshot,\n\t\tcontroller: input.controller,\n\t\tpromise: input.settled.then(({ result }) => result),\n\t\tfailure: input.settled.then(({ error }) => error),\n\t\tarmedAtTokens: input.armedAtTokens,\n\t\tcompleted: false,\n\t};\n\tvoid input.settled.then(() => {\n\t\tjob.completed = true;\n\t});\n\treturn job;\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
+ import { type AssistantMessage, type Message, type ProviderHeaders } from "@earendil-works/pi-ai";
3
+ import type { buildPrompt } from "./prompts.ts";
4
+ import type { SpeculativeCompactionContext, SpeculativeCompactionSnapshot } from "./speculative.ts";
5
+ type CompactionProgressCallback = (delta: string) => void;
6
+ export declare function getSummaryText(message: Message): string;
7
+ export declare function isAssistantMessage(message: Message): message is AssistantMessage;
8
+ export declare function generateSummaryMessage(options: {
9
+ context: SpeculativeCompactionContext;
10
+ messages: AgentMessage[];
11
+ onProgress?: CompactionProgressCallback;
12
+ prompt: ReturnType<typeof buildPrompt>;
13
+ signal?: AbortSignal;
14
+ snapshot: SpeculativeCompactionSnapshot;
15
+ auth: {
16
+ apiKey?: string;
17
+ headers?: ProviderHeaders;
18
+ extraBody?: Record<string, unknown>;
19
+ };
20
+ }): Promise<Message | undefined>;
21
+ export {};
22
+ //# sourceMappingURL=speculative-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculative-summary.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative-summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EACN,KAAK,gBAAgB,EAGrB,KAAK,OAAO,EAEZ,KAAK,eAAe,EAIpB,MAAM,uBAAuB,CAAC;AAQ/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,4BAA4B,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAKpG,KAAK,0BAA0B,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAqC1D,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CASvD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAEhF;AAkBD,wBAAsB,sBAAsB,CAAC,OAAO,EAAE;IACrD,OAAO,EAAE,4BAA4B,CAAC;IACtC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,6BAA6B,CAAC;IACxC,IAAI,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,eAAe,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;CACF,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CA8D/B"}
@@ -0,0 +1,131 @@
1
+ import { sanitizeAnthropicToolPairs as sanitizeAnthropicPayload, } from "@earendil-works/pi-ai";
2
+ import { stream } from "@earendil-works/pi-ai/compat";
3
+ import { consumeStreamWithIdleTimeout, DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS, DEFAULT_SUMMARIZATION_MAX_DURATION_MS, } from "../../../compaction/stream-watchdog.js";
4
+ import { convertToLlm } from "../../../messages.js";
5
+ import { repairOrphanedToolResults } from "./repair-tool-pairs.js";
6
+ import { normalizeSummarizationTurnOrder } from "./summarization-turn-order.js";
7
+ const SUMMARY_TOKEN_HEADROOM = 32_768;
8
+ const SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;
9
+ function summaryMaxTokens(model, contextWindow) {
10
+ const headroom = model.maxTokens > 0 ? Math.min(SUMMARY_TOKEN_HEADROOM, model.maxTokens) : SUMMARY_TOKEN_HEADROOM;
11
+ if (contextWindow > 0) {
12
+ return Math.min(headroom, Math.floor(contextWindow * SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO));
13
+ }
14
+ return headroom;
15
+ }
16
+ /**
17
+ * Reasoning override for summarization requests. Compaction must be fast: a
18
+ * summarization request that inherits the provider's default reasoning mode
19
+ * burns its latency (and output budget) on invisible thinking before emitting
20
+ * the summary. Disable or minimize reasoning per wire family; adapters ignore
21
+ * options their provider does not support. Mirrors how OpenAI Codex keeps its
22
+ * compaction turn cheap.
23
+ */
24
+ function summarizationReasoningOptions(model) {
25
+ if (!model.reasoning)
26
+ return {};
27
+ if (model.api === "anthropic-messages")
28
+ return { thinkingEnabled: false };
29
+ const reasoningEffort = ["low", "medium", "high"].find((level) => model.thinkingLevelMap?.[level] !== null);
30
+ if (!reasoningEffort)
31
+ return {};
32
+ switch (model.api) {
33
+ case "openai-responses":
34
+ case "openai-codex-responses":
35
+ case "azure-openai-responses":
36
+ return { reasoningEffort, reasoningSummary: null };
37
+ case "openai-completions":
38
+ return { reasoningEffort };
39
+ default:
40
+ return {};
41
+ }
42
+ }
43
+ export function getSummaryText(message) {
44
+ const content = Array.isArray(message.content)
45
+ ? message.content
46
+ : [{ type: "text", text: message.content }];
47
+ return content
48
+ .filter((content) => content.type === "text")
49
+ .map((content) => content.text)
50
+ .join("\n")
51
+ .trim();
52
+ }
53
+ export function isAssistantMessage(message) {
54
+ return message.role === "assistant" && "stopReason" in message;
55
+ }
56
+ /**
57
+ * Providers registered through `pi.registerProvider()` (claude-sdk-oauth, Kiro, any
58
+ * extension provider) exist only in Senpi's ModelRuntime, never in compat's builtin
59
+ * api-registry, which rejects their api id outright. Dispatch through the runtime
60
+ * whenever it is reachable and keep compat for contexts constructed without a registry.
61
+ */
62
+ function summarizationStream(context, model, requestContext, options) {
63
+ const runtime = context.modelRegistry?.modelRuntime;
64
+ return runtime ? runtime.stream(model, requestContext, options) : stream(model, requestContext, options);
65
+ }
66
+ export async function generateSummaryMessage(options) {
67
+ // Send the conversation as native LLM messages with the summarization
68
+ // instruction as a trailing user message, mirroring normal agent traffic.
69
+ // A single serialized `<conversation>` text dump of a large session is
70
+ // deterministically refused by Anthropic's anti-distillation classifier
71
+ // ("reverse engineering or duplicating model outputs"), while the same
72
+ // content as native blocks with the agent's system prompt and tools passes.
73
+ // Request-local controller: the idle watchdog must be able to tear down a
74
+ // stalled summarization request without aborting the caller's own signal.
75
+ const requestController = new AbortController();
76
+ const onCallerAbort = () => requestController.abort(options.signal?.reason);
77
+ if (options.signal) {
78
+ if (options.signal.aborted)
79
+ onCallerAbort();
80
+ else
81
+ options.signal.addEventListener("abort", onCallerAbort, { once: true });
82
+ }
83
+ try {
84
+ const requestMessages = [
85
+ ...options.messages,
86
+ {
87
+ role: "user",
88
+ content: [{ type: "text", text: options.prompt.user }],
89
+ timestamp: Date.now(),
90
+ },
91
+ ];
92
+ const providerRequest = await options.context.prepareProviderRequest?.(requestMessages);
93
+ const requestContext = {
94
+ systemPrompt: options.snapshot.systemPrompt ?? options.prompt.system,
95
+ messages: repairOrphanedToolResults(normalizeSummarizationTurnOrder(convertToLlm(providerRequest?.messages ?? requestMessages))),
96
+ ...(options.snapshot.tools && options.snapshot.tools.length > 0 ? { tools: options.snapshot.tools } : {}),
97
+ };
98
+ const headers = providerRequest
99
+ ? await providerRequest.transformHeaders(options.auth.headers ?? {})
100
+ : options.auth.headers;
101
+ const responseStream = summarizationStream(options.context, options.snapshot.model, requestContext, {
102
+ apiKey: options.auth.apiKey,
103
+ headers,
104
+ extraBody: options.auth.extraBody,
105
+ onPayload: async (payload, model) => {
106
+ const sanitized = model.api === "anthropic-messages" ? sanitizeAnthropicPayload(payload) : payload;
107
+ return providerRequest ? await providerRequest.transformPayload(sanitized) : sanitized;
108
+ },
109
+ maxTokens: summaryMaxTokens(options.snapshot.model, options.snapshot.contextWindow),
110
+ signal: requestController.signal,
111
+ ...summarizationReasoningOptions(options.snapshot.model),
112
+ });
113
+ await consumeStreamWithIdleTimeout(responseStream, {
114
+ idleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,
115
+ maxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,
116
+ abort: () => requestController.abort(),
117
+ signal: options.signal,
118
+ onEvent: (event) => {
119
+ if (event.type === "text_delta" && event.delta) {
120
+ options.onProgress?.(event.delta);
121
+ }
122
+ },
123
+ });
124
+ return await responseStream.result();
125
+ }
126
+ finally {
127
+ if (options.signal)
128
+ options.signal.removeEventListener("abort", onCallerAbort);
129
+ }
130
+ }
131
+ //# sourceMappingURL=speculative-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speculative-summary.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative-summary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessage,\n\ttype AssistantMessageEventStream,\n\ttype Context,\n\ttype Message,\n\ttype Model,\n\ttype ProviderHeaders,\n\ttype StreamOptions,\n\tsanitizeAnthropicToolPairs as sanitizeAnthropicPayload,\n\ttype TextContent,\n} from \"@earendil-works/pi-ai\";\nimport { stream } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tconsumeStreamWithIdleTimeout,\n\tDEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,\n\tDEFAULT_SUMMARIZATION_MAX_DURATION_MS,\n} from \"../../../compaction/stream-watchdog.ts\";\nimport { convertToLlm } from \"../../../messages.ts\";\nimport type { buildPrompt } from \"./prompts.ts\";\nimport { repairOrphanedToolResults } from \"./repair-tool-pairs.ts\";\nimport type { SpeculativeCompactionContext, SpeculativeCompactionSnapshot } from \"./speculative.ts\";\nimport { normalizeSummarizationTurnOrder } from \"./summarization-turn-order.ts\";\n\nconst SUMMARY_TOKEN_HEADROOM = 32_768;\nconst SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;\ntype CompactionProgressCallback = (delta: string) => void;\n\nfunction summaryMaxTokens(model: Model<any>, contextWindow: number): number {\n\tconst headroom = model.maxTokens > 0 ? Math.min(SUMMARY_TOKEN_HEADROOM, model.maxTokens) : SUMMARY_TOKEN_HEADROOM;\n\tif (contextWindow > 0) {\n\t\treturn Math.min(headroom, Math.floor(contextWindow * SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO));\n\t}\n\treturn headroom;\n}\n\n/**\n * Reasoning override for summarization requests. Compaction must be fast: a\n * summarization request that inherits the provider's default reasoning mode\n * burns its latency (and output budget) on invisible thinking before emitting\n * the summary. Disable or minimize reasoning per wire family; adapters ignore\n * options their provider does not support. Mirrors how OpenAI Codex keeps its\n * compaction turn cheap.\n */\nfunction summarizationReasoningOptions(model: Model<any>): Record<string, unknown> {\n\tif (!model.reasoning) return {};\n\tif (model.api === \"anthropic-messages\") return { thinkingEnabled: false };\n\tconst reasoningEffort = ([\"low\", \"medium\", \"high\"] as const).find(\n\t\t(level) => model.thinkingLevelMap?.[level] !== null,\n\t);\n\tif (!reasoningEffort) return {};\n\tswitch (model.api) {\n\t\tcase \"openai-responses\":\n\t\tcase \"openai-codex-responses\":\n\t\tcase \"azure-openai-responses\":\n\t\t\treturn { reasoningEffort, reasoningSummary: null };\n\t\tcase \"openai-completions\":\n\t\t\treturn { reasoningEffort };\n\t\tdefault:\n\t\t\treturn {};\n\t}\n}\n\nexport function getSummaryText(message: Message): string {\n\tconst content = Array.isArray(message.content)\n\t\t? message.content\n\t\t: [{ type: \"text\" as const, text: message.content }];\n\treturn content\n\t\t.filter((content): content is TextContent => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nexport function isAssistantMessage(message: Message): message is AssistantMessage {\n\treturn message.role === \"assistant\" && \"stopReason\" in message;\n}\n\n/**\n * Providers registered through `pi.registerProvider()` (claude-sdk-oauth, Kiro, any\n * extension provider) exist only in Senpi's ModelRuntime, never in compat's builtin\n * api-registry, which rejects their api id outright. Dispatch through the runtime\n * whenever it is reachable and keep compat for contexts constructed without a registry.\n */\nfunction summarizationStream(\n\tcontext: SpeculativeCompactionContext,\n\tmodel: Model<any>,\n\trequestContext: Context,\n\toptions: StreamOptions & Record<string, unknown>,\n): AssistantMessageEventStream {\n\tconst runtime = context.modelRegistry?.modelRuntime;\n\treturn runtime ? runtime.stream(model, requestContext, options) : stream(model, requestContext, options);\n}\n\nexport async function generateSummaryMessage(options: {\n\tcontext: SpeculativeCompactionContext;\n\tmessages: AgentMessage[];\n\tonProgress?: CompactionProgressCallback;\n\tprompt: ReturnType<typeof buildPrompt>;\n\tsignal?: AbortSignal;\n\tsnapshot: SpeculativeCompactionSnapshot;\n\tauth: {\n\t\tapiKey?: string;\n\t\theaders?: ProviderHeaders;\n\t\textraBody?: Record<string, unknown>;\n\t};\n}): Promise<Message | undefined> {\n\t// Send the conversation as native LLM messages with the summarization\n\t// instruction as a trailing user message, mirroring normal agent traffic.\n\t// A single serialized `<conversation>` text dump of a large session is\n\t// deterministically refused by Anthropic's anti-distillation classifier\n\t// (\"reverse engineering or duplicating model outputs\"), while the same\n\t// content as native blocks with the agent's system prompt and tools passes.\n\t// Request-local controller: the idle watchdog must be able to tear down a\n\t// stalled summarization request without aborting the caller's own signal.\n\tconst requestController = new AbortController();\n\tconst onCallerAbort = () => requestController.abort(options.signal?.reason);\n\tif (options.signal) {\n\t\tif (options.signal.aborted) onCallerAbort();\n\t\telse options.signal.addEventListener(\"abort\", onCallerAbort, { once: true });\n\t}\n\ttry {\n\t\tconst requestMessages: AgentMessage[] = [\n\t\t\t...options.messages,\n\t\t\t{\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: options.prompt.user }],\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t},\n\t\t];\n\t\tconst providerRequest = await options.context.prepareProviderRequest?.(requestMessages);\n\t\tconst requestContext = {\n\t\t\tsystemPrompt: options.snapshot.systemPrompt ?? options.prompt.system,\n\t\t\tmessages: repairOrphanedToolResults(\n\t\t\t\tnormalizeSummarizationTurnOrder(convertToLlm(providerRequest?.messages ?? requestMessages)),\n\t\t\t),\n\t\t\t...(options.snapshot.tools && options.snapshot.tools.length > 0 ? { tools: options.snapshot.tools } : {}),\n\t\t};\n\t\tconst headers = providerRequest\n\t\t\t? await providerRequest.transformHeaders(options.auth.headers ?? {})\n\t\t\t: options.auth.headers;\n\t\tconst responseStream = summarizationStream(options.context, options.snapshot.model, requestContext, {\n\t\t\tapiKey: options.auth.apiKey,\n\t\t\theaders,\n\t\t\textraBody: options.auth.extraBody,\n\t\t\tonPayload: async (payload, model) => {\n\t\t\t\tconst sanitized = model.api === \"anthropic-messages\" ? sanitizeAnthropicPayload(payload) : payload;\n\t\t\t\treturn providerRequest ? await providerRequest.transformPayload(sanitized) : sanitized;\n\t\t\t},\n\t\t\tmaxTokens: summaryMaxTokens(options.snapshot.model, options.snapshot.contextWindow),\n\t\t\tsignal: requestController.signal,\n\t\t\t...summarizationReasoningOptions(options.snapshot.model),\n\t\t});\n\t\tawait consumeStreamWithIdleTimeout(responseStream, {\n\t\t\tidleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,\n\t\t\tmaxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,\n\t\t\tabort: () => requestController.abort(),\n\t\t\tsignal: options.signal,\n\t\t\tonEvent: (event) => {\n\t\t\t\tif (event.type === \"text_delta\" && event.delta) {\n\t\t\t\t\toptions.onProgress?.(event.delta);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\treturn await responseStream.result();\n\t} finally {\n\t\tif (options.signal) options.signal.removeEventListener(\"abort\", onCallerAbort);\n\t}\n}\n"]}