@herbertgao/pi-extensions 2026.9.19 → 2026.10.0

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 (444) hide show
  1. package/README.md +14 -16
  2. package/THIRD_PARTY_NOTICES.md +29 -3
  3. package/node_modules/@herbertgao/pi-bark/README.md +39 -3
  4. package/node_modules/@herbertgao/pi-bark/package.json +1 -1
  5. package/node_modules/@herbertgao/pi-bark/src/index.ts +275 -15
  6. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +85 -68
  7. package/node_modules/@herbertgao/pi-cc-extensions/README.md +79 -62
  8. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +116 -34
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +370 -118
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +31 -33
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +521 -0
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/mcp-chip.ts +136 -0
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +58 -38
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1127 -231
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +267 -262
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +38 -48
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +287 -114
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +303 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +151 -0
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +4 -4
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +103 -48
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +8 -7
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +2 -1
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +171 -196
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +27 -93
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +429 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +259 -164
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +77 -0
  61. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  62. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  64. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  65. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/package.json +10 -8
  67. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  68. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  69. package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +3 -2
  70. package/node_modules/@herbertgao/sol-pi/CONTRIBUTING.md +22 -0
  71. package/node_modules/@herbertgao/sol-pi/README.md +36 -17
  72. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +10 -6
  73. package/node_modules/@herbertgao/sol-pi/agents-install.md +15 -12
  74. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +24 -8
  75. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +2 -2
  76. package/node_modules/@herbertgao/sol-pi/docs/star-history.md +18 -0
  77. package/node_modules/@herbertgao/sol-pi/package.json +4 -2
  78. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +1 -1
  79. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +1 -1
  80. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +23 -4
  81. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +32 -1
  82. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +3 -2
  83. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +1 -1
  84. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +27 -7
  85. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +137 -41
  86. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +1 -0
  87. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +2 -1
  88. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/projection.ts +58 -0
  89. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +28 -6
  90. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +2 -1
  91. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +15 -2
  92. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  93. package/node_modules/@pi-plugins/fast-mode/README.md +7 -1
  94. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  95. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +7 -1
  96. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  97. package/node_modules/@pi-plugins/fast-mode/package.json +5 -5
  98. package/node_modules/pi-antigravity/README.md +3 -0
  99. package/node_modules/pi-antigravity/package.json +8 -8
  100. package/node_modules/pi-antigravity/src/auth/oauth.ts +6 -3
  101. package/node_modules/pi-antigravity/src/index.ts +114 -110
  102. package/node_modules/pi-antigravity/src/stream/stream.ts +1 -1
  103. package/node_modules/pi-antigravity/src/utils/util.ts +18 -1
  104. package/node_modules/pi-multi-account/CHANGELOG.md +20 -0
  105. package/node_modules/pi-multi-account/README.md +46 -8
  106. package/node_modules/pi-multi-account/config-file-transaction.ts +42 -0
  107. package/node_modules/pi-multi-account/index.ts +255 -269
  108. package/node_modules/pi-multi-account/model-pins.ts +36 -0
  109. package/node_modules/pi-multi-account/package.json +9 -7
  110. package/node_modules/pi-multi-account/slot-proxy-auth.ts +12 -2
  111. package/node_modules/pi-multi-account/slot-proxy.ts +27 -5
  112. package/node_modules/pi-web-access/CHANGELOG.md +17 -0
  113. package/node_modules/pi-web-access/README.md +6 -3
  114. package/node_modules/pi-web-access/brave-rate-limit.ts +170 -0
  115. package/node_modules/pi-web-access/brave.ts +28 -11
  116. package/node_modules/pi-web-access/dist/index.js +202 -33
  117. package/node_modules/pi-web-access/gemini-search.ts +2 -5
  118. package/node_modules/pi-web-access/index.ts +13 -7
  119. package/node_modules/pi-web-access/openai-search.ts +24 -10
  120. package/node_modules/pi-web-access/package.json +1 -1
  121. package/node_modules/pi-web-access/summary-review.ts +8 -2
  122. package/node_modules/{@herbertgao/resume-from → resume-from}/README.md +16 -12
  123. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.d.ts +0 -5
  124. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.js +2 -3
  125. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.d.ts +2 -2
  126. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.d.ts +3 -0
  127. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.js +27 -15
  128. package/node_modules/{@herbertgao/resume-from/dist/adapters/codex → resume-from/dist/adapters/claude-code}/redaction.js +16 -3
  129. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.d.ts +2 -4
  130. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.js +1 -1
  131. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.d.ts +2 -4
  132. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.js +1 -2
  133. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/read.d.ts +16 -0
  134. package/node_modules/resume-from/dist/adapters/codex/read.js +723 -0
  135. package/node_modules/{@herbertgao/resume-from/dist/adapters/pi → resume-from/dist/adapters/codex}/redaction.js +16 -3
  136. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.d.ts +44 -4
  137. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.js +88 -4
  138. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.d.ts +2 -2
  139. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.js +2 -2
  140. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.d.ts +5 -1
  141. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.js +10 -6
  142. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.d.ts +2 -2
  143. package/node_modules/{@herbertgao/resume-from/dist/adapters/claude-code → resume-from/dist/adapters/pi}/redaction.js +16 -3
  144. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.d.ts +2 -4
  145. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.js +2 -2
  146. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.d.ts +1 -1
  147. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.js +4 -4
  148. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.js +2 -2
  149. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.d.ts +2 -2
  150. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.js +31 -8
  151. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.d.ts +1 -1
  152. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.js +1 -2
  153. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.d.ts +4 -1
  154. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.js +2 -2
  155. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.d.ts +8 -6
  156. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.d.ts +10 -5
  157. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/finder.d.ts +2 -1
  158. package/node_modules/resume-from/dist/import/discovery/finder.js +269 -0
  159. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.d.ts +3 -3
  160. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.js +3 -3
  161. package/node_modules/resume-from/dist/import/pipeline.d.ts +28 -0
  162. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/pipeline.js +31 -11
  163. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.d.ts +2 -2
  164. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.js +9 -5
  165. package/node_modules/resume-from/dist/import/preview/warnings.d.ts +14 -0
  166. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/warnings.js +26 -20
  167. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.js +12 -2
  168. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.d.ts +9 -3
  169. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.d.ts +4 -4
  170. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.js +7 -4
  171. package/node_modules/resume-from/dist/platform/repo/reader.d.ts +3 -0
  172. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/reader.js +60 -20
  173. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.d.ts +8 -1
  174. package/node_modules/{@herbertgao/resume-from → resume-from}/package.json +19 -32
  175. package/node_modules/{@herbertgao/resume-from → resume-from}/shims/pi/extensions/resume-from.js +2 -2
  176. package/package.json +18 -22
  177. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  178. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  179. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  180. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  181. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  182. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  183. package/node_modules/@herbertgao/resume-from/dist/adapters/codex/read.js +0 -270
  184. package/node_modules/@herbertgao/resume-from/dist/import/discovery/finder.js +0 -129
  185. package/node_modules/@herbertgao/resume-from/dist/import/pipeline.d.ts +0 -17
  186. package/node_modules/@herbertgao/resume-from/dist/import/preview/warnings.d.ts +0 -11
  187. package/node_modules/@herbertgao/resume-from/dist/platform/repo/reader.d.ts +0 -8
  188. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  189. package/node_modules/pi-footer/LICENSE +0 -21
  190. package/node_modules/pi-footer/README.md +0 -354
  191. package/node_modules/pi-footer/package.json +0 -68
  192. package/node_modules/pi-footer/src/cache.ts +0 -106
  193. package/node_modules/pi-footer/src/colors.ts +0 -237
  194. package/node_modules/pi-footer/src/config.ts +0 -202
  195. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  196. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  197. package/node_modules/pi-footer/src/git.ts +0 -135
  198. package/node_modules/pi-footer/src/index.ts +0 -268
  199. package/node_modules/pi-footer/src/metrics.ts +0 -141
  200. package/node_modules/pi-footer/src/presets.ts +0 -383
  201. package/node_modules/pi-footer/src/render.ts +0 -114
  202. package/node_modules/pi-footer/src/separators.ts +0 -52
  203. package/node_modules/pi-footer/src/types.ts +0 -122
  204. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  205. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  206. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  207. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  208. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  209. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  210. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  211. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  212. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  213. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  214. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  215. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  216. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  217. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  218. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  219. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  220. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  221. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  222. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  223. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  224. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  225. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  226. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  227. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  228. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  229. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  230. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  231. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  232. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  233. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  234. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  235. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  236. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  237. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  238. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  239. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  240. package/node_modules/pi-footer/src/ui.ts +0 -66
  241. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  242. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  243. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  244. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  245. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  246. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  247. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  248. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  249. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  250. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  251. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  252. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  253. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  254. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  255. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  256. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  257. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  258. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  259. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  260. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  261. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  262. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  263. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  264. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  265. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  266. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  267. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  268. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  269. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  270. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  271. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  272. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  273. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  274. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  275. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  276. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  277. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  278. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  279. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  280. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  281. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  282. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  283. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  284. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  285. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  286. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  287. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  288. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  289. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  290. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  291. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  292. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  293. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  294. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  295. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  296. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  297. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  298. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  299. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  300. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  301. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  302. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  303. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  304. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  305. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  306. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
  307. /package/node_modules/{@herbertgao/resume-from → resume-from}/LICENSE +0 -0
  308. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.js +0 -0
  309. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.d.ts +0 -0
  310. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.js +0 -0
  311. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.d.ts +0 -0
  312. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.js +0 -0
  313. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.d.ts +0 -0
  314. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.js +0 -0
  315. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.d.ts +0 -0
  316. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.js +0 -0
  317. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/redaction.d.ts +0 -0
  318. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.d.ts +0 -0
  319. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.js +0 -0
  320. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.js +0 -0
  321. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.d.ts +0 -0
  322. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.d.ts +0 -0
  323. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.js +0 -0
  324. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/redaction.d.ts +0 -0
  325. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.d.ts +0 -0
  326. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.js +0 -0
  327. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.js +0 -0
  328. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.d.ts +0 -0
  329. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.js +0 -0
  330. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.d.ts +0 -0
  331. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.js +0 -0
  332. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.d.ts +0 -0
  333. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.js +0 -0
  334. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.d.ts +0 -0
  335. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.js +0 -0
  336. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/redaction.d.ts +0 -0
  337. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.d.ts +0 -0
  338. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.js +0 -0
  339. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.d.ts +0 -0
  340. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.js +0 -0
  341. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.d.ts +0 -0
  342. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.js +0 -0
  343. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.d.ts +0 -0
  344. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.js +0 -0
  345. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.d.ts +0 -0
  346. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.js +0 -0
  347. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.d.ts +0 -0
  348. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.js +0 -0
  349. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.d.ts +0 -0
  350. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.js +0 -0
  351. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.d.ts +0 -0
  352. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.js +0 -0
  353. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.d.ts +0 -0
  354. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.js +0 -0
  355. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.d.ts +0 -0
  356. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.js +0 -0
  357. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.d.ts +0 -0
  358. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.js +0 -0
  359. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.d.ts +0 -0
  360. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.d.ts +0 -0
  361. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.js +0 -0
  362. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.d.ts +0 -0
  363. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.js +0 -0
  364. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.d.ts +0 -0
  365. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.js +0 -0
  366. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.d.ts +0 -0
  367. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.js +0 -0
  368. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.d.ts +0 -0
  369. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.js +0 -0
  370. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.d.ts +0 -0
  371. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.js +0 -0
  372. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.d.ts +0 -0
  373. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.js +0 -0
  374. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.d.ts +0 -0
  375. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.js +0 -0
  376. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.js +0 -0
  377. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.js +0 -0
  378. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.d.ts +0 -0
  379. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.js +0 -0
  380. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.d.ts +0 -0
  381. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.js +0 -0
  382. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.d.ts +0 -0
  383. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.js +0 -0
  384. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.d.ts +0 -0
  385. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.js +0 -0
  386. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.d.ts +0 -0
  387. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.js +0 -0
  388. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.d.ts +0 -0
  389. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.js +0 -0
  390. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.js +0 -0
  391. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.d.ts +0 -0
  392. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.js +0 -0
  393. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.d.ts +0 -0
  394. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.js +0 -0
  395. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.d.ts +0 -0
  396. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.js +0 -0
  397. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.d.ts +0 -0
  398. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.d.ts +0 -0
  399. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.js +0 -0
  400. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.d.ts +0 -0
  401. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.js +0 -0
  402. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.d.ts +0 -0
  403. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.js +0 -0
  404. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.d.ts +0 -0
  405. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.js +0 -0
  406. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.d.ts +0 -0
  407. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.js +0 -0
  408. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.d.ts +0 -0
  409. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.js +0 -0
  410. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.d.ts +0 -0
  411. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.js +0 -0
  412. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.d.ts +0 -0
  413. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.d.ts +0 -0
  414. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.js +0 -0
  415. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.d.ts +0 -0
  416. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.js +0 -0
  417. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.d.ts +0 -0
  418. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.js +0 -0
  419. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.d.ts +0 -0
  420. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.js +0 -0
  421. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.d.ts +0 -0
  422. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.js +0 -0
  423. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.d.ts +0 -0
  424. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.js +0 -0
  425. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.d.ts +0 -0
  426. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.js +0 -0
  427. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.d.ts +0 -0
  428. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.js +0 -0
  429. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.js +0 -0
  430. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.d.ts +0 -0
  431. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.js +0 -0
  432. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.d.ts +0 -0
  433. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.js +0 -0
  434. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.d.ts +0 -0
  435. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.js +0 -0
  436. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.d.ts +0 -0
  437. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.js +0 -0
  438. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.d.ts +0 -0
  439. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.js +0 -0
  440. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.d.ts +0 -0
  441. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.js +0 -0
  442. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.d.ts +0 -0
  443. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.js +0 -0
  444. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.js +0 -0
@@ -9,6 +9,8 @@ export type CompactionEconomics = {
9
9
  readonly windowReserveTokens: number;
10
10
  readonly firstCompactionRequestScale: number;
11
11
  readonly subsequentCompactionMargin: number;
12
+ /** Minimum provider requests since the last compaction before economics may compact again. */
13
+ readonly minimumRequestsSinceCompaction: number;
12
14
  };
13
15
 
14
16
  export const DEFAULT_COMPACTION_ECONOMICS: CompactionEconomics = Object.freeze({
@@ -17,6 +19,7 @@ export const DEFAULT_COMPACTION_ECONOMICS: CompactionEconomics = Object.freeze({
17
19
  windowReserveTokens: 16_384,
18
20
  firstCompactionRequestScale: 2,
19
21
  subsequentCompactionMargin: 1.5,
22
+ minimumRequestsSinceCompaction: 2,
20
23
  });
21
24
 
22
25
  export type CompactionReason =
@@ -25,6 +28,7 @@ export type CompactionReason =
25
28
  | "deferred_economic"
26
29
  | "deferred_subsequent_margin"
27
30
  | "deferred_carried_debt"
31
+ | "deferred_post_compaction_cooldown"
28
32
  | "horizon_unavailable"
29
33
  | "cache_ratio_unavailable"
30
34
  | "native_not_compactable"
@@ -44,6 +48,8 @@ export type CompactionDecision = {
44
48
  readonly writeTokens: number;
45
49
  readonly archiveTokens: number;
46
50
  readonly memoTokens: number;
51
+ /** Estimated context written after compaction, including the replacement memo. */
52
+ readonly postCompactionTokens: number;
47
53
  readonly contextTokens: number;
48
54
  readonly completedBoundaryRequestCounts: readonly number[] | null;
49
55
  readonly requestsPerBoundaryMean: number | null;
@@ -58,6 +64,7 @@ export type CompactionDecision = {
58
64
  readonly cacheWriteReadRatio: number | null;
59
65
  readonly incrementalCacheCostRatio: number | null;
60
66
  readonly priorCompactionCount: number;
67
+ readonly requestsSinceLastCompaction: number | null;
61
68
  readonly carriedDebtTokens: number;
62
69
  readonly cacheDebtRepaymentTokens: number;
63
70
  readonly compact: boolean;
@@ -129,6 +136,8 @@ export function decideCompaction(input: {
129
136
  readonly averageContextTokenIncrement: number | null;
130
137
  readonly contextWindowTokens: number | null;
131
138
  readonly priorCompactionCount: number;
139
+ /** Provider requests since the last compaction; null when never compacted. */
140
+ readonly requestsSinceLastCompaction?: number | null;
132
141
  readonly carriedDebtTokens: number;
133
142
  readonly cacheDebtRepaymentTokens: number;
134
143
  readonly cacheWriteReadRatio: number | null;
@@ -147,15 +156,16 @@ export function decideCompaction(input: {
147
156
  averageContextTokenIncrement: input.averageContextTokenIncrement,
148
157
  });
149
158
  const savingTokens = input.archiveTokens - input.memoTokens;
159
+ const postCompactionTokens = Math.max(0, input.writeTokens - savingTokens);
150
160
  const incrementalCacheCostRatio =
151
161
  input.cacheWriteReadRatio === null ? null : Math.max(0, input.cacheWriteReadRatio - 1);
162
+ const newDebtTokens = postCompactionTokens * (incrementalCacheCostRatio ?? 0);
152
163
  const breakevenRequests =
153
- savingTokens > 0 && incrementalCacheCostRatio !== null
154
- ? (input.writeTokens * incrementalCacheCostRatio) / savingTokens
155
- : null;
164
+ savingTokens > 0 && incrementalCacheCostRatio !== null ? newDebtTokens / savingTokens : null;
165
+ const combinedRepaymentTokens = input.cacheDebtRepaymentTokens + savingTokens;
156
166
  const combinedBreakevenRequests =
157
- savingTokens > 0 && incrementalCacheCostRatio !== null
158
- ? (input.carriedDebtTokens + input.writeTokens * incrementalCacheCostRatio) / savingTokens
167
+ savingTokens > 0 && incrementalCacheCostRatio !== null && combinedRepaymentTokens > 0
168
+ ? (input.carriedDebtTokens + newDebtTokens) / combinedRepaymentTokens
159
169
  : null;
160
170
  const firstCompaction = input.priorCompactionCount === 0;
161
171
  const effectiveHorizonRequests =
@@ -193,12 +203,19 @@ export function decideCompaction(input: {
193
203
  combinedBreakevenRequests <= horizon.expectedRemainingRequests;
194
204
  const economic = firstCompaction ? firstEconomic : baseEconomic && subsequentMarginOpen && carriedDebtGateOpen;
195
205
  const compressible = savingTokens > 0;
196
- const compact = compressible && (windowProtection || economic);
206
+ const cooldownActive =
207
+ input.requestsSinceLastCompaction !== null &&
208
+ input.requestsSinceLastCompaction !== undefined &&
209
+ input.requestsSinceLastCompaction < input.economics.minimumRequestsSinceCompaction;
210
+ // Window protection stays absolute: near the context limit, compact even in cooldown.
211
+ const economicAllowed = economic && !cooldownActive;
212
+ const compact = compressible && (windowProtection || economicAllowed);
197
213
 
198
214
  return {
199
215
  writeTokens: input.writeTokens,
200
216
  archiveTokens: input.archiveTokens,
201
217
  memoTokens: input.memoTokens,
218
+ postCompactionTokens,
202
219
  contextTokens: input.contextTokens,
203
220
  ...(horizon ?? {
204
221
  completedBoundaryRequestCounts: null,
@@ -215,13 +232,16 @@ export function decideCompaction(input: {
215
232
  cacheWriteReadRatio: input.cacheWriteReadRatio,
216
233
  incrementalCacheCostRatio,
217
234
  priorCompactionCount: input.priorCompactionCount,
235
+ requestsSinceLastCompaction: input.requestsSinceLastCompaction ?? null,
218
236
  carriedDebtTokens: input.carriedDebtTokens,
219
237
  cacheDebtRepaymentTokens: input.cacheDebtRepaymentTokens,
220
238
  compact,
221
239
  reason: compressible
222
240
  ? windowProtection
223
241
  ? "window_protection"
224
- : economic
242
+ : economic && cooldownActive
243
+ ? "deferred_post_compaction_cooldown"
244
+ : economic
225
245
  ? "economic"
226
246
  : horizon === null
227
247
  ? "horizon_unavailable"
@@ -4,7 +4,6 @@
4
4
  */
5
5
  import type { AgentMessage, AgentToolResult, ThinkingLevel } from "@earendil-works/pi-agent-core";
6
6
  import {
7
- buildSessionContext,
8
7
  estimateTokens,
9
8
  findCutPoint,
10
9
  sessionEntryToContextMessages,
@@ -20,11 +19,13 @@ import {
20
19
  type CompactionDecision,
21
20
  } from "./economics.ts";
22
21
  import { analyzePlanTransition, formatPlanSnapshot, parsePlanSteps } from "./plan.ts";
22
+ import { projectedEntryTokens } from "./projection.ts";
23
23
  import {
24
24
  appendOnlineState,
25
25
  initialOnlineState,
26
26
  recordBoundary,
27
27
  recordCompaction,
28
+ recordCompletedPlanHandoff,
28
29
  recordCorrection,
29
30
  recordProviderRequest,
30
31
  restoreOnlineState,
@@ -39,7 +40,17 @@ export const BOUNDARY_COMPACTION_INSTRUCTIONS =
39
40
  "Preserve completed work, verification results, important decisions, and remaining work.";
40
41
  export const POST_COMPACTION_PLAN_REMINDER =
41
42
  "Online context compaction finished. The parent task is still active. " +
42
- "Before continuing work, call update_plan with a fresh plan for the remaining work.";
43
+ "Continue the remaining work from the current plan. Preserve existing step IDs when updating progress.";
44
+ export const SKIPPED_COMPACTION_REMINDER =
45
+ "Online context compaction was skipped. The existing context is still available. " +
46
+ "Continue the remaining work from the current plan.";
47
+ // Pi rejects these before committing a replacement summary, so the current
48
+ // context is still usable. Unknown errors and user cancellation remain distinct.
49
+ const RECOVERABLE_COMPACTION_ERRORS = new Set([
50
+ "Nothing to compact (session too small)",
51
+ "Already compacted",
52
+ "Summarization failed: generation hit the token cap and the summary is incomplete",
53
+ ]);
43
54
 
44
55
  export type OnlineContextCompactOptions = {
45
56
  readonly cacheWriteReadRatio?: number | null;
@@ -49,6 +60,11 @@ export type OnlineContextCompactOptions = {
49
60
  type PendingBoundary = { readonly toolCallId: string };
50
61
  type SelectedCompaction = { readonly decision: CompactionDecision };
51
62
  type CacheDebt = { readonly debtTokens: number; readonly repaymentTokens: number };
63
+ type PendingContinuation = { readonly promise: Promise<void>; readonly resolve: () => void };
64
+
65
+ function releaseParentContinuation(continuation: PendingContinuation | undefined): void {
66
+ if (continuation) setTimeout(continuation.resolve, 0);
67
+ }
52
68
 
53
69
  const SUBAGENTS_MANAGER_KEY = Symbol.for("pi-subagents:manager");
54
70
 
@@ -100,13 +116,24 @@ function progressSummary(input: PlanUpdateInput, completedStepId: string): Progr
100
116
  };
101
117
  }
102
118
 
103
- function compactionMessageCount(entries: readonly SessionEntry[], startIndex: number, endIndex: number): number {
104
- let count = 0;
119
+ function compactionTokenEstimate(
120
+ entries: readonly SessionEntry[],
121
+ startIndex: number,
122
+ endIndex: number,
123
+ projected?: ReadonlyMap<string, number>,
124
+ ): number {
125
+ let tokens = 0;
105
126
  for (let index = startIndex; index < endIndex; index++) {
106
127
  const entry = entries[index];
107
- if (entry && entry.type !== "compaction" && sessionEntryToContextMessages(entry).length > 0) count++;
128
+ if (!entry || entry.type === "compaction") continue;
129
+ if (projected) {
130
+ tokens += projected.get(entry.id) ?? 0;
131
+ continue;
132
+ }
133
+ const message = sessionEntryToContextMessages(entry)[0];
134
+ if (message) tokens += estimateTokens(message);
108
135
  }
109
- return count;
136
+ return tokens;
110
137
  }
111
138
 
112
139
  function branchAfterAbort(entries: readonly SessionEntry[]): SessionEntry[] {
@@ -140,25 +167,33 @@ function branchAfterAbort(entries: readonly SessionEntry[]): SessionEntry[] {
140
167
  ];
141
168
  }
142
169
 
143
- function nativeCompactionFeasible(entries: readonly SessionEntry[], keepRecentTokens: number): boolean {
170
+ export function estimateNativeCompactionTokens(
171
+ entries: readonly SessionEntry[],
172
+ keepRecentTokens: number,
173
+ projectedMessages?: readonly AgentMessage[],
174
+ ): number {
144
175
  const path = branchAfterAbort(entries);
176
+ const projected = projectedMessages === undefined ? undefined : projectedEntryTokens(entries, projectedMessages);
145
177
  let startIndex = 0;
178
+ let previousSummaryTokens = 0;
146
179
  for (let index = path.length - 1; index >= 0; index--) {
147
180
  const entry = path[index];
148
181
  if (entry?.type !== "compaction") continue;
149
182
  const keptIndex = path.findIndex((item) => item.id === entry.firstKeptEntryId);
150
183
  startIndex = keptIndex >= 0 ? keptIndex : index + 1;
184
+ const previousSummary = sessionEntryToContextMessages(entry)[0];
185
+ previousSummaryTokens = projected
186
+ ? projected.get(entry.id) ?? 0
187
+ : previousSummary ? estimateTokens(previousSummary) : 0;
151
188
  break;
152
189
  }
153
190
 
191
+ // Keep Pi's native cut on session entries; price only the corresponding
192
+ // messages that the provider actually saw after context projection.
154
193
  const cut = findCutPoint(path, startIndex, path.length, keepRecentTokens);
155
- const historyEnd = cut.isSplitTurn ? cut.turnStartIndex : cut.firstKeptEntryIndex;
156
- const historyMessages = historyEnd > startIndex ? compactionMessageCount(path, startIndex, historyEnd) : 0;
157
- const prefixMessages =
158
- cut.isSplitTurn && cut.turnStartIndex >= 0
159
- ? compactionMessageCount(path, cut.turnStartIndex, cut.firstKeptEntryIndex)
160
- : 0;
161
- return historyMessages > 0 || prefixMessages > 0;
194
+ const firstKept = cut.firstKeptEntryIndex;
195
+ if (compactionTokenEstimate(path, startIndex, firstKept) === 0) return 0;
196
+ return previousSummaryTokens + compactionTokenEstimate(path, startIndex, firstKept, projected);
162
197
  }
163
198
 
164
199
  function validPositiveInteger(value: unknown): value is number {
@@ -209,18 +244,26 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
209
244
  let activeDebt: CacheDebt | undefined;
210
245
  let compactionInFlight = false;
211
246
  let compactionThinkingOverride: CompactionThinkingOverride | undefined;
247
+ let nextContinuation: PendingContinuation | undefined;
248
+ let compactionRefused = false;
249
+
250
+ const releaseContinuation = (): void => {
251
+ const continuation = nextContinuation;
252
+ nextContinuation = undefined;
253
+ continuation?.resolve();
254
+ };
212
255
 
213
256
  const restore = (context: ExtensionContext): void => {
257
+ releaseContinuation();
214
258
  state = restoreOnlineState(context.sessionManager.getBranch());
215
259
  restored = true;
216
- observedMessages = buildSessionContext(
217
- context.sessionManager.getEntries(),
218
- context.sessionManager.getLeafId(),
219
- ).messages;
260
+ // Restoring raw history is not evidence of a provider-visible projection.
261
+ observedMessages = [];
220
262
  pendingBoundary = undefined;
221
263
  selected = undefined;
222
264
  activeDebt = undefined;
223
265
  compactionInFlight = false;
266
+ compactionRefused = false;
224
267
  };
225
268
  const ensureRestored = (context: ExtensionContext): void => {
226
269
  if (!restored) restore(context);
@@ -245,7 +288,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
245
288
  if (completedIds.length > 0) {
246
289
  state = recordBoundary(state, steps, progressSummary(input, completedIds[0] ?? ""));
247
290
  if (!pendingBoundary) pendingBoundary = { toolCallId: input.toolCallId };
248
- } else if (JSON.stringify(state.plan) !== JSON.stringify(steps)) {
291
+ } else {
249
292
  state = { ...state, plan: [...steps] };
250
293
  }
251
294
  save();
@@ -279,10 +322,16 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
279
322
  });
280
323
 
281
324
  pi.on("input", (event, context) => {
325
+ compactionRefused = false;
326
+ ensureRestored(context);
282
327
  if (event.streamingBehavior !== "steer" && !event.text.startsWith("CORRECTION:")) {
328
+ const next = recordCompletedPlanHandoff(state);
329
+ if (next !== state) {
330
+ state = next;
331
+ save();
332
+ }
283
333
  return { action: "continue" as const };
284
334
  }
285
- ensureRestored(context);
286
335
  pendingBoundary = undefined;
287
336
  selected = undefined;
288
337
  activeDebt = undefined;
@@ -292,9 +341,12 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
292
341
  });
293
342
 
294
343
  pi.on("turn_end", (event, context) => {
344
+ // Plan chatter cannot make a rejected compact feasible. Require actual
345
+ // tool work or new user input before attempting another boundary.
346
+ if (event.toolResults.some((item) => item.toolName !== "update_plan" && !item.isError)) compactionRefused = false;
295
347
  const boundary = pendingBoundary;
296
348
  pendingBoundary = undefined;
297
- if (!boundary || selected || hasRunningSubagents()) return;
349
+ if (!boundary || selected || compactionRefused || hasRunningSubagents()) return;
298
350
  const toolResult = event.toolResults.find((item) => item.toolCallId === boundary.toolCallId);
299
351
  if (
300
352
  event.message.role !== "assistant" ||
@@ -309,8 +361,11 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
309
361
 
310
362
  const usage = context.getContextUsage();
311
363
  const writeTokens = contextTokens(context);
312
- const fixedTokens = tokenEstimate(context.getSystemPrompt());
313
- const archiveTokens = Math.max(0, writeTokens - fixedTokens - keepRecentTokens);
364
+ const archiveTokens = estimateNativeCompactionTokens(
365
+ context.sessionManager.getBranch(),
366
+ keepRecentTokens,
367
+ observedMessages,
368
+ );
314
369
  const contextWindowTokens = validPositiveInteger(usage?.contextWindow)
315
370
  ? usage.contextWindow
316
371
  : validPositiveInteger(context.model?.contextWindow)
@@ -330,13 +385,17 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
330
385
  averageContextTokenIncrement,
331
386
  contextWindowTokens,
332
387
  priorCompactionCount: state.nativeCompactionCount,
388
+ requestsSinceLastCompaction:
389
+ state.lastCompactionRequestCount === null
390
+ ? null
391
+ : state.requestCount - state.lastCompactionRequestCount,
333
392
  carriedDebtTokens: state.cacheDebtTokens,
334
393
  cacheDebtRepaymentTokens: state.cacheDebtRepaymentTokens,
335
394
  cacheWriteReadRatio,
336
395
  economics: DEFAULT_COMPACTION_ECONOMICS,
337
396
  });
338
397
  const decision: CompactionDecision =
339
- priced.compact && !nativeCompactionFeasible(context.sessionManager.getBranch(), keepRecentTokens)
398
+ priced.compact && archiveTokens === 0
340
399
  ? { ...priced, compact: false, reason: "native_not_compactable" }
341
400
  : priced;
342
401
  if (!decision.compact) return;
@@ -346,16 +405,24 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
346
405
  });
347
406
 
348
407
  pi.on("agent_settled", async (_event, context) => {
408
+ // Older hosts start a continuation synchronously; newer hosts defer it
409
+ // until settled handlers return. Preserve both print-mode barriers.
410
+ const parentContinuation = nextContinuation;
411
+ nextContinuation = undefined;
349
412
  const pending = selected;
350
413
  selected = undefined;
351
414
  if (!context.isIdle()) {
352
415
  selected = pending;
416
+ nextContinuation = parentContinuation;
417
+ return;
418
+ }
419
+ if (!pending || hasRunningSubagents()) {
420
+ releaseParentContinuation(parentContinuation);
353
421
  return;
354
422
  }
355
- if (!pending || hasRunningSubagents()) return;
356
423
 
357
424
  activeDebt = {
358
- debtTokens: pending.decision.writeTokens * (pending.decision.incrementalCacheCostRatio ?? 0),
425
+ debtTokens: pending.decision.postCompactionTokens * (pending.decision.incrementalCacheCostRatio ?? 0),
359
426
  repaymentTokens: Math.max(0, pending.decision.archiveTokens - pending.decision.memoTokens),
360
427
  };
361
428
  let compacted = false;
@@ -391,6 +458,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
391
458
  }
392
459
  },
393
460
  onError: (error) => {
461
+ activeDebt = undefined;
394
462
  compactionError = error;
395
463
  finish();
396
464
  },
@@ -399,36 +467,66 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
399
467
  restoreCompactionThinking(pi, compactionThinkingOverride);
400
468
  compactionThinkingOverride = undefined;
401
469
  compactionInFlight = false;
470
+ const recoverableError = compactionError !== undefined && RECOVERABLE_COMPACTION_ERRORS.has(compactionError.message);
402
471
  if (
403
472
  compactionError &&
473
+ !recoverableError &&
404
474
  compactionError.name !== "AbortError" &&
405
475
  compactionError.message !== "Compaction cancelled"
406
476
  ) {
407
477
  throw compactionError;
408
478
  }
409
479
 
410
- if (compacted) {
411
- // Pi >=0.87 defers this turn until agent_settled handlers finish and
412
- // awaits it before prompt() resolves, so print/JSON mode stays alive.
413
- pi.sendMessage(
414
- {
415
- customType: "sol-pi-online-context-compact",
416
- content: POST_COMPACTION_PLAN_REMINDER,
417
- display: false,
418
- },
419
- { triggerTurn: true },
420
- );
480
+ if (recoverableError) {
481
+ compactionRefused = true;
482
+ pi.appendEntry("sol-pi-online-context-compact-skipped", { reason: compactionError!.message });
483
+ if (context.mode === "tui") context.ui.notify(`Online compaction skipped: ${compactionError!.message}`, "warning");
484
+ }
485
+ if (compacted || recoverableError) {
486
+ let resolveContinuation!: () => void;
487
+ const continuation: PendingContinuation = {
488
+ promise: new Promise<void>((resolve) => {
489
+ resolveContinuation = resolve;
490
+ }),
491
+ resolve: () => resolveContinuation(),
492
+ };
493
+ nextContinuation = continuation;
494
+ try {
495
+ pi.sendMessage(
496
+ {
497
+ customType: "sol-pi-online-context-compact",
498
+ content: compacted ? POST_COMPACTION_PLAN_REMINDER : SKIPPED_COMPACTION_REMINDER,
499
+ display: false,
500
+ },
501
+ { triggerTurn: true },
502
+ );
503
+ } catch (error) {
504
+ if (nextContinuation === continuation) nextContinuation = undefined;
505
+ continuation.resolve();
506
+ throw error;
507
+ }
508
+ if (context.isIdle() && nextContinuation === continuation) {
509
+ // Newer Pi hosts defer runs until settled handlers return. Hand
510
+ // control back to that host instead of waiting on a deferred run.
511
+ nextContinuation = undefined;
512
+ continuation.resolve();
513
+ } else {
514
+ // Pi 0.85.1 starts synchronously; keep its print-mode barrier.
515
+ await continuation.promise;
516
+ }
421
517
  }
422
518
  } finally {
423
519
  restoreCompactionThinking(pi, compactionThinkingOverride);
424
520
  compactionThinkingOverride = undefined;
425
521
  compactionInFlight = false;
426
522
  activeDebt = undefined;
523
+ releaseParentContinuation(parentContinuation);
427
524
  }
428
525
  });
429
526
 
430
527
  pi.on("session_compact", (event, context) => {
431
528
  ensureRestored(context);
529
+ compactionRefused = false;
432
530
  state = recordCompaction(
433
531
  state,
434
532
  event.fromExtension || !activeDebt ? { debtTokens: 0, repaymentTokens: 0 } : activeDebt,
@@ -437,13 +535,11 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
437
535
  pendingBoundary = undefined;
438
536
  selected = undefined;
439
537
  activeDebt = undefined;
440
- observedMessages = buildSessionContext(
441
- context.sessionManager.getEntries(),
442
- context.sessionManager.getLeafId(),
443
- ).messages;
538
+ observedMessages = [];
444
539
  });
445
540
 
446
541
  pi.on("session_shutdown", () => {
542
+ releaseContinuation();
447
543
  restoreCompactionThinking(pi, compactionThinkingOverride);
448
544
  compactionThinkingOverride = undefined;
449
545
  pendingBoundary = undefined;
@@ -19,6 +19,7 @@ export {
19
19
  createOnlineContextCompactExtension,
20
20
  DEFAULT_KEEP_RECENT_TOKENS,
21
21
  DEFAULT_NATIVE_SUMMARY_TOKEN_ESTIMATE,
22
+ estimateNativeCompactionTokens,
22
23
  POST_COMPACTION_PLAN_REMINDER,
23
24
  type OnlineContextCompactOptions,
24
25
  resolveKeepRecentTokens,
@@ -59,7 +59,8 @@ export function analyzePlanTransition(previous: readonly PlanStep[], next: reado
59
59
 
60
60
  for (const step of next) {
61
61
  const prior = previousById.get(step.id);
62
- if ((!prior || prior.status !== "completed") && step.status === "completed") completedSteps.push(step);
62
+ // A newly introduced completed step establishes history, not a status transition.
63
+ if (prior && prior.status !== "completed" && step.status === "completed") completedSteps.push(step);
63
64
  if (prior && prior.goal !== step.goal) {
64
65
  advice.push(`Plan step ${JSON.stringify(step.id)} changed goal; reuse an id only for the same goal.`);
65
66
  }
@@ -0,0 +1,58 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
6
+ import { estimateTokens, sessionEntryToContextMessages, type SessionEntry } from "@earendil-works/pi-coding-agent";
7
+
8
+ /** ObservationPack changes tool-result content while preserving its call identity. */
9
+ function messageKey(message: AgentMessage): string {
10
+ return message.role === "toolResult"
11
+ ? `tool:${JSON.stringify([message.toolCallId, message.toolName, message.timestamp])}`
12
+ : JSON.stringify(message);
13
+ }
14
+
15
+ /** Map the last observed projection to source entries, without rerunning context hooks. */
16
+ export function projectedEntryTokens(
17
+ entries: readonly SessionEntry[],
18
+ projected: readonly AgentMessage[],
19
+ ): ReadonlyMap<string, number> {
20
+ const lastCompaction = entries.findLastIndex((entry) => entry.type === "compaction");
21
+ let active = entries;
22
+ if (lastCompaction >= 0) {
23
+ const compaction = entries[lastCompaction];
24
+ if (compaction?.type === "compaction") {
25
+ const firstKept = entries.findIndex((entry) => entry.id === compaction.firstKeptEntryId);
26
+ active = [compaction, ...(firstKept >= 0 ? entries.slice(firstKept, lastCompaction) : []), ...entries.slice(lastCompaction + 1)];
27
+ }
28
+ }
29
+ const sources = new Map<string, string[]>();
30
+ for (const entry of active) {
31
+ if (entry.type === "compaction" && entry !== entries[lastCompaction]) continue;
32
+ for (const message of sessionEntryToContextMessages(entry)) {
33
+ const key = messageKey(message);
34
+ const ids = sources.get(key) ?? [];
35
+ ids.push(entry.id);
36
+ sources.set(key, ids);
37
+ }
38
+ }
39
+ const visible = new Map<string, number[]>();
40
+ for (const message of projected) {
41
+ const key = messageKey(message);
42
+ const sizes = visible.get(key) ?? [];
43
+ sizes.push(estimateTokens(message));
44
+ visible.set(key, sizes);
45
+ }
46
+ const tokens = new Map<string, number>();
47
+ for (const [key, ids] of sources) {
48
+ const sizes = visible.get(key);
49
+ // Dropped, rewritten, newly appended, or ambiguously duplicated messages
50
+ // provide no proven savings. Never fall back to their raw content size.
51
+ if (!sizes || sizes.length !== ids.length || (key.startsWith("tool:") && ids.length > 1)) continue;
52
+ for (let index = 0; index < ids.length; index++) {
53
+ const id = ids[index]!;
54
+ tokens.set(id, (tokens.get(id) ?? 0) + sizes[index]!);
55
+ }
56
+ }
57
+ return tokens;
58
+ }
@@ -22,6 +22,8 @@ export type OnlineState = {
22
22
  readonly plan: readonly PlanStep[];
23
23
  readonly pendingProgress: readonly ProgressSummary[];
24
24
  readonly requestCount: number;
25
+ /** requestCount when the last compaction ran; null before the first compaction. */
26
+ readonly lastCompactionRequestCount: number | null;
25
27
  readonly lastBoundaryRequestCount: number;
26
28
  readonly completedBoundaryRequestCounts: readonly number[];
27
29
  readonly lastContextTokens: number | null;
@@ -39,6 +41,7 @@ export function initialOnlineState(): OnlineState {
39
41
  plan: [],
40
42
  pendingProgress: [],
41
43
  requestCount: 0,
44
+ lastCompactionRequestCount: null,
42
45
  lastBoundaryRequestCount: 0,
43
46
  completedBoundaryRequestCounts: [],
44
47
  lastContextTokens: null,
@@ -101,6 +104,8 @@ function parseOnlineState(value: unknown): OnlineState | undefined {
101
104
  !completedBoundaryRequestCounts ||
102
105
  !completedBoundaryRequestCounts.every(nonNegativeInteger) ||
103
106
  !nonNegativeInteger(record.epoch) ||
107
+ (typeof record.lastCompactionRequestCount !== "undefined" &&
108
+ !(record.lastCompactionRequestCount === null || nonNegativeInteger(record.lastCompactionRequestCount))) ||
104
109
  !nonNegativeInteger(record.requestCount) ||
105
110
  !nonNegativeInteger(record.lastBoundaryRequestCount) ||
106
111
  record.lastBoundaryRequestCount > record.requestCount ||
@@ -119,6 +124,7 @@ function parseOnlineState(value: unknown): OnlineState | undefined {
119
124
  plan,
120
125
  pendingProgress: pendingProgress as readonly ProgressSummary[],
121
126
  requestCount: record.requestCount,
127
+ lastCompactionRequestCount: record.lastCompactionRequestCount ?? null,
122
128
  lastBoundaryRequestCount: record.lastBoundaryRequestCount,
123
129
  completedBoundaryRequestCounts: completedBoundaryRequestCounts as readonly number[],
124
130
  lastContextTokens: record.lastContextTokens,
@@ -180,16 +186,16 @@ export function recordCompaction(
180
186
  return {
181
187
  ...state,
182
188
  epoch: state.epoch + 1,
183
- // Keep the plan so the post-compaction rebuild does not reclassify
184
- // already-completed steps as a new boundary.
189
+ // Preserve the plan and its progress samples. Compaction changes the
190
+ // context representation, not which steps have completed.
185
191
  plan: [...state.plan],
192
+ lastCompactionRequestCount: state.requestCount,
186
193
  pendingProgress: [],
194
+ // Do not compare context sizes across the replacement summary.
187
195
  lastContextTokens: null,
188
- positiveContextDeltaTotal: 0,
189
- positiveContextDeltaCount: 0,
190
196
  nativeCompactionCount: state.nativeCompactionCount + 1,
191
- cacheDebtTokens: Math.max(0, debt.debtTokens),
192
- cacheDebtRepaymentTokens: Math.max(0, debt.repaymentTokens),
197
+ cacheDebtTokens: state.cacheDebtTokens + Math.max(0, debt.debtTokens),
198
+ cacheDebtRepaymentTokens: state.cacheDebtRepaymentTokens + Math.max(0, debt.repaymentTokens),
193
199
  };
194
200
  }
195
201
 
@@ -208,3 +214,19 @@ export function recordCorrection(state: OnlineState): OnlineState {
208
214
  cacheDebtRepaymentTokens: 0,
209
215
  };
210
216
  }
217
+
218
+ /** A new user task must not inherit the completed task's request horizon. */
219
+ export function recordCompletedPlanHandoff(state: OnlineState): OnlineState {
220
+ if (state.plan.length === 0 || state.plan.some((step) => step.status !== "completed")) return state;
221
+ return {
222
+ ...state,
223
+ epoch: state.epoch + 1,
224
+ plan: [],
225
+ pendingProgress: [],
226
+ lastBoundaryRequestCount: state.requestCount,
227
+ completedBoundaryRequestCounts: [],
228
+ lastContextTokens: null,
229
+ positiveContextDeltaTotal: 0,
230
+ positiveContextDeltaCount: 0,
231
+ };
232
+ }
@@ -50,10 +50,11 @@ export function registerOnlineTools(pi: ExtensionAPI, handlers: OnlineToolHandle
50
50
  name: "update_plan",
51
51
  label: "Update plan",
52
52
  description:
53
- "Replace the complete working plan. A newly completed step becomes a safe point where SoL-Pi may compact context if doing so is economical.",
53
+ "Replace the complete working plan. Completing a previously registered unfinished step becomes a safe point where SoL-Pi may compact context if doing so is economical. Newly introduced completed steps are recorded as history.",
54
54
  promptSnippet: "Keep the working plan current",
55
55
  promptGuidelines: [
56
56
  "Send the complete plan on every update_plan call.",
57
+ "Preserve step IDs and register unfinished steps before reporting their completion.",
57
58
  "Keep at most one step in_progress and mark finished steps completed.",
58
59
  "When completing a step, include concise progress evidence when available.",
59
60
  ],
@@ -3,15 +3,28 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import { mkdtempSync } from "node:fs";
7
+ import { tmpdir } from "node:os";
6
8
  import { join } from "node:path";
7
9
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
8
10
 
11
+ const temporaryRoots = new Map<string, string>();
12
+
9
13
  export function runtimeRoot(ctx: ExtensionContext): string {
10
14
  const sessionDir = ctx.sessionManager.getSessionDir();
11
- if (!sessionDir) throw new Error("SoL-Pi requires a persistent Pi session directory");
12
15
  const sessionId = ctx.sessionManager.getSessionId();
13
16
  if (!/^[a-z0-9][a-z0-9._-]*$/iu.test(sessionId)) {
14
17
  throw new Error("SoL-Pi requires a safe Pi session id");
15
18
  }
16
- return join(sessionDir, "sol-pi", sessionId);
19
+ if (sessionDir) return join(sessionDir, "sol-pi", sessionId);
20
+
21
+ // --no-session and SDK in-memory sessions still need files for exact recall.
22
+ // Share the root across contexts and mechanisms, without sharing a predictable
23
+ // directory with other processes. Keep files after shutdown for parent workers.
24
+ let root = temporaryRoots.get(sessionId);
25
+ if (!root) {
26
+ root = mkdtempSync(join(tmpdir(), `sol-pi-${sessionId}-`));
27
+ temporaryRoots.set(sessionId, root);
28
+ }
29
+ return root;
17
30
  }