gsd-pi 2.77.0-dev.c9c8932c6 → 2.77.0-dev.cfd69e714

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 (708) hide show
  1. package/README.md +1 -1
  2. package/dist/claude-cli-check.js +5 -1
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +24 -2
  6. package/dist/headless.js +49 -4
  7. package/dist/provider-migrations.d.ts +18 -0
  8. package/dist/provider-migrations.js +14 -0
  9. package/dist/resource-loader.d.ts +40 -0
  10. package/dist/resource-loader.js +32 -13
  11. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  12. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  13. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  14. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  15. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  16. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +495 -27
  19. package/dist/resources/extensions/github-sync/templates.js +103 -0
  20. package/dist/resources/extensions/google-search/index.js +3 -2
  21. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  22. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  23. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  24. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  25. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
  26. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  27. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +166 -29
  29. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  30. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  31. package/dist/resources/extensions/gsd/auto-post-unit.js +181 -64
  32. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  33. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  34. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  35. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  36. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  37. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  38. package/dist/resources/extensions/gsd/auto-worktree.js +180 -34
  39. package/dist/resources/extensions/gsd/auto.js +80 -21
  40. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  41. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -6
  43. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  44. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  45. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  46. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  47. package/dist/resources/extensions/gsd/component-types.js +69 -0
  48. package/dist/resources/extensions/gsd/context-store.js +23 -7
  49. package/dist/resources/extensions/gsd/detection.js +49 -1
  50. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  51. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  52. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  53. package/dist/resources/extensions/gsd/forensics.js +106 -0
  54. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  55. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  56. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  57. package/dist/resources/extensions/gsd/git-service.js +127 -2
  58. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  59. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  60. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  61. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  62. package/dist/resources/extensions/gsd/journal.js +17 -2
  63. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  64. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  65. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  66. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  67. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  68. package/dist/resources/extensions/gsd/model-router.js +6 -0
  69. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  70. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  71. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  72. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  73. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  74. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  75. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  76. package/dist/resources/extensions/gsd/reports.js +5 -4
  77. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  78. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  79. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  80. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  81. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  83. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  84. package/dist/resources/extensions/gsd/state.js +69 -58
  85. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  86. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  87. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  88. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  89. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  90. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  91. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  92. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  93. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  94. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  95. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  96. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  97. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  98. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  99. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  100. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  101. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  102. package/dist/resources/extensions/gsd/worktree-manager.js +86 -8
  103. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  104. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  105. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  106. package/dist/resources/extensions/mcp-client/index.js +121 -10
  107. package/dist/resources/extensions/ollama/index.js +5 -1
  108. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  109. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  110. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  111. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  112. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  113. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  114. package/dist/web/standalone/.next/BUILD_ID +1 -1
  115. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  116. package/dist/web/standalone/.next/build-manifest.json +3 -3
  117. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  118. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  207. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  208. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  211. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  213. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  214. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/{webpack-1832629448831fdc.js → webpack-2e68521d7c82f7c2.js} +1 -1
  217. package/package.json +4 -5
  218. package/packages/daemon/src/logger.ts +4 -3
  219. package/packages/mcp-server/README.md +3 -3
  220. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  221. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/env-writer.js +74 -6
  223. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  224. package/packages/mcp-server/dist/server.d.ts +24 -0
  225. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/server.js +111 -87
  227. package/packages/mcp-server/dist/server.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  232. package/packages/mcp-server/src/env-writer.ts +76 -6
  233. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  234. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  235. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  236. package/packages/mcp-server/src/server.ts +158 -105
  237. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  238. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  239. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  240. package/packages/native/package.json +1 -1
  241. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  242. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  243. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  244. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  245. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  246. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  247. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  248. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  249. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  250. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  251. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  252. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  253. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  255. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  257. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  258. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  259. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  261. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  262. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  263. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  264. package/packages/pi-ai/dist/models.test.js +36 -11
  265. package/packages/pi-ai/dist/models.test.js.map +1 -1
  266. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  267. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  268. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  269. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  270. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  271. package/packages/pi-ai/src/models.test.ts +48 -11
  272. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  273. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  274. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  276. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  278. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +21 -16
  282. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  284. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  285. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  286. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  287. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  288. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  290. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  292. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  294. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  296. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  299. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  301. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  303. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  305. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  307. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  309. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  311. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  313. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  315. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  317. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/index.js +1 -0
  319. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  338. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  340. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  342. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  345. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  347. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  349. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  350. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  351. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  352. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  353. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  354. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  355. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  356. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +24 -17
  357. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  358. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  359. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  360. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  361. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  362. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  363. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  364. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  365. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  366. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  367. package/packages/pi-coding-agent/src/index.ts +1 -0
  368. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  369. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  370. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  371. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  372. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  373. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  374. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  375. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  376. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  377. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  378. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  379. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  380. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  381. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  382. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  383. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  384. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +51 -6
  385. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  386. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  387. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  388. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  389. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  390. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  391. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  392. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  393. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  394. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  395. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  396. package/packages/pi-tui/dist/components/editor.js +19 -0
  397. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  398. package/packages/pi-tui/dist/components/image.test.js +6 -5
  399. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  400. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  401. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  403. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  404. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  405. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  406. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  407. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  408. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  409. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +62 -6
  410. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  411. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  412. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  413. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  414. package/packages/pi-tui/src/components/editor.ts +22 -0
  415. package/packages/pi-tui/src/components/image.test.ts +10 -5
  416. package/packages/pi-tui/src/editor-component.ts +3 -0
  417. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  418. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  419. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  420. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  421. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  422. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  423. package/scripts/install.js +15 -1
  424. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  425. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  426. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  427. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  428. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  429. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  430. package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
  431. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +532 -29
  432. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +941 -91
  433. package/src/resources/extensions/github-sync/templates.ts +151 -0
  434. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  435. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  436. package/src/resources/extensions/google-search/index.ts +3 -2
  437. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  438. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  439. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  440. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  441. package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
  442. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  443. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  444. package/src/resources/extensions/gsd/auto-dispatch.ts +176 -29
  445. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  446. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  447. package/src/resources/extensions/gsd/auto-post-unit.ts +193 -73
  448. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  449. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  450. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  451. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  452. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  453. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  454. package/src/resources/extensions/gsd/auto-worktree.ts +190 -31
  455. package/src/resources/extensions/gsd/auto.ts +95 -23
  456. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  457. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  458. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -6
  459. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  460. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  461. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  462. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  463. package/src/resources/extensions/gsd/component-types.ts +362 -0
  464. package/src/resources/extensions/gsd/context-store.ts +25 -8
  465. package/src/resources/extensions/gsd/detection.ts +58 -1
  466. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  468. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  469. package/src/resources/extensions/gsd/forensics.ts +118 -1
  470. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  471. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  472. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  473. package/src/resources/extensions/gsd/git-service.ts +150 -2
  474. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  475. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  476. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  477. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  478. package/src/resources/extensions/gsd/journal.ts +38 -3
  479. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  480. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  481. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  482. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  483. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  484. package/src/resources/extensions/gsd/model-router.ts +6 -0
  485. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  486. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  487. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  488. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  489. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  490. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  491. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  492. package/src/resources/extensions/gsd/reports.ts +5 -4
  493. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  494. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  495. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  496. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  497. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  498. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  499. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  500. package/src/resources/extensions/gsd/state.ts +76 -66
  501. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  502. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  503. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  504. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  505. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  506. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -285
  507. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  508. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  509. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  510. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  511. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  512. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  513. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  514. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  515. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  516. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  517. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  518. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  519. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  520. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  521. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  522. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  523. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  524. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  525. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  527. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  528. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  529. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  530. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  531. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  532. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  533. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  534. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  535. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  536. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  537. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  538. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  539. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  540. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  541. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  542. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  543. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  544. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  545. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  546. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  547. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  548. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  549. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  550. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  551. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  552. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  553. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  554. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  555. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  556. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  557. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  558. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  559. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  560. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  561. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  562. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  563. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  564. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  565. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  566. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  567. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  568. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  569. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
  570. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  571. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  572. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  573. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  574. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  575. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  576. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  577. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  578. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  579. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  580. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  581. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  582. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  583. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  584. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  585. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +54 -41
  586. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +213 -0
  587. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  588. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  589. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  590. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  591. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  592. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  593. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  594. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  595. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  596. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  597. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  598. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  599. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  600. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  601. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  602. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  603. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  604. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  605. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  606. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  607. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  608. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  609. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  610. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  611. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  612. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  613. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  614. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  615. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  616. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  617. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  618. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  619. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  620. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  621. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  622. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  623. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  624. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  625. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  626. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  627. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  628. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  629. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  630. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  631. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  632. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  633. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  634. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  635. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  636. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  637. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  638. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  639. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  640. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  641. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  642. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  643. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  644. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  645. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  646. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  647. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  648. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  649. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  650. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  651. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  652. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  653. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  654. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  655. package/src/resources/extensions/gsd/types.ts +3 -3
  656. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  657. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  658. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  659. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  660. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  661. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  662. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  663. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  664. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  665. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  666. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  667. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  668. package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
  669. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  670. package/src/resources/extensions/gsd/worktree-manager.ts +109 -7
  671. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  672. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  673. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  674. package/src/resources/extensions/mcp-client/index.ts +132 -11
  675. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  676. package/src/resources/extensions/ollama/index.ts +5 -1
  677. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  678. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  679. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  680. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  681. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  682. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  683. package/src/resources/skills/create-skill/SKILL.md +2 -2
  684. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  685. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  686. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  687. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  688. package/dist/web/standalone/.next/static/chunks/2826.d445fb428ef41fa1.js +0 -9
  689. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  690. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  691. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  692. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  693. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  694. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  695. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  696. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  697. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  698. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  699. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  700. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  701. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  702. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  703. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  704. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  705. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  706. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  707. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
  708. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"retry-handler.js","sourceRoot":"","sources":["../../src/core/retry-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RetryHandler - Automatic retry logic with exponential backoff and credential/provider fallback.\n *\n * Handles retryable errors (overloaded, rate limit, server errors) by:\n * 1. Trying alternate credentials for the same provider\n * 2. Falling back to other providers via FallbackResolver\n * 3. Exponential backoff with configurable max retries\n *\n * Context overflow errors are NOT handled here (see compaction).\n */\n\nimport type { Agent } from \"@gsd/pi-agent-core\";\nimport type { AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport { isContextOverflow } from \"@gsd/pi-ai\";\nimport type { UsageLimitErrorType } from \"./auth-storage.js\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\nimport { sleep } from \"../utils/sleep.js\";\nimport type { AgentSessionEvent } from \"./agent-session.js\";\n\n/** Dependencies injected from AgentSession into RetryHandler */\nexport interface RetryHandlerDeps {\n\treadonly agent: Agent;\n\treadonly settingsManager: SettingsManager;\n\treadonly modelRegistry: ModelRegistry;\n\treadonly fallbackResolver: FallbackResolver;\n\tgetModel: () => Model<any> | undefined;\n\tgetSessionId: () => string;\n\temit: (event: AgentSessionEvent) => void;\n\t/** Called when the retry handler switches to a fallback model */\n\tonModelChange: (model: Model<any>) => void;\n\t/** Optional: check if the claude-code CLI provider is ready (installed + authed).\n\t * Injected from the app layer to preserve package boundary. */\n\tisClaudeCodeReady?: () => boolean;\n}\n\nexport class RetryHandler {\n\tprivate _retryAbortController: AbortController | undefined = undefined;\n\tprivate _retryAttempt = 0;\n\tprivate _retryPromise: Promise<void> | undefined = undefined;\n\tprivate _retryResolve: (() => void) | undefined = undefined;\n\tprivate _retryGeneration = 0;\n\tprivate _continueTimeout: ReturnType<typeof setTimeout> | undefined = undefined;\n\n\tconstructor(private readonly _deps: RetryHandlerDeps) {}\n\n\t/** Current retry attempt (0 if not retrying) */\n\tget retryAttempt(): number {\n\t\treturn this._retryAttempt;\n\t}\n\n\t/** Whether auto-retry is currently in progress */\n\tget isRetrying(): boolean {\n\t\treturn this._retryPromise !== undefined;\n\t}\n\n\t/** Whether auto-retry is enabled */\n\tget autoRetryEnabled(): boolean {\n\t\treturn this._deps.settingsManager.getRetryEnabled();\n\t}\n\n\t/** Toggle auto-retry setting */\n\tsetAutoRetryEnabled(enabled: boolean): void {\n\t\tthis._deps.settingsManager.setRetryEnabled(enabled);\n\t}\n\n\t/**\n\t * Create a retry promise synchronously for agent_end events.\n\t * Must be called synchronously from the agent event handler before\n\t * any async processing, so that waitForRetry() doesn't miss in-flight retries.\n\t */\n\tcreateRetryPromiseForAgentEnd(messages: Array<{ role: string } & Record<string, any>>): void {\n\t\tif (this._retryPromise) return;\n\n\t\tconst settings = this._deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled) return;\n\n\t\tconst lastAssistant = this._findLastAssistantInMessages(messages);\n\t\tif (!lastAssistant || !this.isRetryableError(lastAssistant)) return;\n\n\t\tthis._retryPromise = new Promise((resolve) => {\n\t\t\tthis._retryResolve = resolve;\n\t\t});\n\t}\n\n\t/**\n\t * Handle a successful assistant response by resetting retry state.\n\t * Call this when an assistant message completes without error.\n\t */\n\thandleSuccessfulResponse(): void {\n\t\tif (this._retryAttempt > 0) {\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: true,\n\t\t\t\tattempt: this._retryAttempt,\n\t\t\t});\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._resolveRetry();\n\t\t}\n\t}\n\n\t/**\n\t * Check if an error is retryable (overloaded, rate limit, server errors).\n\t * Context overflow errors are NOT retryable (handled by compaction instead).\n\t */\n\tisRetryableError(message: AssistantMessage): boolean {\n\t\tif (message.stopReason !== \"error\" || !message.errorMessage) return false;\n\n\t\t// Context overflow is handled by compaction, not retry\n\t\tconst contextWindow = this._deps.getModel()?.contextWindow ?? 0;\n\t\tif (isContextOverflow(message, contextWindow)) return false;\n\n\t\tconst err = message.errorMessage;\n\t\t// \"temporarily backed off\" is intentionally excluded: it is an internally-\n\t\t// generated error from getApiKey() when credentials are in a backoff window.\n\t\t// Re-entering the retry handler for that message creates a cascade of empty\n\t\t// error entries in the session file, breaking resume (#3429).\n\t\treturn /overloaded|rate.?limit|too many requests|402|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\\s+)?unavailable|credentials.*expired|requires more credits|can only afford|insufficient credits|not enough credits|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i.test(\n\t\t\terr,\n\t\t);\n\t}\n\n\t/**\n\t * Handle retryable errors with exponential backoff.\n\t * When multiple credentials are available, marks the failing credential\n\t * as backed off and retries immediately with the next one.\n\t * @returns true if retry was initiated, false if max retries exceeded or disabled\n\t */\n\tasync handleRetryableError(message: AssistantMessage): Promise<boolean> {\n\t\tconst settings = this._deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled) {\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Retry promise is created synchronously in createRetryPromiseForAgentEnd.\n\t\t// Keep a defensive fallback here in case a future refactor bypasses that path.\n\t\tif (!this._retryPromise) {\n\t\t\tthis._retryPromise = new Promise((resolve) => {\n\t\t\t\tthis._retryResolve = resolve;\n\t\t\t});\n\t\t}\n\n\t\t// Try credential fallback before counting against retry budget.\n\t\tconst retryGeneration = this._retryGeneration;\n\t\tif (this._deps.getModel() && message.errorMessage) {\n\t\t\t// Third-party subscription block (#3772): Anthropic blocks third-party apps\n\t\t\t// from using Pro/Max subscription quotas. If the claude-code CLI provider is\n\t\t\t// available, switch to it immediately — credential rotation won't help.\n\t\t\tif (this._isThirdPartyBlock(message.errorMessage)) {\n\t\t\t\tconst switched = this._tryClaudeCodeFallback(message, retryGeneration);\n\t\t\t\tif (switched) return true;\n\t\t\t\t// CLI not available — fall through to standard error handling\n\t\t\t}\n\n\t\t\tconst errorType = this._classifyErrorType(message.errorMessage);\n\t\t\tconst isRateLimit = errorType === \"rate_limit\";\n\t\t\tconst isQuotaError = errorType === \"quota_exhausted\";\n\n\t\t\t// Credit-aware retry (OpenRouter-style 402 affordability errors):\n\t\t\t// when provider reports \"can only afford N\", lower maxTokens and retry\n\t\t\t// on the same model before rotating credentials/providers.\n\t\t\tif (isQuotaError) {\n\t\t\t\tconst adjusted = this._tryAffordableMaxTokensRetry(message, retryGeneration);\n\t\t\t\tif (adjusted) return true;\n\t\t\t}\n\n\t\t\t// Credential rotation — only for transient rate limits (#3430).\n\t\t\t// Quota errors (\"Extra usage is required\") are account-level billing\n\t\t\t// gates; rotating to another credential on the same account won't help\n\t\t\t// and the 30-minute backoff blocks all provider requests needlessly.\n\t\t\tif (isRateLimit) {\n\t\t\t\tconst hasAlternate =\n\t\t\t\t\tthis._deps.modelRegistry.authStorage.markUsageLimitReached(\n\t\t\t\t\t\tthis._deps.getModel()!.provider,\n\t\t\t\t\t\tthis._deps.getSessionId(),\n\t\t\t\t\t\t{ errorType },\n\t\t\t\t\t);\n\n\t\t\t\tif (hasAlternate) {\n\t\t\t\t\tthis._removeLastAssistantError();\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_start\",\n\t\t\t\t\t\tattempt: this._retryAttempt + 1,\n\t\t\t\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\t\t\t\tdelayMs: 0,\n\t\t\t\t\t\terrorMessage: `${message.errorMessage} (switching credential)`,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Retry immediately with the next credential - don't increment _retryAttempt\n\t\t\t\t\tthis._scheduleContinue(retryGeneration);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Cross-provider fallback — for rate limits with all creds backed off,\n\t\t\t// or quota errors (which skip credential backoff entirely).\n\t\t\tif (isRateLimit || isQuotaError) {\n\t\t\t\tconst fallbackResult = await this._deps.fallbackResolver.findFallback(\n\t\t\t\t\tthis._deps.getModel()!,\n\t\t\t\t\terrorType,\n\t\t\t\t);\n\n\t\t\t\tif (fallbackResult) {\n\t\t\t\t\tconst previousProvider = this._deps.getModel()!.provider;\n\t\t\t\t\tthis._deps.agent.setModel(fallbackResult.model);\n\t\t\t\t\tthis._deps.onModelChange(fallbackResult.model);\n\t\t\t\t\tthis._removeLastAssistantError();\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"fallback_provider_switch\",\n\t\t\t\t\t\tfrom: `${previousProvider}/${this._deps.getModel()?.id}`,\n\t\t\t\t\t\tto: `${fallbackResult.model.provider}/${fallbackResult.model.id}`,\n\t\t\t\t\t\treason: fallbackResult.reason,\n\t\t\t\t\t});\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_start\",\n\t\t\t\t\t\tattempt: this._retryAttempt + 1,\n\t\t\t\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\t\t\t\tdelayMs: 0,\n\t\t\t\t\t\terrorMessage: `${message.errorMessage} (${fallbackResult.reason})`,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Retry immediately with fallback provider - don't increment _retryAttempt\n\t\t\t\t\tthis._scheduleContinue(retryGeneration);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// No fallback available either\n\t\t\t\tif (isQuotaError) {\n\t\t\t\t\t// Try long-context model downgrade ([1m] → base) before giving up\n\t\t\t\t\tconst downgraded = this._tryLongContextDowngrade(message, retryGeneration);\n\t\t\t\t\tif (downgraded) return true;\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"fallback_chain_exhausted\",\n\t\t\t\t\t\treason: `All providers exhausted for ${this._deps.getModel()!.provider}/${this._deps.getModel()!.id}`,\n\t\t\t\t\t});\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tattempt: this._retryAttempt,\n\t\t\t\t\t\tfinalError: message.errorMessage,\n\t\t\t\t\t});\n\t\t\t\t\tthis._retryAttempt = 0;\n\t\t\t\t\tthis._resolveRetry();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._retryAttempt++;\n\n\t\tif (this._retryAttempt > settings.maxRetries) {\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt: this._retryAttempt - 1,\n\t\t\t\tfinalError: message.errorMessage,\n\t\t\t});\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Use server-requested delay when available, capped by maxDelayMs.\n\t\t// Fall back to exponential backoff when no server hint is present.\n\t\tconst exponentialDelayMs = settings.baseDelayMs * 2 ** (this._retryAttempt - 1);\n\t\tlet delayMs: number;\n\t\tif (message.retryAfterMs !== undefined) {\n\t\t\tconst cap = settings.maxDelayMs > 0 ? settings.maxDelayMs : Infinity;\n\t\t\tif (message.retryAfterMs > cap) {\n\t\t\t\tthis._deps.emit({\n\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tattempt: this._retryAttempt - 1,\n\t\t\t\t\tfinalError: `Rate limit reset in ${Math.ceil(message.retryAfterMs / 1000)}s (max: ${Math.ceil(cap / 1000)}s). ${message.errorMessage || \"\"}`.trim(),\n\t\t\t\t});\n\t\t\t\tthis._retryAttempt = 0;\n\t\t\t\tthis._resolveRetry();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tdelayMs = message.retryAfterMs;\n\t\t} else {\n\t\t\tdelayMs = exponentialDelayMs;\n\t\t}\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt,\n\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\tdelayMs,\n\t\t\terrorMessage: message.errorMessage || \"Unknown error\",\n\t\t});\n\n\t\tthis._removeLastAssistantError();\n\n\t\t// Wait with exponential backoff (abortable)\n\t\tthis._retryAbortController = new AbortController();\n\t\ttry {\n\t\t\tawait sleep(delayMs, this._retryAbortController.signal);\n\t\t} catch {\n\t\t\t// Aborted during sleep. If the retry generation already advanced, this\n\t\t\t// cancellation was handled externally (e.g. explicit model switch).\n\t\t\tif (retryGeneration !== this._retryGeneration) {\n\t\t\t\tthis._retryAbortController = undefined;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst attempt = this._retryAttempt;\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._retryAbortController = undefined;\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt,\n\t\t\t\tfinalError: \"Retry cancelled\",\n\t\t\t});\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\t\tthis._retryAbortController = undefined;\n\n\t\t// Retry via continue() - use setTimeout to break out of event handler chain\n\t\tthis._scheduleContinue(retryGeneration);\n\n\t\treturn true;\n\t}\n\n\t/** Cancel in-progress retry */\n\tabortRetry(): void {\n\t\tconst hadRetry =\n\t\t\tthis._retryPromise !== undefined\n\t\t\t|| this._retryAbortController !== undefined\n\t\t\t|| this._continueTimeout !== undefined;\n\t\tif (!hadRetry) return;\n\n\t\tconst attempt = this._retryAttempt > 0 ? this._retryAttempt : 1;\n\t\tthis._retryGeneration++;\n\t\tif (this._continueTimeout) {\n\t\t\tclearTimeout(this._continueTimeout);\n\t\t\tthis._continueTimeout = undefined;\n\t\t}\n\t\tif (this._retryAbortController) {\n\t\t\tthis._retryAbortController.abort();\n\t\t\tthis._retryAbortController = undefined;\n\t\t}\n\t\tthis._retryAttempt = 0;\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_end\",\n\t\t\tsuccess: false,\n\t\t\tattempt,\n\t\t\tfinalError: \"Retry cancelled\",\n\t\t});\n\t\tthis._resolveRetry();\n\t}\n\n\t/**\n\t * Wait for any in-progress retry to complete.\n\t * Returns immediately if no retry is in progress.\n\t */\n\tasync waitForRetry(): Promise<void> {\n\t\tif (this._retryPromise) {\n\t\t\tawait this._retryPromise;\n\t\t}\n\t}\n\n\t/** Resolve the pending retry promise */\n\tresolveRetry(): void {\n\t\tthis._resolveRetry();\n\t}\n\n\t// =========================================================================\n\t// Private helpers\n\t// =========================================================================\n\n\tprivate _resolveRetry(): void {\n\t\tif (this._retryResolve) {\n\t\t\tthis._retryResolve();\n\t\t\tthis._retryResolve = undefined;\n\t\t\tthis._retryPromise = undefined;\n\t\t}\n\t}\n\n\tprivate _scheduleContinue(retryGeneration: number): void {\n\t\tif (this._continueTimeout) {\n\t\t\tclearTimeout(this._continueTimeout);\n\t\t}\n\t\tthis._continueTimeout = setTimeout(() => {\n\t\t\tthis._continueTimeout = undefined;\n\t\t\tif (retryGeneration !== this._retryGeneration) return;\n\t\t\tthis._deps.agent.continue().catch(() => {});\n\t\t}, 0);\n\t}\n\n\tprivate _findLastAssistantInMessages(\n\t\tmessages: Array<{ role: string } & Record<string, any>>,\n\t): AssistantMessage | undefined {\n\t\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\t\tconst message = messages[i];\n\t\t\tif (message.role === \"assistant\") {\n\t\t\t\treturn message as AssistantMessage;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Classify an error message into a usage-limit error type for credential backoff.\n\t */\n\tprivate _classifyErrorType(errorMessage: string): UsageLimitErrorType {\n\t\tconst err = errorMessage.toLowerCase();\n\t\t// Long-context entitlement errors are billing gates, not transient rate limits.\n\t\t// Must be checked before the generic 429/rate_limit regex.\n\t\tif (/extra usage is required|long context required/i.test(err)) return \"quota_exhausted\";\n\t\tif (/requires more credits|can only afford|insufficient credits|not enough credits|credit balance/i.test(err))\n\t\t\treturn \"quota_exhausted\";\n\t\tif (/quota|billing|exceeded.*limit|usage.*limit/i.test(err)) return \"quota_exhausted\";\n\t\tif (/rate.?limit|too many requests|429/i.test(err)) return \"rate_limit\";\n\t\tif (/500|502|503|504|server.?error|internal.?error|service.?unavailable/i.test(err)) return \"server_error\";\n\t\treturn \"unknown\";\n\t}\n\n\t/**\n\t * Attempt a same-model retry by reducing maxTokens when provider reports\n\t * an affordability cap (e.g., \"can only afford 329\").\n\t */\n\tprivate _tryAffordableMaxTokensRetry(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel || !message.errorMessage) return false;\n\n\t\t// Example: \"can only afford 329\"\n\t\tconst match = message.errorMessage.match(/can only afford\\s+([\\d,]+)/i);\n\t\tif (!match?.[1]) return false;\n\n\t\tconst affordable = Number.parseInt(match[1].replace(/,/g, \"\"), 10);\n\t\tif (!Number.isFinite(affordable) || affordable <= 0) return false;\n\n\t\t// Leave a small buffer so slight input variance doesn't immediately re-fail.\n\t\tconst safetyBuffer = Math.min(64, Math.max(16, Math.floor(affordable * 0.1)));\n\t\tconst targetMaxTokens = Math.max(64, affordable - safetyBuffer);\n\t\tconst downgradedMaxTokens = Math.min(currentModel.maxTokens, targetMaxTokens);\n\t\tif (downgradedMaxTokens >= currentModel.maxTokens) return false;\n\n\t\tconst downgradedModel = {\n\t\t\t...currentModel,\n\t\t\tmaxTokens: downgradedMaxTokens,\n\t\t};\n\n\t\tthis._deps.agent.setModel(downgradedModel);\n\t\tthis._deps.onModelChange(downgradedModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${currentModel.provider}/${currentModel.id} (maxTokens=${currentModel.maxTokens})`,\n\t\t\tto: `${downgradedModel.provider}/${downgradedModel.id} (maxTokens=${downgradedModel.maxTokens})`,\n\t\t\treason: `credit-aware retry: provider affordable cap ${affordable} tokens`,\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (reducing max tokens)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Attempt to downgrade a long-context model (e.g. claude-opus-4-6[1m]) to its\n\t * base model (claude-opus-4-6) when the account lacks the long-context billing\n\t * entitlement. Returns true if the downgrade was initiated.\n\t */\n\tprivate _tryLongContextDowngrade(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel) return false;\n\n\t\t// Only attempt downgrade for [1m] (or similar long-context) model IDs\n\t\tconst match = currentModel.id.match(/^(.+)\\[\\d+m\\]$/);\n\t\tif (!match) return false;\n\n\t\tconst baseModelId = match[1];\n\t\tconst baseModel = this._deps.modelRegistry.find(currentModel.provider, baseModelId);\n\t\tif (!baseModel) return false;\n\n\t\tconst previousId = currentModel.id;\n\t\tthis._deps.agent.setModel(baseModel);\n\t\tthis._deps.onModelChange(baseModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${currentModel.provider}/${previousId}`,\n\t\t\tto: `${baseModel.provider}/${baseModel.id}`,\n\t\t\treason: `long context downgrade: ${previousId} → ${baseModel.id}`,\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (long context downgrade)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Detect Anthropic subscription block errors (#3772).\n\t * These are hard policy blocks, not transient rate limits — credential\n\t * rotation will not help. Matches both the explicit \"third-party\" message\n\t * and the \"out of extra usage\" variant that subscription users receive.\n\t */\n\tprivate _isThirdPartyBlock(errorMessage: string): boolean {\n\t\treturn /third[- .]party.*(?:draw from extra|not.*available|plan limits|not permitted|cannot be used|not supported)|(?:out of|no) extra usage/i.test(errorMessage);\n\t}\n\n\t/**\n\t * Attempt to switch to the claude-code CLI provider when the current\n\t * Anthropic provider is blocked by the third-party policy (#3772).\n\t * Returns true if the switch was made and retry scheduled.\n\t */\n\tprivate _tryClaudeCodeFallback(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tif (!this._deps.isClaudeCodeReady?.()) return false;\n\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel) return false;\n\n\t\t// Only attempt claude-code fallback when the current provider is anthropic.\n\t\t// Transport-specific (ADR-012): intentionally keys on provider, not api —\n\t\t// the fallback specifically reroutes the plain `anthropic` transport to\n\t\t// the `claude-code` transport. Other Anthropic-fronting transports\n\t\t// (anthropic-vertex, amazon-bedrock) must not be rerouted.\n\t\tif (currentModel.provider !== \"anthropic\") return false;\n\n\t\t// Find the same model ID under the claude-code provider\n\t\tconst ccModel = this._deps.modelRegistry.find(\"claude-code\", currentModel.id);\n\t\tif (!ccModel) return false;\n\n\t\tconst previousProvider = currentModel.provider;\n\t\tthis._deps.agent.setModel(ccModel);\n\t\tthis._deps.onModelChange(ccModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${previousProvider}/${currentModel.id}`,\n\t\t\tto: `claude-code/${ccModel.id}`,\n\t\t\treason: \"Anthropic subscription blocked for third-party apps — routing through Claude Code CLI\",\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (switching to Claude Code CLI)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\t\treturn true;\n\t}\n\n\t/** Remove the last assistant error message from agent state */\n\tprivate _removeLastAssistantError(): void {\n\t\tconst messages = this._deps.agent.state.messages;\n\t\tif (messages.length > 0 && messages[messages.length - 1].role === \"assistant\") {\n\t\t\tthis._deps.agent.replaceMessages(messages.slice(0, -1));\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"retry-handler.js","sourceRoot":"","sources":["../../src/core/retry-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAkBhE,MAAM,OAAO,YAAY;IAQxB,YAA6B,KAAuB;QAAvB,UAAK,GAAL,KAAK,CAAkB;QAP5C,0BAAqB,GAAgC,SAAS,CAAC;QAC/D,kBAAa,GAAG,CAAC,CAAC;QAClB,kBAAa,GAA8B,SAAS,CAAC;QACrD,kBAAa,GAA6B,SAAS,CAAC;QACpD,qBAAgB,GAAG,CAAC,CAAC;QACrB,qBAAgB,GAA8C,SAAS,CAAC;IAEzB,CAAC;IAExD,gDAAgD;IAChD,IAAI,YAAY;QACf,OAAO,IAAI,CAAC,aAAa,CAAC;IAC3B,CAAC;IAED,kDAAkD;IAClD,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC;IACzC,CAAC;IAED,oCAAoC;IACpC,IAAI,gBAAgB;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,eAAe,EAAE,CAAC;IACrD,CAAC;IAED,gCAAgC;IAChC,mBAAmB,CAAC,OAAgB;QACnC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACH,6BAA6B,CAAC,QAAuD;QACpF,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO;QAE/B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC;QAC/D,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,OAAO;QAE9B,MAAM,aAAa,GAAG,IAAI,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC;QAClE,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;YAAE,OAAO;QAEpE,IAAI,CAAC,aAAa,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC5C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC9B,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,wBAAwB;QACvB,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI,CAAC,aAAa;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC;IACF,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,OAAyB;QACzC,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAE1E,uDAAuD;QACvD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,aAAa,IAAI,CAAC,CAAC;QAChE,IAAI,iBAAiB,CAAC,OAAO,EAAE,aAAa,CAAC;YAAE,OAAO,KAAK,CAAC;QAE5D,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACtD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,oBAAoB,CAAC,OAAyB;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC;QAC/D,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACd,CAAC;QAED,2EAA2E;QAC3E,+EAA+E;QAC/E,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACzB,IAAI,CAAC,aAAa,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC5C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;YAC9B,CAAC,CAAC,CAAC;QACJ,CAAC;QAED,gEAAgE;QAChE,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC9C,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACnD,4EAA4E;YAC5E,6EAA6E;YAC7E,wEAAwE;YACxE,IAAI,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;gBACvE,IAAI,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1B,8DAA8D;YAC/D,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAChE,MAAM,WAAW,GAAG,SAAS,KAAK,YAAY,CAAC;YAC/C,MAAM,YAAY,GAAG,SAAS,KAAK,iBAAiB,CAAC;YAErD,kEAAkE;YAClE,uEAAuE;YACvE,2DAA2D;YAC3D,IAAI,YAAY,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;gBAC7E,IAAI,QAAQ;oBAAE,OAAO,IAAI,CAAC;YAC3B,CAAC;YAED,gEAAgE;YAChE,qEAAqE;YACrE,uEAAuE;YACvE,qEAAqE;YACrE,IAAI,WAAW,EAAE,CAAC;gBACjB,MAAM,YAAY,GACjB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,qBAAqB,CACzD,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAG,CAAC,QAAQ,EAC/B,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,EACzB,EAAE,SAAS,EAAE,CACb,CAAC;gBAEH,IAAI,YAAY,EAAE,CAAC;oBAClB,IAAI,CAAC,yBAAyB,EAAE,CAAC;oBAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,kBAAkB;wBACxB,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;wBAC/B,WAAW,EAAE,QAAQ,CAAC,UAAU;wBAChC,OAAO,EAAE,CAAC;wBACV,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,yBAAyB;qBAC9D,CAAC,CAAC;oBAEH,6EAA6E;oBAC7E,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;oBAExC,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,uEAAuE;YACvE,4DAA4D;YAC5D,IAAI,WAAW,IAAI,YAAY,EAAE,CAAC;gBACjC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,YAAY,CACpE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAG,EACtB,SAAS,CACT,CAAC;gBAEF,IAAI,cAAc,EAAE,CAAC;oBACpB,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAG,CAAC,QAAQ,CAAC;oBACzD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;oBAChD,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;oBAC/C,IAAI,CAAC,yBAAyB,EAAE,CAAC;oBAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,0BAA0B;wBAChC,IAAI,EAAE,GAAG,gBAAgB,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE;wBACxD,EAAE,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE;wBACjE,MAAM,EAAE,cAAc,CAAC,MAAM;qBAC7B,CAAC,CAAC;oBAEH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,kBAAkB;wBACxB,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;wBAC/B,WAAW,EAAE,QAAQ,CAAC,UAAU;wBAChC,OAAO,EAAE,CAAC;wBACV,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,KAAK,cAAc,CAAC,MAAM,GAAG;qBAClE,CAAC,CAAC;oBAEH,2EAA2E;oBAC3E,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;oBAExC,OAAO,IAAI,CAAC;gBACb,CAAC;gBAED,+BAA+B;gBAC/B,IAAI,YAAY,EAAE,CAAC;oBAClB,kEAAkE;oBAClE,MAAM,UAAU,GAAG,IAAI,CAAC,wBAAwB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;oBAC3E,IAAI,UAAU;wBAAE,OAAO,IAAI,CAAC;oBAE5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,0BAA0B;wBAChC,MAAM,EAAE,+BAA+B,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAG,CAAC,EAAE,EAAE;qBACrG,CAAC,CAAC;oBACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,gBAAgB;wBACtB,OAAO,EAAE,KAAK;wBACd,OAAO,EAAE,IAAI,CAAC,aAAa;wBAC3B,UAAU,EAAE,OAAO,CAAC,YAAY;qBAChC,CAAC,CAAC;oBACH,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;oBACvB,IAAI,CAAC,aAAa,EAAE,CAAC;oBACrB,OAAO,KAAK,CAAC;gBACd,CAAC;YACF,CAAC;QACF,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,IAAI,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC9C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;gBAC/B,UAAU,EAAE,OAAO,CAAC,YAAY;aAChC,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACd,CAAC;QAED,mEAAmE;QACnE,mEAAmE;QACnE,MAAM,kBAAkB,GAAG,QAAQ,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;QAChF,IAAI,OAAe,CAAC;QACpB,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;YACrE,IAAI,OAAO,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,gBAAgB;oBACtB,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;oBAC/B,UAAU,EAAE,uBAAuB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,OAAO,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;iBACnJ,CAAC,CAAC;gBACH,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,aAAa,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACd,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;QAChC,CAAC;aAAM,CAAC;YACP,OAAO,GAAG,kBAAkB,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,IAAI,CAAC,aAAa;YAC3B,WAAW,EAAE,QAAQ,CAAC,UAAU;YAChC,OAAO;YACP,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,eAAe;SACrD,CAAC,CAAC;QAEH,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAEjC,4CAA4C;QAC5C,IAAI,CAAC,qBAAqB,GAAG,IAAI,eAAe,EAAE,CAAC;QACnD,IAAI,CAAC;YACJ,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACR,uEAAuE;YACvE,oEAAoE;YACpE,IAAI,eAAe,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC/C,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;gBACvC,OAAO,KAAK,CAAC;YACd,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC;YACnC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,KAAK;gBACd,OAAO;gBACP,UAAU,EAAE,iBAAiB;aAC7B,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QAEvC,4EAA4E;QAC5E,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAExC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,+BAA+B;IAC/B,UAAU;QACT,MAAM,QAAQ,GACb,IAAI,CAAC,aAAa,KAAK,SAAS;eAC7B,IAAI,CAAC,qBAAqB,KAAK,SAAS;eACxC,IAAI,CAAC,gBAAgB,KAAK,SAAS,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACnC,CAAC;QACD,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAChC,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC;YACnC,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,KAAK;YACd,OAAO;YACP,UAAU,EAAE,iBAAiB;SAC7B,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,EAAE,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QACjB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,aAAa,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,wCAAwC;IACxC,YAAY;QACX,IAAI,CAAC,aAAa,EAAE,CAAC;IACtB,CAAC;IAED,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAEpE,aAAa;QACpB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;YAC/B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAChC,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,eAAuB;QAChD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;YACvC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAClC,IAAI,eAAe,KAAK,IAAI,CAAC,gBAAgB;gBAAE,OAAO;YACtD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC7C,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,4BAA4B,CACnC,QAAuD;QAEvD,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAClC,OAAO,OAA2B,CAAC;YACpC,CAAC;QACF,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,YAAoB;QAC9C,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;QACvC,gFAAgF;QAChF,2DAA2D;QAC3D,IAAI,gDAAgD,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,iBAAiB,CAAC;QACzF,IAAI,+FAA+F,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5G,OAAO,iBAAiB,CAAC;QAC1B,IAAI,6CAA6C,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,iBAAiB,CAAC;QACtF,IAAI,oCAAoC,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,YAAY,CAAC;QACxE,IAAI,qEAAqE,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,cAAc,CAAC;QAC3G,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;OAGG;IACK,4BAA4B,CAAC,OAAyB,EAAE,eAAuB;QACtF,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAEzD,iCAAiC;QACjC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACxE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAE9B,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAElE,6EAA6E;QAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;QAChE,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAC9E,IAAI,mBAAmB,IAAI,YAAY,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAEhE,MAAM,eAAe,GAAG;YACvB,GAAG,YAAY;YACf,SAAS,EAAE,mBAAmB;SAC9B,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;QAC1C,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,0BAA0B;YAChC,IAAI,EAAE,GAAG,YAAY,CAAC,QAAQ,IAAI,YAAY,CAAC,EAAE,eAAe,YAAY,CAAC,SAAS,GAAG;YACzF,EAAE,EAAE,GAAG,eAAe,CAAC,QAAQ,IAAI,eAAe,CAAC,EAAE,eAAe,eAAe,CAAC,SAAS,GAAG;YAChG,MAAM,EAAE,+CAA+C,UAAU,SAAS;SAC1E,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;YAC/B,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC,UAAU;YACrE,OAAO,EAAE,CAAC;YACV,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,wBAAwB;SAC7D,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;OAIG;IACK,wBAAwB,CAAC,OAAyB,EAAE,eAAuB;QAClF,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAEhC,sEAAsE;QACtE,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAEzB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACpF,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAE7B,MAAM,UAAU,GAAG,YAAY,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,0BAA0B;YAChC,IAAI,EAAE,GAAG,YAAY,CAAC,QAAQ,IAAI,UAAU,EAAE;YAC9C,EAAE,EAAE,GAAG,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,EAAE,EAAE;YAC3C,MAAM,EAAE,2BAA2B,UAAU,MAAM,SAAS,CAAC,EAAE,EAAE;SACjE,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;YAC/B,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC,UAAU;YACrE,OAAO,EAAE,CAAC;YACV,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,2BAA2B;SAChE,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAExC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACK,kBAAkB,CAAC,YAAoB;QAC9C,OAAO,uIAAuI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnK,CAAC;IAED;;;;OAIG;IACK,sBAAsB,CAAC,OAAyB,EAAE,eAAuB;QAChF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE;YAAE,OAAO,KAAK,CAAC;QAEpD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAEhC,4EAA4E;QAC5E,0EAA0E;QAC1E,wEAAwE;QACxE,mEAAmE;QACnE,2DAA2D;QAC3D,IAAI,YAAY,CAAC,QAAQ,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAExD,wDAAwD;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,0BAA0B;YAChC,IAAI,EAAE,GAAG,gBAAgB,IAAI,YAAY,CAAC,EAAE,EAAE;YAC9C,EAAE,EAAE,eAAe,OAAO,CAAC,EAAE,EAAE;YAC/B,MAAM,EAAE,uFAAuF;SAC/F,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC;YAC/B,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC,UAAU;YACrE,OAAO,EAAE,CAAC;YACV,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,iCAAiC;SACtE,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,+DAA+D;IACvD,yBAAyB;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;QACjD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/E,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACF,CAAC;CACD","sourcesContent":["/**\n * RetryHandler - Automatic retry logic with exponential backoff and credential/provider fallback.\n *\n * Handles retryable errors (overloaded, rate limit, server errors) by:\n * 1. Trying alternate credentials for the same provider\n * 2. Falling back to other providers via FallbackResolver\n * 3. Exponential backoff with configurable max retries\n *\n * Context overflow errors are NOT handled here (see compaction).\n */\n\nimport type { Agent } from \"@gsd/pi-agent-core\";\nimport type { AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport { isContextOverflow } from \"@gsd/pi-ai\";\nimport type { UsageLimitErrorType } from \"./auth-storage.js\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\nimport { sleep } from \"../utils/sleep.js\";\nimport type { AgentSessionEvent } from \"./agent-session.js\";\nimport { RETRYABLE_ERROR_RE } from \"./retryable-error-regex.js\";\n\n/** Dependencies injected from AgentSession into RetryHandler */\nexport interface RetryHandlerDeps {\n\treadonly agent: Agent;\n\treadonly settingsManager: SettingsManager;\n\treadonly modelRegistry: ModelRegistry;\n\treadonly fallbackResolver: FallbackResolver;\n\tgetModel: () => Model<any> | undefined;\n\tgetSessionId: () => string;\n\temit: (event: AgentSessionEvent) => void;\n\t/** Called when the retry handler switches to a fallback model */\n\tonModelChange: (model: Model<any>) => void;\n\t/** Optional: check if the claude-code CLI provider is ready (installed + authed).\n\t * Injected from the app layer to preserve package boundary. */\n\tisClaudeCodeReady?: () => boolean;\n}\n\nexport class RetryHandler {\n\tprivate _retryAbortController: AbortController | undefined = undefined;\n\tprivate _retryAttempt = 0;\n\tprivate _retryPromise: Promise<void> | undefined = undefined;\n\tprivate _retryResolve: (() => void) | undefined = undefined;\n\tprivate _retryGeneration = 0;\n\tprivate _continueTimeout: ReturnType<typeof setTimeout> | undefined = undefined;\n\n\tconstructor(private readonly _deps: RetryHandlerDeps) {}\n\n\t/** Current retry attempt (0 if not retrying) */\n\tget retryAttempt(): number {\n\t\treturn this._retryAttempt;\n\t}\n\n\t/** Whether auto-retry is currently in progress */\n\tget isRetrying(): boolean {\n\t\treturn this._retryPromise !== undefined;\n\t}\n\n\t/** Whether auto-retry is enabled */\n\tget autoRetryEnabled(): boolean {\n\t\treturn this._deps.settingsManager.getRetryEnabled();\n\t}\n\n\t/** Toggle auto-retry setting */\n\tsetAutoRetryEnabled(enabled: boolean): void {\n\t\tthis._deps.settingsManager.setRetryEnabled(enabled);\n\t}\n\n\t/**\n\t * Create a retry promise synchronously for agent_end events.\n\t * Must be called synchronously from the agent event handler before\n\t * any async processing, so that waitForRetry() doesn't miss in-flight retries.\n\t */\n\tcreateRetryPromiseForAgentEnd(messages: Array<{ role: string } & Record<string, any>>): void {\n\t\tif (this._retryPromise) return;\n\n\t\tconst settings = this._deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled) return;\n\n\t\tconst lastAssistant = this._findLastAssistantInMessages(messages);\n\t\tif (!lastAssistant || !this.isRetryableError(lastAssistant)) return;\n\n\t\tthis._retryPromise = new Promise((resolve) => {\n\t\t\tthis._retryResolve = resolve;\n\t\t});\n\t}\n\n\t/**\n\t * Handle a successful assistant response by resetting retry state.\n\t * Call this when an assistant message completes without error.\n\t */\n\thandleSuccessfulResponse(): void {\n\t\tif (this._retryAttempt > 0) {\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: true,\n\t\t\t\tattempt: this._retryAttempt,\n\t\t\t});\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._resolveRetry();\n\t\t}\n\t}\n\n\t/**\n\t * Check if an error is retryable (overloaded, rate limit, server errors).\n\t * Context overflow errors are NOT retryable (handled by compaction instead).\n\t */\n\tisRetryableError(message: AssistantMessage): boolean {\n\t\tif (message.stopReason !== \"error\" || !message.errorMessage) return false;\n\n\t\t// Context overflow is handled by compaction, not retry\n\t\tconst contextWindow = this._deps.getModel()?.contextWindow ?? 0;\n\t\tif (isContextOverflow(message, contextWindow)) return false;\n\n\t\treturn RETRYABLE_ERROR_RE.test(message.errorMessage);\n\t}\n\n\t/**\n\t * Handle retryable errors with exponential backoff.\n\t * When multiple credentials are available, marks the failing credential\n\t * as backed off and retries immediately with the next one.\n\t * @returns true if retry was initiated, false if max retries exceeded or disabled\n\t */\n\tasync handleRetryableError(message: AssistantMessage): Promise<boolean> {\n\t\tconst settings = this._deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled) {\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Retry promise is created synchronously in createRetryPromiseForAgentEnd.\n\t\t// Keep a defensive fallback here in case a future refactor bypasses that path.\n\t\tif (!this._retryPromise) {\n\t\t\tthis._retryPromise = new Promise((resolve) => {\n\t\t\t\tthis._retryResolve = resolve;\n\t\t\t});\n\t\t}\n\n\t\t// Try credential fallback before counting against retry budget.\n\t\tconst retryGeneration = this._retryGeneration;\n\t\tif (this._deps.getModel() && message.errorMessage) {\n\t\t\t// Third-party subscription block (#3772): Anthropic blocks third-party apps\n\t\t\t// from using Pro/Max subscription quotas. If the claude-code CLI provider is\n\t\t\t// available, switch to it immediately — credential rotation won't help.\n\t\t\tif (this._isThirdPartyBlock(message.errorMessage)) {\n\t\t\t\tconst switched = this._tryClaudeCodeFallback(message, retryGeneration);\n\t\t\t\tif (switched) return true;\n\t\t\t\t// CLI not available — fall through to standard error handling\n\t\t\t}\n\n\t\t\tconst errorType = this._classifyErrorType(message.errorMessage);\n\t\t\tconst isRateLimit = errorType === \"rate_limit\";\n\t\t\tconst isQuotaError = errorType === \"quota_exhausted\";\n\n\t\t\t// Credit-aware retry (OpenRouter-style 402 affordability errors):\n\t\t\t// when provider reports \"can only afford N\", lower maxTokens and retry\n\t\t\t// on the same model before rotating credentials/providers.\n\t\t\tif (isQuotaError) {\n\t\t\t\tconst adjusted = this._tryAffordableMaxTokensRetry(message, retryGeneration);\n\t\t\t\tif (adjusted) return true;\n\t\t\t}\n\n\t\t\t// Credential rotation — only for transient rate limits (#3430).\n\t\t\t// Quota errors (\"Extra usage is required\") are account-level billing\n\t\t\t// gates; rotating to another credential on the same account won't help\n\t\t\t// and the 30-minute backoff blocks all provider requests needlessly.\n\t\t\tif (isRateLimit) {\n\t\t\t\tconst hasAlternate =\n\t\t\t\t\tthis._deps.modelRegistry.authStorage.markUsageLimitReached(\n\t\t\t\t\t\tthis._deps.getModel()!.provider,\n\t\t\t\t\t\tthis._deps.getSessionId(),\n\t\t\t\t\t\t{ errorType },\n\t\t\t\t\t);\n\n\t\t\t\tif (hasAlternate) {\n\t\t\t\t\tthis._removeLastAssistantError();\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_start\",\n\t\t\t\t\t\tattempt: this._retryAttempt + 1,\n\t\t\t\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\t\t\t\tdelayMs: 0,\n\t\t\t\t\t\terrorMessage: `${message.errorMessage} (switching credential)`,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Retry immediately with the next credential - don't increment _retryAttempt\n\t\t\t\t\tthis._scheduleContinue(retryGeneration);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Cross-provider fallback — for rate limits with all creds backed off,\n\t\t\t// or quota errors (which skip credential backoff entirely).\n\t\t\tif (isRateLimit || isQuotaError) {\n\t\t\t\tconst fallbackResult = await this._deps.fallbackResolver.findFallback(\n\t\t\t\t\tthis._deps.getModel()!,\n\t\t\t\t\terrorType,\n\t\t\t\t);\n\n\t\t\t\tif (fallbackResult) {\n\t\t\t\t\tconst previousProvider = this._deps.getModel()!.provider;\n\t\t\t\t\tthis._deps.agent.setModel(fallbackResult.model);\n\t\t\t\t\tthis._deps.onModelChange(fallbackResult.model);\n\t\t\t\t\tthis._removeLastAssistantError();\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"fallback_provider_switch\",\n\t\t\t\t\t\tfrom: `${previousProvider}/${this._deps.getModel()?.id}`,\n\t\t\t\t\t\tto: `${fallbackResult.model.provider}/${fallbackResult.model.id}`,\n\t\t\t\t\t\treason: fallbackResult.reason,\n\t\t\t\t\t});\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_start\",\n\t\t\t\t\t\tattempt: this._retryAttempt + 1,\n\t\t\t\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\t\t\t\tdelayMs: 0,\n\t\t\t\t\t\terrorMessage: `${message.errorMessage} (${fallbackResult.reason})`,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Retry immediately with fallback provider - don't increment _retryAttempt\n\t\t\t\t\tthis._scheduleContinue(retryGeneration);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// No fallback available either\n\t\t\t\tif (isQuotaError) {\n\t\t\t\t\t// Try long-context model downgrade ([1m] → base) before giving up\n\t\t\t\t\tconst downgraded = this._tryLongContextDowngrade(message, retryGeneration);\n\t\t\t\t\tif (downgraded) return true;\n\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"fallback_chain_exhausted\",\n\t\t\t\t\t\treason: `All providers exhausted for ${this._deps.getModel()!.provider}/${this._deps.getModel()!.id}`,\n\t\t\t\t\t});\n\t\t\t\t\tthis._deps.emit({\n\t\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tattempt: this._retryAttempt,\n\t\t\t\t\t\tfinalError: message.errorMessage,\n\t\t\t\t\t});\n\t\t\t\t\tthis._retryAttempt = 0;\n\t\t\t\t\tthis._resolveRetry();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._retryAttempt++;\n\n\t\tif (this._retryAttempt > settings.maxRetries) {\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt: this._retryAttempt - 1,\n\t\t\t\tfinalError: message.errorMessage,\n\t\t\t});\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Use server-requested delay when available, capped by maxDelayMs.\n\t\t// Fall back to exponential backoff when no server hint is present.\n\t\tconst exponentialDelayMs = settings.baseDelayMs * 2 ** (this._retryAttempt - 1);\n\t\tlet delayMs: number;\n\t\tif (message.retryAfterMs !== undefined) {\n\t\t\tconst cap = settings.maxDelayMs > 0 ? settings.maxDelayMs : Infinity;\n\t\t\tif (message.retryAfterMs > cap) {\n\t\t\t\tthis._deps.emit({\n\t\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tattempt: this._retryAttempt - 1,\n\t\t\t\t\tfinalError: `Rate limit reset in ${Math.ceil(message.retryAfterMs / 1000)}s (max: ${Math.ceil(cap / 1000)}s). ${message.errorMessage || \"\"}`.trim(),\n\t\t\t\t});\n\t\t\t\tthis._retryAttempt = 0;\n\t\t\t\tthis._resolveRetry();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tdelayMs = message.retryAfterMs;\n\t\t} else {\n\t\t\tdelayMs = exponentialDelayMs;\n\t\t}\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt,\n\t\t\tmaxAttempts: settings.maxRetries,\n\t\t\tdelayMs,\n\t\t\terrorMessage: message.errorMessage || \"Unknown error\",\n\t\t});\n\n\t\tthis._removeLastAssistantError();\n\n\t\t// Wait with exponential backoff (abortable)\n\t\tthis._retryAbortController = new AbortController();\n\t\ttry {\n\t\t\tawait sleep(delayMs, this._retryAbortController.signal);\n\t\t} catch {\n\t\t\t// Aborted during sleep. If the retry generation already advanced, this\n\t\t\t// cancellation was handled externally (e.g. explicit model switch).\n\t\t\tif (retryGeneration !== this._retryGeneration) {\n\t\t\t\tthis._retryAbortController = undefined;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst attempt = this._retryAttempt;\n\t\t\tthis._retryAttempt = 0;\n\t\t\tthis._retryAbortController = undefined;\n\t\t\tthis._deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt,\n\t\t\t\tfinalError: \"Retry cancelled\",\n\t\t\t});\n\t\t\tthis._resolveRetry();\n\t\t\treturn false;\n\t\t}\n\t\tthis._retryAbortController = undefined;\n\n\t\t// Retry via continue() - use setTimeout to break out of event handler chain\n\t\tthis._scheduleContinue(retryGeneration);\n\n\t\treturn true;\n\t}\n\n\t/** Cancel in-progress retry */\n\tabortRetry(): void {\n\t\tconst hadRetry =\n\t\t\tthis._retryPromise !== undefined\n\t\t\t|| this._retryAbortController !== undefined\n\t\t\t|| this._continueTimeout !== undefined;\n\t\tif (!hadRetry) return;\n\n\t\tconst attempt = this._retryAttempt > 0 ? this._retryAttempt : 1;\n\t\tthis._retryGeneration++;\n\t\tif (this._continueTimeout) {\n\t\t\tclearTimeout(this._continueTimeout);\n\t\t\tthis._continueTimeout = undefined;\n\t\t}\n\t\tif (this._retryAbortController) {\n\t\t\tthis._retryAbortController.abort();\n\t\t\tthis._retryAbortController = undefined;\n\t\t}\n\t\tthis._retryAttempt = 0;\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_end\",\n\t\t\tsuccess: false,\n\t\t\tattempt,\n\t\t\tfinalError: \"Retry cancelled\",\n\t\t});\n\t\tthis._resolveRetry();\n\t}\n\n\t/**\n\t * Wait for any in-progress retry to complete.\n\t * Returns immediately if no retry is in progress.\n\t */\n\tasync waitForRetry(): Promise<void> {\n\t\tif (this._retryPromise) {\n\t\t\tawait this._retryPromise;\n\t\t}\n\t}\n\n\t/** Resolve the pending retry promise */\n\tresolveRetry(): void {\n\t\tthis._resolveRetry();\n\t}\n\n\t// =========================================================================\n\t// Private helpers\n\t// =========================================================================\n\n\tprivate _resolveRetry(): void {\n\t\tif (this._retryResolve) {\n\t\t\tthis._retryResolve();\n\t\t\tthis._retryResolve = undefined;\n\t\t\tthis._retryPromise = undefined;\n\t\t}\n\t}\n\n\tprivate _scheduleContinue(retryGeneration: number): void {\n\t\tif (this._continueTimeout) {\n\t\t\tclearTimeout(this._continueTimeout);\n\t\t}\n\t\tthis._continueTimeout = setTimeout(() => {\n\t\t\tthis._continueTimeout = undefined;\n\t\t\tif (retryGeneration !== this._retryGeneration) return;\n\t\t\tthis._deps.agent.continue().catch(() => {});\n\t\t}, 0);\n\t}\n\n\tprivate _findLastAssistantInMessages(\n\t\tmessages: Array<{ role: string } & Record<string, any>>,\n\t): AssistantMessage | undefined {\n\t\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\t\tconst message = messages[i];\n\t\t\tif (message.role === \"assistant\") {\n\t\t\t\treturn message as AssistantMessage;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Classify an error message into a usage-limit error type for credential backoff.\n\t */\n\tprivate _classifyErrorType(errorMessage: string): UsageLimitErrorType {\n\t\tconst err = errorMessage.toLowerCase();\n\t\t// Long-context entitlement errors are billing gates, not transient rate limits.\n\t\t// Must be checked before the generic 429/rate_limit regex.\n\t\tif (/extra usage is required|long context required/i.test(err)) return \"quota_exhausted\";\n\t\tif (/requires more credits|can only afford|insufficient credits|not enough credits|credit balance/i.test(err))\n\t\t\treturn \"quota_exhausted\";\n\t\tif (/quota|billing|exceeded.*limit|usage.*limit/i.test(err)) return \"quota_exhausted\";\n\t\tif (/rate.?limit|too many requests|429/i.test(err)) return \"rate_limit\";\n\t\tif (/500|502|503|504|server.?error|internal.?error|service.?unavailable/i.test(err)) return \"server_error\";\n\t\treturn \"unknown\";\n\t}\n\n\t/**\n\t * Attempt a same-model retry by reducing maxTokens when provider reports\n\t * an affordability cap (e.g., \"can only afford 329\").\n\t */\n\tprivate _tryAffordableMaxTokensRetry(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel || !message.errorMessage) return false;\n\n\t\t// Example: \"can only afford 329\"\n\t\tconst match = message.errorMessage.match(/can only afford\\s+([\\d,]+)/i);\n\t\tif (!match?.[1]) return false;\n\n\t\tconst affordable = Number.parseInt(match[1].replace(/,/g, \"\"), 10);\n\t\tif (!Number.isFinite(affordable) || affordable <= 0) return false;\n\n\t\t// Leave a small buffer so slight input variance doesn't immediately re-fail.\n\t\tconst safetyBuffer = Math.min(64, Math.max(16, Math.floor(affordable * 0.1)));\n\t\tconst targetMaxTokens = Math.max(64, affordable - safetyBuffer);\n\t\tconst downgradedMaxTokens = Math.min(currentModel.maxTokens, targetMaxTokens);\n\t\tif (downgradedMaxTokens >= currentModel.maxTokens) return false;\n\n\t\tconst downgradedModel = {\n\t\t\t...currentModel,\n\t\t\tmaxTokens: downgradedMaxTokens,\n\t\t};\n\n\t\tthis._deps.agent.setModel(downgradedModel);\n\t\tthis._deps.onModelChange(downgradedModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${currentModel.provider}/${currentModel.id} (maxTokens=${currentModel.maxTokens})`,\n\t\t\tto: `${downgradedModel.provider}/${downgradedModel.id} (maxTokens=${downgradedModel.maxTokens})`,\n\t\t\treason: `credit-aware retry: provider affordable cap ${affordable} tokens`,\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (reducing max tokens)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Attempt to downgrade a long-context model (e.g. claude-opus-4-6[1m]) to its\n\t * base model (claude-opus-4-6) when the account lacks the long-context billing\n\t * entitlement. Returns true if the downgrade was initiated.\n\t */\n\tprivate _tryLongContextDowngrade(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel) return false;\n\n\t\t// Only attempt downgrade for [1m] (or similar long-context) model IDs\n\t\tconst match = currentModel.id.match(/^(.+)\\[\\d+m\\]$/);\n\t\tif (!match) return false;\n\n\t\tconst baseModelId = match[1];\n\t\tconst baseModel = this._deps.modelRegistry.find(currentModel.provider, baseModelId);\n\t\tif (!baseModel) return false;\n\n\t\tconst previousId = currentModel.id;\n\t\tthis._deps.agent.setModel(baseModel);\n\t\tthis._deps.onModelChange(baseModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${currentModel.provider}/${previousId}`,\n\t\t\tto: `${baseModel.provider}/${baseModel.id}`,\n\t\t\treason: `long context downgrade: ${previousId} → ${baseModel.id}`,\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (long context downgrade)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Detect Anthropic subscription block errors (#3772).\n\t * These are hard policy blocks, not transient rate limits — credential\n\t * rotation will not help. Matches both the explicit \"third-party\" message\n\t * and the \"out of extra usage\" variant that subscription users receive.\n\t */\n\tprivate _isThirdPartyBlock(errorMessage: string): boolean {\n\t\treturn /third[- .]party.*(?:draw from extra|not.*available|plan limits|not permitted|cannot be used|not supported)|(?:out of|no) extra usage/i.test(errorMessage);\n\t}\n\n\t/**\n\t * Attempt to switch to the claude-code CLI provider when the current\n\t * Anthropic provider is blocked by the third-party policy (#3772).\n\t * Returns true if the switch was made and retry scheduled.\n\t */\n\tprivate _tryClaudeCodeFallback(message: AssistantMessage, retryGeneration: number): boolean {\n\t\tif (!this._deps.isClaudeCodeReady?.()) return false;\n\n\t\tconst currentModel = this._deps.getModel();\n\t\tif (!currentModel) return false;\n\n\t\t// Only attempt claude-code fallback when the current provider is anthropic.\n\t\t// Transport-specific (ADR-012): intentionally keys on provider, not api —\n\t\t// the fallback specifically reroutes the plain `anthropic` transport to\n\t\t// the `claude-code` transport. Other Anthropic-fronting transports\n\t\t// (anthropic-vertex, amazon-bedrock) must not be rerouted.\n\t\tif (currentModel.provider !== \"anthropic\") return false;\n\n\t\t// Find the same model ID under the claude-code provider\n\t\tconst ccModel = this._deps.modelRegistry.find(\"claude-code\", currentModel.id);\n\t\tif (!ccModel) return false;\n\n\t\tconst previousProvider = currentModel.provider;\n\t\tthis._deps.agent.setModel(ccModel);\n\t\tthis._deps.onModelChange(ccModel);\n\t\tthis._removeLastAssistantError();\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"fallback_provider_switch\",\n\t\t\tfrom: `${previousProvider}/${currentModel.id}`,\n\t\t\tto: `claude-code/${ccModel.id}`,\n\t\t\treason: \"Anthropic subscription blocked for third-party apps — routing through Claude Code CLI\",\n\t\t});\n\n\t\tthis._deps.emit({\n\t\t\ttype: \"auto_retry_start\",\n\t\t\tattempt: this._retryAttempt + 1,\n\t\t\tmaxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,\n\t\t\tdelayMs: 0,\n\t\t\terrorMessage: `${message.errorMessage} (switching to Claude Code CLI)`,\n\t\t});\n\n\t\tthis._scheduleContinue(retryGeneration);\n\t\treturn true;\n\t}\n\n\t/** Remove the last assistant error message from agent state */\n\tprivate _removeLastAssistantError(): void {\n\t\tconst messages = this._deps.agent.state.messages;\n\t\tif (messages.length > 0 && messages[messages.length - 1].role === \"assistant\") {\n\t\t\tthis._deps.agent.replaceMessages(messages.slice(0, -1));\n\t\t}\n\t}\n}\n"]}
@@ -204,7 +204,11 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
204
204
  const result = await handler.handleRetryableError(msg);
205
205
  assert.equal(result, true, "retry should be initiated");
206
206
  handler.abortRetry();
207
- await new Promise((resolve) => setTimeout(resolve, 10));
207
+ // Yield the microtask queue so any synchronous continuation
208
+ // scheduled by abortRetry() settles before we assert. This is
209
+ // deterministic — no magic-sleep dependency (#4798 / #4784).
210
+ await Promise.resolve();
211
+ await Promise.resolve();
208
212
  assert.equal(continueFn.mock.calls.length, 0, "cancelled retry must not continue after explicit abort");
209
213
  const endEvents = emittedEvents.filter((e) => e.type === "auto_retry_end");
210
214
  assert.equal(endEvents.length, 1, "retry cancellation should emit a single auto_retry_end event");
@@ -1 +1 @@
1
- {"version":3,"file":"retry-handler.test.js","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RetryHandler tests — long-context entitlement 429 error handling (#2803)\n *\n * Verifies that \"Extra usage is required for long context requests\" errors\n * are classified as quota_exhausted (not rate_limit) and trigger a model\n * downgrade from [1m] to base when no cross-provider fallback exists.\n */\n\nimport { describe, it, beforeEach, mock, type Mock } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { RetryHandler, type RetryHandlerDeps } from \"./retry-handler.js\";\nimport type { Api, AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction createMockModel(provider: string, id: string): Model<Api> {\n\treturn {\n\t\tid,\n\t\tname: id,\n\t\tapi: \"anthropic\" as Api,\n\t\tprovider,\n\t\tbaseUrl: \"https://api.anthropic.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 1_000_000,\n\t\tmaxTokens: 16384,\n\t} as Model<Api>;\n}\n\nfunction errorMessage(msg: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6[1m]\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"error\",\n\t\terrorMessage: msg,\n\t\ttimestamp: Date.now(),\n\t} as AssistantMessage;\n}\n\ninterface MockDeps {\n\tdeps: RetryHandlerDeps;\n\temittedEvents: Array<Record<string, any>>;\n\tcontinueFn: Mock<() => Promise<void>>;\n\tonModelChangeFn: Mock<(model: Model<any>) => void>;\n\tmarkUsageLimitReached: Mock<(...args: any[]) => boolean>;\n\tfindFallback: Mock<(...args: any[]) => Promise<any>>;\n\tfindModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;\n}\n\nfunction createMockDeps(overrides?: {\n\tmodel?: Model<Api>;\n\tretryEnabled?: boolean;\n\tmarkUsageLimitReachedResult?: boolean;\n\tfallbackResult?: any;\n\tfindModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;\n\tretrySettings?: {\n\t\tmaxRetries?: number;\n\t\tbaseDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): MockDeps {\n\tconst model = overrides?.model ?? createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\");\n\tconst emittedEvents: Array<Record<string, any>> = [];\n\tconst continueFn = mock.fn(async () => {});\n\tconst onModelChangeFn = mock.fn((_model: Model<any>) => {});\n\tconst markUsageLimitReached = mock.fn(\n\t\t() => overrides?.markUsageLimitReachedResult ?? false,\n\t);\n\tconst findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);\n\tconst findModel = mock.fn(\n\t\toverrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),\n\t);\n\n\tconst messages: Array<{ role: string } & Record<string, any>> = [];\n\n\tconst deps: RetryHandlerDeps = {\n\t\tagent: {\n\t\t\tcontinue: continueFn,\n\t\t\tstate: { messages },\n\t\t\tsetModel: mock.fn(),\n\t\t\treplaceMessages: mock.fn((newMessages: any[]) => {\n\t\t\t\tmessages.length = 0;\n\t\t\t\tmessages.push(...newMessages);\n\t\t\t}),\n\t\t} as any,\n\t\tsettingsManager: {\n\t\t\tgetRetryEnabled: () => overrides?.retryEnabled ?? true,\n\t\t\tgetRetrySettings: () => ({\n\t\t\t\tenabled: overrides?.retryEnabled ?? true,\n\t\t\t\tmaxRetries: overrides?.retrySettings?.maxRetries ?? 5,\n\t\t\t\tbaseDelayMs: overrides?.retrySettings?.baseDelayMs ?? 1000,\n\t\t\t\tmaxDelayMs: overrides?.retrySettings?.maxDelayMs ?? 30000,\n\t\t\t}),\n\t\t} as unknown as SettingsManager,\n\t\tmodelRegistry: {\n\t\t\tauthStorage: {\n\t\t\t\tmarkUsageLimitReached,\n\t\t\t},\n\t\t\tfind: findModel,\n\t\t} as unknown as ModelRegistry,\n\t\tfallbackResolver: {\n\t\t\tfindFallback,\n\t\t} as unknown as FallbackResolver,\n\t\tgetModel: () => model,\n\t\tgetSessionId: () => \"test-session\",\n\t\temit: (event: any) => emittedEvents.push(event),\n\t\tonModelChange: onModelChangeFn,\n\t};\n\n\treturn { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };\n}\n\n// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────\n\ndescribe(\"RetryHandler — long-context entitlement 429 (#2803)\", () => {\n\n\tdescribe(\"error classification\", () => {\n\t\tit(\"classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit\", async () => {\n\t\t\t// When the error is classified as quota_exhausted AND no alternate credentials\n\t\t\t// AND no fallback, the handler should emit fallback_chain_exhausted and stop.\n\t\t\t// If misclassified as rate_limit, it would enter the backoff loop instead.\n\t\t\tconst { deps, emittedEvents, findModel } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false, // no alternate credentials\n\t\t\t\tfallbackResult: null, // no cross-provider fallback\n\t\t\t\tfindModelResult: () => undefined, // no base model either\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}'\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT retry (would be true if misclassified as rate_limit entering backoff)\n\t\t\tassert.equal(result, false);\n\n\t\t\t// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted event for entitlement error\");\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.equal(retryStart, undefined, \"Should NOT emit auto_retry_start for entitlement error\");\n\t\t});\n\n\t\tit(\"still classifies regular 429 rate limits as rate_limit\", async () => {\n\t\t\t// A normal \"rate limit\" 429 should still be classified as rate_limit\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should enter the backoff loop (rate_limit path, not quota_exhausted)\n\t\t\tassert.equal(result, true);\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Regular 429 should enter backoff retry\");\n\t\t});\n\n\t\tit(\"classifies OpenRouter credit affordability errors as quota_exhausted\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openrouter\", \"openai/gpt-5-pro\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"affordability error should trigger credit-aware retry\");\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Expected immediate retry after reducing max tokens\");\n\t\t});\n\t});\n\n\tdescribe(\"long-context model downgrade\", () => {\n\t\tit(\"downgrades from [1m] to base model when entitlement error and no fallback\", async () => {\n\t\t\tconst baseModel = createMockModel(\"anthropic\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"anthropic\" && modelId === \"claude-opus-4-6\") return baseModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"Should retry after downgrade\");\n\n\t\t\t// Should have called setModel with the base model\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1);\n\t\t\tassert.equal(setModelCalls[0].arguments[0].id, \"claude-opus-4-6\");\n\n\t\t\t// Should have notified about model change\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1);\n\n\t\t\t// Should emit a fallback_provider_switch event indicating downgrade\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event for downgrade\");\n\t\t\tassert.ok(switchEvent!.reason.includes(\"long context downgrade\"), `reason should mention downgrade: ${switchEvent!.reason}`);\n\t\t});\n\n\t\tit(\"emits fallback_chain_exhausted when base model is also unavailable\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined, // base model not found\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted when base model unavailable\");\n\t\t});\n\n\t\tit(\"does not attempt downgrade for non-[1m] models\", async () => {\n\t\t\t// When a regular model (no [1m] suffix) gets a quota_exhausted error\n\t\t\t// with no fallback, it should just stop — no downgrade attempt.\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted);\n\n\t\t\t// No downgrade switch should occur\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.equal(switchEvent, undefined, \"Should not switch for non-[1m] models\");\n\t\t});\n\t});\n\n\tdescribe(\"retry cancellation\", () => {\n\t\tit(\"cancels queued immediate continue callbacks when retry is aborted\", async () => {\n\t\t\tconst { deps, emittedEvents, continueFn } = createMockDeps({\n\t\t\t\tmarkUsageLimitReachedResult: true,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"retry should be initiated\");\n\n\t\t\thandler.abortRetry();\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 10));\n\n\t\t\tassert.equal(continueFn.mock.calls.length, 0, \"cancelled retry must not continue after explicit abort\");\n\t\t\tconst endEvents = emittedEvents.filter((e) => e.type === \"auto_retry_end\");\n\t\t\tassert.equal(endEvents.length, 1, \"retry cancellation should emit a single auto_retry_end event\");\n\t\t\tassert.equal(endEvents[0]?.finalError, \"Retry cancelled\");\n\t\t});\n\t});\n\n\tdescribe(\"credit-aware maxTokens retry\", () => {\n\t\tit(\"reduces maxTokens on same model when provider reports affordable cap\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"should retry after reducing maxTokens\");\n\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1, \"should apply one model downgrade\");\n\t\t\tconst downgraded = setModelCalls[0].arguments[0] as Model<Api>;\n\t\t\tassert.equal(downgraded.provider, \"openrouter\");\n\t\t\tassert.equal(downgraded.id, \"openai/gpt-5-pro\");\n\t\t\tassert.equal(downgraded.maxTokens, 297, \"expected affordability cap with safety buffer\");\n\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1, \"should notify about model update\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"should emit model-adjustment event\");\n\t\t\tassert.ok(\n\t\t\t\tString(switchEvent?.reason || \"\").includes(\"credit-aware retry\"),\n\t\t\t\t\"switch reason should mention credit-aware retry\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not mark credentials in cooldown for affordability quota errors\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\t\t\tassert.equal(markUsageLimitReached.mock.calls.length, 0, \"quota error should skip credential cooldown\");\n\t\t});\n\t});\n\n\tdescribe(\"isRetryableError\", () => {\n\t\tit(\"considers long-context entitlement error as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\n\t\tit(\"does NOT consider credential cooldown error as retryable (#3429)\", () => {\n\t\t\t// The credential cooldown message from getApiKey() must not re-enter\n\t\t\t// the retry handler. Re-entry creates cascading empty error entries\n\t\t\t// in the session file that break resume.\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'All credentials for \"anthropic\" are in a cooldown window. ' +\n\t\t\t\t'Please wait a moment and try again, or switch to a different provider.',\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), false);\n\t\t});\n\n\t\tit(\"considers OpenRouter affordability credit errors as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\t});\n\n\tdescribe(\"third-party block claude-code fallback (#3772)\", () => {\n\t\tit(\"switches to claude-code provider when current provider is anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps cannot draw from extra usage\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"switches to claude-code on 'out of extra usage' error (#3772)\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"You're out of extra usage. Add more at claude.ai/settings/usage and keep going.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"does NOT switch to claude-code when current provider is not anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"gpt-4o\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openai\", \"gpt-4o\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"gpt-4o\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps are not supported for this plan\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT have triggered the claude-code fallback\n\t\t\tconst switchEvent = emittedEvents.find(\n\t\t\t\t(e) => e.type === \"fallback_provider_switch\" && e.to?.startsWith(\"claude-code/\"),\n\t\t\t);\n\t\t\tassert.equal(switchEvent, undefined, \"Should NOT switch non-anthropic provider to claude-code\");\n\t\t});\n\t});\n\n\tdescribe(\"quota_exhausted credential backoff (#3430)\", () => {\n\t\tit(\"does NOT call markUsageLimitReached for quota_exhausted errors\", async () => {\n\t\t\t// \"Extra usage is required\" is an account-level billing gate.\n\t\t\t// Backing off the credential for 30 minutes blocks all provider\n\t\t\t// requests and has no effect on the billing condition.\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}',\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"markUsageLimitReached must NOT be called for quota_exhausted errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still calls markUsageLimitReached for regular rate_limit errors\", async () => {\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t1,\n\t\t\t\t\"markUsageLimitReached should be called for rate_limit errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still tries cross-provider fallback for quota_exhausted without credential backoff\", async () => {\n\t\t\tconst fallbackModel = createMockModel(\"openai\", \"gpt-4o\");\n\t\t\tconst { deps, markUsageLimitReached, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: { model: fallbackModel, reason: \"cross-provider fallback\" },\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry with fallback provider\");\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"should NOT back off credentials before trying fallback\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"retry-handler.test.js","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RetryHandler tests — long-context entitlement 429 error handling (#2803)\n *\n * Verifies that \"Extra usage is required for long context requests\" errors\n * are classified as quota_exhausted (not rate_limit) and trigger a model\n * downgrade from [1m] to base when no cross-provider fallback exists.\n */\n\nimport { describe, it, beforeEach, mock, type Mock } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { RetryHandler, type RetryHandlerDeps } from \"./retry-handler.js\";\nimport type { Api, AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction createMockModel(provider: string, id: string): Model<Api> {\n\treturn {\n\t\tid,\n\t\tname: id,\n\t\tapi: \"anthropic\" as Api,\n\t\tprovider,\n\t\tbaseUrl: \"https://api.anthropic.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 1_000_000,\n\t\tmaxTokens: 16384,\n\t} as Model<Api>;\n}\n\nfunction errorMessage(msg: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6[1m]\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"error\",\n\t\terrorMessage: msg,\n\t\ttimestamp: Date.now(),\n\t} as AssistantMessage;\n}\n\ninterface MockDeps {\n\tdeps: RetryHandlerDeps;\n\temittedEvents: Array<Record<string, any>>;\n\tcontinueFn: Mock<() => Promise<void>>;\n\tonModelChangeFn: Mock<(model: Model<any>) => void>;\n\tmarkUsageLimitReached: Mock<(...args: any[]) => boolean>;\n\tfindFallback: Mock<(...args: any[]) => Promise<any>>;\n\tfindModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;\n}\n\nfunction createMockDeps(overrides?: {\n\tmodel?: Model<Api>;\n\tretryEnabled?: boolean;\n\tmarkUsageLimitReachedResult?: boolean;\n\tfallbackResult?: any;\n\tfindModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;\n\tretrySettings?: {\n\t\tmaxRetries?: number;\n\t\tbaseDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): MockDeps {\n\tconst model = overrides?.model ?? createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\");\n\tconst emittedEvents: Array<Record<string, any>> = [];\n\tconst continueFn = mock.fn(async () => {});\n\tconst onModelChangeFn = mock.fn((_model: Model<any>) => {});\n\tconst markUsageLimitReached = mock.fn(\n\t\t() => overrides?.markUsageLimitReachedResult ?? false,\n\t);\n\tconst findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);\n\tconst findModel = mock.fn(\n\t\toverrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),\n\t);\n\n\tconst messages: Array<{ role: string } & Record<string, any>> = [];\n\n\tconst deps: RetryHandlerDeps = {\n\t\tagent: {\n\t\t\tcontinue: continueFn,\n\t\t\tstate: { messages },\n\t\t\tsetModel: mock.fn(),\n\t\t\treplaceMessages: mock.fn((newMessages: any[]) => {\n\t\t\t\tmessages.length = 0;\n\t\t\t\tmessages.push(...newMessages);\n\t\t\t}),\n\t\t} as any,\n\t\tsettingsManager: {\n\t\t\tgetRetryEnabled: () => overrides?.retryEnabled ?? true,\n\t\t\tgetRetrySettings: () => ({\n\t\t\t\tenabled: overrides?.retryEnabled ?? true,\n\t\t\t\tmaxRetries: overrides?.retrySettings?.maxRetries ?? 5,\n\t\t\t\tbaseDelayMs: overrides?.retrySettings?.baseDelayMs ?? 1000,\n\t\t\t\tmaxDelayMs: overrides?.retrySettings?.maxDelayMs ?? 30000,\n\t\t\t}),\n\t\t} as unknown as SettingsManager,\n\t\tmodelRegistry: {\n\t\t\tauthStorage: {\n\t\t\t\tmarkUsageLimitReached,\n\t\t\t},\n\t\t\tfind: findModel,\n\t\t} as unknown as ModelRegistry,\n\t\tfallbackResolver: {\n\t\t\tfindFallback,\n\t\t} as unknown as FallbackResolver,\n\t\tgetModel: () => model,\n\t\tgetSessionId: () => \"test-session\",\n\t\temit: (event: any) => emittedEvents.push(event),\n\t\tonModelChange: onModelChangeFn,\n\t};\n\n\treturn { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };\n}\n\n// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────\n\ndescribe(\"RetryHandler — long-context entitlement 429 (#2803)\", () => {\n\n\tdescribe(\"error classification\", () => {\n\t\tit(\"classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit\", async () => {\n\t\t\t// When the error is classified as quota_exhausted AND no alternate credentials\n\t\t\t// AND no fallback, the handler should emit fallback_chain_exhausted and stop.\n\t\t\t// If misclassified as rate_limit, it would enter the backoff loop instead.\n\t\t\tconst { deps, emittedEvents, findModel } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false, // no alternate credentials\n\t\t\t\tfallbackResult: null, // no cross-provider fallback\n\t\t\t\tfindModelResult: () => undefined, // no base model either\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}'\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT retry (would be true if misclassified as rate_limit entering backoff)\n\t\t\tassert.equal(result, false);\n\n\t\t\t// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted event for entitlement error\");\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.equal(retryStart, undefined, \"Should NOT emit auto_retry_start for entitlement error\");\n\t\t});\n\n\t\tit(\"still classifies regular 429 rate limits as rate_limit\", async () => {\n\t\t\t// A normal \"rate limit\" 429 should still be classified as rate_limit\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should enter the backoff loop (rate_limit path, not quota_exhausted)\n\t\t\tassert.equal(result, true);\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Regular 429 should enter backoff retry\");\n\t\t});\n\n\t\tit(\"classifies OpenRouter credit affordability errors as quota_exhausted\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openrouter\", \"openai/gpt-5-pro\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"affordability error should trigger credit-aware retry\");\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Expected immediate retry after reducing max tokens\");\n\t\t});\n\t});\n\n\tdescribe(\"long-context model downgrade\", () => {\n\t\tit(\"downgrades from [1m] to base model when entitlement error and no fallback\", async () => {\n\t\t\tconst baseModel = createMockModel(\"anthropic\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"anthropic\" && modelId === \"claude-opus-4-6\") return baseModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"Should retry after downgrade\");\n\n\t\t\t// Should have called setModel with the base model\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1);\n\t\t\tassert.equal(setModelCalls[0].arguments[0].id, \"claude-opus-4-6\");\n\n\t\t\t// Should have notified about model change\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1);\n\n\t\t\t// Should emit a fallback_provider_switch event indicating downgrade\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event for downgrade\");\n\t\t\tassert.ok(switchEvent!.reason.includes(\"long context downgrade\"), `reason should mention downgrade: ${switchEvent!.reason}`);\n\t\t});\n\n\t\tit(\"emits fallback_chain_exhausted when base model is also unavailable\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined, // base model not found\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted when base model unavailable\");\n\t\t});\n\n\t\tit(\"does not attempt downgrade for non-[1m] models\", async () => {\n\t\t\t// When a regular model (no [1m] suffix) gets a quota_exhausted error\n\t\t\t// with no fallback, it should just stop — no downgrade attempt.\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted);\n\n\t\t\t// No downgrade switch should occur\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.equal(switchEvent, undefined, \"Should not switch for non-[1m] models\");\n\t\t});\n\t});\n\n\tdescribe(\"retry cancellation\", () => {\n\t\tit(\"cancels queued immediate continue callbacks when retry is aborted\", async () => {\n\t\t\tconst { deps, emittedEvents, continueFn } = createMockDeps({\n\t\t\t\tmarkUsageLimitReachedResult: true,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"retry should be initiated\");\n\n\t\t\thandler.abortRetry();\n\t\t\t// Yield the microtask queue so any synchronous continuation\n\t\t\t// scheduled by abortRetry() settles before we assert. This is\n\t\t\t// deterministic — no magic-sleep dependency (#4798 / #4784).\n\t\t\tawait Promise.resolve();\n\t\t\tawait Promise.resolve();\n\n\t\t\tassert.equal(continueFn.mock.calls.length, 0, \"cancelled retry must not continue after explicit abort\");\n\t\t\tconst endEvents = emittedEvents.filter((e) => e.type === \"auto_retry_end\");\n\t\t\tassert.equal(endEvents.length, 1, \"retry cancellation should emit a single auto_retry_end event\");\n\t\t\tassert.equal(endEvents[0]?.finalError, \"Retry cancelled\");\n\t\t});\n\t});\n\n\tdescribe(\"credit-aware maxTokens retry\", () => {\n\t\tit(\"reduces maxTokens on same model when provider reports affordable cap\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"should retry after reducing maxTokens\");\n\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1, \"should apply one model downgrade\");\n\t\t\tconst downgraded = setModelCalls[0].arguments[0] as Model<Api>;\n\t\t\tassert.equal(downgraded.provider, \"openrouter\");\n\t\t\tassert.equal(downgraded.id, \"openai/gpt-5-pro\");\n\t\t\tassert.equal(downgraded.maxTokens, 297, \"expected affordability cap with safety buffer\");\n\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1, \"should notify about model update\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"should emit model-adjustment event\");\n\t\t\tassert.ok(\n\t\t\t\tString(switchEvent?.reason || \"\").includes(\"credit-aware retry\"),\n\t\t\t\t\"switch reason should mention credit-aware retry\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not mark credentials in cooldown for affordability quota errors\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\t\t\tassert.equal(markUsageLimitReached.mock.calls.length, 0, \"quota error should skip credential cooldown\");\n\t\t});\n\t});\n\n\tdescribe(\"isRetryableError\", () => {\n\t\tit(\"considers long-context entitlement error as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\n\t\tit(\"does NOT consider credential cooldown error as retryable (#3429)\", () => {\n\t\t\t// The credential cooldown message from getApiKey() must not re-enter\n\t\t\t// the retry handler. Re-entry creates cascading empty error entries\n\t\t\t// in the session file that break resume.\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'All credentials for \"anthropic\" are in a cooldown window. ' +\n\t\t\t\t'Please wait a moment and try again, or switch to a different provider.',\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), false);\n\t\t});\n\n\t\tit(\"considers OpenRouter affordability credit errors as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\t});\n\n\tdescribe(\"third-party block claude-code fallback (#3772)\", () => {\n\t\tit(\"switches to claude-code provider when current provider is anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps cannot draw from extra usage\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"switches to claude-code on 'out of extra usage' error (#3772)\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"You're out of extra usage. Add more at claude.ai/settings/usage and keep going.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"does NOT switch to claude-code when current provider is not anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"gpt-4o\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openai\", \"gpt-4o\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"gpt-4o\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps are not supported for this plan\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT have triggered the claude-code fallback\n\t\t\tconst switchEvent = emittedEvents.find(\n\t\t\t\t(e) => e.type === \"fallback_provider_switch\" && e.to?.startsWith(\"claude-code/\"),\n\t\t\t);\n\t\t\tassert.equal(switchEvent, undefined, \"Should NOT switch non-anthropic provider to claude-code\");\n\t\t});\n\t});\n\n\tdescribe(\"quota_exhausted credential backoff (#3430)\", () => {\n\t\tit(\"does NOT call markUsageLimitReached for quota_exhausted errors\", async () => {\n\t\t\t// \"Extra usage is required\" is an account-level billing gate.\n\t\t\t// Backing off the credential for 30 minutes blocks all provider\n\t\t\t// requests and has no effect on the billing condition.\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}',\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"markUsageLimitReached must NOT be called for quota_exhausted errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still calls markUsageLimitReached for regular rate_limit errors\", async () => {\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t1,\n\t\t\t\t\"markUsageLimitReached should be called for rate_limit errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still tries cross-provider fallback for quota_exhausted without credential backoff\", async () => {\n\t\t\tconst fallbackModel = createMockModel(\"openai\", \"gpt-4o\");\n\t\t\tconst { deps, markUsageLimitReached, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: { model: fallbackModel, reason: \"cross-provider fallback\" },\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry with fallback provider\");\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"should NOT back off credentials before trying fallback\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Regex matching retryable provider errors — overloaded, rate limits, transient
3
+ * server/connection failures, credential-backoff, quota/credit issues.
4
+ *
5
+ * Kept in its own zero-import module so tests can consume the live pattern
6
+ * without pulling in the full RetryHandler dependency graph (Agent /
7
+ * FallbackResolver / ModelRegistry / @gsd/pi-ai …). The test in
8
+ * `src/resources/extensions/gsd/tests/provider-errors.test.ts` previously
9
+ * redefined this regex inline, which meant runtime and test could drift
10
+ * silently on every edit (see #4837).
11
+ *
12
+ * "temporarily backed off" is intentionally excluded: it is an internally-
13
+ * generated error from getApiKey() when credentials are in a backoff window.
14
+ * Re-entering the retry handler for that message creates a cascade of empty
15
+ * error entries in the session file, breaking resume (#3429).
16
+ */
17
+ export declare const RETRYABLE_ERROR_RE: RegExp;
18
+ //# sourceMappingURL=retryable-error-regex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retryable-error-regex.d.ts","sourceRoot":"","sources":["../../src/core/retryable-error-regex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,kBAAkB,QACwc,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Regex matching retryable provider errors — overloaded, rate limits, transient
3
+ * server/connection failures, credential-backoff, quota/credit issues.
4
+ *
5
+ * Kept in its own zero-import module so tests can consume the live pattern
6
+ * without pulling in the full RetryHandler dependency graph (Agent /
7
+ * FallbackResolver / ModelRegistry / @gsd/pi-ai …). The test in
8
+ * `src/resources/extensions/gsd/tests/provider-errors.test.ts` previously
9
+ * redefined this regex inline, which meant runtime and test could drift
10
+ * silently on every edit (see #4837).
11
+ *
12
+ * "temporarily backed off" is intentionally excluded: it is an internally-
13
+ * generated error from getApiKey() when credentials are in a backoff window.
14
+ * Re-entering the retry handler for that message creates a cascade of empty
15
+ * error entries in the session file, breaking resume (#3429).
16
+ */
17
+ export const RETRYABLE_ERROR_RE = /overloaded|rate.?limit|too many requests|402|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|requires more credits|can only afford|insufficient credits|not enough credits|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i;
18
+ //# sourceMappingURL=retryable-error-regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retryable-error-regex.js","sourceRoot":"","sources":["../../src/core/retryable-error-regex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAC9B,seAAse,CAAC","sourcesContent":["/**\n * Regex matching retryable provider errors — overloaded, rate limits, transient\n * server/connection failures, credential-backoff, quota/credit issues.\n *\n * Kept in its own zero-import module so tests can consume the live pattern\n * without pulling in the full RetryHandler dependency graph (Agent /\n * FallbackResolver / ModelRegistry / @gsd/pi-ai …). The test in\n * `src/resources/extensions/gsd/tests/provider-errors.test.ts` previously\n * redefined this regex inline, which meant runtime and test could drift\n * silently on every edit (see #4837).\n *\n * \"temporarily backed off\" is intentionally excluded: it is an internally-\n * generated error from getApiKey() when credentials are in a backoff window.\n * Re-entering the retry handler for that message creates a cascade of empty\n * error entries in the session file, breaking resume (#3429).\n */\nexport const RETRYABLE_ERROR_RE =\n\t/overloaded|rate.?limit|too many requests|402|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\\s+)?unavailable|credentials.*expired|requires more credits|can only afford|insufficient credits|not enough credits|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i;\n"]}
@@ -9,6 +9,7 @@ export declare class CredentialCooldownError extends Error {
9
9
  readonly retryAfterMs: number | undefined;
10
10
  constructor(provider: string, retryAfterMs?: number);
11
11
  }
12
+ export declare function canRestoreSessionModel(modelRegistry: Pick<ModelRegistry, "isProviderRequestReady">, model: Model<any>): boolean;
12
13
  import { type ThinkingLevel } from "@gsd/pi-agent-core";
13
14
  import type { Model } from "@gsd/pi-ai";
14
15
  import { AgentSession } from "./agent-session.js";
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,9 @@ export class CredentialCooldownError extends Error {
24
24
  this.retryAfterMs = retryAfterMs;
25
25
  }
26
26
  }
27
+ export function canRestoreSessionModel(modelRegistry, model) {
28
+ return modelRegistry.isProviderRequestReady(model.provider);
29
+ }
27
30
  import { Agent } from "@gsd/pi-agent-core";
28
31
  import { getAgentDir, getDocsPath } from "../config.js";
29
32
  import { AgentSession } from "./agent-session.js";
@@ -117,7 +120,7 @@ export async function createAgentSession(options = {}) {
117
120
  // If session has data, try to restore model from it
118
121
  if (!model && hasExistingSession && existingSession.model) {
119
122
  const restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);
120
- if (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {
123
+ if (restoredModel && canRestoreSessionModel(modelRegistry, restoredModel)) {
121
124
  model = restoredModel;
122
125
  }
123
126
  if (!model) {