@code-yeongyu/senpi 2026.8.29 → 2026.8.30-3

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 (346) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/dist/core/agent-session.d.ts +47 -1
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +406 -39
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/bash-executor.d.ts.map +1 -1
  7. package/dist/core/bash-executor.js +155 -37
  8. package/dist/core/bash-executor.js.map +1 -1
  9. package/dist/core/compaction/compaction-execution.d.ts +14 -0
  10. package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
  11. package/dist/core/compaction/compaction-execution.js +121 -0
  12. package/dist/core/compaction/compaction-execution.js.map +1 -0
  13. package/dist/core/compaction/compaction-settings.d.ts +17 -0
  14. package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
  15. package/dist/core/compaction/compaction-settings.js +17 -0
  16. package/dist/core/compaction/compaction-settings.js.map +1 -0
  17. package/dist/core/compaction/compaction.d.ts +13 -26
  18. package/dist/core/compaction/compaction.d.ts.map +1 -1
  19. package/dist/core/compaction/compaction.js +7 -136
  20. package/dist/core/compaction/compaction.js.map +1 -1
  21. package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
  22. package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
  23. package/dist/core/compaction/ideal-compaction-settings.js +7 -0
  24. package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
  25. package/dist/core/compaction-settings-access.d.ts +19 -0
  26. package/dist/core/compaction-settings-access.d.ts.map +1 -0
  27. package/dist/core/compaction-settings-access.js +10 -0
  28. package/dist/core/compaction-settings-access.js.map +1 -0
  29. package/dist/core/compaction-settings-resolver.d.ts +22 -0
  30. package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
  31. package/dist/core/compaction-settings-resolver.js +46 -0
  32. package/dist/core/compaction-settings-resolver.js.map +1 -0
  33. package/dist/core/credential-accounts.d.ts.map +1 -1
  34. package/dist/core/credential-accounts.js +23 -9
  35. package/dist/core/credential-accounts.js.map +1 -1
  36. package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
  37. package/dist/core/credential-pool/env-slots.js +2 -0
  38. package/dist/core/credential-pool/env-slots.js.map +1 -1
  39. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +18 -0
  40. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
  41. package/dist/core/extensions/builtin/compaction/context-pipeline.js +32 -0
  42. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
  43. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -2
  44. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +164 -48
  46. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  47. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
  48. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
  49. package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
  50. package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
  52. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
  53. package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
  54. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
  55. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
  56. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
  58. package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
  59. package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
  60. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/compaction/idle.js +13 -2
  62. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
  63. package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
  64. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/compaction/index.js +148 -150
  66. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  67. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  68. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/compaction/log.js +2 -0
  70. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  71. package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
  72. package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
  73. package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
  74. package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
  75. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
  76. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
  77. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
  78. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
  79. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
  80. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
  81. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
  82. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
  83. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
  84. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  85. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  86. package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
  87. package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
  88. package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
  89. package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
  90. package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
  91. package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
  92. package/dist/core/extensions/builtin/compaction/policy.js +52 -26
  93. package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
  94. package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts.map +1 -1
  95. package/dist/core/extensions/builtin/compaction/retained-message-safety.js +31 -8
  96. package/dist/core/extensions/builtin/compaction/retained-message-safety.js.map +1 -1
  97. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
  98. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
  99. package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
  100. package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
  101. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
  102. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
  103. package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
  104. package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
  105. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +22 -0
  106. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
  107. package/dist/core/extensions/builtin/compaction/speculative-summary.js +131 -0
  108. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
  109. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
  110. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  111. package/dist/core/extensions/builtin/compaction/speculative.js +7 -196
  112. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  113. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
  114. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
  115. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
  116. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
  117. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
  118. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
  119. package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
  120. package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
  121. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.d.ts.map +1 -1
  122. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +8 -28
  123. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
  124. package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
  125. package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
  126. package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
  127. package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
  129. package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
  130. package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
  131. package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
  132. package/dist/core/extensions/builtin/terminal/manager.js +31 -3
  133. package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
  134. package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
  135. package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
  136. package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
  137. package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
  138. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
  139. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
  141. package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
  142. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
  143. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
  144. package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
  145. package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
  146. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
  147. package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
  148. package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
  149. package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
  151. package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
  152. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
  153. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
  154. package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
  155. package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
  156. package/dist/core/model-resolver.js +2 -2
  157. package/dist/core/model-resolver.js.map +1 -1
  158. package/dist/core/sdk.d.ts.map +1 -1
  159. package/dist/core/sdk.js +5 -0
  160. package/dist/core/sdk.js.map +1 -1
  161. package/dist/core/session-manager.d.ts.map +1 -1
  162. package/dist/core/session-manager.js +10 -1
  163. package/dist/core/session-manager.js.map +1 -1
  164. package/dist/core/settings-manager.d.ts +15 -85
  165. package/dist/core/settings-manager.d.ts.map +1 -1
  166. package/dist/core/settings-manager.js +15 -17
  167. package/dist/core/settings-manager.js.map +1 -1
  168. package/dist/core/settings-public-types.d.ts +11 -0
  169. package/dist/core/settings-public-types.d.ts.map +1 -0
  170. package/dist/core/settings-public-types.js +2 -0
  171. package/dist/core/settings-public-types.js.map +1 -0
  172. package/dist/core/settings-shapes.d.ts +36 -0
  173. package/dist/core/settings-shapes.d.ts.map +1 -0
  174. package/dist/core/settings-shapes.js +2 -0
  175. package/dist/core/settings-shapes.js.map +1 -0
  176. package/dist/core/shared-host-policy.d.ts +6 -0
  177. package/dist/core/shared-host-policy.d.ts.map +1 -0
  178. package/dist/core/shared-host-policy.js +7 -0
  179. package/dist/core/shared-host-policy.js.map +1 -0
  180. package/dist/core/terminal-settings.d.ts +22 -0
  181. package/dist/core/terminal-settings.d.ts.map +1 -0
  182. package/dist/core/terminal-settings.js +2 -0
  183. package/dist/core/terminal-settings.js.map +1 -0
  184. package/dist/core/tools/bash.d.ts.map +1 -1
  185. package/dist/core/tools/bash.js +97 -15
  186. package/dist/core/tools/bash.js.map +1 -1
  187. package/dist/core/tools/index.d.ts +1 -0
  188. package/dist/core/tools/index.d.ts.map +1 -1
  189. package/dist/core/tools/index.js +8 -0
  190. package/dist/core/tools/index.js.map +1 -1
  191. package/dist/core/tools/output-accumulator.d.ts +1 -1
  192. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  193. package/dist/core/tools/output-accumulator.js +76 -34
  194. package/dist/core/tools/output-accumulator.js.map +1 -1
  195. package/dist/index.d.ts +1 -1
  196. package/dist/index.d.ts.map +1 -1
  197. package/dist/index.js +1 -1
  198. package/dist/index.js.map +1 -1
  199. package/dist/main.d.ts.map +1 -1
  200. package/dist/main.js +17 -5
  201. package/dist/main.js.map +1 -1
  202. package/dist/modes/index.d.ts +1 -1
  203. package/dist/modes/index.d.ts.map +1 -1
  204. package/dist/modes/index.js +1 -1
  205. package/dist/modes/index.js.map +1 -1
  206. package/dist/modes/interactive/components/footer.d.ts +7 -0
  207. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  208. package/dist/modes/interactive/components/footer.js +34 -8
  209. package/dist/modes/interactive/components/footer.js.map +1 -1
  210. package/dist/modes/interactive/grok/chrome.d.ts +2 -0
  211. package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
  212. package/dist/modes/interactive/grok/chrome.js.map +1 -1
  213. package/dist/modes/interactive/interactive-host-runtime.d.ts +132 -1
  214. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  215. package/dist/modes/interactive/interactive-host-runtime.js +633 -117
  216. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  217. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  218. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  219. package/dist/modes/interactive/interactive-mode.js +114 -2
  220. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  221. package/dist/modes/rpc/connection-handler.d.ts +8 -1
  222. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  223. package/dist/modes/rpc/connection-handler.js +158 -49
  224. package/dist/modes/rpc/connection-handler.js.map +1 -1
  225. package/dist/modes/rpc/host-ensure.d.ts +19 -0
  226. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  227. package/dist/modes/rpc/host-ensure.js +79 -15
  228. package/dist/modes/rpc/host-ensure.js.map +1 -1
  229. package/dist/modes/rpc/host-lifecycle.d.ts +29 -0
  230. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  231. package/dist/modes/rpc/host-lifecycle.js +96 -25
  232. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  233. package/dist/modes/rpc/host-watchdog.d.ts +2 -0
  234. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  235. package/dist/modes/rpc/host-watchdog.js +23 -12
  236. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  237. package/dist/modes/rpc/multi-session-host.js +6 -4
  238. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  239. package/dist/modes/rpc/rpc-client.d.ts +20 -4
  240. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  241. package/dist/modes/rpc/rpc-client.js +76 -17
  242. package/dist/modes/rpc/rpc-client.js.map +1 -1
  243. package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
  244. package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
  245. package/dist/modes/rpc/rpc-input-validation.js +66 -0
  246. package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
  247. package/dist/modes/rpc/rpc-types.d.ts +86 -1
  248. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  249. package/dist/modes/rpc/rpc-types.js.map +1 -1
  250. package/dist/modes/rpc/session-binding.d.ts +1 -0
  251. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  252. package/dist/modes/rpc/session-binding.js +21 -1
  253. package/dist/modes/rpc/session-binding.js.map +1 -1
  254. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  255. package/dist/modes/rpc/session-command-router.js +1 -0
  256. package/dist/modes/rpc/session-command-router.js.map +1 -1
  257. package/dist/modes/rpc/session-event-writer.d.ts +2 -0
  258. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  259. package/dist/modes/rpc/session-event-writer.js +54 -7
  260. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  261. package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
  262. package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
  263. package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
  264. package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
  265. package/dist/modes/rpc/session-registry.d.ts +10 -2
  266. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  267. package/dist/modes/rpc/session-registry.js +58 -4
  268. package/dist/modes/rpc/session-registry.js.map +1 -1
  269. package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
  270. package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
  271. package/dist/modes/rpc/socket-event-fanout.js +84 -0
  272. package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
  273. package/docs/rpc.md +22 -2
  274. package/docs/settings.md +34 -0
  275. package/docs/windows.md +2 -0
  276. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +62 -0
  277. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  278. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
  279. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
  280. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  281. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
  282. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  283. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
  284. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  285. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
  287. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
  288. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
  289. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
  290. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  291. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  292. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +67 -38
  293. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  294. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +20 -0
  295. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -0
  296. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +443 -0
  297. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -0
  298. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
  299. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +2 -0
  301. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
  303. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  304. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  305. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  307. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  309. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  315. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  317. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  318. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  319. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
  320. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
  321. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
  322. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
  323. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
  324. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
  325. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
  326. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
  327. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
  328. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
  330. package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  332. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  333. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +7 -0
  334. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  335. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -0
  336. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  337. package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +1 -1
  338. package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -1
  339. package/node_modules/@earendil-works/pi-tui/dist/mux.js +2 -2
  340. package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -1
  341. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
  342. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  343. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +19 -0
  344. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  345. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  346. package/package.json +7 -7
@@ -0,0 +1,103 @@
1
+ import { copyContextProvenance } from "@earendil-works/pi-ai";
2
+ import { estimateTokens } from "../../../compaction/index.js";
3
+ import { shouldWarmAtIdle } from "./idle.js";
4
+ import * as policy from "./policy.js";
5
+ import { isWarmResultStale, isWithinGraceBand, resolveSpeculationLeadTokens } from "./speculation-lead.js";
6
+ import { admitToolResult, admitToolResultWithinBudget, resolveToolResultAdmissionCapTokens } from "./tool-admission.js";
7
+ export function resolveCompactionGeometry(input) {
8
+ const thresholdTokens = input.contextWindow * policy.computeEffectiveThreshold(input.contextWindow, input.lastYield);
9
+ return {
10
+ reserveTokens: policy.resolveEffectiveReserveTokens(input.contextWindow, input.settings),
11
+ thresholdTokens,
12
+ leadTokens: resolveSpeculationLeadTokens(thresholdTokens, input.settings.speculativeLeadTokens),
13
+ };
14
+ }
15
+ export function shouldDeferGraceBand(input) {
16
+ return (input.compactionInFlight &&
17
+ input.graceBandEnabled !== false &&
18
+ isWithinGraceBand(input.tokens, input.thresholdTokens, input.leadTokens, input.contextWindow, input.reserveTokens));
19
+ }
20
+ export function injectTokenBudgetReminder(messages, reminder) {
21
+ if (!reminder)
22
+ return messages;
23
+ for (let index = messages.length - 1; index >= 0; index--) {
24
+ const message = messages[index];
25
+ if (message?.role !== "user")
26
+ continue;
27
+ const content = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
28
+ const firstPart = content[0];
29
+ if (firstPart?.type === "text" && firstPart.text === reminder)
30
+ return messages;
31
+ const reminded = copyContextProvenance(message, {
32
+ ...message,
33
+ content: [{ type: "text", text: reminder }, ...content],
34
+ });
35
+ return messages.map((candidate, candidateIndex) => (candidateIndex === index ? reminded : candidate));
36
+ }
37
+ return messages;
38
+ }
39
+ export function resolveBeforeAgentStartMessage(input) {
40
+ if (!input.reminder || input.reminderEnabled === false)
41
+ return input.message;
42
+ if (!input.message)
43
+ return undefined;
44
+ return { ...input.message, content: `${input.message.content}\n\n${input.reminder}` };
45
+ }
46
+ export function resolveReminderSystemPrompt(input) {
47
+ if (!input.reminder || input.reminderEnabled === false)
48
+ return undefined;
49
+ return `${input.systemPrompt}\n\n${input.reminder}`;
50
+ }
51
+ export function resolveIdleWarmAction(decision, job) {
52
+ if (!shouldWarmAtIdle(decision))
53
+ return "none";
54
+ if (!job)
55
+ return "start";
56
+ const currentTokens = decision.usage?.tokens ?? 0;
57
+ return isWarmResultStale(job.armedAtTokens, currentTokens, decision.settings.keepRecentTokens) ? "replace" : "none";
58
+ }
59
+ export function admitContextToolResult(text, contextWindow) {
60
+ const result = admitToolResult({ text, contextWindow });
61
+ return { text: result.text, admitted: result.projected };
62
+ }
63
+ export function admitContextToolResults(messages, contextWindow, enabled) {
64
+ if (!enabled)
65
+ return messages;
66
+ return messages.map((message) => {
67
+ if (message.role !== "toolResult")
68
+ return message;
69
+ if (typeof message.content === "string") {
70
+ const admitted = admitContextToolResult(message.content, contextWindow);
71
+ return admitted.admitted ? { ...message, content: [{ type: "text", text: admitted.text }] } : message;
72
+ }
73
+ const textTokens = message.content.map((part) => part.type === "text" ? estimateTokens({ role: "user", content: part.text, timestamp: 0 }) : 0);
74
+ const totalTextTokens = textTokens.reduce((total, tokens) => total + tokens, 0);
75
+ const capTokens = resolveToolResultAdmissionCapTokens(contextWindow);
76
+ if (totalTextTokens <= capTokens)
77
+ return message;
78
+ const preservedTokens = textTokens.reduce((total, tokens) => total + (tokens <= capTokens ? tokens : 0), 0);
79
+ const preserveUnderCap = preservedTokens <= capTokens;
80
+ let remainingBudget = preserveUnderCap ? capTokens - preservedTokens : capTokens;
81
+ let remainingOversizedTokens = preserveUnderCap
82
+ ? textTokens.reduce((total, tokens) => total + (tokens > capTokens ? tokens : 0), 0)
83
+ : totalTextTokens;
84
+ let projected = false;
85
+ const content = message.content.map((part, index) => {
86
+ if (part.type !== "text")
87
+ return part;
88
+ const partTokens = textTokens[index] ?? 0;
89
+ if (preserveUnderCap && partTokens <= capTokens)
90
+ return part;
91
+ const budget = Math.floor((remainingBudget * partTokens) / Math.max(1, remainingOversizedTokens));
92
+ const admitted = admitToolResultWithinBudget(part.text, budget);
93
+ remainingOversizedTokens -= partTokens;
94
+ remainingBudget -= estimateTokens({ role: "user", content: admitted.text, timestamp: 0 });
95
+ if (!admitted.projected)
96
+ return part;
97
+ projected = true;
98
+ return { ...part, text: admitted.text };
99
+ });
100
+ return projected ? { ...message, content } : message;
101
+ });
102
+ }
103
+ //# sourceMappingURL=orchestration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestration.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/orchestration.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { copyContextProvenance } from \"@earendil-works/pi-ai\";\nimport { type CompactionPreparation, estimateTokens } from \"../../../compaction/index.ts\";\nimport type { BeforeAgentStartEventResult } from \"../../types.ts\";\nimport { type IdleCompactionDecision, shouldWarmAtIdle } from \"./idle.ts\";\nimport * as policy from \"./policy.ts\";\nimport { isWarmResultStale, isWithinGraceBand, resolveSpeculationLeadTokens } from \"./speculation-lead.ts\";\nimport { admitToolResult, admitToolResultWithinBudget, resolveToolResultAdmissionCapTokens } from \"./tool-admission.ts\";\n\nexport interface CompactionGeometry {\n\treserveTokens: number;\n\tthresholdTokens: number;\n\tleadTokens: number;\n}\n\nexport function resolveCompactionGeometry(input: {\n\tcontextWindow: number;\n\tsettings: CompactionPreparation[\"settings\"];\n\tlastYield?: { savedTokens: number; tokensBefore: number };\n}): CompactionGeometry {\n\tconst thresholdTokens = input.contextWindow * policy.computeEffectiveThreshold(input.contextWindow, input.lastYield);\n\treturn {\n\t\treserveTokens: policy.resolveEffectiveReserveTokens(input.contextWindow, input.settings),\n\t\tthresholdTokens,\n\t\tleadTokens: resolveSpeculationLeadTokens(thresholdTokens, input.settings.speculativeLeadTokens),\n\t};\n}\n\nexport function shouldDeferGraceBand(input: {\n\ttokens: number;\n\tthresholdTokens: number;\n\tleadTokens: number;\n\tcontextWindow: number;\n\treserveTokens: number;\n\tcompactionInFlight: boolean;\n\tgraceBandEnabled?: boolean;\n}): boolean {\n\treturn (\n\t\tinput.compactionInFlight &&\n\t\tinput.graceBandEnabled !== false &&\n\t\tisWithinGraceBand(input.tokens, input.thresholdTokens, input.leadTokens, input.contextWindow, input.reserveTokens)\n\t);\n}\n\nexport function injectTokenBudgetReminder(messages: AgentMessage[], reminder?: string): AgentMessage[] {\n\tif (!reminder) return messages;\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role !== \"user\") continue;\n\t\tconst content =\n\t\t\ttypeof message.content === \"string\" ? [{ type: \"text\" as const, text: message.content }] : message.content;\n\t\tconst firstPart = content[0];\n\t\tif (firstPart?.type === \"text\" && firstPart.text === reminder) return messages;\n\t\tconst reminded = copyContextProvenance(message, {\n\t\t\t...message,\n\t\t\tcontent: [{ type: \"text\" as const, text: reminder }, ...content],\n\t\t});\n\t\treturn messages.map((candidate, candidateIndex) => (candidateIndex === index ? reminded : candidate));\n\t}\n\treturn messages;\n}\n\nexport function resolveBeforeAgentStartMessage(input: {\n\tmessage?: BeforeAgentStartEventResult[\"message\"];\n\treminder?: string;\n\treminderEnabled?: boolean;\n}): BeforeAgentStartEventResult[\"message\"] | undefined {\n\tif (!input.reminder || input.reminderEnabled === false) return input.message;\n\tif (!input.message) return undefined;\n\treturn { ...input.message, content: `${input.message.content}\\n\\n${input.reminder}` };\n}\n\nexport function resolveReminderSystemPrompt(input: {\n\tsystemPrompt: string;\n\treminder?: string;\n\treminderEnabled?: boolean;\n}): string | undefined {\n\tif (!input.reminder || input.reminderEnabled === false) return undefined;\n\treturn `${input.systemPrompt}\\n\\n${input.reminder}`;\n}\n\nexport function resolveIdleWarmAction(\n\tdecision: IdleCompactionDecision,\n\tjob: { armedAtTokens: number } | undefined,\n): \"none\" | \"start\" | \"replace\" {\n\tif (!shouldWarmAtIdle(decision)) return \"none\";\n\tif (!job) return \"start\";\n\tconst currentTokens = decision.usage?.tokens ?? 0;\n\treturn isWarmResultStale(job.armedAtTokens, currentTokens, decision.settings.keepRecentTokens) ? \"replace\" : \"none\";\n}\n\nexport function admitContextToolResult(text: string, contextWindow: number): { text: string; admitted: boolean } {\n\tconst result = admitToolResult({ text, contextWindow });\n\treturn { text: result.text, admitted: result.projected };\n}\n\nexport function admitContextToolResults(\n\tmessages: AgentMessage[],\n\tcontextWindow: number,\n\tenabled: boolean,\n): AgentMessage[] {\n\tif (!enabled) return messages;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tif (typeof message.content === \"string\") {\n\t\t\tconst admitted = admitContextToolResult(message.content, contextWindow);\n\t\t\treturn admitted.admitted ? { ...message, content: [{ type: \"text\", text: admitted.text }] } : message;\n\t\t}\n\n\t\tconst textTokens = message.content.map((part) =>\n\t\t\tpart.type === \"text\" ? estimateTokens({ role: \"user\", content: part.text, timestamp: 0 }) : 0,\n\t\t);\n\t\tconst totalTextTokens = textTokens.reduce((total, tokens) => total + tokens, 0);\n\t\tconst capTokens = resolveToolResultAdmissionCapTokens(contextWindow);\n\t\tif (totalTextTokens <= capTokens) return message;\n\n\t\tconst preservedTokens = textTokens.reduce((total, tokens) => total + (tokens <= capTokens ? tokens : 0), 0);\n\t\tconst preserveUnderCap = preservedTokens <= capTokens;\n\t\tlet remainingBudget = preserveUnderCap ? capTokens - preservedTokens : capTokens;\n\t\tlet remainingOversizedTokens = preserveUnderCap\n\t\t\t? textTokens.reduce((total, tokens) => total + (tokens > capTokens ? tokens : 0), 0)\n\t\t\t: totalTextTokens;\n\t\tlet projected = false;\n\t\tconst content = message.content.map((part, index) => {\n\t\t\tif (part.type !== \"text\") return part;\n\t\t\tconst partTokens = textTokens[index] ?? 0;\n\t\t\tif (preserveUnderCap && partTokens <= capTokens) return part;\n\t\t\tconst budget = Math.floor((remainingBudget * partTokens) / Math.max(1, remainingOversizedTokens));\n\t\t\tconst admitted = admitToolResultWithinBudget(part.text, budget);\n\t\t\tremainingOversizedTokens -= partTokens;\n\t\t\tremainingBudget -= estimateTokens({ role: \"user\", content: admitted.text, timestamp: 0 });\n\t\t\tif (!admitted.projected) return part;\n\t\t\tprojected = true;\n\t\t\treturn { ...part, text: admitted.text };\n\t\t});\n\t\treturn projected ? { ...message, content } : message;\n\t});\n}\n"]}
@@ -5,10 +5,20 @@ export interface CompactionYield {
5
5
  savedTokens: number;
6
6
  tokensBefore: number;
7
7
  }
8
+ export declare function baseThresholdRatioForWindow(contextWindow: number): number;
9
+ export declare function resolveReserveTokens(contextWindow: number, configuredReserve: number): number;
10
+ /**
11
+ * The single effective reserve for one window. Every consumer that reasons about
12
+ * the usable prompt budget — the hard-limit valve, restoration, and deterministic
13
+ * fallback acceptance — must resolve it here so acceptance can never admit a
14
+ * context the hard valve would immediately compact again. Scaling is idempotent,
15
+ * so re-resolving an already-scaled reserve never double-scales it.
16
+ */
17
+ export declare function resolveEffectiveReserveTokens(contextWindow: number, settings: Pick<CompactionSettings, "reserveTokens" | "reserveScalingEnabled">): number;
8
18
  export declare function computeAdaptiveThresholdRatio(contextWindow: number, priorCompactionSavedTokens?: number): number;
9
- export declare function computeEffectiveThreshold(contextWindow: number, lastYield?: CompactionYield | number): number;
19
+ export declare function computeEffectiveThreshold(contextWindow: number, lastYield?: CompactionYield): number;
10
20
  export declare function computeEffectiveKeepRecentTokens(setting: number, contextWindow: number, thresholdRatio: number, margin?: number): number;
11
- export declare function shouldStartSpeculativeCompaction(usage: ContextUsage, contextWindow: number, settings: CompactionSettings, lastYield?: CompactionYield): boolean;
21
+ export declare function shouldStartSpeculativeCompaction(usage: ContextUsage, contextWindow: number, settings: CompactionSettings, lastYield?: CompactionYield, leadTokens?: number): boolean;
12
22
  export declare function isAtHardLimit(usage: ContextUsage, contextWindow: number, reserveTokens: number, additionalTokens?: number): boolean;
13
23
  export declare function shouldTriggerCompaction(usage: ContextUsage, contextWindow: number, settings: CompactionSettings, lastYield?: CompactionYield): boolean;
14
24
  //# sourceMappingURL=policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AASnD,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAoCD,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,MAAM,EAAE,0BAA0B,CAAC,EAAE,MAAM,GAAG,MAAM,CAqBhH;AAED,wBAAgB,yBAAyB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,CAU7G;AAED,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,SAAO,GACX,MAAM,CAGR;AAED,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,CAAC,EAAE,eAAe,GACzB,OAAO,CAOT;AAED,wBAAgB,aAAa,CAC5B,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,gBAAgB,SAAI,GAClB,OAAO,CAET;AAED,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,CAAC,EAAE,eAAe,GACzB,OAAO,CAMT"}
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAanD,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAyCD,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAoBzE;AAED,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAK7F;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,GAAG,uBAAuB,CAAC,GAC3E,MAAM,CAIR;AAED,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,MAAM,EAAE,0BAA0B,CAAC,EAAE,MAAM,GAAG,MAAM,CAQhH;AAED,wBAAgB,yBAAyB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,MAAM,CAMpG;AAED,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,SAAO,GACX,MAAM,CAUR;AAED,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,CAAC,EAAE,eAAe,EAC3B,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAYT;AAED,wBAAgB,aAAa,CAC5B,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,gBAAgB,SAAI,GAClB,OAAO,CAET;AAED,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,CAAC,EAAE,eAAe,GACzB,OAAO,CAMT"}
@@ -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,53 +34,75 @@ 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
+ /**
66
+ * The single effective reserve for one window. Every consumer that reasons about
67
+ * the usable prompt budget — the hard-limit valve, restoration, and deterministic
68
+ * fallback acceptance — must resolve it here so acceptance can never admit a
69
+ * context the hard valve would immediately compact again. Scaling is idempotent,
70
+ * so re-resolving an already-scaled reserve never double-scales it.
71
+ */
72
+ export function resolveEffectiveReserveTokens(contextWindow, settings) {
73
+ return settings.reserveScalingEnabled === false
74
+ ? settings.reserveTokens
75
+ : resolveReserveTokens(contextWindow, settings.reserveTokens);
76
+ }
77
+ export function computeAdaptiveThresholdRatio(contextWindow, priorCompactionSavedTokens) {
78
+ const ratio = baseThresholdRatioForWindow(contextWindow);
57
79
  if (priorCompactionSavedTokens === undefined) {
58
80
  return ratio;
59
81
  }
60
82
  return adjustThresholdRatio(ratio, priorCompactionSavedTokens, contextWindow);
61
83
  }
62
84
  export function computeEffectiveThreshold(contextWindow, lastYield) {
63
- if (typeof lastYield === "number") {
64
- return Math.max(contextWindow, lastYield);
65
- }
66
85
  let ratio = computeAdaptiveThresholdRatio(contextWindow);
67
86
  if (lastYield) {
68
- ratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore);
87
+ ratio = adjustEffectiveThresholdRatio(ratio, lastYield.savedTokens, lastYield.tokensBefore, contextWindow);
69
88
  }
70
89
  return clampThresholdRatio(ratio);
71
90
  }
72
91
  export function computeEffectiveKeepRecentTokens(setting, contextWindow, thresholdRatio, margin = 0.05) {
92
+ const scaled = contextWindow > 409_600 && setting >= 10_000
93
+ ? Math.max(setting, Math.min(Math.floor(KEEP_RECENT_WINDOW_FRACTION * contextWindow), MAX_SCALED_KEEP_RECENT_TOKENS))
94
+ : setting;
73
95
  const capped = Math.floor(contextWindow * (1 - thresholdRatio - margin));
74
- return Math.min(setting, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));
96
+ return Math.min(scaled, Math.max(MIN_EFFECTIVE_KEEP_RECENT_TOKENS, capped));
75
97
  }
76
- export function shouldStartSpeculativeCompaction(usage, contextWindow, settings, lastYield) {
98
+ export function shouldStartSpeculativeCompaction(usage, contextWindow, settings, lastYield, leadTokens) {
77
99
  if (settings.speculativeEnabled === false || usage.tokens === null || contextWindow <= 0) {
78
100
  return false;
79
101
  }
102
+ if (typeof leadTokens === "number" && Number.isFinite(leadTokens) && leadTokens > 0) {
103
+ const leadTrigger = Math.max(0, contextWindow * computeEffectiveThreshold(contextWindow, lastYield) - leadTokens);
104
+ return usage.tokens >= leadTrigger;
105
+ }
80
106
  const fraction = settings.speculativeFraction ?? SPECULATIVE_FRACTION;
81
107
  return usage.tokens >= contextWindow * computeEffectiveThreshold(contextWindow, lastYield) * fraction;
82
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/policy.ts"],"names":[],"mappings":"AAGA,MAAM,4BAA4B,GAAG,GAAG,CAAC;AACzC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AACzC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AACnC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,gCAAgC,GAAG,IAAI,CAAC;AAE9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAOzC,SAAS,mBAAmB,CAAC,KAAa;IACzC,OAAO,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC,CAAC;AAC9F,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa,EAAE,WAAmB,EAAE,YAAoB;IACrF,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,GAAG,YAAY,CAAC;IAC9C,IAAI,UAAU,GAAG,uBAAuB,EAAE,CAAC;QAC1C,OAAO,mBAAmB,CAAC,KAAK,GAAG,sBAAsB,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,UAAU,GAAG,sBAAsB,EAAE,CAAC;QACzC,OAAO,mBAAmB,CAAC,KAAK,GAAG,sBAAsB,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAa,EAAE,WAAmB,EAAE,YAAoB;IAC9F,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,GAAG,YAAY,CAAC;IAC9C,IAAI,UAAU,GAAG,uBAAuB,EAAE,CAAC;QAC1C,OAAO,KAAK,GAAG,sBAAsB,CAAC;IACvC,CAAC;IACD,IAAI,UAAU,GAAG,sBAAsB,EAAE,CAAC;QACzC,OAAO,KAAK,GAAG,sBAAsB,CAAC;IACvC,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,aAAqB,EAAE,0BAAmC;IACvG,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1B,KAAK,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;QACpC,KAAK,GAAG,IAAI,CAAC;IACd,CAAC;SAAM,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;QACpC,KAAK,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;QACpC,KAAK,GAAG,IAAI,CAAC;IACd,CAAC;SAAM,IAAI,aAAa,IAAI,OAAO,EAAE,CAAC;QACrC,KAAK,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,CAAC;QACP,KAAK,GAAG,IAAI,CAAC;IACd,CAAC;IAED,IAAI,0BAA0B,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,oBAAoB,CAAC,KAAK,EAAE,0BAA0B,EAAE,aAAa,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,aAAqB,EAAE,SAAoC;IACpG,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;IACzD,IAAI,SAAS,EAAE,CAAC;QACf,KAAK,GAAG,6BAA6B,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC/C,OAAe,EACf,aAAqB,EACrB,cAAsB,EACtB,MAAM,GAAG,IAAI;IAEb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC/C,KAAmB,EACnB,aAAqB,EACrB,QAA4B,EAC5B,SAA2B;IAE3B,IAAI,QAAQ,CAAC,kBAAkB,KAAK,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QAC1F,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,mBAAmB,IAAI,oBAAoB,CAAC;IACtE,OAAO,KAAK,CAAC,MAAM,IAAI,aAAa,GAAG,yBAAyB,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,aAAa,CAC5B,KAAmB,EACnB,aAAqB,EACrB,aAAqB,EACrB,gBAAgB,GAAG,CAAC;IAEpB,OAAO,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,GAAG,aAAa,IAAI,aAAa,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,uBAAuB,CACtC,KAAmB,EACnB,aAAqB,EACrB,QAA4B,EAC5B,SAA2B;IAE3B,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,IAAI,aAAa,GAAG,yBAAyB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAC5F,CAAC","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\n/**\n * The single effective reserve for one window. Every consumer that reasons about\n * the usable prompt budget — the hard-limit valve, restoration, and deterministic\n * fallback acceptance — must resolve it here so acceptance can never admit a\n * context the hard valve would immediately compact again. Scaling is idempotent,\n * so re-resolving an already-scaled reserve never double-scales it.\n */\nexport function resolveEffectiveReserveTokens(\n\tcontextWindow: number,\n\tsettings: Pick<CompactionSettings, \"reserveTokens\" | \"reserveScalingEnabled\">,\n): number {\n\treturn settings.reserveScalingEnabled === false\n\t\t? settings.reserveTokens\n\t\t: resolveReserveTokens(contextWindow, settings.reserveTokens);\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 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"}