@code-yeongyu/senpi 2026.9.10 → 2026.9.12-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  3. package/dist/core/agent-session-runtime.js +5 -1
  4. package/dist/core/agent-session-runtime.js.map +1 -1
  5. package/dist/core/agent-session.d.ts +70 -9
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +183 -140
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/auth-storage.d.ts +2 -0
  10. package/dist/core/auth-storage.d.ts.map +1 -1
  11. package/dist/core/auth-storage.js +49 -17
  12. package/dist/core/auth-storage.js.map +1 -1
  13. package/dist/core/brand.d.ts +5 -0
  14. package/dist/core/brand.d.ts.map +1 -1
  15. package/dist/core/brand.js +13 -0
  16. package/dist/core/brand.js.map +1 -1
  17. package/dist/core/changelog-source.d.ts +8 -0
  18. package/dist/core/changelog-source.d.ts.map +1 -0
  19. package/dist/core/changelog-source.js +19 -0
  20. package/dist/core/changelog-source.js.map +1 -0
  21. package/dist/core/credential-accounts.d.ts +3 -0
  22. package/dist/core/credential-accounts.d.ts.map +1 -1
  23. package/dist/core/credential-accounts.js +20 -1
  24. package/dist/core/credential-accounts.js.map +1 -1
  25. package/dist/core/credential-pool/classify.d.ts.map +1 -1
  26. package/dist/core/credential-pool/classify.js +8 -0
  27. package/dist/core/credential-pool/classify.js.map +1 -1
  28. package/dist/core/cursor-history-admission.d.ts +50 -0
  29. package/dist/core/cursor-history-admission.d.ts.map +1 -0
  30. package/dist/core/cursor-history-admission.js +130 -0
  31. package/dist/core/cursor-history-admission.js.map +1 -0
  32. package/dist/core/extensions/builtin/account/index.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/account/index.js +7 -3
  34. package/dist/core/extensions/builtin/account/index.js.map +1 -1
  35. package/dist/core/extensions/builtin/account-display-name.d.ts +7 -0
  36. package/dist/core/extensions/builtin/account-display-name.d.ts.map +1 -0
  37. package/dist/core/extensions/builtin/account-display-name.js +40 -0
  38. package/dist/core/extensions/builtin/account-display-name.js.map +1 -0
  39. package/dist/core/extensions/builtin/ask-user/format.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/ask-user/format.js +7 -2
  41. package/dist/core/extensions/builtin/ask-user/format.js.map +1 -1
  42. package/dist/core/extensions/builtin/ask-user/pending.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/ask-user/pending.js +3 -0
  44. package/dist/core/extensions/builtin/ask-user/pending.js.map +1 -1
  45. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts.map +1 -1
  46. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js +21 -9
  47. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js.map +1 -1
  48. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts +1 -0
  49. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js +11 -6
  51. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js.map +1 -1
  52. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts +9 -0
  53. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js +10 -1
  55. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js.map +1 -1
  56. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +3 -0
  57. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  58. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
  59. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +19 -10
  60. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
  61. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.d.ts.map +1 -1
  62. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js +3 -9
  63. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js.map +1 -1
  64. package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/config-reload/routine-settings.js +1 -0
  66. package/dist/core/extensions/builtin/config-reload/routine-settings.js.map +1 -1
  67. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +5 -3
  69. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js.map +1 -1
  70. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts +1 -0
  71. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts.map +1 -1
  72. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.js.map +1 -1
  73. package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/cursor-cli-oauth/models.js +2 -1
  75. package/dist/core/extensions/builtin/cursor-cli-oauth/models.js.map +1 -1
  76. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts.map +1 -1
  77. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js +3 -9
  78. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js.map +1 -1
  79. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  80. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +13 -1
  81. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  82. package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -1
  83. package/dist/core/extensions/builtin/goal/prompt.js +11 -8
  84. package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
  85. package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts +1 -0
  86. package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/goal/terminal-provider-error.js +28 -0
  88. package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
  89. package/dist/core/extensions/builtin/goal/todo-gate.js +2 -2
  90. package/dist/core/extensions/builtin/goal/todo-gate.js.map +1 -1
  91. package/dist/core/extensions/builtin/goal/tool-registration.js +2 -2
  92. package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
  93. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -1
  94. package/dist/core/extensions/builtin/gpt-account.js +19 -8
  95. package/dist/core/extensions/builtin/gpt-account.js.map +1 -1
  96. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts +3 -0
  97. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts.map +1 -0
  98. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js +19 -0
  99. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js.map +1 -0
  100. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +6 -6
  101. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
  102. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +26 -7
  103. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
  104. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  105. package/dist/core/extensions/builtin/prompt-preset/presets.js +29 -0
  106. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  107. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  108. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  109. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  110. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  111. package/dist/core/high-reasoning-warning.d.ts.map +1 -1
  112. package/dist/core/high-reasoning-warning.js +5 -1
  113. package/dist/core/high-reasoning-warning.js.map +1 -1
  114. package/dist/core/manual-continue.d.ts +14 -0
  115. package/dist/core/manual-continue.d.ts.map +1 -1
  116. package/dist/core/manual-continue.js +13 -0
  117. package/dist/core/manual-continue.js.map +1 -1
  118. package/dist/core/model-runtime.d.ts.map +1 -1
  119. package/dist/core/model-runtime.js +2 -2
  120. package/dist/core/model-runtime.js.map +1 -1
  121. package/dist/core/remote-catalog-merge.d.ts +16 -0
  122. package/dist/core/remote-catalog-merge.d.ts.map +1 -0
  123. package/dist/core/remote-catalog-merge.js +75 -0
  124. package/dist/core/remote-catalog-merge.js.map +1 -0
  125. package/dist/core/remote-catalog-provider.d.ts +3 -0
  126. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  127. package/dist/core/remote-catalog-provider.js +12 -40
  128. package/dist/core/remote-catalog-provider.js.map +1 -1
  129. package/dist/core/session-entry-materializer.d.ts +12 -0
  130. package/dist/core/session-entry-materializer.d.ts.map +1 -0
  131. package/dist/core/session-entry-materializer.js +26 -0
  132. package/dist/core/session-entry-materializer.js.map +1 -0
  133. package/dist/core/session-manager.d.ts +38 -1
  134. package/dist/core/session-manager.d.ts.map +1 -1
  135. package/dist/core/session-manager.js +60 -21
  136. package/dist/core/session-manager.js.map +1 -1
  137. package/dist/core/session-write-reservation.d.ts +9 -0
  138. package/dist/core/session-write-reservation.d.ts.map +1 -1
  139. package/dist/core/session-write-reservation.js +33 -0
  140. package/dist/core/session-write-reservation.js.map +1 -1
  141. package/dist/core/settings-manager.d.ts +3 -0
  142. package/dist/core/settings-manager.d.ts.map +1 -1
  143. package/dist/core/settings-manager.js +10 -0
  144. package/dist/core/settings-manager.js.map +1 -1
  145. package/dist/modes/app-server/daemon/process.d.ts +6 -1
  146. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  147. package/dist/modes/app-server/daemon/process.js +23 -4
  148. package/dist/modes/app-server/daemon/process.js.map +1 -1
  149. package/dist/modes/app-server/protocol/account.d.ts +2 -0
  150. package/dist/modes/app-server/protocol/account.d.ts.map +1 -1
  151. package/dist/modes/app-server/protocol/account.js.map +1 -1
  152. package/dist/modes/interactive/components/ask-user-async-widget.d.ts +2 -0
  153. package/dist/modes/interactive/components/ask-user-async-widget.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/ask-user-async-widget.js +17 -1
  155. package/dist/modes/interactive/components/ask-user-async-widget.js.map +1 -1
  156. package/dist/modes/interactive/components/ask-user-question-keys.d.ts +1 -1
  157. package/dist/modes/interactive/components/ask-user-question-keys.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/ask-user-question-keys.js +65 -17
  159. package/dist/modes/interactive/components/ask-user-question-keys.js.map +1 -1
  160. package/dist/modes/interactive/components/ask-user-question-render.d.ts +2 -1
  161. package/dist/modes/interactive/components/ask-user-question-render.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/ask-user-question-render.js +39 -9
  163. package/dist/modes/interactive/components/ask-user-question-render.js.map +1 -1
  164. package/dist/modes/interactive/components/ask-user-question-state.d.ts +14 -4
  165. package/dist/modes/interactive/components/ask-user-question-state.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/ask-user-question-state.js +63 -6
  167. package/dist/modes/interactive/components/ask-user-question-state.js.map +1 -1
  168. package/dist/modes/interactive/components/ask-user-question.d.ts +2 -0
  169. package/dist/modes/interactive/components/ask-user-question.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/ask-user-question.js +27 -14
  171. package/dist/modes/interactive/components/ask-user-question.js.map +1 -1
  172. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  173. package/dist/modes/interactive/components/footer.js +51 -19
  174. package/dist/modes/interactive/components/footer.js.map +1 -1
  175. package/dist/modes/interactive/components/login-dialog.d.ts +11 -0
  176. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  177. package/dist/modes/interactive/components/login-dialog.js +29 -9
  178. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  179. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  180. package/dist/modes/interactive/components/tree-selector.js +7 -0
  181. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  182. package/dist/modes/interactive/help-content.d.ts.map +1 -1
  183. package/dist/modes/interactive/help-content.js +4 -0
  184. package/dist/modes/interactive/help-content.js.map +1 -1
  185. package/dist/modes/interactive/interactive-mode.d.ts +13 -4
  186. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/dist/modes/interactive/interactive-mode.js +46 -17
  188. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/dist/modes/interactive/tips/catalog/input-tips.js +1 -1
  190. package/dist/modes/interactive/tips/catalog/input-tips.js.map +1 -1
  191. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  192. package/dist/modes/rpc/connection-handler.js +3 -1
  193. package/dist/modes/rpc/connection-handler.js.map +1 -1
  194. package/dist/modes/rpc/connection-question-bridge.js +1 -1
  195. package/dist/modes/rpc/connection-question-bridge.js.map +1 -1
  196. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  197. package/dist/modes/rpc/host-ensure.js +33 -11
  198. package/dist/modes/rpc/host-ensure.js.map +1 -1
  199. package/dist/modes/rpc/host-lifecycle.d.ts +14 -0
  200. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  201. package/dist/modes/rpc/host-lifecycle.js +31 -5
  202. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  203. package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
  204. package/dist/modes/rpc/rpc-input-validation.js +2 -0
  205. package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
  206. package/dist/modes/rpc/rpc-types.d.ts +4 -1
  207. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  208. package/dist/modes/rpc/rpc-types.js +1 -0
  209. package/dist/modes/rpc/rpc-types.js.map +1 -1
  210. package/dist/modes/rpc/session-path-reservations.d.ts +30 -0
  211. package/dist/modes/rpc/session-path-reservations.d.ts.map +1 -0
  212. package/dist/modes/rpc/session-path-reservations.js +58 -0
  213. package/dist/modes/rpc/session-path-reservations.js.map +1 -0
  214. package/dist/modes/rpc/session-registry.d.ts +3 -1
  215. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  216. package/dist/modes/rpc/session-registry.js.map +1 -1
  217. package/dist/modes/rpc/session-worker-client.d.ts +10 -8
  218. package/dist/modes/rpc/session-worker-client.d.ts.map +1 -1
  219. package/dist/modes/rpc/session-worker-client.js +14 -23
  220. package/dist/modes/rpc/session-worker-client.js.map +1 -1
  221. package/dist/modes/rpc/session-worker-credit.d.ts +17 -0
  222. package/dist/modes/rpc/session-worker-credit.d.ts.map +1 -0
  223. package/dist/modes/rpc/session-worker-credit.js +39 -0
  224. package/dist/modes/rpc/session-worker-credit.js.map +1 -0
  225. package/dist/modes/rpc/session-worker-protocol.d.ts +10 -0
  226. package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -1
  227. package/dist/modes/rpc/session-worker-protocol.js +2 -0
  228. package/dist/modes/rpc/session-worker-protocol.js.map +1 -1
  229. package/dist/modes/rpc/session-worker-signals.d.ts +7 -0
  230. package/dist/modes/rpc/session-worker-signals.d.ts.map +1 -0
  231. package/dist/modes/rpc/session-worker-signals.js +19 -0
  232. package/dist/modes/rpc/session-worker-signals.js.map +1 -0
  233. package/dist/modes/rpc/session-worker.js +12 -16
  234. package/dist/modes/rpc/session-worker.js.map +1 -1
  235. package/dist/modes/rpc/worker-session-registry.d.ts +12 -0
  236. package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -1
  237. package/dist/modes/rpc/worker-session-registry.js +51 -24
  238. package/dist/modes/rpc/worker-session-registry.js.map +1 -1
  239. package/dist/utils/changelog.d.ts +3 -1
  240. package/dist/utils/changelog.d.ts.map +1 -1
  241. package/dist/utils/changelog.js +89 -23
  242. package/dist/utils/changelog.js.map +1 -1
  243. package/dist/utils/paths.d.ts +5 -0
  244. package/dist/utils/paths.d.ts.map +1 -1
  245. package/dist/utils/paths.js +14 -1
  246. package/dist/utils/paths.js.map +1 -1
  247. package/docs/app-server.md +6 -0
  248. package/docs/extensions.md +19 -3
  249. package/docs/rpc.md +24 -6
  250. package/docs/settings.md +2 -1
  251. package/docs/tui.md +1 -1
  252. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
  253. package/node_modules/@code-yeongyu/senpi-codemode/README.md +5 -4
  254. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  255. package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output-buffer.ts +58 -0
  256. package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output.ts +9 -64
  257. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +1 -1
  258. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  259. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +11 -0
  260. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -1
  261. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +18 -0
  262. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -1
  263. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +1 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  265. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +5 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts +19 -0
  268. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts.map +1 -0
  269. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js +135 -0
  270. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js.map +1 -0
  271. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts +23 -0
  272. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts.map +1 -0
  273. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js +71 -0
  274. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js.map +1 -0
  275. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts +1261 -0
  276. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts.map +1 -0
  277. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js +431 -0
  278. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js.map +1 -0
  279. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts +42 -0
  280. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts.map +1 -0
  281. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js +68 -0
  282. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js.map +1 -0
  283. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts +43 -0
  284. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts.map +1 -0
  285. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js +43 -0
  286. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js.map +1 -0
  287. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts +36 -0
  288. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts.map +1 -0
  289. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js +158 -0
  290. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js.map +1 -0
  291. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts +26 -0
  292. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts.map +1 -0
  293. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js +145 -0
  294. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js.map +1 -0
  295. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.d.ts +16 -0
  296. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.d.ts.map +1 -0
  297. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.js +69 -0
  298. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.js.map +1 -0
  299. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts +12 -0
  300. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts.map +1 -0
  301. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js +3 -0
  302. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js.map +1 -0
  303. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.d.ts +26 -0
  304. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.d.ts.map +1 -0
  305. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.js +61 -0
  306. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.js.map +1 -0
  307. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts +8 -0
  308. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts.map +1 -0
  309. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js +8 -0
  310. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js.map +1 -0
  311. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts +22 -0
  312. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts.map +1 -0
  313. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js +217 -0
  314. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js.map +1 -0
  315. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts +5 -0
  316. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts.map +1 -0
  317. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js +23 -0
  318. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js.map +1 -0
  319. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts +25 -0
  320. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts.map +1 -0
  321. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js +124 -0
  322. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js.map +1 -0
  323. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts +18 -0
  324. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts.map +1 -0
  325. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js +101 -0
  326. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js.map +1 -0
  327. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts +19 -0
  328. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts.map +1 -0
  329. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js +116 -0
  330. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js.map +1 -0
  331. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +5 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts +24 -0
  335. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts.map +1 -0
  336. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js +86 -0
  337. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js.map +1 -0
  338. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts +2 -0
  339. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +5 -0
  341. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +51 -4
  343. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +196 -7
  345. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +8 -0
  347. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +10 -0
  349. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +9 -1
  351. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  353. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts.map +1 -1
  354. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +2 -0
  355. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js.map +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +1 -0
  357. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
  358. package/node_modules/@earendil-works/pi-ai/dist/compat.js +3 -0
  359. package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
  360. package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.d.ts +32 -0
  361. package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.d.ts.map +1 -0
  362. package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.js +62 -0
  363. package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.js.map +1 -0
  364. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts.map +1 -1
  365. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js +2 -1
  366. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js.map +1 -1
  367. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +4 -4
  368. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  369. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -1
  370. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  371. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -1
  372. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  373. package/node_modules/@earendil-works/pi-ai/dist/model.d.ts +11 -1
  374. package/node_modules/@earendil-works/pi-ai/dist/model.d.ts.map +1 -1
  375. package/node_modules/@earendil-works/pi-ai/dist/model.js.map +1 -1
  376. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +1 -1
  377. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  378. package/node_modules/@earendil-works/pi-ai/dist/models.js +14 -5
  379. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  380. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  381. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -0
  382. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  383. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.d.ts.map +1 -1
  384. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js +2 -1
  385. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js.map +1 -1
  386. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  387. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  388. package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  389. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  390. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  391. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  392. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  393. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts +12 -0
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts.map +1 -0
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js +62 -0
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js.map +1 -0
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +12 -0
  401. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -0
  402. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +37 -0
  403. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -0
  404. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +3 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  406. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.d.ts +12 -0
  408. package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.d.ts.map +1 -0
  409. package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.js +93 -0
  410. package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.js.map +1 -0
  411. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  412. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +4 -0
  413. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  414. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  415. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  416. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  417. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts +1 -1
  418. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js +55 -16
  420. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js.map +1 -1
  421. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  422. package/package.json +7 -7
@@ -18,8 +18,9 @@ import { rm } from "node:fs/promises";
18
18
  import { basename, dirname } from "node:path";
19
19
  import { isDeepStrictEqual } from "node:util";
20
20
  import { ProviderRetryWatchdogAbortError, prepareAgentToolCall } from "@earendil-works/pi-agent-core";
21
- import { contentText, measureCursorHistorySerializedBytes, SERVER_FALLBACK_ABORTED_DIAGNOSTIC, } from "@earendil-works/pi-ai";
21
+ import { contentText, providerNotConfiguredMessage, SERVER_FALLBACK_ABORTED_DIAGNOSTIC, } from "@earendil-works/pi-ai";
22
22
  import { cleanupSessionResources, cursorOverflowCompactionSettings, isClassifierRefusal, isContextOverflow, isCursorPayloadResourceExhausted, isCursorQuotaResourceExhausted, isCursorZeroTokenResourceExhausted, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, shouldRetryOverflowWithoutCompact, streamSimple, } from "@earendil-works/pi-ai/compat";
23
+ import { getCursorContextLimit } from "@earendil-works/pi-ai/utils/cursor-context-limit";
23
24
  import { extract429RetryAfterMs, parseRetryAfterMsMarker } from "@earendil-works/pi-ai/utils/retry-hint";
24
25
  import { retryBackoffDelayMs } from "@earendil-works/pi-ai/utils/retry-profile/backoff";
25
26
  import { getAgentDir } from "../config.js";
@@ -37,12 +38,14 @@ import { calculateContextTokens, collectEntriesForBranchSummary, compact, estima
37
38
  import { CompactionLifecycleCoordinator } from "./compaction/lifecycle.js";
38
39
  import { isTurnStuckOnContextOverflow } from "./compaction/stuck-overflow.js";
39
40
  import { isWarmSummaryAnchorValid } from "./compaction/warm-anchor.js";
41
+ import { admitCursorHistory, cursorAdmissionBudgetBytes } from "./cursor-history-admission.js";
40
42
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
41
43
  import { buildDynamicSystemPrompt } from "./dynamic-prompt/index.js";
42
44
  import { AssistantEditError, assertExpectedLeaf, assistantTextEquals, buildEditedAssistantMessage, SessionStreamingError, } from "./edited-assistant-message.js";
43
45
  import { areExperimentalFeaturesEnabled } from "./experimental.js";
44
46
  import { exportSessionToHtml } from "./export-html/index.js";
45
47
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
48
+ import { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "./extensions/builtin/claude-sdk-oauth/account-management.js";
46
49
  import { ModelUsabilityBudgetError, projectModelUsabilityBudget, } from "./extensions/builtin/compaction/model-usability-budget.js";
47
50
  import { resolveEffectiveReserveTokens, resolveReserveTokens, shouldTriggerCompaction, } from "./extensions/builtin/compaction/policy.js";
48
51
  import { createResumeCompactionRequirement, } from "./extensions/builtin/compaction/resume-admission.js";
@@ -55,8 +58,8 @@ import { ExecuteToolError, ExtensionRunner, wrapRegisteredTools, } from "./exten
55
58
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
56
59
  import { normalizeToolExposure, RUNTIME_EXTENSION_PATH } from "./extensions/types.js";
57
60
  import { shouldWarnHighReasoning } from "./high-reasoning-warning.js";
58
- import { MANUAL_CONTINUE_CUSTOM_TYPE, MANUAL_CONTINUE_DIRECTIVE } from "./manual-continue.js";
59
- import { convertToLlm, filterContextExcludedMessages, } from "./messages.js";
61
+ import { isManualContinueSubmission, MANUAL_CONTINUE_CUSTOM_TYPE, MANUAL_CONTINUE_DIRECTIVE, } from "./manual-continue.js";
62
+ import { filterContextExcludedMessages } from "./messages.js";
60
63
  import { ModelRegistry } from "./model-registry.js";
61
64
  import { getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.js";
62
65
  import { PROMPT_CACHE_SAFE_WAIT_ENV, resolvePromptCacheSafeWaitSeconds } from "./prompt-cache-budget.js";
@@ -334,121 +337,11 @@ function isSameOverflowSource(message, model, upstreamModelId) {
334
337
  const THINKING_LEVELS_WITH_MAX = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
335
338
  /** Caps explicit skill expansion so one prompt cannot consume unbounded context. */
336
339
  export const MAX_SKILL_EXPANSIONS_PER_PROMPT = 5;
337
- /** Cursor ingest rejects large verbatim tool payloads. The bound is UTF-8 bytes. */
338
- export const CURSOR_TOOL_RESULT_MAX_CHARS = 2000;
339
- export const CURSOR_TOOL_RESULT_MAX_BYTES = 50_000;
340
- const CURSOR_TRUNCATION_MARKER = "\n...[truncated]";
341
- export function truncateToolResultBodies(messages, maxChars = CURSOR_TOOL_RESULT_MAX_CHARS, maxBytes = CURSOR_TOOL_RESULT_MAX_BYTES, convert = (candidate) => convertToLlm(candidate)) {
342
- if (!Array.isArray(messages) || messages.length === 0)
343
- return { messages, changed: false };
344
- const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
345
- const markerChars = [...segmenter.segment(CURSOR_TRUNCATION_MARKER)].length;
346
- const result = messages.slice();
347
- let changed = false;
348
- // Apply the per-result character cap first, independent of the aggregate wire cap.
349
- for (let messageIndex = result.length - 1; messageIndex >= 0; messageIndex--) {
350
- const message = result[messageIndex];
351
- if (message.role !== "toolResult" || !Array.isArray(message.content))
352
- continue;
353
- let content = message.content;
354
- for (let partIndex = content.length - 1; partIndex >= 0; partIndex--) {
355
- const part = content[partIndex];
356
- if (part.type === "image" && typeof part.data === "string")
357
- continue;
358
- if (part.type !== "text" || typeof part.text !== "string")
359
- continue;
360
- const graphemes = [...segmenter.segment(part.text)].map((item) => item.segment);
361
- if (graphemes.length <= maxChars)
362
- continue;
363
- const kept = graphemes.slice(0, Math.max(0, maxChars - markerChars)).join("");
364
- const nextText = kept + CURSOR_TRUNCATION_MARKER;
365
- content = content === message.content ? content.slice() : content;
366
- content[partIndex] = { ...part, text: nextText };
367
- result[messageIndex] = { ...message, content };
368
- changed = true;
369
- }
370
- }
371
- const measure = (candidate) => {
372
- const converted = convert(candidate);
373
- const activeUserMessageIndex = converted.at(-1)?.role === "user" ? converted.length - 1 : -1;
374
- return measureCursorHistorySerializedBytes(converted, activeUserMessageIndex);
375
- };
376
- const fits = (candidate = result) => measure(candidate) <= maxBytes;
377
- if (fits())
378
- return { messages: changed ? result : messages, changed };
379
- // Empty the oldest result bodies. Search the monotonic prefix of candidates
380
- // rather than serializing once for every result (admission must stay bounded).
381
- const emptyToolResult = (message) => {
382
- if (message.role !== "toolResult" || !Array.isArray(message.content))
383
- return message;
384
- const emptiedContent = message.content.map((part) => part.type === "text" ? { ...part, text: "" } : part.type === "image" ? { ...part, data: "" } : part);
385
- const content = emptiedContent.filter((part, index) => {
386
- if (index === 0)
387
- return true;
388
- const previous = emptiedContent[index - 1];
389
- const empty = part.type === "text" ? part.text === "" : part.type === "image" && part.data === "";
390
- const previousEmpty = previous.type === "text" ? previous.text === "" : previous.type === "image" && previous.data === "";
391
- return !empty || !previousEmpty;
392
- });
393
- return { ...message, content };
394
- };
395
- const toolResultIndexes = result.flatMap((message, index) => message.role === "toolResult" && Array.isArray(message.content) ? [index] : []);
396
- const withEmptyPrefix = (count) => {
397
- const candidate = result.slice();
398
- for (let i = 0; i < count; i++)
399
- candidate[toolResultIndexes[i]] = emptyToolResult(candidate[toolResultIndexes[i]]);
400
- return candidate;
401
- };
402
- let low = 0;
403
- let high = toolResultIndexes.length;
404
- while (low < high) {
405
- const middle = Math.floor((low + high) / 2);
406
- if (fits(withEmptyPrefix(middle + 1)))
407
- high = middle;
408
- else
409
- low = middle + 1;
410
- }
411
- const emptyCount = Math.min(low + 1, toolResultIndexes.length);
412
- if (emptyCount > 0) {
413
- result.splice(0, result.length, ...withEmptyPrefix(emptyCount));
414
- changed = true;
415
- }
416
- if (fits())
417
- return { messages: changed ? result : messages, changed };
418
- // If metadata alone exceeds the cap, discard the oldest complete turns. This
419
- // search is also monotonic and avoids quadratic whole-history reserialization.
420
- const turnRanges = [];
421
- const isConvertedUser = (message) => convert([message])[0]?.role === "user";
422
- for (let index = 0; index < result.length; index++) {
423
- if (!isConvertedUser(result[index]))
424
- continue;
425
- const nextUser = result.findIndex((message, nextIndex) => nextIndex > index && isConvertedUser(message));
426
- turnRanges.push([index, nextUser < 0 ? result.length : nextUser]);
427
- }
428
- const withoutTurns = (count) => {
429
- if (count === 0)
430
- return result;
431
- const start = turnRanges[0]?.[0] ?? 0;
432
- const end = turnRanges[count - 1]?.[1] ?? start;
433
- return [...result.slice(0, start), ...result.slice(end)];
434
- };
435
- low = 0;
436
- high = turnRanges.length;
437
- while (low < high) {
438
- const middle = Math.floor((low + high) / 2);
439
- if (fits(withoutTurns(middle + 1)))
440
- high = middle;
441
- else
442
- low = middle + 1;
443
- }
444
- const turnCount = Math.min(low + 1, turnRanges.length);
445
- if (turnCount > 0) {
446
- const next = withoutTurns(turnCount);
447
- result.splice(0, result.length, ...next);
448
- changed = true;
449
- }
450
- return { messages: changed ? result : messages, changed };
451
- }
340
+ /**
341
+ * Cursor admission lives in its own module; the names stay exported here so
342
+ * existing importers keep resolving them.
343
+ */
344
+ export { CURSOR_TOOL_RESULT_MAX_CHARS, truncateToolResultBodies } from "./cursor-history-admission.js";
452
345
  // ============================================================================
453
346
  // AgentSession Class
454
347
  // ============================================================================
@@ -904,6 +797,20 @@ export class AgentSession {
904
797
  usage: hookResult?.usage,
905
798
  };
906
799
  }
800
+ /**
801
+ * Cursor states a model's real context ceiling on every conversation
802
+ * checkpoint. Once observed, it replaces the catalog guess on the live model
803
+ * so context usage, compaction thresholds and admission all size against the
804
+ * window the server will actually enforce.
805
+ */
806
+ _applyObservedCursorContextWindow(model) {
807
+ const observed = getCursorContextLimit(model.id);
808
+ if (observed === undefined || observed <= 0 || observed === model.contextWindow)
809
+ return;
810
+ const previous = model.contextWindow;
811
+ model.contextWindow = observed;
812
+ this._sessionLogger.info("cursor_context_window_observed", { modelId: model.id, previous, observed });
813
+ }
907
814
  _installAgentNextTurnRefresh() {
908
815
  const previousPrepareNextTurnWithContext = this.agent.prepareNextTurnWithContext ??
909
816
  (this.agent.prepareNextTurn
@@ -912,10 +819,33 @@ export class AgentSession {
912
819
  const previousTransformContext = this.agent.transformContext;
913
820
  this.agent.transformContext = async (messages, signal) => {
914
821
  const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
915
- if (this.model?.provider === "cursor" || this.model?.provider === "cursor-cli-oauth") {
916
- return ((await truncateToolResultBodies(transformed, CURSOR_TOOL_RESULT_MAX_CHARS, CURSOR_TOOL_RESULT_MAX_BYTES, (candidate) => this.agent.convertToLlm(candidate))).messages ?? transformed);
822
+ const model = this.model;
823
+ if (model?.provider !== "cursor" && model?.provider !== "cursor-cli-oauth")
824
+ return transformed;
825
+ this._applyObservedCursorContextWindow(model);
826
+ const budgetBytes = cursorAdmissionBudgetBytes(model.contextWindow);
827
+ const admission = admitCursorHistory({
828
+ messages: transformed,
829
+ budgetBytes,
830
+ convert: (candidate) => this.agent.convertToLlm(candidate),
831
+ });
832
+ if (admission.blankedToolResults > 0) {
833
+ this._sessionLogger.info("cursor_admission_truncated", {
834
+ blankedToolResults: admission.blankedToolResults,
835
+ bytesBefore: admission.bytesBefore,
836
+ bytesAfter: admission.bytesAfter,
837
+ budgetBytes,
838
+ });
839
+ }
840
+ if (admission.overBudget) {
841
+ // The request is still admitted: Cursor answers an oversized history
842
+ // with a 0-token resource_exhausted, which the session layer compacts.
843
+ this._sessionLogger.warn("cursor_admission_over_budget", {
844
+ bytes: admission.bytesAfter,
845
+ budgetBytes,
846
+ });
917
847
  }
918
- return transformed;
848
+ return admission.messages ?? transformed;
919
849
  };
920
850
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
921
851
  // Enforce compaction only when this prepare precedes an actual provider
@@ -1700,9 +1630,14 @@ export class AgentSession {
1700
1630
  const hardErrorFallbackEligible = this._isHardErrorFallbackEligible(msg);
1701
1631
  const cursorZeroTokenRe = isCursorZeroTokenResourceExhausted(msg);
1702
1632
  const cursorQuotaRe = isCursorQuotaResourceExhausted(msg, this.model?.contextWindow ?? 0);
1633
+ const claudeSdkSameModelRemint = this._isClaudeSdkSameModelRemintError(msg);
1703
1634
  const retryCanAdmitProvider = !userAbortSuppressedQueuedContinuation &&
1704
1635
  this.settingsManager.getRetrySettings().enabled &&
1705
- (retryableError || hardErrorFallbackEligible || cursorZeroTokenRe || cursorQuotaRe);
1636
+ (retryableError ||
1637
+ hardErrorFallbackEligible ||
1638
+ cursorZeroTokenRe ||
1639
+ cursorQuotaRe ||
1640
+ claudeSdkSameModelRemint);
1706
1641
  let compactedBeforeRetry = false;
1707
1642
  if (retryCanAdmitProvider &&
1708
1643
  requiredAutoCompaction &&
@@ -1725,6 +1660,9 @@ export class AgentSession {
1725
1660
  this._retireFailedRetryAssistant(msg);
1726
1661
  retryOutcome = await this._handleRetryableError(msg, { hardErrorFallback: true });
1727
1662
  }
1663
+ else if (claudeSdkSameModelRemint) {
1664
+ retryOutcome = await this._handleRetryableError(msg, { sameModelRemint: true });
1665
+ }
1728
1666
  else if (retryableError) {
1729
1667
  retryOutcome = await this._handleRetryableError(msg);
1730
1668
  }
@@ -2791,7 +2729,11 @@ export class AgentSession {
2791
2729
  // empty session, or a "." carrying image attachments (the user is sending
2792
2730
  // the images, not asking to continue), falls through to ordinary prompt
2793
2731
  // handling below.
2794
- if (text.trim() === "." && this.agent.state.messages.length > 0 && !options?.images?.length) {
2732
+ if (isManualContinueSubmission({
2733
+ text,
2734
+ hasMessages: this.agent.state.messages.length > 0,
2735
+ hasImages: (options?.images?.length ?? 0) > 0,
2736
+ })) {
2795
2737
  await this.sendCustomMessage({
2796
2738
  customType: MANUAL_CONTINUE_CUSTOM_TYPE,
2797
2739
  content: MANUAL_CONTINUE_DIRECTIVE,
@@ -3782,10 +3724,67 @@ export class AgentSession {
3782
3724
  async setSessionModel(model) {
3783
3725
  return this._setModel(model, false);
3784
3726
  }
3727
+ /**
3728
+ * #1526: every switch guard rejects before `_switchActiveModel` appends its
3729
+ * `model_change`, so a refused switch used to leave no entry, no event, and
3730
+ * no log line - indistinguishable from a switch the user never attempted.
3731
+ * Record the refusal, then rethrow the original error unchanged.
3732
+ */
3733
+ _recordRejectedModelChange(model, error) {
3734
+ const budget = error instanceof ModelUsabilityBudgetError ? error.projection : undefined;
3735
+ const detail = error instanceof Error ? error.message : String(error);
3736
+ const reason = budget ? "context-budget" : "auth";
3737
+ const numbers = budget
3738
+ ? {
3739
+ contextWindow: budget.contextWindow,
3740
+ liveContextTokens: budget.liveContextTokens,
3741
+ requiredTokens: budget.requiredTokens,
3742
+ shortfallTokens: budget.shortfallTokens,
3743
+ safetyMarginProfile: budget.safetyMarginProfile,
3744
+ }
3745
+ : {};
3746
+ this.sessionManager.appendModelChangeRejected({
3747
+ provider: model.provider,
3748
+ modelId: model.id,
3749
+ reason,
3750
+ detail,
3751
+ ...numbers,
3752
+ });
3753
+ this._emit({ type: "model_change_rejected", model, reason, detail, ...numbers });
3754
+ }
3755
+ /**
3756
+ * The admission only selects wording, and the switch wording's remedy
3757
+ * ("Compact the session, ...") is executable only when there is context to
3758
+ * compact. `_setModel` is also reachable from `session_start` (the
3759
+ * `recommended-models` builtin switches the model there), so derive the
3760
+ * admission from the branch instead of hardcoding a switch: with conversation
3761
+ * context this is a switch, on an empty session it is still a cold start.
3762
+ */
3763
+ _modelSwitchAdmission() {
3764
+ return this.sessionManager.hasContextMessages() ? "switch" : "start";
3765
+ }
3766
+ /**
3767
+ * The single guard seam for a model switch (#1526): every site that can
3768
+ * refuse a switch - the `_setModel` pre-flight, the post-`model_select`
3769
+ * revalidation in `_switchActiveModel`, and both cycle guards - records the
3770
+ * refusal and rethrows the original error unchanged, so no refusal is
3771
+ * observable on one path and invisible on its sibling.
3772
+ */
3773
+ _assertModelUsableForSwitch(model, liveContextTokens) {
3774
+ try {
3775
+ this.assertModelUsable(model, liveContextTokens, { admission: this._modelSwitchAdmission() });
3776
+ }
3777
+ catch (error) {
3778
+ this._recordRejectedModelChange(model, error);
3779
+ throw error;
3780
+ }
3781
+ }
3785
3782
  async _setModel(model, updateGlobalDefaults) {
3786
- this.assertModelUsable(model, this._getDownswitchLiveContextTokens(model));
3783
+ this._assertModelUsableForSwitch(model, this._getDownswitchLiveContextTokens(model));
3787
3784
  if (!(await this._modelRuntime.checkAuth(model.provider))) {
3788
- throw new Error(`No API key for ${model.provider}/${model.id}`);
3785
+ const error = new Error(`No API key for ${model.provider}/${model.id}`);
3786
+ this._recordRejectedModelChange(model, error);
3787
+ throw error;
3789
3788
  }
3790
3789
  // A manual model change abandons any active fallback window; if a fallback
3791
3790
  // retry sleep is still pending, cancel it so no surprise continuation fires.
@@ -3859,7 +3858,7 @@ export class AgentSession {
3859
3858
  const systemPromptChange = opts.emitModelSelect
3860
3859
  ? await this._emitModelSelect(model, previousModel, opts.modelSelectSource)
3861
3860
  : undefined;
3862
- this.assertModelUsable(model, liveContextTokens);
3861
+ this._assertModelUsableForSwitch(model, liveContextTokens);
3863
3862
  if (opts.appendSessionEntry) {
3864
3863
  this.sessionManager.appendModelChange(model.provider, model.id, opts.entryReason, previousModel?.provider, previousModel?.id);
3865
3864
  }
@@ -3959,7 +3958,7 @@ export class AgentSession {
3959
3958
  const alternatives = favoriteModels.filter((entry) => !modelsAreEqual(entry.model, currentModel));
3960
3959
  const onlyAlternative = alternatives.length === 1 ? alternatives[0] : undefined;
3961
3960
  if (onlyAlternative) {
3962
- this.assertModelUsable(onlyAlternative.model, this._getDownswitchLiveContextTokens(onlyAlternative.model));
3961
+ this._assertModelUsableForSwitch(onlyAlternative.model, this._getDownswitchLiveContextTokens(onlyAlternative.model));
3963
3962
  }
3964
3963
  return {
3965
3964
  model: currentModel,
@@ -3970,7 +3969,7 @@ export class AgentSession {
3970
3969
  }
3971
3970
  const next = favoriteModels[selectedIndex];
3972
3971
  const liveContextTokens = this._getDownswitchLiveContextTokens(next.model);
3973
- this.assertModelUsable(next.model, liveContextTokens);
3972
+ this._assertModelUsableForSwitch(next.model, liveContextTokens);
3974
3973
  const invalidatesCompaction = this._modelSelectionChangesContext(currentModel, next.model) ||
3975
3974
  currentModel?.provider !== next.model.provider ||
3976
3975
  currentModel?.id !== next.model.id;
@@ -3981,25 +3980,30 @@ export class AgentSession {
3981
3980
  this._retryFallback.clearForManualModelChange(next.model);
3982
3981
  const thinking = this._getThinkingForModelSwitch(next.model, next.thinkingLevel, next.thinkingSelection);
3983
3982
  this.agent.state.model = next.model;
3984
- this.sessionManager.appendModelChange(next.model.provider, next.model.id);
3985
- this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
3986
3983
  const previousTier = this._currentServiceTier;
3987
3984
  const previousFastMode = this.isFastModeActive();
3988
3985
  this._currentServiceTier = this._resolveServiceTier(next.model, next.serviceTier);
3989
3986
  // Apply thinking level and provenance from the favorite projection or remembered preference.
3990
3987
  this._setThinkingLevel(thinking.level, false, thinking.selection);
3991
- // Post-switch, same contract as _switchActiveModel: the level in force AFTER the cycle.
3992
- this._emit({
3993
- type: "model_changed",
3994
- model: next.model,
3995
- thinkingLevel: this.thinkingLevel,
3996
- source: "cycle",
3997
- });
3998
- this._emitServiceTierChangeIfNeeded(previousTier, previousFastMode);
3999
3988
  const previousSystemPrompt = this.agent.state.systemPrompt;
4000
3989
  try {
4001
3990
  const systemPromptChange = await this._emitModelSelect(next.model, currentModel, "cycle");
4002
- this.assertModelUsable(next.model, liveContextTokens);
3991
+ // #1526: the `model_select` hook may have grown the system prompt, so the
3992
+ // switch is not decided yet. Nothing durable - no `model_change`, no global
3993
+ // default - may be written before this guard accepts, or a refused cycle
3994
+ // would resume on a model that never ran (the ordering `_switchActiveModel`
3995
+ // already uses).
3996
+ this._assertModelUsableForSwitch(next.model, liveContextTokens);
3997
+ this.sessionManager.appendModelChange(next.model.provider, next.model.id);
3998
+ this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
3999
+ // Post-switch, same contract as _switchActiveModel: the level in force AFTER the cycle.
4000
+ this._emit({
4001
+ type: "model_changed",
4002
+ model: next.model,
4003
+ thinkingLevel: this.thinkingLevel,
4004
+ source: "cycle",
4005
+ });
4006
+ this._emitServiceTierChangeIfNeeded(previousTier, previousFastMode);
4003
4007
  const cycleResult = {
4004
4008
  model: next.model,
4005
4009
  thinkingLevel: this.thinkingLevel,
@@ -4017,6 +4021,7 @@ export class AgentSession {
4017
4021
  else
4018
4022
  delete this.agent.state.model;
4019
4023
  this.agent.state.systemPrompt = previousSystemPrompt;
4024
+ this._currentServiceTier = previousTier;
4020
4025
  throw error;
4021
4026
  }
4022
4027
  }
@@ -4821,7 +4826,11 @@ export class AgentSession {
4821
4826
  // Size the same retained context that will be admitted to Cursor. Persisted JSONL
4822
4827
  // remains verbatim, but the in-memory request representation is bounded first.
4823
4828
  if (model.provider === "cursor" || model.provider === "cursor-cli-oauth") {
4824
- simulatedMessages = truncateToolResultBodies(simulatedMessages).messages ?? simulatedMessages;
4829
+ simulatedMessages =
4830
+ admitCursorHistory({
4831
+ messages: simulatedMessages,
4832
+ budgetBytes: cursorAdmissionBudgetBytes(model.contextWindow),
4833
+ }).messages ?? simulatedMessages;
4825
4834
  }
4826
4835
  const contextTokens = estimateMessagesTokens(filterContextExcludedMessages(simulatedMessages));
4827
4836
  const settings = this._getCompactionSettings();
@@ -6336,8 +6345,42 @@ export class AgentSession {
6336
6345
  this.agent.state.messages = messages.slice(lastUser);
6337
6346
  return true;
6338
6347
  }
6348
+ _isClaudeSdkSessionLockError(message) {
6349
+ return (message.errorMessage ?? "").includes("Lock file is already being held");
6350
+ }
6351
+ _isClaudeSdkInvalidRequestError(message) {
6352
+ return message.errorMessage === "invalid_request";
6353
+ }
6354
+ /**
6355
+ * Claude-SDK-only quirks that a provider hop cannot fix: the session.json
6356
+ * lock is held by this session's own subprocess, and a bare `invalid_request`
6357
+ * from the SDK boundary carries no provider-neutral meaning. Both are scoped
6358
+ * to the Claude SDK lane, because the SAME wording from another provider is
6359
+ * an ordinary failure whose classification (transient retry, or hard-error
6360
+ * fallback) must not change. Provider-agnostic classes - the stream-stall
6361
+ * watchdog above all - stay out of this predicate: they already consume the
6362
+ * shared same-model budget through `isRetryableAssistantError` and must still
6363
+ * escalate to the fallback chain when that budget runs out.
6364
+ */
6365
+ _isClaudeSdkSameModelRemintError(message) {
6366
+ if (this.model?.provider !== CLAUDE_SDK_OAUTH_PROVIDER_ID)
6367
+ return false;
6368
+ return this._isClaudeSdkSessionLockError(message) || this._isClaudeSdkInvalidRequestError(message);
6369
+ }
6370
+ /**
6371
+ * The Claude SDK lane owns its own account pool: an auth miss there is
6372
+ * repaired or failed over inside the pool, so hopping to another provider
6373
+ * would abandon the user's Claude subscription on a recoverable miss. Every
6374
+ * other provider keeps the configured fallback-chain hop.
6375
+ */
6376
+ _isClaudeSdkAuthMissError(message) {
6377
+ return (this.model?.provider === CLAUDE_SDK_OAUTH_PROVIDER_ID &&
6378
+ message.errorMessage === providerNotConfiguredMessage(CLAUDE_SDK_OAUTH_PROVIDER_ID));
6379
+ }
6339
6380
  _isHardErrorFallbackEligible(message) {
6340
6381
  return (!message.errorMessage?.startsWith(TURN_RETRY_SUPPRESSION_PREFIX) &&
6382
+ !this._isClaudeSdkAuthMissError(message) &&
6383
+ !this._isClaudeSdkSameModelRemintError(message) &&
6341
6384
  message.stopReason === "error" &&
6342
6385
  !isContextOverflow(message, this.model?.contextWindow ?? 0) &&
6343
6386
  !this._isCursorPayloadOverflow(message) &&