@code-yeongyu/senpi 2026.8.30 → 2026.9.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 (373) hide show
  1. package/CHANGELOG.md +174 -2
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +28 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +161 -14
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/compaction-execution.d.ts +14 -0
  8. package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
  9. package/dist/core/compaction/compaction-execution.js +121 -0
  10. package/dist/core/compaction/compaction-execution.js.map +1 -0
  11. package/dist/core/compaction/compaction-settings.d.ts +17 -0
  12. package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
  13. package/dist/core/compaction/compaction-settings.js +17 -0
  14. package/dist/core/compaction/compaction-settings.js.map +1 -0
  15. package/dist/core/compaction/compaction.d.ts +13 -26
  16. package/dist/core/compaction/compaction.d.ts.map +1 -1
  17. package/dist/core/compaction/compaction.js +7 -136
  18. package/dist/core/compaction/compaction.js.map +1 -1
  19. package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
  20. package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
  21. package/dist/core/compaction/ideal-compaction-settings.js +7 -0
  22. package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
  23. package/dist/core/compaction-settings-access.d.ts +19 -0
  24. package/dist/core/compaction-settings-access.d.ts.map +1 -0
  25. package/dist/core/compaction-settings-access.js +10 -0
  26. package/dist/core/compaction-settings-access.js.map +1 -0
  27. package/dist/core/compaction-settings-resolver.d.ts +22 -0
  28. package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
  29. package/dist/core/compaction-settings-resolver.js +46 -0
  30. package/dist/core/compaction-settings-resolver.js.map +1 -0
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
  34. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +24 -0
  36. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
  37. package/dist/core/extensions/builtin/compaction/context-pipeline.js +43 -0
  38. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
  39. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
  40. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +8 -2
  42. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  43. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
  44. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
  45. package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
  46. package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
  47. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
  48. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
  49. package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
  50. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
  52. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
  54. package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
  55. package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
  56. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/compaction/idle.js +13 -2
  58. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
  59. package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
  60. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/compaction/index.js +152 -154
  62. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  63. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  64. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/compaction/log.js +2 -0
  66. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  67. package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
  68. package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
  69. package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
  70. package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
  71. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
  72. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
  73. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
  74. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
  75. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
  76. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
  77. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
  78. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
  79. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
  80. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  81. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  82. package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
  83. package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
  85. package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
  86. package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
  87. package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
  88. package/dist/core/extensions/builtin/compaction/policy.js +52 -26
  89. package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
  90. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
  91. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
  92. package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
  93. package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
  94. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
  95. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
  96. package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
  97. package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
  98. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +23 -0
  99. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
  100. package/dist/core/extensions/builtin/compaction/speculative-summary.js +132 -0
  101. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
  102. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
  103. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  104. package/dist/core/extensions/builtin/compaction/speculative.js +21 -197
  105. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  106. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
  107. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
  108. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
  109. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
  110. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
  111. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
  112. package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
  113. package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
  114. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
  115. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
  116. package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
  117. package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
  118. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
  119. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  120. package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
  121. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  122. package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
  123. package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
  124. package/dist/core/extensions/builtin/hooks/trust.js +1 -72
  125. package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
  126. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
  127. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
  128. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +108 -0
  129. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
  130. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/prompt-preset/presets.js +11 -0
  132. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  133. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  134. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  135. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  136. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  137. package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
  138. package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
  139. package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
  140. package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
  141. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
  142. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
  144. package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
  145. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/ttsr/index.js +4 -0
  147. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  148. package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
  149. package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
  151. package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
  152. package/dist/core/extensions/runner.d.ts +5 -0
  153. package/dist/core/extensions/runner.d.ts.map +1 -1
  154. package/dist/core/extensions/runner.js +7 -0
  155. package/dist/core/extensions/runner.js.map +1 -1
  156. package/dist/core/retry-fallback/controller.d.ts +14 -0
  157. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  158. package/dist/core/retry-fallback/controller.js +33 -3
  159. package/dist/core/retry-fallback/controller.js.map +1 -1
  160. package/dist/core/retry-fallback/log.js +1 -1
  161. package/dist/core/retry-fallback/log.js.map +1 -1
  162. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  163. package/dist/core/retry-fallback/settings.js +1 -0
  164. package/dist/core/retry-fallback/settings.js.map +1 -1
  165. package/dist/core/sdk.d.ts.map +1 -1
  166. package/dist/core/sdk.js +5 -0
  167. package/dist/core/sdk.js.map +1 -1
  168. package/dist/core/session-activity.d.ts +47 -0
  169. package/dist/core/session-activity.d.ts.map +1 -0
  170. package/dist/core/session-activity.js +58 -0
  171. package/dist/core/session-activity.js.map +1 -0
  172. package/dist/core/session-manager.d.ts +8 -12
  173. package/dist/core/session-manager.d.ts.map +1 -1
  174. package/dist/core/session-manager.js +118 -7
  175. package/dist/core/session-manager.js.map +1 -1
  176. package/dist/core/session-resident-store.d.ts +8 -1
  177. package/dist/core/session-resident-store.d.ts.map +1 -1
  178. package/dist/core/session-resident-store.js +12 -5
  179. package/dist/core/session-resident-store.js.map +1 -1
  180. package/dist/core/settings-manager.d.ts +8 -85
  181. package/dist/core/settings-manager.d.ts.map +1 -1
  182. package/dist/core/settings-manager.js +9 -17
  183. package/dist/core/settings-manager.js.map +1 -1
  184. package/dist/core/settings-public-types.d.ts +11 -0
  185. package/dist/core/settings-public-types.d.ts.map +1 -0
  186. package/dist/core/settings-public-types.js +2 -0
  187. package/dist/core/settings-public-types.js.map +1 -0
  188. package/dist/core/settings-shapes.d.ts +36 -0
  189. package/dist/core/settings-shapes.d.ts.map +1 -0
  190. package/dist/core/settings-shapes.js +2 -0
  191. package/dist/core/settings-shapes.js.map +1 -0
  192. package/dist/core/shared-host-policy.d.ts +6 -0
  193. package/dist/core/shared-host-policy.d.ts.map +1 -0
  194. package/dist/core/shared-host-policy.js +7 -0
  195. package/dist/core/shared-host-policy.js.map +1 -0
  196. package/dist/core/terminal-settings.d.ts +22 -0
  197. package/dist/core/terminal-settings.d.ts.map +1 -0
  198. package/dist/core/terminal-settings.js +2 -0
  199. package/dist/core/terminal-settings.js.map +1 -0
  200. package/dist/index.d.ts +1 -1
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +1 -1
  203. package/dist/index.js.map +1 -1
  204. package/dist/main.d.ts +4 -4
  205. package/dist/main.d.ts.map +1 -1
  206. package/dist/main.js +27 -11
  207. package/dist/main.js.map +1 -1
  208. package/dist/modes/app-server/daemon/process.d.ts +13 -2
  209. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  210. package/dist/modes/app-server/daemon/process.js +58 -12
  211. package/dist/modes/app-server/daemon/process.js.map +1 -1
  212. package/dist/modes/app-server/daemon.js +65 -7
  213. package/dist/modes/app-server/daemon.js.map +1 -1
  214. package/dist/modes/index.d.ts +1 -1
  215. package/dist/modes/index.d.ts.map +1 -1
  216. package/dist/modes/index.js +1 -1
  217. package/dist/modes/index.js.map +1 -1
  218. package/dist/modes/interactive/interactive-host-runtime.d.ts +84 -1
  219. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  220. package/dist/modes/interactive/interactive-host-runtime.js +435 -112
  221. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  222. package/dist/modes/interactive/interactive-mode.d.ts +11 -1
  223. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  224. package/dist/modes/interactive/interactive-mode.js +59 -6
  225. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  226. package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
  227. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  228. package/dist/modes/rpc/connection-handler.d.ts +12 -5
  229. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  230. package/dist/modes/rpc/connection-handler.js +180 -25
  231. package/dist/modes/rpc/connection-handler.js.map +1 -1
  232. package/dist/modes/rpc/custom-capability.d.ts +2 -0
  233. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  234. package/dist/modes/rpc/custom-capability.js +2 -0
  235. package/dist/modes/rpc/custom-capability.js.map +1 -1
  236. package/dist/modes/rpc/host-ensure.d.ts +17 -0
  237. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  238. package/dist/modes/rpc/host-ensure.js +150 -23
  239. package/dist/modes/rpc/host-ensure.js.map +1 -1
  240. package/dist/modes/rpc/host-lifecycle.d.ts +54 -0
  241. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  242. package/dist/modes/rpc/host-lifecycle.js +259 -69
  243. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  244. package/dist/modes/rpc/host-watchdog.d.ts +2 -2
  245. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  246. package/dist/modes/rpc/host-watchdog.js +89 -21
  247. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  248. package/dist/modes/rpc/multi-session-host.d.ts +38 -0
  249. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  250. package/dist/modes/rpc/multi-session-host.js +149 -61
  251. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  252. package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
  253. package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
  254. package/dist/modes/rpc/ownership-safe-lock.js +87 -0
  255. package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
  256. package/dist/modes/rpc/rpc-client.d.ts +13 -2
  257. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  258. package/dist/modes/rpc/rpc-client.js +46 -12
  259. package/dist/modes/rpc/rpc-client.js.map +1 -1
  260. package/dist/modes/rpc/rpc-types.d.ts +21 -3
  261. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  262. package/dist/modes/rpc/rpc-types.js +1 -0
  263. package/dist/modes/rpc/rpc-types.js.map +1 -1
  264. package/dist/modes/rpc/session-binding.d.ts +2 -1
  265. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  266. package/dist/modes/rpc/session-binding.js +1 -0
  267. package/dist/modes/rpc/session-binding.js.map +1 -1
  268. package/dist/modes/rpc/session-command-router.d.ts +54 -1
  269. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  270. package/dist/modes/rpc/session-command-router.js +180 -3
  271. package/dist/modes/rpc/session-command-router.js.map +1 -1
  272. package/dist/modes/rpc/session-event-writer.d.ts +18 -0
  273. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  274. package/dist/modes/rpc/session-event-writer.js +88 -8
  275. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  276. package/dist/modes/rpc/session-registry.d.ts +11 -1
  277. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  278. package/dist/modes/rpc/session-registry.js +25 -0
  279. package/dist/modes/rpc/session-registry.js.map +1 -1
  280. package/dist/modes/rpc/socket-transport.d.ts +13 -0
  281. package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
  282. package/dist/modes/rpc/socket-transport.js +92 -0
  283. package/dist/modes/rpc/socket-transport.js.map +1 -0
  284. package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
  285. package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
  286. package/dist/modes/rpc/widget-line-renderer.js +73 -0
  287. package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
  288. package/dist/utils/fs-watch.d.ts.map +1 -1
  289. package/dist/utils/fs-watch.js +11 -2
  290. package/dist/utils/fs-watch.js.map +1 -1
  291. package/docs/app-server.md +2 -2
  292. package/docs/containerization.md +2 -2
  293. package/docs/development.md +7 -7
  294. package/docs/extensions.md +5 -5
  295. package/docs/grok-neo.md +1 -1
  296. package/docs/index.md +1 -1
  297. package/docs/packages.md +2 -2
  298. package/docs/quickstart.md +4 -4
  299. package/docs/release-guide.md +21 -21
  300. package/docs/rpc.md +83 -6
  301. package/docs/sdk.md +1 -1
  302. package/docs/settings.md +4 -4
  303. package/docs/skills.md +2 -2
  304. package/docs/terminal-tools.md +1 -1
  305. package/docs/termux.md +1 -1
  306. package/docs/tui.md +1 -1
  307. package/examples/AGENTS.md +1 -1
  308. package/examples/sdk/README.md +1 -1
  309. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
  310. package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
  311. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  312. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
  313. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
  314. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
  315. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
  316. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
  317. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
  318. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
  319. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
  320. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
  321. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
  322. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
  323. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
  324. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
  325. package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
  326. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  327. package/node_modules/@earendil-works/pi-ai/README.md +6 -3
  328. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -7
  330. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
  332. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
  334. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  335. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
  336. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
  337. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
  338. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
  339. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
  340. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  341. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
  342. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  343. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  345. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  347. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  353. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  354. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
  355. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
  356. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
  357. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
  358. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
  359. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
  360. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
  361. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
  362. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
  363. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
  364. package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
  365. package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
  366. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  367. package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
  368. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  369. package/node_modules/@earendil-works/pi-tui/README.md +5 -4
  370. package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
  371. package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
  372. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  373. 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":"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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\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"]}
@@ -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,23 @@
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
+ forbidToolCalls?: boolean;
11
+ messages: AgentMessage[];
12
+ onProgress?: CompactionProgressCallback;
13
+ prompt: ReturnType<typeof buildPrompt>;
14
+ signal?: AbortSignal;
15
+ snapshot: SpeculativeCompactionSnapshot;
16
+ auth: {
17
+ apiKey?: string;
18
+ headers?: ProviderHeaders;
19
+ extraBody?: Record<string, unknown>;
20
+ };
21
+ }): Promise<Message | undefined>;
22
+ export {};
23
+ //# 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,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,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,CA+D/B"}
@@ -0,0 +1,132 @@
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
+ ...(options.forbidToolCalls ? { toolChoice: "none" } : {}),
113
+ });
114
+ await consumeStreamWithIdleTimeout(responseStream, {
115
+ idleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,
116
+ maxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,
117
+ abort: () => requestController.abort(),
118
+ signal: options.signal,
119
+ onEvent: (event) => {
120
+ if (event.type === "text_delta" && event.delta) {
121
+ options.onProgress?.(event.delta);
122
+ }
123
+ },
124
+ });
125
+ return await responseStream.result();
126
+ }
127
+ finally {
128
+ if (options.signal)
129
+ options.signal.removeEventListener("abort", onCallerAbort);
130
+ }
131
+ }
132
+ //# 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\tforbidToolCalls?: boolean;\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\t...(options.forbidToolCalls ? { toolChoice: \"none\" as const } : {}),\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"]}