@code-yeongyu/senpi 2026.8.18-3 → 2026.8.19

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 (353) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +33 -4
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +293 -55
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  11. package/dist/core/compaction/branch-summarization.js +3 -0
  12. package/dist/core/compaction/branch-summarization.js.map +1 -1
  13. package/dist/core/compaction/compaction.d.ts +20 -3
  14. package/dist/core/compaction/compaction.d.ts.map +1 -1
  15. package/dist/core/compaction/compaction.js +182 -52
  16. package/dist/core/compaction/compaction.js.map +1 -1
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts +3 -0
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts.map +1 -1
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js +18 -1
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js.map +1 -1
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts +1 -0
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts.map +1 -1
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js +7 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js.map +1 -1
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.d.ts +8 -0
  26. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.d.ts.map +1 -1
  27. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js +18 -0
  28. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js.map +1 -1
  29. package/dist/core/extensions/builtin/cursor-cli-oauth/guardrails.d.ts +7 -0
  30. package/dist/core/extensions/builtin/cursor-cli-oauth/guardrails.d.ts.map +1 -1
  31. package/dist/core/extensions/builtin/cursor-cli-oauth/guardrails.js +10 -1
  32. package/dist/core/extensions/builtin/cursor-cli-oauth/guardrails.js.map +1 -1
  33. package/dist/core/extensions/builtin/cursor-cli-oauth/index.d.ts.map +1 -1
  34. package/dist/core/extensions/builtin/cursor-cli-oauth/index.js +12 -1
  35. package/dist/core/extensions/builtin/cursor-cli-oauth/index.js.map +1 -1
  36. package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts +12 -1
  37. package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts.map +1 -1
  38. package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js +20 -1
  39. package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js.map +1 -1
  40. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts +11 -0
  41. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts.map +1 -1
  42. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js +7 -2
  43. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js.map +1 -1
  44. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +7 -2
  46. package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
  47. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/index.js +2 -0
  49. package/dist/core/extensions/builtin/index.js.map +1 -1
  50. package/dist/core/extensions/builtin/loop/command-registration.d.ts +7 -0
  51. package/dist/core/extensions/builtin/loop/command-registration.d.ts.map +1 -0
  52. package/dist/core/extensions/builtin/loop/command-registration.js +13 -0
  53. package/dist/core/extensions/builtin/loop/command-registration.js.map +1 -0
  54. package/dist/core/extensions/builtin/loop/command.d.ts +41 -0
  55. package/dist/core/extensions/builtin/loop/command.d.ts.map +1 -0
  56. package/dist/core/extensions/builtin/loop/command.js +281 -0
  57. package/dist/core/extensions/builtin/loop/command.js.map +1 -0
  58. package/dist/core/extensions/builtin/loop/cron-planner.d.ts +23 -0
  59. package/dist/core/extensions/builtin/loop/cron-planner.d.ts.map +1 -0
  60. package/dist/core/extensions/builtin/loop/cron-planner.js +88 -0
  61. package/dist/core/extensions/builtin/loop/cron-planner.js.map +1 -0
  62. package/dist/core/extensions/builtin/loop/index.d.ts +134 -0
  63. package/dist/core/extensions/builtin/loop/index.d.ts.map +1 -0
  64. package/dist/core/extensions/builtin/loop/index.js +742 -0
  65. package/dist/core/extensions/builtin/loop/index.js.map +1 -0
  66. package/dist/core/extensions/builtin/loop/loopfile.d.ts +40 -0
  67. package/dist/core/extensions/builtin/loop/loopfile.d.ts.map +1 -0
  68. package/dist/core/extensions/builtin/loop/loopfile.js +102 -0
  69. package/dist/core/extensions/builtin/loop/loopfile.js.map +1 -0
  70. package/dist/core/extensions/builtin/loop/parse.d.ts +45 -0
  71. package/dist/core/extensions/builtin/loop/parse.d.ts.map +1 -0
  72. package/dist/core/extensions/builtin/loop/parse.js +92 -0
  73. package/dist/core/extensions/builtin/loop/parse.js.map +1 -0
  74. package/dist/core/extensions/builtin/loop/scheduler.d.ts +225 -0
  75. package/dist/core/extensions/builtin/loop/scheduler.d.ts.map +1 -0
  76. package/dist/core/extensions/builtin/loop/scheduler.js +708 -0
  77. package/dist/core/extensions/builtin/loop/scheduler.js.map +1 -0
  78. package/dist/core/extensions/builtin/loop/status.d.ts +24 -0
  79. package/dist/core/extensions/builtin/loop/status.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/loop/status.js +113 -0
  81. package/dist/core/extensions/builtin/loop/status.js.map +1 -0
  82. package/dist/core/extensions/builtin/loop/store.d.ts +49 -0
  83. package/dist/core/extensions/builtin/loop/store.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/loop/store.js +424 -0
  85. package/dist/core/extensions/builtin/loop/store.js.map +1 -0
  86. package/dist/core/extensions/builtin/loop/tick-prompt.d.ts +64 -0
  87. package/dist/core/extensions/builtin/loop/tick-prompt.d.ts.map +1 -0
  88. package/dist/core/extensions/builtin/loop/tick-prompt.js +183 -0
  89. package/dist/core/extensions/builtin/loop/tick-prompt.js.map +1 -0
  90. package/dist/core/extensions/builtin/loop/tools.d.ts +122 -0
  91. package/dist/core/extensions/builtin/loop/tools.d.ts.map +1 -0
  92. package/dist/core/extensions/builtin/loop/tools.js +155 -0
  93. package/dist/core/extensions/builtin/loop/tools.js.map +1 -0
  94. package/dist/core/extensions/builtin/loop/types.d.ts +206 -0
  95. package/dist/core/extensions/builtin/loop/types.d.ts.map +1 -0
  96. package/dist/core/extensions/builtin/loop/types.js +37 -0
  97. package/dist/core/extensions/builtin/loop/types.js.map +1 -0
  98. package/dist/core/extensions/index.d.ts +1 -1
  99. package/dist/core/extensions/index.d.ts.map +1 -1
  100. package/dist/core/extensions/index.js.map +1 -1
  101. package/dist/core/extensions/loader.d.ts.map +1 -1
  102. package/dist/core/extensions/loader.js +10 -5
  103. package/dist/core/extensions/loader.js.map +1 -1
  104. package/dist/core/extensions/types.d.ts +30 -3
  105. package/dist/core/extensions/types.d.ts.map +1 -1
  106. package/dist/core/extensions/types.js.map +1 -1
  107. package/dist/core/footer-data-provider.d.ts.map +1 -1
  108. package/dist/core/footer-data-provider.js +5 -10
  109. package/dist/core/footer-data-provider.js.map +1 -1
  110. package/dist/core/model-registry.d.ts +2 -0
  111. package/dist/core/model-registry.d.ts.map +1 -1
  112. package/dist/core/model-registry.js +4 -0
  113. package/dist/core/model-registry.js.map +1 -1
  114. package/dist/core/model-runtime.d.ts +7 -0
  115. package/dist/core/model-runtime.d.ts.map +1 -1
  116. package/dist/core/model-runtime.js +17 -0
  117. package/dist/core/model-runtime.js.map +1 -1
  118. package/dist/core/package-manager.d.ts.map +1 -1
  119. package/dist/core/package-manager.js +8 -4
  120. package/dist/core/package-manager.js.map +1 -1
  121. package/dist/core/provider-composer.d.ts +8 -0
  122. package/dist/core/provider-composer.d.ts.map +1 -1
  123. package/dist/core/provider-composer.js.map +1 -1
  124. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  125. package/dist/core/remote-catalog-provider.js +2 -1
  126. package/dist/core/remote-catalog-provider.js.map +1 -1
  127. package/dist/core/retry-fallback/chains.d.ts +1 -0
  128. package/dist/core/retry-fallback/chains.d.ts.map +1 -1
  129. package/dist/core/retry-fallback/chains.js +3 -0
  130. package/dist/core/retry-fallback/chains.js.map +1 -1
  131. package/dist/core/retry-fallback/controller.d.ts +2 -0
  132. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  133. package/dist/core/retry-fallback/controller.js.map +1 -1
  134. package/dist/core/retry-fallback/expansion.d.ts +8 -0
  135. package/dist/core/retry-fallback/expansion.d.ts.map +1 -1
  136. package/dist/core/retry-fallback/expansion.js +2 -0
  137. package/dist/core/retry-fallback/expansion.js.map +1 -1
  138. package/dist/core/settings-manager.d.ts +1 -1
  139. package/dist/core/settings-manager.d.ts.map +1 -1
  140. package/dist/core/settings-manager.js +14 -3
  141. package/dist/core/settings-manager.js.map +1 -1
  142. package/dist/core/skills.d.ts.map +1 -1
  143. package/dist/core/skills.js +51 -33
  144. package/dist/core/skills.js.map +1 -1
  145. package/dist/core/tools/edit.d.ts.map +1 -1
  146. package/dist/core/tools/edit.js +17 -2
  147. package/dist/core/tools/edit.js.map +1 -1
  148. package/dist/extensions/llama/index.d.ts.map +1 -1
  149. package/dist/extensions/llama/index.js +2 -0
  150. package/dist/extensions/llama/index.js.map +1 -1
  151. package/dist/extensions/llama/provider.d.ts.map +1 -1
  152. package/dist/extensions/llama/provider.js +6 -6
  153. package/dist/extensions/llama/provider.js.map +1 -1
  154. package/dist/index.d.ts +1 -1
  155. package/dist/index.d.ts.map +1 -1
  156. package/dist/index.js.map +1 -1
  157. package/dist/main.d.ts +4 -0
  158. package/dist/main.d.ts.map +1 -1
  159. package/dist/main.js +4 -4
  160. package/dist/main.js.map +1 -1
  161. package/dist/modes/interactive/components/settings-selector.js +1 -1
  162. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  163. package/dist/modes/interactive/editor-paste-transfer.d.ts +10 -1
  164. package/dist/modes/interactive/editor-paste-transfer.d.ts.map +1 -1
  165. package/dist/modes/interactive/editor-paste-transfer.js +27 -2
  166. package/dist/modes/interactive/editor-paste-transfer.js.map +1 -1
  167. package/dist/modes/interactive/interactive-mode.d.ts +69 -1
  168. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  169. package/dist/modes/interactive/interactive-mode.js +434 -63
  170. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  171. package/dist/modes/interactive/tips/catalog/dag-tips.d.ts +7 -0
  172. package/dist/modes/interactive/tips/catalog/dag-tips.d.ts.map +1 -0
  173. package/dist/modes/interactive/tips/catalog/dag-tips.js +57 -0
  174. package/dist/modes/interactive/tips/catalog/dag-tips.js.map +1 -0
  175. package/dist/modes/interactive/tips/catalog/memory-tips.d.ts +7 -0
  176. package/dist/modes/interactive/tips/catalog/memory-tips.d.ts.map +1 -0
  177. package/dist/modes/interactive/tips/catalog/memory-tips.js +100 -0
  178. package/dist/modes/interactive/tips/catalog/memory-tips.js.map +1 -0
  179. package/dist/modes/interactive/tips/registry.d.ts.map +1 -1
  180. package/dist/modes/interactive/tips/registry.js +4 -0
  181. package/dist/modes/interactive/tips/registry.js.map +1 -1
  182. package/dist/utils/management-http.d.ts +5 -3
  183. package/dist/utils/management-http.d.ts.map +1 -1
  184. package/dist/utils/management-http.js +14 -10
  185. package/dist/utils/management-http.js.map +1 -1
  186. package/docs/compaction.md +17 -0
  187. package/docs/custom-provider.md +5 -2
  188. package/docs/extensions.md +11 -2
  189. package/docs/llama-cpp.md +2 -0
  190. package/docs/models.md +8 -2
  191. package/docs/providers.md +5 -3
  192. package/docs/settings.md +22 -2
  193. package/docs/skills.md +4 -3
  194. package/examples/extensions/border-status-editor.ts +1 -1
  195. package/examples/extensions/git-checkpoint.ts +2 -2
  196. package/examples/extensions/notify.ts +3 -1
  197. package/examples/extensions/subagent/index.ts +6 -1
  198. package/examples/extensions/titlebar-spinner.ts +1 -1
  199. package/examples/rpc-extension-ui.ts +1 -1
  200. package/examples/sdk/06-extensions.ts +1 -1
  201. package/examples/sdk/README.md +1 -1
  202. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  203. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  204. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts +3 -1
  205. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  206. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +51 -17
  207. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  208. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +4 -2
  209. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  210. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +5 -1
  211. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-agent-core/dist/harness/skills.d.ts +3 -2
  213. package/node_modules/@earendil-works/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  214. package/node_modules/@earendil-works/pi-agent-core/dist/harness/skills.js +13 -3
  215. package/node_modules/@earendil-works/pi-agent-core/dist/harness/skills.js.map +1 -1
  216. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
  217. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +14 -1
  218. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
  219. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  220. package/node_modules/@earendil-works/pi-ai/README.md +5 -3
  221. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts +7 -1
  222. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +21 -4
  224. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  225. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts +2 -0
  226. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +7 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +39 -2
  231. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/gen/agent_pb.d.ts +22 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/gen/agent_pb.d.ts.map +1 -1
  234. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/gen/agent_pb.js +1 -1
  235. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/gen/agent_pb.js.map +1 -1
  236. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +1 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  238. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +51 -2
  239. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  240. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts +2 -2
  241. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +14 -11
  243. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.d.ts +5 -2
  245. package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.d.ts.map +1 -1
  246. package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js +16 -0
  247. package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js.map +1 -1
  248. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts +2 -2
  249. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +13 -10
  251. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
  252. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.d.ts.map +1 -1
  253. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js +4 -1
  254. package/node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js.map +1 -1
  255. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  256. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +4 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  258. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts +1 -1
  259. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  260. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +45 -29
  261. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  262. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  263. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +8 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  265. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.d.ts +4 -0
  268. package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.d.ts.map +1 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js +18 -9
  270. package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js.map +1 -1
  271. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.d.ts +1 -0
  272. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.d.ts.map +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.js +1 -1
  274. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.js.map +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js +22 -9
  277. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +2 -1
  279. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  281. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  285. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  287. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  288. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  289. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-individual.json +1 -1
  290. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  291. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -1
  292. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
  293. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
  294. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
  295. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi.json +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  297. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
  298. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts +1 -1
  299. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts.map +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js +1 -5
  301. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +28 -4
  303. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  304. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  305. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +15 -0
  307. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.d.ts +2 -0
  309. package/node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.js +7 -0
  311. package/node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.d.ts +2 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js +2 -0
  315. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-ai/package.json +2 -3
  317. package/node_modules/@earendil-works/pi-pty/dist/loader.d.ts +6 -0
  318. package/node_modules/@earendil-works/pi-pty/dist/loader.d.ts.map +1 -1
  319. package/node_modules/@earendil-works/pi-pty/dist/loader.js +11 -0
  320. package/node_modules/@earendil-works/pi-pty/dist/loader.js.map +1 -1
  321. package/node_modules/@earendil-works/pi-pty/dist/quarantine.d.ts +15 -0
  322. package/node_modules/@earendil-works/pi-pty/dist/quarantine.d.ts.map +1 -0
  323. package/node_modules/@earendil-works/pi-pty/dist/quarantine.js +27 -0
  324. package/node_modules/@earendil-works/pi-pty/dist/quarantine.js.map +1 -0
  325. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  326. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  327. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +73 -1
  328. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +173 -17
  330. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-tui/dist/components/text.d.ts.map +1 -1
  332. package/node_modules/@earendil-works/pi-tui/dist/components/text.js +5 -4
  333. package/node_modules/@earendil-works/pi-tui/dist/components/text.js.map +1 -1
  334. package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts +69 -0
  335. package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts.map +1 -1
  336. package/node_modules/@earendil-works/pi-tui/dist/editor-component.js.map +1 -1
  337. package/node_modules/@earendil-works/pi-tui/dist/image-markers.d.ts +46 -0
  338. package/node_modules/@earendil-works/pi-tui/dist/image-markers.d.ts.map +1 -0
  339. package/node_modules/@earendil-works/pi-tui/dist/image-markers.js +130 -0
  340. package/node_modules/@earendil-works/pi-tui/dist/image-markers.js.map +1 -0
  341. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -0
  342. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  343. package/node_modules/@earendil-works/pi-tui/dist/index.js +2 -0
  344. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  345. package/node_modules/@earendil-works/pi-tui/dist/paste-markers.d.ts +3 -0
  346. package/node_modules/@earendil-works/pi-tui/dist/paste-markers.d.ts.map +1 -1
  347. package/node_modules/@earendil-works/pi-tui/dist/paste-markers.js +23 -7
  348. package/node_modules/@earendil-works/pi-tui/dist/paste-markers.js.map +1 -1
  349. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts.map +1 -1
  350. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js +5 -1
  351. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js.map +1 -1
  352. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  353. package/package.json +7 -7
@@ -15,6 +15,7 @@
15
15
  import { randomUUID } from "node:crypto";
16
16
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { basename, dirname } from "node:path";
18
+ import { isDeepStrictEqual } from "node:util";
18
19
  import { prepareAgentToolCall } from "@earendil-works/pi-agent-core";
19
20
  import { contentText, SERVER_FALLBACK_ABORTED_DIAGNOSTIC } from "@earendil-works/pi-ai";
20
21
  import { cleanupSessionResources, isClassifierRefusal, isContextOverflow, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
@@ -35,6 +36,7 @@ import { CompactionLifecycleCoordinator } from "./compaction/lifecycle.js";
35
36
  import { isWarmSummaryAnchorValid } from "./compaction/warm-anchor.js";
36
37
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
37
38
  import { buildDynamicSystemPrompt } from "./dynamic-prompt/index.js";
39
+ import { areExperimentalFeaturesEnabled } from "./experimental.js";
38
40
  import { exportSessionToHtml } from "./export-html/index.js";
39
41
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
40
42
  import { CODEX_RESPONSES_API } from "./extensions/builtin/service-tier.js";
@@ -467,7 +469,10 @@ export class AgentSession {
467
469
  // points at the file to open; "default" means no scope configured any.
468
470
  const fallbackChainsSource = this.settingsManager.getFallbackChainsScope() ?? "default";
469
471
  for (const warning of this._fallbackValidationWarnings) {
470
- fallbackLogger.warn("validation_warning", { warning, source: fallbackChainsSource });
472
+ fallbackLogger.warn("validation_warning", {
473
+ warning,
474
+ source: fallbackChainsSource,
475
+ });
471
476
  }
472
477
  this._selectorCooldowns = new SelectorCooldowns(config.fallbackNow ?? (() => Date.now()));
473
478
  this._fallbackNow = config.fallbackNow ?? (() => Date.now());
@@ -500,7 +505,10 @@ export class AgentSession {
500
505
  this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
501
506
  this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
502
507
  this._baseToolsOverride = config.baseToolsOverride;
503
- this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
508
+ this._sessionStartEvent = config.sessionStartEvent ?? {
509
+ type: "session_start",
510
+ reason: "startup",
511
+ };
504
512
  this._autoTitleSessions = config.autoTitleSessions ?? false;
505
513
  const initialModel = this.agent.state.model;
506
514
  if (initialModel) {
@@ -756,7 +764,10 @@ export class AgentSession {
756
764
  // this invocation: one replay is the bounded admission path.
757
765
  const postLateCompactionTurn = {
758
766
  ...turn,
759
- context: { ...turn.context, messages: this.agent.state.messages.slice() },
767
+ context: {
768
+ ...turn.context,
769
+ messages: this.agent.state.messages.slice(),
770
+ },
760
771
  };
761
772
  const postLateCompactionSnapshot = await previousPrepareNextTurnWithContext?.(postLateCompactionTurn, signal);
762
773
  previousSnapshot = {
@@ -791,6 +802,14 @@ export class AgentSession {
791
802
  l(event);
792
803
  }
793
804
  }
805
+ async _emitSessionCompactFailed(event) {
806
+ if (this._extensionRunner.hasHandlers("session_compact_failed")) {
807
+ await this._extensionRunner.emit({
808
+ type: "session_compact_failed",
809
+ ...event,
810
+ });
811
+ }
812
+ }
794
813
  /** Mirror stuck-prone lifecycle transitions into logs/session.log (content-free). */
795
814
  _logSessionEvent(event) {
796
815
  if (event.type === "compaction_start") {
@@ -875,7 +894,10 @@ export class AgentSession {
875
894
  : isProviderTimeoutError(message)
876
895
  ? "timeout"
877
896
  : "error";
878
- this._sessionLogger.warn("provider_error", { kind, error: message.errorMessage });
897
+ this._sessionLogger.warn("provider_error", {
898
+ kind,
899
+ error: message.errorMessage,
900
+ });
879
901
  }
880
902
  }
881
903
  _estimateCompactionLogTokens(source) {
@@ -993,7 +1015,10 @@ export class AgentSession {
993
1015
  const requiredCompactionError = this._requiredCompactionAdmissionError;
994
1016
  this._requiredCompactionAdmissionError = undefined;
995
1017
  if (requiredCompactionError) {
996
- this._sessionLogger.warn("prompt_rejected", { stage: "admission", error: "RequiredCompactionError" });
1018
+ this._sessionLogger.warn("prompt_rejected", {
1019
+ stage: "admission",
1020
+ error: "RequiredCompactionError",
1021
+ });
997
1022
  throw requiredCompactionError;
998
1023
  }
999
1024
  }
@@ -1085,6 +1110,17 @@ export class AgentSession {
1085
1110
  }
1086
1111
  return reason;
1087
1112
  }
1113
+ /**
1114
+ * Threshold checks measure the larger of the provider-reported context and
1115
+ * the plain local-transcript estimate. Providers whose usage tracks a
1116
+ * server-side summarized conversation (native Cursor checkpoints) can report
1117
+ * a context far smaller than the transcript this client replays every turn,
1118
+ * and that small figure must not hide a transcript already past the window.
1119
+ */
1120
+ _resolveThresholdContextTokens(directContextTokens) {
1121
+ const messages = filterContextExcludedMessages(this.agent.state.messages);
1122
+ return Math.max(directContextTokens, estimateMessagesTokens(messages));
1123
+ }
1088
1124
  _getAutoCompactionReason(message) {
1089
1125
  const settings = this.settingsManager.getCompactionSettings();
1090
1126
  if (!settings.enabled || message.stopReason === "aborted") {
@@ -1105,7 +1141,7 @@ export class AgentSession {
1105
1141
  let contextTokens;
1106
1142
  const directContextTokens = message.usage ? calculateContextTokens(message.usage) : 0;
1107
1143
  if (message.stopReason !== "error" && directContextTokens !== 0) {
1108
- contextTokens = directContextTokens;
1144
+ contextTokens = this._resolveThresholdContextTokens(directContextTokens);
1109
1145
  }
1110
1146
  else {
1111
1147
  const messages = filterContextExcludedMessages(this.agent.state.messages);
@@ -1352,7 +1388,9 @@ export class AgentSession {
1352
1388
  retryOutcome = await this._handleRetryableError(msg);
1353
1389
  }
1354
1390
  else if (hardErrorFallbackEligible) {
1355
- retryOutcome = await this._handleRetryableError(msg, { hardErrorFallback: true });
1391
+ retryOutcome = await this._handleRetryableError(msg, {
1392
+ hardErrorFallback: true,
1393
+ });
1356
1394
  }
1357
1395
  }
1358
1396
  if (retryOutcome === "continued") {
@@ -1373,7 +1411,12 @@ export class AgentSession {
1373
1411
  const attempt = this._retryAttempt;
1374
1412
  this._retryAttempt = 0;
1375
1413
  this._resetHintTierState();
1376
- this._emit({ type: "auto_retry_end", success: false, attempt, finalError: msg.errorMessage });
1414
+ this._emit({
1415
+ type: "auto_retry_end",
1416
+ success: false,
1417
+ attempt,
1418
+ finalError: msg.errorMessage,
1419
+ });
1377
1420
  }
1378
1421
  this._resolveRetry();
1379
1422
  retryContinuationBlocked ||= retryOutcome === "blocked";
@@ -1483,7 +1526,13 @@ export class AgentSession {
1483
1526
  try {
1484
1527
  const result = await this._modelRuntime.completeSimple(demotedModel, {
1485
1528
  systemPrompt: "Reply with OK.",
1486
- messages: [{ role: "user", content: [{ type: "text", text: "OK" }], timestamp: now }],
1529
+ messages: [
1530
+ {
1531
+ role: "user",
1532
+ content: [{ type: "text", text: "OK" }],
1533
+ timestamp: now,
1534
+ },
1535
+ ],
1487
1536
  }, { maxTokens: 1, signal });
1488
1537
  return result.stopReason !== "error" && result.stopReason !== "aborted";
1489
1538
  }
@@ -1813,7 +1862,11 @@ export class AgentSession {
1813
1862
  const fastMode = this.isFastModeActive();
1814
1863
  if (previousTier === this._currentServiceTier && previousFastMode === fastMode)
1815
1864
  return;
1816
- this._emit({ type: "service_tier_changed", tier: this.effectiveServiceTier, fastMode });
1865
+ this._emit({
1866
+ type: "service_tier_changed",
1867
+ tier: this.effectiveServiceTier,
1868
+ fastMode,
1869
+ });
1817
1870
  }
1818
1871
  /**
1819
1872
  * Explicit scoped/favorite tiers win; otherwise fall back to the model's
@@ -1913,7 +1966,12 @@ export class AgentSession {
1913
1966
  }
1914
1967
  catch (err) {
1915
1968
  result = {
1916
- content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }],
1969
+ content: [
1970
+ {
1971
+ type: "text",
1972
+ text: err instanceof Error ? err.message : String(err),
1973
+ },
1974
+ ],
1917
1975
  details: { isError: true },
1918
1976
  };
1919
1977
  isError = true;
@@ -2235,13 +2293,20 @@ export class AgentSession {
2235
2293
  const emitPendingCommandInvocation = () => {
2236
2294
  if (!pendingCommandInvocation)
2237
2295
  return;
2238
- this._emit({ type: "command_invocation", command: pendingCommandInvocation });
2296
+ this._emit({
2297
+ type: "command_invocation",
2298
+ command: pendingCommandInvocation,
2299
+ });
2239
2300
  pendingCommandInvocation = undefined;
2240
2301
  };
2241
2302
  const emitInputDisposition = async (disposition) => {
2242
2303
  if (inputId === undefined)
2243
2304
  return;
2244
- await this._extensionRunner.emit({ type: "input_disposition", inputId, disposition });
2305
+ await this._extensionRunner.emit({
2306
+ type: "input_disposition",
2307
+ inputId,
2308
+ disposition,
2309
+ });
2245
2310
  };
2246
2311
  try {
2247
2312
  // Emit input event for extension interception (before skill/template expansion)
@@ -2736,13 +2801,20 @@ export class AgentSession {
2736
2801
  async _queueSteer(text, images, enqueueOrder) {
2737
2802
  this._steeringMessages.push(text);
2738
2803
  this._recordQueuedInput(text, "steer", enqueueOrder);
2739
- this._sessionLogger.debug("queue_enqueue", { mode: "steer", count: this._steeringMessages.length });
2804
+ this._sessionLogger.debug("queue_enqueue", {
2805
+ mode: "steer",
2806
+ count: this._steeringMessages.length,
2807
+ });
2740
2808
  this._emitQueueUpdate();
2741
2809
  const content = [{ type: "text", text }];
2742
2810
  if (images) {
2743
2811
  content.push(...images);
2744
2812
  }
2745
- const message = { role: "user", content, timestamp: Date.now() };
2813
+ const message = {
2814
+ role: "user",
2815
+ content,
2816
+ timestamp: Date.now(),
2817
+ };
2746
2818
  if (this._promptStartPending && this._skipNextPostCompactionAssistantCheck) {
2747
2819
  this._postCompactionDeferredSteeringMessages.push(message);
2748
2820
  return;
@@ -2755,13 +2827,20 @@ export class AgentSession {
2755
2827
  async _queueFollowUp(text, images, enqueueOrder) {
2756
2828
  this._followUpMessages.push(text);
2757
2829
  this._recordQueuedInput(text, "followUp", enqueueOrder);
2758
- this._sessionLogger.debug("queue_enqueue", { mode: "followUp", count: this._followUpMessages.length });
2830
+ this._sessionLogger.debug("queue_enqueue", {
2831
+ mode: "followUp",
2832
+ count: this._followUpMessages.length,
2833
+ });
2759
2834
  this._emitQueueUpdate();
2760
2835
  const content = [{ type: "text", text }];
2761
2836
  if (images) {
2762
2837
  content.push(...images);
2763
2838
  }
2764
- const message = { role: "user", content, timestamp: Date.now() };
2839
+ const message = {
2840
+ role: "user",
2841
+ content,
2842
+ timestamp: Date.now(),
2843
+ };
2765
2844
  if (this._promptStartPending && this._skipNextPostCompactionAssistantCheck) {
2766
2845
  this._postCompactionDeferredFollowUpMessages.push(message);
2767
2846
  return;
@@ -3006,7 +3085,10 @@ export class AgentSession {
3006
3085
  this.agent.clearAllQueues();
3007
3086
  this._emitQueueUpdate();
3008
3087
  const cleared = { steering, followUp };
3009
- Object.defineProperty(cleared, "ordered", { value: ordered, enumerable: false });
3088
+ Object.defineProperty(cleared, "ordered", {
3089
+ value: ordered,
3090
+ enumerable: false,
3091
+ });
3010
3092
  return cleared;
3011
3093
  }
3012
3094
  /** Number of pending messages (includes both steering and follow-up) */
@@ -3234,7 +3316,11 @@ export class AgentSession {
3234
3316
  });
3235
3317
  this._emitServiceTierChangeIfNeeded(previousTier, previousFastMode);
3236
3318
  const systemPromptChange = await this._emitModelSelect(next.model, currentModel, "cycle");
3237
- const cycleResult = { model: next.model, thinkingLevel: this.thinkingLevel, isScoped: true };
3319
+ const cycleResult = {
3320
+ model: next.model,
3321
+ thinkingLevel: this.thinkingLevel,
3322
+ isScoped: true,
3323
+ };
3238
3324
  if (systemPromptChange) {
3239
3325
  cycleResult.systemPromptChange = systemPromptChange;
3240
3326
  }
@@ -3372,7 +3458,10 @@ export class AgentSession {
3372
3458
  }
3373
3459
  requestedLevel ??= DEFAULT_THINKING_LEVEL;
3374
3460
  const level = this._clampThinkingLevel(requestedLevel, getSupportedThinkingLevels(model));
3375
- return { level, selection: selection ? { ...selection, level } : undefined };
3461
+ return {
3462
+ level,
3463
+ selection: selection ? { ...selection, level } : undefined,
3464
+ };
3376
3465
  }
3377
3466
  _clampThinkingLevel(level, availableLevels) {
3378
3467
  const available = new Set(availableLevels);
@@ -3518,9 +3607,66 @@ export class AgentSession {
3518
3607
  }
3519
3608
  }
3520
3609
  }
3610
+ /** Generate the built-in summary while preserving fork routing identity and transforms. */
3611
+ async _runDefaultCompaction(preparation, requestModel, apiKey, headers, extraBody, customInstructions, signal, env, reason) {
3612
+ let cacheFriendly;
3613
+ if (areExperimentalFeaturesEnabled()) {
3614
+ const systemPrompt = this.agent.state.systemPrompt;
3615
+ const tools = this.agent.state.tools.slice();
3616
+ const buildSourceContext = (messages) => this.agent.buildProviderContext({ systemPrompt, messages: messages.slice(), tools: tools.slice() }, signal);
3617
+ const fullContext = await buildSourceContext(this.agent.state.messages);
3618
+ const isExactPrefix = (candidate) => candidate.messages.length > 0 &&
3619
+ candidate.messages.length <= fullContext.messages.length &&
3620
+ isDeepStrictEqual(candidate.messages, fullContext.messages.slice(0, candidate.messages.length));
3621
+ let sourceContext;
3622
+ if (preparation.messagesToSummarize.length > 0 && preparation.sourceMessages) {
3623
+ const candidate = await buildSourceContext(preparation.sourceMessages);
3624
+ if (isExactPrefix(candidate))
3625
+ sourceContext = candidate;
3626
+ }
3627
+ let turnPrefixSourceContext;
3628
+ if (preparation.isSplitTurn &&
3629
+ preparation.turnPrefixMessages.length > 0 &&
3630
+ preparation.turnPrefixSourceMessages) {
3631
+ const candidate = await buildSourceContext(preparation.turnPrefixSourceMessages);
3632
+ const providerTurnPrefix = await this.agent.convertToLlm(preparation.turnPrefixMessages.slice());
3633
+ if (isExactPrefix(candidate) &&
3634
+ providerTurnPrefix.length > 0 &&
3635
+ providerTurnPrefix.length <= candidate.messages.length &&
3636
+ isDeepStrictEqual(candidate.messages.slice(-providerTurnPrefix.length), providerTurnPrefix)) {
3637
+ turnPrefixSourceContext = candidate;
3638
+ }
3639
+ }
3640
+ if (sourceContext || turnPrefixSourceContext) {
3641
+ cacheFriendly = {
3642
+ sourceContext,
3643
+ turnPrefixSourceContext,
3644
+ requestOptions: {
3645
+ sessionId: this.agent.sessionId,
3646
+ onPayload: this.agent.onPayload,
3647
+ onResponse: this.agent.onResponse,
3648
+ transport: this.agent.transport,
3649
+ thinkingBudgets: this.agent.thinkingBudgets,
3650
+ maxRetryDelayMs: this.agent.maxRetryDelayMs,
3651
+ },
3652
+ };
3653
+ }
3654
+ }
3655
+ return compact(preparation, requestModel, apiKey, headers, customInstructions, signal, extraBody, this.thinkingLevel, this.agent.streamFunction, env, this.agent.transformContext, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), this.sessionManager.getSessionId(), cacheFriendly);
3656
+ }
3521
3657
  /**
3522
3658
  * Manually compact the session context.
3523
- * Aborts current agent operation first.
3659
+ *
3660
+ * This is the manual entry point used by `/compact`, RPC, and extensions. It is
3661
+ * separate from automatic threshold/overflow compaction, which enters through
3662
+ * `_checkCompaction()` and `_runAutoCompaction()`. After preparation and the
3663
+ * `session_before_compact` hook, both paths call the lower-level `compact()`
3664
+ * function imported from `./compaction/index.ts`, unless the hook cancels or
3665
+ * supplies a custom result.
3666
+ *
3667
+ * Aborts the current agent operation first. Manual compaction never retries or
3668
+ * continues the interrupted agent turn.
3669
+ *
3524
3670
  * @param customInstructions Optional instructions for the compaction summary
3525
3671
  */
3526
3672
  async compact(customInstructions) {
@@ -3561,6 +3707,7 @@ export class AgentSession {
3561
3707
  }
3562
3708
  const message = error instanceof Error ? error.message : String(error);
3563
3709
  const aborted = isCompactionExecutionAborted(error);
3710
+ const errorMessage = aborted ? undefined : `Compaction failed: ${message}`;
3564
3711
  this._emit({
3565
3712
  type: "compaction_end",
3566
3713
  reason: "manual",
@@ -3568,7 +3715,14 @@ export class AgentSession {
3568
3715
  aborted,
3569
3716
  willRetry: false,
3570
3717
  requestId,
3571
- errorMessage: aborted ? undefined : `Compaction failed: ${message}`,
3718
+ errorMessage,
3719
+ });
3720
+ await this._emitSessionCompactFailed({
3721
+ reason: "manual",
3722
+ errorMessage,
3723
+ aborted,
3724
+ willRetry: false,
3725
+ fromExtension: false,
3572
3726
  });
3573
3727
  throw error;
3574
3728
  }
@@ -3601,7 +3755,11 @@ export class AgentSession {
3601
3755
  : randomUUID();
3602
3756
  if (ownsController) {
3603
3757
  this._claimCompactionController(new AbortController(), "compaction");
3604
- this._emit({ type: "compaction_start", reason: options.reason, requestId });
3758
+ this._emit({
3759
+ type: "compaction_start",
3760
+ reason: options.reason,
3761
+ requestId,
3762
+ });
3605
3763
  }
3606
3764
  const controller = this._compactionAbortController;
3607
3765
  if (!controller)
@@ -3704,7 +3862,6 @@ export class AgentSession {
3704
3862
  const model = this.model;
3705
3863
  if (!model)
3706
3864
  throw new Error(formatNoModelSelectedMessage());
3707
- const thinkingLevel = this.thinkingLevel;
3708
3865
  const controller = request.controller;
3709
3866
  // Async auth and provider preparation may yield to a newer route. A stale
3710
3867
  // controller must never promote itself into a lifecycle generation.
@@ -3771,7 +3928,7 @@ export class AgentSession {
3771
3928
  }
3772
3929
  if (!compactionResult) {
3773
3930
  const { model: requestModel, apiKey, headers, extraBody, env, } = await this._getCompactionRequestAuth(model);
3774
- compactionResult = await compact(preparation, requestModel, apiKey, headers, request.customInstructions, signal, extraBody, thinkingLevel, this.agent.streamFunction, env, this.agent.transformContext, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: request.reason }), this.sessionManager.getSessionId());
3931
+ compactionResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, extraBody, request.customInstructions, signal, env, request.reason);
3775
3932
  }
3776
3933
  }
3777
3934
  if (signal.aborted) {
@@ -3860,7 +4017,13 @@ export class AgentSession {
3860
4017
  fromExtension,
3861
4018
  willRetry: request.willRetry,
3862
4019
  });
3863
- return { accepted: true, requestId, result: compactionResult, compactionEntry: savedEntry, fromExtension };
4020
+ return {
4021
+ accepted: true,
4022
+ requestId,
4023
+ result: compactionResult,
4024
+ compactionEntry: savedEntry,
4025
+ fromExtension,
4026
+ };
3864
4027
  }
3865
4028
  catch (error) {
3866
4029
  if (error instanceof CompactionExecutionError) {
@@ -3995,8 +4158,8 @@ export class AgentSession {
3995
4158
  this._branchSummaryAbortController?.abort();
3996
4159
  }
3997
4160
  /**
3998
- * Check if compaction is needed and run it.
3999
- * Called after agent_end and before prompt submission.
4161
+ * Dispatch automatic compaction after `agent_end` or before prompt submission.
4162
+ * Manual compaction does not call this method; it enters through `compact()`.
4000
4163
  *
4001
4164
  * Two cases:
4002
4165
  * 1. Overflow: LLM returned context overflow error, remove error message from agent state, compact, auto-retry
@@ -4004,6 +4167,7 @@ export class AgentSession {
4004
4167
  *
4005
4168
  * @param assistantMessage The assistant message to check
4006
4169
  * @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
4170
+ * @returns Whether the post-run loop should call `agent.continue()` for overflow recovery or queued messages
4007
4171
  */
4008
4172
  async _enforceCompactionBeforeProvider(assistantMessage, skipAbortedCheck, inlineReason, retryAfterCompaction = false) {
4009
4173
  const blockedAdmission = this._blockedPostCompactionAssistant;
@@ -4049,9 +4213,12 @@ export class AgentSession {
4049
4213
  * reapply their already-assembled one-shot additions after it succeeds.
4050
4214
  */
4051
4215
  async _enforceFinalProviderAdmission(messages) {
4052
- // Normal user-only prompts keep the established provider-overflow recovery
4053
- // path. This final gate closes the separate gap introduced by turn-local
4054
- // custom additions, which the normal pre-prompt check cannot observe.
4216
+ // User-only prompts are deliberately admitted without this gate: prompt
4217
+ // admission must never brick on a rejected or cooled-down compaction
4218
+ // (issues #531/#886), so oversized user prompts rely on threshold
4219
+ // compaction — which also samples the local transcript estimate — and on
4220
+ // provider-overflow recovery. This gate closes the separate gap opened by
4221
+ // turn-local custom additions, which the pre-prompt check cannot observe.
4055
4222
  if (!messages.some((message) => message.role === "custom"))
4056
4223
  return;
4057
4224
  const model = this.model;
@@ -4126,6 +4293,8 @@ export class AgentSession {
4126
4293
  if (isOverflow) {
4127
4294
  this._flushPostCompactionDeferredMessages();
4128
4295
  const willRetry = retryAfterCompaction || assistantMessage.stopReason !== "stop";
4296
+ // Case 2: the response completed successfully. Compact, but do not retry because
4297
+ // agent.continue() cannot continue from a completed assistant response.
4129
4298
  if (!willRetry) {
4130
4299
  const compacted = await this._runAutoCompaction("overflow", false);
4131
4300
  if (!compacted &&
@@ -4154,6 +4323,8 @@ export class AgentSession {
4154
4323
  }
4155
4324
  return false;
4156
4325
  }
4326
+ // Case 1: remove the failed or truncated message from agent state, compact, and
4327
+ // retry once. The message remains in session history but is excluded from retry context.
4157
4328
  this._overflowRecoveryAttempted = true;
4158
4329
  // Remove the error message from agent state (it IS saved to session for history,
4159
4330
  // but we don't want it in context for the retry)
@@ -4193,7 +4364,7 @@ export class AgentSession {
4193
4364
  else {
4194
4365
  const directContextTokens = assistantMessage.usage ? calculateContextTokens(assistantMessage.usage) : 0;
4195
4366
  if (assistantMessage.stopReason !== "error" && directContextTokens !== 0) {
4196
- contextTokens = directContextTokens;
4367
+ contextTokens = this._resolveThresholdContextTokens(directContextTokens);
4197
4368
  }
4198
4369
  else {
4199
4370
  const messages = filterContextExcludedMessages(this.agent.state.messages);
@@ -4419,7 +4590,14 @@ export class AgentSession {
4419
4590
  .catch(() => undefined);
4420
4591
  }
4421
4592
  /**
4422
- * Internal: Run auto-compaction with events.
4593
+ * Execute threshold or overflow compaction. Manual compaction uses
4594
+ * `AgentSession.compact()` instead. Both paths call the lower-level `compact()`
4595
+ * function imported from `./compaction/index.ts` after preparation and extension
4596
+ * interception.
4597
+ *
4598
+ * @param reason Automatic trigger selected by `_checkCompaction()`
4599
+ * @param willRetry Whether to continue the interrupted turn after overflow compaction
4600
+ * @returns Whether the post-run loop should call `agent.continue()`
4423
4601
  */
4424
4602
  async _runAutoCompaction(reason, willRetry) {
4425
4603
  const finishCompactionWork = this._sessionWorkBarrier.begin();
@@ -4520,6 +4698,11 @@ export class AgentSession {
4520
4698
  this._overflowRecoveryAttempted = false;
4521
4699
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
4522
4700
  const aborted = isCompactionExecutionAborted(error);
4701
+ const formattedErrorMessage = aborted
4702
+ ? undefined
4703
+ : reason === "overflow"
4704
+ ? `Context overflow recovery failed: ${errorMessage}`
4705
+ : `Auto-compaction failed: ${errorMessage}`;
4523
4706
  this._emit({
4524
4707
  type: "compaction_end",
4525
4708
  reason,
@@ -4527,11 +4710,14 @@ export class AgentSession {
4527
4710
  aborted,
4528
4711
  willRetry: false,
4529
4712
  requestId,
4530
- errorMessage: aborted
4531
- ? undefined
4532
- : reason === "overflow"
4533
- ? `Context overflow recovery failed: ${errorMessage}`
4534
- : `Auto-compaction failed: ${errorMessage}`,
4713
+ errorMessage: formattedErrorMessage,
4714
+ });
4715
+ await this._emitSessionCompactFailed({
4716
+ reason,
4717
+ errorMessage: formattedErrorMessage,
4718
+ aborted,
4719
+ willRetry: false,
4720
+ fromExtension: false,
4535
4721
  });
4536
4722
  return false;
4537
4723
  }
@@ -4823,7 +5009,11 @@ export class AgentSession {
4823
5009
  await this._abortActiveAgentAndRetry("system");
4824
5010
  this._disconnectFromAgent();
4825
5011
  disconnected = true;
4826
- this._emit({ type: "compaction_start", reason: "extension", requestId });
5012
+ this._emit({
5013
+ type: "compaction_start",
5014
+ reason: "extension",
5015
+ requestId,
5016
+ });
4827
5017
  const execution = await this._executeCompaction({
4828
5018
  controller,
4829
5019
  owner: "compaction",
@@ -4943,7 +5133,9 @@ export class AgentSession {
4943
5133
  ...registeredTools.filter(isConfiguredBuiltinTool),
4944
5134
  ...this._customTools.map((definition) => ({
4945
5135
  definition,
4946
- sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" }),
5136
+ sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, {
5137
+ source: "sdk",
5138
+ }),
4947
5139
  })),
4948
5140
  ].filter((tool) => isAllowedTool(tool.definition.name));
4949
5141
  const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
@@ -4952,7 +5144,9 @@ export class AgentSession {
4952
5144
  name,
4953
5145
  {
4954
5146
  definition,
4955
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
5147
+ sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, {
5148
+ source: "builtin",
5149
+ }),
4956
5150
  },
4957
5151
  ]));
4958
5152
  for (const tool of allCustomTools) {
@@ -5080,7 +5274,10 @@ export class AgentSession {
5080
5274
  if (entry)
5081
5275
  previousActiveToolRegistrationIds.set(name, deriveExtensionRegistrationId(entry.sourceInfo, name));
5082
5276
  }
5083
- await emitSessionShutdownEvent(oldExtensionRunner, { type: "session_shutdown", reason: "reload" });
5277
+ await emitSessionShutdownEvent(oldExtensionRunner, {
5278
+ type: "session_shutdown",
5279
+ reason: "reload",
5280
+ });
5084
5281
  time("shutdown", "reload");
5085
5282
  await this.settingsManager.reload();
5086
5283
  this.syncQueueModesFromSettings();
@@ -5092,14 +5289,18 @@ export class AgentSession {
5092
5289
  // swallows availability errors, so a failed scan must fall back to the runtime and
5093
5290
  // keep the previous refresh-and-surface-the-error behavior.
5094
5291
  const refreshedModels = this._modelRuntime.hasFreshAvailabilitySnapshot()
5095
- ? { getAvailable: async () => this._modelRuntime.getAvailableSnapshot() }
5292
+ ? {
5293
+ getAvailable: async () => this._modelRuntime.getAvailableSnapshot(),
5294
+ }
5096
5295
  : this._modelRuntime;
5097
5296
  this.setScopedModels(await resolveModelScope(getModelNarrowingPatterns({
5098
5297
  legacyEnabledPatterns: this.settingsManager.getEnabledModels(),
5099
5298
  }), refreshedModels));
5100
5299
  this.setFavoriteModels(await resolveModelScope(this.settingsManager.getFavoriteModels() ?? [], refreshedModels));
5101
5300
  time("models", "reload");
5102
- await this._resourceLoader.reload({ settingsAlreadyReloadedFor: this.settingsManager });
5301
+ await this._resourceLoader.reload({
5302
+ settingsAlreadyReloadedFor: this.settingsManager,
5303
+ });
5103
5304
  time("resources", "reload");
5104
5305
  try {
5105
5306
  this._buildRuntime({
@@ -5117,7 +5318,11 @@ export class AgentSession {
5117
5318
  const removed = oldExtensionIdentities.filter((extension) => !newExtensionResolvedPaths.has(extension.resolvedPath));
5118
5319
  try {
5119
5320
  if (removed.length > 0) {
5120
- await oldExtensionRunner.emit({ type: "session_extensions_removed", reason: "reload", removed });
5321
+ await oldExtensionRunner.emit({
5322
+ type: "session_extensions_removed",
5323
+ reason: "reload",
5324
+ removed,
5325
+ });
5121
5326
  }
5122
5327
  }
5123
5328
  finally {
@@ -5132,7 +5337,10 @@ export class AgentSession {
5132
5337
  if (hasBindings) {
5133
5338
  await options?.beforeSessionStart?.();
5134
5339
  this.syncPromptCacheSafeWaitEnv();
5135
- await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
5340
+ await this._extensionRunner.emit({
5341
+ type: "session_start",
5342
+ reason: "reload",
5343
+ });
5136
5344
  await this.extendResourcesFromExtensions("reload");
5137
5345
  }
5138
5346
  time("lifecycle", "reload");
@@ -5149,7 +5357,9 @@ export class AgentSession {
5149
5357
  if (!this._extensionRunner.hasHandlers("session_before_reload")) {
5150
5358
  return { cancelled: false };
5151
5359
  }
5152
- const result = await this._extensionRunner.emit({ type: "session_before_reload" });
5360
+ const result = await this._extensionRunner.emit({
5361
+ type: "session_before_reload",
5362
+ });
5153
5363
  if (result?.cancel !== true) {
5154
5364
  return { cancelled: false };
5155
5365
  }
@@ -5236,9 +5446,18 @@ export class AgentSession {
5236
5446
  const finishTurn = (attempt, finalError) => {
5237
5447
  const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
5238
5448
  if (exhaustedChainKey) {
5239
- this._emit({ type: "retry_fallback_exhausted", chainKey: exhaustedChainKey, lastError: errorMessage });
5449
+ this._emit({
5450
+ type: "retry_fallback_exhausted",
5451
+ chainKey: exhaustedChainKey,
5452
+ lastError: errorMessage,
5453
+ });
5240
5454
  }
5241
- this._emit({ type: "auto_retry_end", success: false, attempt, finalError });
5455
+ this._emit({
5456
+ type: "auto_retry_end",
5457
+ success: false,
5458
+ attempt,
5459
+ finalError,
5460
+ });
5242
5461
  this._retryAttempt = 0;
5243
5462
  this._resetHintTierState();
5244
5463
  this._resolveRetry();
@@ -5284,7 +5503,9 @@ export class AgentSession {
5284
5503
  // Billing-class failures never recover on this account, so the fallback
5285
5504
  // switch pins as the session model instead of reverting after the cooldown.
5286
5505
  const reason = isBillingErrorMessage(errorMessage) ? "billing" : "hard-error";
5287
- switchedFallback = await this._retryFallback.tryFallback(reason, { errorMessage });
5506
+ switchedFallback = await this._retryFallback.tryFallback(reason, {
5507
+ errorMessage,
5508
+ });
5288
5509
  if (!switchedFallback) {
5289
5510
  this._resolveRetry();
5290
5511
  return "not-handled";
@@ -5313,7 +5534,11 @@ export class AgentSession {
5313
5534
  if (!switchedFallback) {
5314
5535
  const exhaustedChainKey = this._retryFallback.exhaustedChainKey;
5315
5536
  if (exhaustedChainKey) {
5316
- this._emit({ type: "retry_fallback_exhausted", chainKey: exhaustedChainKey, lastError: errorMessage });
5537
+ this._emit({
5538
+ type: "retry_fallback_exhausted",
5539
+ chainKey: exhaustedChainKey,
5540
+ lastError: errorMessage,
5541
+ });
5317
5542
  }
5318
5543
  if (this._retryAttempt > 0) {
5319
5544
  this._emit({
@@ -5679,7 +5904,11 @@ export class AgentSession {
5679
5904
  const result = await executeBashWithOperations(resolvedCommand, this.sessionManager.getCwd(), options?.operations ?? createLocalBashOperations({ shellPath }), {
5680
5905
  onChunk: (delta) => {
5681
5906
  onChunk?.(delta);
5682
- this._emit({ type: "bash_execution_update", id: options?.id, delta });
5907
+ this._emit({
5908
+ type: "bash_execution_update",
5909
+ id: options?.id,
5910
+ delta,
5911
+ });
5683
5912
  },
5684
5913
  signal: abortController.signal,
5685
5914
  });
@@ -5759,7 +5988,10 @@ export class AgentSession {
5759
5988
  */
5760
5989
  setSessionName(name) {
5761
5990
  this.sessionManager.appendSessionInfo(name);
5762
- const event = { type: "session_info_changed", name: this.sessionManager.getSessionName() };
5991
+ const event = {
5992
+ type: "session_info_changed",
5993
+ name: this.sessionManager.getSessionName(),
5994
+ };
5763
5995
  this._emit(event);
5764
5996
  void this._extensionRunner.emit(event);
5765
5997
  }
@@ -5860,7 +6092,9 @@ export class AgentSession {
5860
6092
  reserveTokens: branchSummarySettings.reserveTokens,
5861
6093
  streamFn: this.agent.streamFunction,
5862
6094
  retry: this.settingsManager.getRetrySettings(),
5863
- callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
6095
+ callbacks: this._summarizationRetryCallbacks({
6096
+ source: "branchSummary",
6097
+ }),
5864
6098
  });
5865
6099
  if (result.aborted) {
5866
6100
  return { cancelled: true, aborted: true };
@@ -6067,7 +6301,11 @@ export class AgentSession {
6067
6301
  }
6068
6302
  if (!hasPostCompactionUsage) {
6069
6303
  const tokens = messages.reduce((sum, message) => sum + estimateTokens(message), 0);
6070
- return { tokens, contextWindow, percent: (tokens / contextWindow) * 100 };
6304
+ return {
6305
+ tokens,
6306
+ contextWindow,
6307
+ percent: (tokens / contextWindow) * 100,
6308
+ };
6071
6309
  }
6072
6310
  }
6073
6311
  const estimate = estimateContextTokens(messages);