gsd-pi 2.71.0 → 2.72.0-dev.3118184

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 (578) hide show
  1. package/README.md +69 -19
  2. package/dist/cli.js +88 -6
  3. package/dist/headless-events.d.ts +2 -0
  4. package/dist/headless-events.js +7 -0
  5. package/dist/headless.js +16 -3
  6. package/dist/mcp-server.js +40 -17
  7. package/dist/onboarding.js +10 -0
  8. package/dist/provider-migrations.d.ts +10 -0
  9. package/dist/provider-migrations.js +12 -0
  10. package/dist/resource-loader.js +139 -13
  11. package/dist/resources/GSD-WORKFLOW.md +1 -1
  12. package/dist/resources/agents/debugger.md +58 -0
  13. package/dist/resources/agents/doc-writer.md +43 -0
  14. package/dist/resources/agents/git-ops.md +56 -0
  15. package/dist/resources/agents/javascript-pro.md +46 -271
  16. package/dist/resources/agents/planner.md +55 -0
  17. package/dist/resources/agents/refactorer.md +47 -0
  18. package/dist/resources/agents/reviewer.md +48 -0
  19. package/dist/resources/agents/security.md +59 -0
  20. package/dist/resources/agents/tester.md +50 -0
  21. package/dist/resources/agents/typescript-pro.md +41 -235
  22. package/dist/resources/extensions/async-jobs/await-tool.js +7 -4
  23. package/dist/resources/extensions/async-jobs/job-manager.js +28 -3
  24. package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
  25. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +142 -14
  26. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  27. package/dist/resources/extensions/gsd/auto/loop.js +116 -2
  28. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  29. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  30. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  31. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  32. package/dist/resources/extensions/gsd/auto-post-unit.js +6 -0
  33. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  34. package/dist/resources/extensions/gsd/auto-recovery.js +11 -0
  35. package/dist/resources/extensions/gsd/auto-start.js +34 -7
  36. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  37. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  38. package/dist/resources/extensions/gsd/auto.js +81 -19
  39. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  40. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -11
  41. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  42. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  43. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  44. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  45. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  46. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  47. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  49. package/dist/resources/extensions/gsd/commands-handlers.js +4 -1
  50. package/dist/resources/extensions/gsd/context-injector.js +1 -1
  51. package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -7
  52. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  53. package/dist/resources/extensions/gsd/definition-io.js +15 -0
  54. package/dist/resources/extensions/gsd/dispatch-guard.js +22 -1
  55. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  56. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +6 -3
  57. package/dist/resources/extensions/gsd/error-classifier.js +5 -2
  58. package/dist/resources/extensions/gsd/forensics.js +19 -6
  59. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  60. package/dist/resources/extensions/gsd/git-service.js +11 -8
  61. package/dist/resources/extensions/gsd/gitignore.js +12 -6
  62. package/dist/resources/extensions/gsd/gsd-db.js +90 -6
  63. package/dist/resources/extensions/gsd/guided-flow.js +5 -10
  64. package/dist/resources/extensions/gsd/key-manager.js +2 -0
  65. package/dist/resources/extensions/gsd/metrics.js +1 -0
  66. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  67. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  68. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  69. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  70. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  71. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  72. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  73. package/dist/resources/extensions/gsd/preferences-skills.js +2 -34
  74. package/dist/resources/extensions/gsd/preferences-types.js +15 -0
  75. package/dist/resources/extensions/gsd/preferences.js +16 -3
  76. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  77. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  78. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  79. package/dist/resources/extensions/gsd/prompts/discuss.md +123 -12
  80. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  81. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  82. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  83. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  85. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  86. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  87. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  88. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  89. package/dist/resources/extensions/gsd/state.js +29 -2
  90. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  91. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  92. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
  93. package/dist/resources/extensions/gsd/workflow-projections.js +7 -0
  94. package/dist/resources/extensions/gsd/worktree-manager.js +30 -3
  95. package/dist/resources/extensions/gsd/write-intercept.js +10 -1
  96. package/dist/resources/extensions/ollama/index.js +17 -10
  97. package/dist/resources/extensions/ollama/ollama-client.js +35 -6
  98. package/dist/resources/extensions/ollama/ollama-discovery.js +32 -6
  99. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  100. package/dist/resources/extensions/subagent/agents.js +8 -0
  101. package/dist/resources/extensions/subagent/index.js +17 -0
  102. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  103. package/dist/startup-model-validation.d.ts +0 -1
  104. package/dist/startup-model-validation.js +6 -2
  105. package/dist/web/standalone/.next/BUILD_ID +1 -1
  106. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  107. package/dist/web/standalone/.next/build-manifest.json +3 -3
  108. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  109. package/dist/web/standalone/.next/required-server-files.json +3 -3
  110. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  121. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  169. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  179. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  201. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  203. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +3 -3
  205. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/index.html +1 -1
  215. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  216. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  217. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  218. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  220. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/page.js +2 -2
  222. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  224. package/dist/web/standalone/.next/server/chunks/2331.js +16 -16
  225. package/dist/web/standalone/.next/server/chunks/4741.js +12 -12
  226. package/dist/web/standalone/.next/server/chunks/5822.js +2 -2
  227. package/dist/web/standalone/.next/server/chunks/63.js +8 -8
  228. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  229. package/dist/web/standalone/.next/server/edge-runtime-webpack.js +2 -0
  230. package/dist/web/standalone/.next/server/functions-config-manifest.json +0 -9
  231. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware-manifest.json +29 -2
  233. package/dist/web/standalone/.next/server/middleware.js +4 -12
  234. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  235. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  236. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  237. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  238. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  239. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  240. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  241. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  242. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  245. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  246. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  247. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  248. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  249. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  250. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  251. package/dist/web/standalone/server.js +1 -1
  252. package/package.json +1 -1
  253. package/packages/mcp-server/dist/server.d.ts +12 -1
  254. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  255. package/packages/mcp-server/dist/server.js +90 -42
  256. package/packages/mcp-server/dist/server.js.map +1 -1
  257. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  258. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  259. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  260. package/packages/mcp-server/src/server.ts +110 -38
  261. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  262. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  263. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  264. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  265. package/packages/pi-ai/dist/models.custom.d.ts +105 -0
  266. package/packages/pi-ai/dist/models.custom.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/models.custom.js +97 -0
  268. package/packages/pi-ai/dist/models.custom.js.map +1 -1
  269. package/packages/pi-ai/dist/models.generated.d.ts +648 -140
  270. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  271. package/packages/pi-ai/dist/models.generated.js +867 -370
  272. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  273. package/packages/pi-ai/dist/models.generated.test.d.ts +2 -0
  274. package/packages/pi-ai/dist/models.generated.test.d.ts.map +1 -0
  275. package/packages/pi-ai/dist/models.generated.test.js +334 -0
  276. package/packages/pi-ai/dist/models.generated.test.js.map +1 -0
  277. package/packages/pi-ai/dist/models.test.js +105 -0
  278. package/packages/pi-ai/dist/models.test.js.map +1 -1
  279. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  280. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  281. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  282. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  283. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  284. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  285. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  286. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  287. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  288. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  289. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  290. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  291. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  292. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  293. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  294. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  295. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  296. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  297. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  298. package/packages/pi-ai/dist/types.d.ts +1 -1
  299. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  300. package/packages/pi-ai/dist/types.js.map +1 -1
  301. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +5 -1
  303. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  304. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts +2 -0
  305. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts.map +1 -0
  306. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +57 -0
  307. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -0
  308. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  309. package/packages/pi-ai/src/models.custom.ts +98 -0
  310. package/packages/pi-ai/src/models.generated.test.ts +373 -0
  311. package/packages/pi-ai/src/models.generated.ts +867 -370
  312. package/packages/pi-ai/src/models.test.ts +135 -0
  313. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  314. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  315. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  316. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  317. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  318. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  319. package/packages/pi-ai/src/types.ts +1 -0
  320. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +71 -0
  321. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +4 -1
  322. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  323. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  324. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  325. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  326. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  328. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  330. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  332. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  334. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  335. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  336. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  337. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  338. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  339. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/model-resolver.js +23 -18
  341. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  343. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  345. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
  347. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
  349. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
  351. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  353. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/sdk.js +47 -5
  355. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  357. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  358. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  359. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  360. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  361. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/index.js +1 -1
  363. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  365. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  367. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
  369. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  370. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  371. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  373. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  375. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  376. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  377. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  378. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +130 -12
  380. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  382. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +7 -2
  383. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  385. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  386. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  387. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -3
  389. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  390. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  391. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  392. package/packages/pi-coding-agent/package.json +1 -1
  393. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  394. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  395. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  396. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  397. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  398. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  399. package/packages/pi-coding-agent/src/core/model-resolver.ts +23 -18
  400. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
  401. package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
  402. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  403. package/packages/pi-coding-agent/src/core/sdk.ts +55 -9
  404. package/packages/pi-coding-agent/src/index.ts +1 -0
  405. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  406. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
  407. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  408. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  409. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +131 -12
  410. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -2
  411. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  412. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -3
  413. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  414. package/packages/pi-tui/dist/components/__tests__/editor.test.js +12 -0
  415. package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -1
  416. package/packages/pi-tui/dist/components/__tests__/input.test.js +12 -0
  417. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  418. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  419. package/packages/pi-tui/dist/keys.js +27 -0
  420. package/packages/pi-tui/dist/keys.js.map +1 -1
  421. package/packages/pi-tui/src/components/__tests__/editor.test.ts +18 -0
  422. package/packages/pi-tui/src/components/__tests__/input.test.ts +18 -0
  423. package/packages/pi-tui/src/keys.ts +32 -0
  424. package/pkg/package.json +1 -1
  425. package/src/resources/GSD-WORKFLOW.md +1 -1
  426. package/src/resources/agents/debugger.md +58 -0
  427. package/src/resources/agents/doc-writer.md +43 -0
  428. package/src/resources/agents/git-ops.md +56 -0
  429. package/src/resources/agents/javascript-pro.md +46 -271
  430. package/src/resources/agents/planner.md +55 -0
  431. package/src/resources/agents/refactorer.md +47 -0
  432. package/src/resources/agents/reviewer.md +48 -0
  433. package/src/resources/agents/security.md +59 -0
  434. package/src/resources/agents/tester.md +50 -0
  435. package/src/resources/agents/typescript-pro.md +41 -235
  436. package/src/resources/extensions/async-jobs/await-tool.test.ts +40 -7
  437. package/src/resources/extensions/async-jobs/await-tool.ts +7 -4
  438. package/src/resources/extensions/async-jobs/job-manager.ts +33 -3
  439. package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
  440. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +152 -13
  441. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
  442. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +301 -6
  443. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  444. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  445. package/src/resources/extensions/gsd/auto/loop.ts +134 -2
  446. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  447. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  448. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  449. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  450. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -0
  451. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  452. package/src/resources/extensions/gsd/auto-recovery.ts +10 -0
  453. package/src/resources/extensions/gsd/auto-start.ts +41 -7
  454. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  455. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  456. package/src/resources/extensions/gsd/auto.ts +97 -20
  457. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  458. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -10
  459. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  460. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  461. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  462. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  463. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  464. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  465. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  466. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  467. package/src/resources/extensions/gsd/commands-handlers.ts +5 -1
  468. package/src/resources/extensions/gsd/context-injector.ts +1 -1
  469. package/src/resources/extensions/gsd/custom-workflow-engine.ts +4 -8
  470. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  471. package/src/resources/extensions/gsd/definition-io.ts +18 -0
  472. package/src/resources/extensions/gsd/dispatch-guard.ts +23 -1
  473. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  474. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +6 -3
  475. package/src/resources/extensions/gsd/error-classifier.ts +5 -2
  476. package/src/resources/extensions/gsd/forensics.ts +23 -7
  477. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  478. package/src/resources/extensions/gsd/git-service.ts +11 -8
  479. package/src/resources/extensions/gsd/gitignore.ts +12 -6
  480. package/src/resources/extensions/gsd/gsd-db.ts +105 -6
  481. package/src/resources/extensions/gsd/guided-flow.ts +5 -10
  482. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  483. package/src/resources/extensions/gsd/key-manager.ts +2 -0
  484. package/src/resources/extensions/gsd/metrics.ts +12 -1
  485. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  486. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  487. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  488. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  489. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  490. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  491. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  492. package/src/resources/extensions/gsd/preferences-skills.ts +2 -36
  493. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  494. package/src/resources/extensions/gsd/preferences.ts +19 -6
  495. package/src/resources/extensions/gsd/prompt-loader.ts +6 -1
  496. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  497. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  498. package/src/resources/extensions/gsd/prompts/discuss.md +123 -12
  499. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  500. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  501. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  502. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  503. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  504. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  505. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  506. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  507. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  508. package/src/resources/extensions/gsd/state.ts +33 -2
  509. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +27 -0
  510. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  511. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  512. package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
  513. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  514. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  515. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  516. package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
  517. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +53 -0
  518. package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
  519. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  520. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  521. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +104 -0
  522. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  523. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  524. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  525. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  526. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +107 -5
  527. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  528. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  529. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  530. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +8 -6
  531. package/src/resources/extensions/gsd/tests/key-manager.test.ts +63 -0
  532. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +54 -0
  533. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  534. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  535. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  536. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  537. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  538. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  539. package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +62 -0
  540. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +34 -0
  541. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  542. package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
  543. package/src/resources/extensions/gsd/tests/preferences.test.ts +53 -0
  544. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +96 -1
  545. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  546. package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
  547. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  548. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
  549. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +97 -0
  550. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  551. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  552. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +41 -0
  553. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  554. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  555. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  556. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  557. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  558. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
  559. package/src/resources/extensions/gsd/types.ts +26 -0
  560. package/src/resources/extensions/gsd/workflow-projections.ts +8 -0
  561. package/src/resources/extensions/gsd/worktree-manager.ts +29 -3
  562. package/src/resources/extensions/gsd/write-intercept.ts +10 -1
  563. package/src/resources/extensions/ollama/index.ts +17 -8
  564. package/src/resources/extensions/ollama/ollama-client.ts +35 -6
  565. package/src/resources/extensions/ollama/ollama-discovery.ts +37 -6
  566. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  567. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +54 -0
  568. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  569. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  570. package/src/resources/extensions/subagent/agents.ts +10 -0
  571. package/src/resources/extensions/subagent/index.ts +18 -0
  572. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  573. package/src/resources/skills/create-skill/SKILL.md +2 -0
  574. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  575. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  576. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  577. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → NzO79SOz9jHX-VY5-0t2O}/_buildManifest.js +0 -0
  578. /package/dist/web/standalone/.next/static/{nPky_WQC28aBD77eZsRAB → NzO79SOz9jHX-VY5-0t2O}/_ssgManifest.js +0 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Regression test for the #unconfigured-models fix: findInitialModel() must
3
+ * skip the saved default when its provider has no working auth, rather than
4
+ * returning an unusable model that every selector surface would display as
5
+ * "current".
6
+ */
7
+
8
+ import test from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { findInitialModel } from "./model-resolver.js";
11
+
12
+ function fakeRegistry(options: {
13
+ models: Array<{ provider: string; id: string }>;
14
+ readyProviders: Set<string>;
15
+ }) {
16
+ const fullModels = options.models.map((m) => ({
17
+ ...m,
18
+ name: m.id,
19
+ api: "anthropic-messages",
20
+ baseUrl: "",
21
+ reasoning: false,
22
+ input: ["text"],
23
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
24
+ contextWindow: 128_000,
25
+ maxTokens: 4096,
26
+ }));
27
+ const available = fullModels.filter((m) => options.readyProviders.has(m.provider));
28
+ return {
29
+ find(provider: string, id: string) {
30
+ return fullModels.find((m) => m.provider === provider && m.id === id);
31
+ },
32
+ getAvailable() {
33
+ return available;
34
+ },
35
+ isProviderRequestReady(provider: string) {
36
+ return options.readyProviders.has(provider);
37
+ },
38
+ };
39
+ }
40
+
41
+ test("findInitialModel skips saved default when provider has no auth", async () => {
42
+ // User saved xai/grok-4 as default, but XAI_API_KEY is unset so xai is
43
+ // in the registry but not ready. Previously findInitialModel() step 3
44
+ // returned xai anyway — now it must fall through to step 4 and pick
45
+ // an available model.
46
+ const registry = fakeRegistry({
47
+ models: [
48
+ { provider: "xai", id: "grok-4-fast-non-reasoning" },
49
+ { provider: "anthropic", id: "claude-opus-4-6" },
50
+ ],
51
+ readyProviders: new Set(["anthropic"]),
52
+ });
53
+
54
+ const result = await findInitialModel({
55
+ scopedModels: [],
56
+ isContinuing: false,
57
+ defaultProvider: "xai",
58
+ defaultModelId: "grok-4-fast-non-reasoning",
59
+ modelRegistry: registry as any,
60
+ });
61
+
62
+ assert.ok(result.model, "a model must be returned");
63
+ assert.equal(result.model!.provider, "anthropic", "unauth'd saved default must be skipped");
64
+ });
65
+
66
+ test("findInitialModel keeps saved default when provider has auth", async () => {
67
+ const registry = fakeRegistry({
68
+ models: [
69
+ { provider: "anthropic", id: "claude-opus-4-6" },
70
+ { provider: "openai", id: "gpt-5.4" },
71
+ ],
72
+ readyProviders: new Set(["anthropic", "openai"]),
73
+ });
74
+
75
+ const result = await findInitialModel({
76
+ scopedModels: [],
77
+ isContinuing: false,
78
+ defaultProvider: "openai",
79
+ defaultModelId: "gpt-5.4",
80
+ modelRegistry: registry as any,
81
+ });
82
+
83
+ assert.equal(result.model?.provider, "openai");
84
+ assert.equal(result.model?.id, "gpt-5.4");
85
+ });
@@ -37,6 +37,7 @@ const defaultModelPerProvider: Record<KnownProvider, string> = {
37
37
  "opencode-go": "kimi-k2.5",
38
38
  "kimi-coding": "kimi-k2-thinking",
39
39
  "alibaba-coding-plan": "qwen3.5-plus",
40
+ "alibaba-dashscope": "qwen3.5-plus",
40
41
  ollama: "llama3.1:8b",
41
42
  "ollama-cloud": "qwen3:32b",
42
43
  };
@@ -504,27 +505,31 @@ export async function findInitialModel(options: {
504
505
 
505
506
  // 3. Try saved default from settings
506
507
  if (defaultProvider && defaultModelId) {
507
- const found = modelRegistry.find(defaultProvider, defaultModelId);
508
- if (found) {
509
- // Check if the provider's recommended default is a higher-capability variant
510
- // of the saved model (e.g. saved "claude-opus-4-6" vs recommended "claude-opus-4-6-extended").
511
- // If so, prefer the recommended variant to avoid using a smaller context window (#1125).
512
- const recommendedId = defaultModelPerProvider[defaultProvider as KnownProvider];
513
- if (recommendedId && recommendedId !== defaultModelId && recommendedId.startsWith(defaultModelId)) {
514
- const recommended = modelRegistry.find(defaultProvider, recommendedId);
515
- if (recommended) {
516
- model = recommended;
517
- if (defaultThinkingLevel) {
518
- thinkingLevel = defaultThinkingLevel;
508
+ // Guard against stale settings defaults: only use the saved provider/model
509
+ // if the provider is actually request-ready (auth/OAuth/CLI ready).
510
+ if (modelRegistry.isProviderRequestReady(defaultProvider)) {
511
+ const found = modelRegistry.find(defaultProvider, defaultModelId);
512
+ if (found) {
513
+ // Check if the provider's recommended default is a higher-capability variant
514
+ // of the saved model (e.g. saved "claude-opus-4-6" vs recommended "claude-opus-4-6-extended").
515
+ // If so, prefer the recommended variant to avoid using a smaller context window (#1125).
516
+ const recommendedId = defaultModelPerProvider[defaultProvider as KnownProvider];
517
+ if (recommendedId && recommendedId !== defaultModelId && recommendedId.startsWith(defaultModelId)) {
518
+ const recommended = modelRegistry.find(defaultProvider, recommendedId);
519
+ if (recommended) {
520
+ model = recommended;
521
+ if (defaultThinkingLevel) {
522
+ thinkingLevel = defaultThinkingLevel;
523
+ }
524
+ return { model, thinkingLevel, fallbackMessage: undefined };
519
525
  }
520
- return { model, thinkingLevel, fallbackMessage: undefined };
521
526
  }
527
+ model = found;
528
+ if (defaultThinkingLevel) {
529
+ thinkingLevel = defaultThinkingLevel;
530
+ }
531
+ return { model, thinkingLevel, fallbackMessage: undefined };
522
532
  }
523
- model = found;
524
- if (defaultThinkingLevel) {
525
- thinkingLevel = defaultThinkingLevel;
526
- }
527
- return { model, thinkingLevel, fallbackMessage: undefined };
528
533
  }
529
534
  }
530
535
 
@@ -171,6 +171,25 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
171
171
  const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
172
172
  assert.ok(retryStart, "Regular 429 should enter backoff retry");
173
173
  });
174
+
175
+ it("classifies OpenRouter credit affordability errors as quota_exhausted", async () => {
176
+ const { deps, emittedEvents } = createMockDeps({
177
+ model: createMockModel("openrouter", "openai/gpt-5-pro"),
178
+ markUsageLimitReachedResult: false,
179
+ fallbackResult: null,
180
+ });
181
+
182
+ const handler = new RetryHandler(deps);
183
+ const msg = errorMessage(
184
+ "402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.",
185
+ );
186
+
187
+ const result = await handler.handleRetryableError(msg);
188
+
189
+ assert.equal(result, true, "affordability error should trigger credit-aware retry");
190
+ const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
191
+ assert.ok(retryStart, "Expected immediate retry after reducing max tokens");
192
+ });
174
193
  });
175
194
 
176
195
  describe("long-context model downgrade", () => {
@@ -271,6 +290,61 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
271
290
  });
272
291
  });
273
292
 
293
+ describe("credit-aware maxTokens retry", () => {
294
+ it("reduces maxTokens on same model when provider reports affordable cap", async () => {
295
+ const expensiveModel = createMockModel("openrouter", "openai/gpt-5-pro");
296
+ expensiveModel.maxTokens = 128000;
297
+
298
+ const { deps, emittedEvents, onModelChangeFn } = createMockDeps({
299
+ model: expensiveModel,
300
+ markUsageLimitReachedResult: false,
301
+ fallbackResult: null,
302
+ });
303
+
304
+ const handler = new RetryHandler(deps);
305
+ const msg = errorMessage(
306
+ "402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.",
307
+ );
308
+
309
+ const result = await handler.handleRetryableError(msg);
310
+ assert.equal(result, true, "should retry after reducing maxTokens");
311
+
312
+ const setModelCalls = (deps.agent.setModel as any).mock.calls;
313
+ assert.equal(setModelCalls.length, 1, "should apply one model downgrade");
314
+ const downgraded = setModelCalls[0].arguments[0] as Model<Api>;
315
+ assert.equal(downgraded.provider, "openrouter");
316
+ assert.equal(downgraded.id, "openai/gpt-5-pro");
317
+ assert.equal(downgraded.maxTokens, 297, "expected affordability cap with safety buffer");
318
+
319
+ assert.equal(onModelChangeFn.mock.calls.length, 1, "should notify about model update");
320
+ const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
321
+ assert.ok(switchEvent, "should emit model-adjustment event");
322
+ assert.ok(
323
+ String(switchEvent?.reason || "").includes("credit-aware retry"),
324
+ "switch reason should mention credit-aware retry",
325
+ );
326
+ });
327
+
328
+ it("does not mark credentials in cooldown for affordability quota errors", async () => {
329
+ const expensiveModel = createMockModel("openrouter", "openai/gpt-5-pro");
330
+ expensiveModel.maxTokens = 128000;
331
+
332
+ const { deps, markUsageLimitReached } = createMockDeps({
333
+ model: expensiveModel,
334
+ markUsageLimitReachedResult: false,
335
+ fallbackResult: null,
336
+ });
337
+
338
+ const handler = new RetryHandler(deps);
339
+ const msg = errorMessage(
340
+ "402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.",
341
+ );
342
+
343
+ await handler.handleRetryableError(msg);
344
+ assert.equal(markUsageLimitReached.mock.calls.length, 0, "quota error should skip credential cooldown");
345
+ });
346
+ });
347
+
274
348
  describe("isRetryableError", () => {
275
349
  it("considers long-context entitlement error as retryable", () => {
276
350
  const { deps } = createMockDeps();
@@ -291,6 +365,15 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
291
365
  );
292
366
  assert.equal(handler.isRetryableError(msg), false);
293
367
  });
368
+
369
+ it("considers OpenRouter affordability credit errors as retryable", () => {
370
+ const { deps } = createMockDeps();
371
+ const handler = new RetryHandler(deps);
372
+ const msg = errorMessage(
373
+ "402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.",
374
+ );
375
+ assert.equal(handler.isRetryableError(msg), true);
376
+ });
294
377
  });
295
378
 
296
379
  describe("third-party block claude-code fallback (#3772)", () => {
@@ -116,7 +116,7 @@ export class RetryHandler {
116
116
  // generated error from getApiKey() when credentials are in a backoff window.
117
117
  // Re-entering the retry handler for that message creates a cascade of empty
118
118
  // error entries in the session file, breaking resume (#3429).
119
- return /overloaded|rate.?limit|too many requests|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|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i.test(
119
+ return /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(
120
120
  err,
121
121
  );
122
122
  }
@@ -158,6 +158,14 @@ export class RetryHandler {
158
158
  const isRateLimit = errorType === "rate_limit";
159
159
  const isQuotaError = errorType === "quota_exhausted";
160
160
 
161
+ // Credit-aware retry (OpenRouter-style 402 affordability errors):
162
+ // when provider reports "can only afford N", lower maxTokens and retry
163
+ // on the same model before rotating credentials/providers.
164
+ if (isQuotaError) {
165
+ const adjusted = this._tryAffordableMaxTokensRetry(message, retryGeneration);
166
+ if (adjusted) return true;
167
+ }
168
+
161
169
  // Credential rotation — only for transient rate limits (#3430).
162
170
  // Quota errors ("Extra usage is required") are account-level billing
163
171
  // gates; rotating to another credential on the same account won't help
@@ -409,12 +417,63 @@ export class RetryHandler {
409
417
  // Long-context entitlement errors are billing gates, not transient rate limits.
410
418
  // Must be checked before the generic 429/rate_limit regex.
411
419
  if (/extra usage is required|long context required/i.test(err)) return "quota_exhausted";
420
+ if (/requires more credits|can only afford|insufficient credits|not enough credits|credit balance/i.test(err))
421
+ return "quota_exhausted";
412
422
  if (/quota|billing|exceeded.*limit|usage.*limit/i.test(err)) return "quota_exhausted";
413
423
  if (/rate.?limit|too many requests|429/i.test(err)) return "rate_limit";
414
424
  if (/500|502|503|504|server.?error|internal.?error|service.?unavailable/i.test(err)) return "server_error";
415
425
  return "unknown";
416
426
  }
417
427
 
428
+ /**
429
+ * Attempt a same-model retry by reducing maxTokens when provider reports
430
+ * an affordability cap (e.g., "can only afford 329").
431
+ */
432
+ private _tryAffordableMaxTokensRetry(message: AssistantMessage, retryGeneration: number): boolean {
433
+ const currentModel = this._deps.getModel();
434
+ if (!currentModel || !message.errorMessage) return false;
435
+
436
+ // Example: "can only afford 329"
437
+ const match = message.errorMessage.match(/can only afford\s+([\d,]+)/i);
438
+ if (!match?.[1]) return false;
439
+
440
+ const affordable = Number.parseInt(match[1].replace(/,/g, ""), 10);
441
+ if (!Number.isFinite(affordable) || affordable <= 0) return false;
442
+
443
+ // Leave a small buffer so slight input variance doesn't immediately re-fail.
444
+ const safetyBuffer = Math.min(64, Math.max(16, Math.floor(affordable * 0.1)));
445
+ const targetMaxTokens = Math.max(64, affordable - safetyBuffer);
446
+ const downgradedMaxTokens = Math.min(currentModel.maxTokens, targetMaxTokens);
447
+ if (downgradedMaxTokens >= currentModel.maxTokens) return false;
448
+
449
+ const downgradedModel = {
450
+ ...currentModel,
451
+ maxTokens: downgradedMaxTokens,
452
+ };
453
+
454
+ this._deps.agent.setModel(downgradedModel);
455
+ this._deps.onModelChange(downgradedModel);
456
+ this._removeLastAssistantError();
457
+
458
+ this._deps.emit({
459
+ type: "fallback_provider_switch",
460
+ from: `${currentModel.provider}/${currentModel.id} (maxTokens=${currentModel.maxTokens})`,
461
+ to: `${downgradedModel.provider}/${downgradedModel.id} (maxTokens=${downgradedModel.maxTokens})`,
462
+ reason: `credit-aware retry: provider affordable cap ${affordable} tokens`,
463
+ });
464
+
465
+ this._deps.emit({
466
+ type: "auto_retry_start",
467
+ attempt: this._retryAttempt + 1,
468
+ maxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,
469
+ delayMs: 0,
470
+ errorMessage: `${message.errorMessage} (reducing max tokens)`,
471
+ });
472
+
473
+ this._scheduleContinue(retryGeneration);
474
+ return true;
475
+ }
476
+
418
477
  /**
419
478
  * Attempt to downgrade a long-context model (e.g. claude-opus-4-6[1m]) to its
420
479
  * base model (claude-opus-4-6) when the account lacks the long-context billing
@@ -0,0 +1,89 @@
1
+ // pi-coding-agent / CredentialCooldownError unit tests
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ import { describe, it } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { CredentialCooldownError } from "./sdk.js";
7
+
8
+ // ─── CredentialCooldownError ──────────────────────────────────────────────────
9
+
10
+ describe("CredentialCooldownError", () => {
11
+ it("is an instance of Error", () => {
12
+ const err = new CredentialCooldownError("anthropic");
13
+ assert.ok(err instanceof Error);
14
+ });
15
+
16
+ it("has name set to CredentialCooldownError", () => {
17
+ const err = new CredentialCooldownError("anthropic");
18
+ assert.equal(err.name, "CredentialCooldownError");
19
+ });
20
+
21
+ it("has code set to AUTH_COOLDOWN", () => {
22
+ const err = new CredentialCooldownError("anthropic");
23
+ assert.equal(err.code, "AUTH_COOLDOWN");
24
+ });
25
+
26
+ it("message includes the provider name", () => {
27
+ const err = new CredentialCooldownError("openai");
28
+ assert.ok(
29
+ err.message.includes("openai"),
30
+ `Expected message to include provider "openai", got: ${err.message}`,
31
+ );
32
+ });
33
+
34
+ it("message mentions cooldown window", () => {
35
+ const err = new CredentialCooldownError("anthropic");
36
+ assert.ok(
37
+ /cooldown window/i.test(err.message),
38
+ `Expected message to mention "cooldown window", got: ${err.message}`,
39
+ );
40
+ });
41
+
42
+ it("retryAfterMs is undefined when not provided", () => {
43
+ const err = new CredentialCooldownError("anthropic");
44
+ assert.equal(err.retryAfterMs, undefined);
45
+ });
46
+
47
+ it("retryAfterMs holds the provided value when specified", () => {
48
+ const err = new CredentialCooldownError("anthropic", 30_000);
49
+ assert.equal(err.retryAfterMs, 30_000);
50
+ });
51
+
52
+ it("retryAfterMs is 0 when explicitly passed as 0", () => {
53
+ const err = new CredentialCooldownError("anthropic", 0);
54
+ assert.equal(err.retryAfterMs, 0);
55
+ });
56
+
57
+ it("code property is readonly and always AUTH_COOLDOWN regardless of provider", () => {
58
+ for (const provider of ["anthropic", "openai", "google", "openrouter"]) {
59
+ const err = new CredentialCooldownError(provider);
60
+ assert.equal(err.code, "AUTH_COOLDOWN", `code should be AUTH_COOLDOWN for provider "${provider}"`);
61
+ }
62
+ });
63
+
64
+ it("different providers produce different messages", () => {
65
+ const err1 = new CredentialCooldownError("anthropic");
66
+ const err2 = new CredentialCooldownError("openai");
67
+ assert.notEqual(err1.message, err2.message);
68
+ });
69
+
70
+ it("can be caught as an Error in a try/catch", () => {
71
+ let caught: unknown;
72
+ try {
73
+ throw new CredentialCooldownError("anthropic", 5_000);
74
+ } catch (e) {
75
+ caught = e;
76
+ }
77
+ assert.ok(caught instanceof Error);
78
+ assert.ok(caught instanceof CredentialCooldownError);
79
+ assert.equal((caught as CredentialCooldownError).retryAfterMs, 5_000);
80
+ });
81
+
82
+ it("code property is detectable via plain object check (cross-process pattern)", () => {
83
+ const err = new CredentialCooldownError("anthropic", 15_000);
84
+ // Simulate cross-process serialization: only plain properties survive JSON round-trip
85
+ const plain = { code: err.code, retryAfterMs: err.retryAfterMs, message: err.message };
86
+ assert.equal(plain.code, "AUTH_COOLDOWN");
87
+ assert.equal(plain.retryAfterMs, 15_000);
88
+ });
89
+ });
@@ -1,4 +1,24 @@
1
1
  import { join } from "node:path";
2
+
3
+ /**
4
+ * Structured error thrown when all credentials for a provider are in a
5
+ * backoff window. Carries typed metadata so callers (e.g. the auto-loop)
6
+ * can make informed retry decisions instead of string-matching the message.
7
+ */
8
+ export class CredentialCooldownError extends Error {
9
+ readonly code = "AUTH_COOLDOWN" as const;
10
+ /** Milliseconds until the earliest credential becomes available, or undefined if unknown. */
11
+ readonly retryAfterMs: number | undefined;
12
+
13
+ constructor(provider: string, retryAfterMs?: number) {
14
+ super(
15
+ `All credentials for "${provider}" are in a cooldown window. ` +
16
+ `Please wait a moment and try again, or switch to a different provider.`,
17
+ );
18
+ this.name = "CredentialCooldownError";
19
+ this.retryAfterMs = retryAfterMs;
20
+ }
21
+ }
2
22
  import { Agent, type AgentMessage, type ThinkingLevel } from "@gsd/pi-agent-core";
3
23
  import type { Message, Model } from "@gsd/pi-ai";
4
24
  import { getAgentDir, getDocsPath } from "../config.js";
@@ -199,6 +219,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
199
219
  time("resourceLoader.reload");
200
220
  }
201
221
 
222
+ // Flush provider registrations queued during extension loading so that
223
+ // extension models (e.g. pi-claude-cli) are visible in the registry before
224
+ // findInitialModel() runs. bindCore() repeats this flush as a safety net
225
+ // for any late-arriving registrations.
226
+ const { runtime: extensionRuntime } = resourceLoader.getExtensions();
227
+ for (const { name, config } of extensionRuntime.pendingProviderRegistrations) {
228
+ modelRegistry.registerProvider(name, config);
229
+ }
230
+ extensionRuntime.pendingProviderRegistrations = [];
231
+
202
232
  // Check if session has existing data to restore
203
233
  const existingSession = sessionManager.buildSessionContext();
204
234
  const hasExistingSession = existingSession.messages.length > 0;
@@ -363,8 +393,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
363
393
 
364
394
  // Retry key resolution with backoff to handle transient network failures
365
395
  // (e.g., OAuth token refresh failing due to brief connectivity loss).
396
+ // When credentials are in a cooldown window (e.g., after a 429), wait
397
+ // for the backoff to expire instead of using fixed delays that are
398
+ // shorter than the cooldown duration.
366
399
  const maxAttempts = 3;
367
400
  const baseDelayMs = 2000;
401
+ const maxCooldownWaitMs = 60_000; // Don't wait longer than 60s (skip quota-exhausted 30min backoffs)
368
402
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
369
403
  const key = await modelRegistry.getApiKeyForProvider(resolvedProvider);
370
404
  if (key) return key;
@@ -379,7 +413,21 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
379
413
  const isOAuth = model && modelRegistry.isUsingOAuth(model);
380
414
  if (!hasAuth && !isOAuth) break;
381
415
 
382
- // Wait with exponential backoff before retrying
416
+ // If credentials are in a cooldown window, wait for the earliest
417
+ // one to expire rather than using a fixed delay that's too short.
418
+ const backoffExpiry = modelRegistry.authStorage.getEarliestBackoffExpiry(resolvedProvider);
419
+ if (backoffExpiry !== undefined) {
420
+ const waitMs = backoffExpiry - Date.now() + 500; // 500ms buffer
421
+ if (waitMs > 0 && waitMs <= maxCooldownWaitMs) {
422
+ await new Promise(resolve => setTimeout(resolve, waitMs));
423
+ continue; // Retry immediately after cooldown clears
424
+ }
425
+ if (waitMs > maxCooldownWaitMs) {
426
+ break; // Quota-exhausted or very long backoff — don't block
427
+ }
428
+ }
429
+
430
+ // Standard exponential backoff for non-cooldown transient failures
383
431
  await new Promise(resolve => setTimeout(resolve, baseDelayMs * attempt));
384
432
  }
385
433
 
@@ -390,10 +438,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
390
438
  // the retry handler and creating cascading error entries (#3429).
391
439
  const hasAuth = modelRegistry.authStorage.hasAuth(resolvedProvider);
392
440
  if (hasAuth) {
393
- throw new Error(
394
- `All credentials for "${resolvedProvider}" are in a cooldown window. ` +
395
- `Please wait a moment and try again, or switch to a different provider.`,
396
- );
441
+ const expiry = modelRegistry.authStorage.getEarliestBackoffExpiry(resolvedProvider);
442
+ const retryAfterMs = expiry !== undefined ? Math.max(0, expiry - Date.now()) : undefined;
443
+ throw new CredentialCooldownError(resolvedProvider, retryAfterMs);
397
444
  }
398
445
  const model = agent.state.model;
399
446
  const isOAuth = model && modelRegistry.isUsingOAuth(model);
@@ -401,10 +448,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
401
448
  // If credentials exist but are all in a backoff window (quota / rate-limit),
402
449
  // surface a specific message instead of the misleading "Authentication failed".
403
450
  if (modelRegistry.authStorage.areAllCredentialsBackedOff(resolvedProvider)) {
404
- throw new Error(
405
- `All credentials for "${resolvedProvider}" are in a cooldown window. ` +
406
- `Please wait a moment and try again, or switch to a different provider.`,
407
- );
451
+ const expiry = modelRegistry.authStorage.getEarliestBackoffExpiry(resolvedProvider);
452
+ const retryAfterMs = expiry !== undefined ? Math.max(0, expiry - Date.now()) : undefined;
453
+ throw new CredentialCooldownError(resolvedProvider, retryAfterMs);
408
454
  }
409
455
  throw new Error(
410
456
  `Authentication failed for "${resolvedProvider}". ` +
@@ -176,6 +176,7 @@ export { DefaultResourceLoader } from "./core/resource-loader.js";
176
176
  export {
177
177
  type CreateAgentSessionOptions,
178
178
  type CreateAgentSessionResult,
179
+ CredentialCooldownError,
179
180
  // Factory
180
181
  createAgentSession,
181
182
  createBashTool,
@@ -0,0 +1,24 @@
1
+ import { describe, test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { buildAuthUrlPresentation } from "../login-dialog.js";
4
+
5
+ describe("LoginDialogComponent", () => {
6
+ test("shows the full OAuth URL when the hyperlink label is truncated", () => {
7
+ const presentation = buildAuthUrlPresentation(
8
+ "https://auth.example.com/device?code=ABCD-1234&callback=oauth&state=needs-full-visibility",
9
+ 52,
10
+ );
11
+
12
+ assert.notEqual(
13
+ presentation.displayUrl,
14
+ "https://auth.example.com/device?code=ABCD-1234&callback=oauth&state=needs-full-visibility",
15
+ "narrow terminals should still truncate the hyperlink label",
16
+ );
17
+ assert.ok(presentation.fullUrlLines.length > 1, "truncated URLs should expose wrapped full-url lines");
18
+ assert.match(presentation.fullUrlLines[0] ?? "", /https:\/\/auth\.example\.com\/device\?code=ABCD-1234&/);
19
+ assert.match(
20
+ presentation.fullUrlLines[presentation.fullUrlLines.length - 1] ?? "",
21
+ /state=needs-full-visibility/,
22
+ );
23
+ });
24
+ });
@@ -27,6 +27,26 @@ function renderTool(
27
27
  return stripAnsi(component.render(120).join("\n"));
28
28
  }
29
29
 
30
+ function renderToolCollapsed(
31
+ toolName: string,
32
+ args: Record<string, unknown>,
33
+ result?: {
34
+ content: Array<{ type: string; text?: string }>;
35
+ isError: boolean;
36
+ details?: Record<string, unknown>;
37
+ },
38
+ ): string {
39
+ const component = new ToolExecutionComponent(
40
+ toolName,
41
+ args,
42
+ {},
43
+ undefined,
44
+ { requestRender() {} } as any,
45
+ );
46
+ if (result) component.updateResult(result);
47
+ return stripAnsi(component.render(120).join("\n"));
48
+ }
49
+
30
50
  describe("ToolExecutionComponent", () => {
31
51
  test("renders capitalized Claude Code Bash tool names with bash output instead of generic args JSON", () => {
32
52
  const rendered = renderTool(
@@ -51,4 +71,56 @@ describe("ToolExecutionComponent", () => {
51
71
  assert.match(rendered, /hello/);
52
72
  assert.match(rendered, /world/);
53
73
  });
74
+
75
+ test("generic fallback strips mcp__<server>__ prefix and shows server·tool title", () => {
76
+ const rendered = renderTool(
77
+ "mcp__context7__resolve_library_id",
78
+ { name: "react" },
79
+ { content: [{ type: "text", text: "react@18.3.1" }], isError: false },
80
+ );
81
+
82
+ assert.match(rendered, /context7\u00b7resolve_library_id/);
83
+ assert.doesNotMatch(rendered, /mcp__/);
84
+ assert.match(rendered, /name="react"/);
85
+ assert.match(rendered, /react@18\.3\.1/);
86
+ });
87
+
88
+ test("generic fallback renders compact key=value args for primitive args", () => {
89
+ const rendered = renderTool(
90
+ "some_unknown_tool",
91
+ { count: 3, enabled: true, label: "hello" },
92
+ );
93
+
94
+ assert.match(rendered, /some_unknown_tool/);
95
+ assert.match(rendered, /count=3/);
96
+ assert.match(rendered, /enabled=true/);
97
+ assert.match(rendered, /label="hello"/);
98
+ assert.doesNotMatch(rendered, /^\{$/m);
99
+ });
100
+
101
+ test("generic fallback truncates long output when collapsed", () => {
102
+ const longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join("\n");
103
+ const rendered = renderToolCollapsed(
104
+ "mcp__demo__do_thing",
105
+ { ok: true },
106
+ { content: [{ type: "text", text: longOutput }], isError: false },
107
+ );
108
+
109
+ assert.match(rendered, /line 1\b/);
110
+ assert.match(rendered, /line 10\b/);
111
+ assert.doesNotMatch(rendered, /line 20\b/);
112
+ assert.match(rendered, /\(15 more lines/);
113
+ });
114
+
115
+ test("generic fallback falls back to truncated JSON for complex args", () => {
116
+ const rendered = renderTool(
117
+ "mcp__demo__nested",
118
+ { payload: { nested: { deeply: ["a", "b", "c"] } }, name: "x" },
119
+ );
120
+
121
+ assert.match(rendered, /demo\u00b7nested/);
122
+ // Multi-line JSON dump for the complex payload
123
+ assert.match(rendered, /"payload"/);
124
+ assert.match(rendered, /"nested"/);
125
+ });
54
126
  });