gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7

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 (473) hide show
  1. package/dist/headless.js +3 -1
  2. package/dist/mcp-server.js +6 -2
  3. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
  4. package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
  5. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  6. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
  9. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
  11. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  12. package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
  13. package/dist/resources/extensions/gsd/auto-start.js +35 -1
  14. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  16. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  17. package/dist/resources/extensions/gsd/auto.js +2 -2
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
  20. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  21. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +12 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
  26. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  31. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  32. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  33. package/dist/resources/extensions/gsd/detection.js +1 -1
  34. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  35. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  36. package/dist/resources/extensions/gsd/doctor.js +2 -1
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  41. package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
  42. package/dist/resources/extensions/gsd/notification-store.js +273 -0
  43. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  44. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  45. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  46. package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +7 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
  49. package/dist/resources/extensions/gsd/preferences.js +13 -2
  50. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  51. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  52. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  55. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  56. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  58. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  60. package/dist/resources/extensions/gsd/quick.js +19 -15
  61. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  62. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  63. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  64. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  65. package/dist/resources/extensions/gsd/state.js +100 -12
  66. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  67. package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
  68. package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
  69. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  71. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  74. package/dist/resources/extensions/gsd/triage-resolution.js +25 -9
  75. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  76. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  77. package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
  78. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
  79. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  80. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  81. package/dist/resources/extensions/gsd/worktree.js +9 -0
  82. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  88. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  89. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  106. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  107. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  108. package/dist/web/standalone/.next/server/app/index.html +1 -1
  109. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  116. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/dist/web/standalone/.next/static/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
  123. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  124. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  125. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  126. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  127. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  128. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  129. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  130. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  133. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  135. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  136. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  137. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  138. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  139. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  140. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  141. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  150. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  151. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  153. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  155. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  156. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  158. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  159. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  160. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  161. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  162. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  163. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  164. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  165. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  166. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  167. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  168. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  169. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  170. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  171. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  172. package/package.json +1 -1
  173. package/packages/pi-agent-core/dist/agent-loop.js +26 -9
  174. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  175. package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
  176. package/packages/pi-agent-core/src/agent-loop.ts +43 -12
  177. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  183. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  185. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  187. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
  190. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  197. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +28 -5
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  214. package/packages/pi-coding-agent/package.json +1 -1
  215. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  216. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  217. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  218. package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -1
  219. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  220. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  221. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  222. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  223. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +29 -4
  224. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  226. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
  227. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
  228. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
  229. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
  230. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
  231. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  232. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  233. package/packages/pi-tui/dist/components/image.js +4 -0
  234. package/packages/pi-tui/dist/components/image.js.map +1 -1
  235. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  236. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  237. package/packages/pi-tui/dist/components/image.test.js +32 -0
  238. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  239. package/packages/pi-tui/dist/components/loader.d.ts +4 -2
  240. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  241. package/packages/pi-tui/dist/components/loader.js +27 -9
  242. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  243. package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
  244. package/packages/pi-tui/dist/components/text.js +2 -0
  245. package/packages/pi-tui/dist/components/text.js.map +1 -1
  246. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/overlay-layout.js +12 -1
  248. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  249. package/packages/pi-tui/dist/tui.d.ts +4 -0
  250. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  251. package/packages/pi-tui/dist/tui.js +35 -0
  252. package/packages/pi-tui/dist/tui.js.map +1 -1
  253. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
  254. package/packages/pi-tui/src/components/image.test.ts +36 -0
  255. package/packages/pi-tui/src/components/image.ts +5 -0
  256. package/packages/pi-tui/src/components/loader.ts +27 -10
  257. package/packages/pi-tui/src/components/text.ts +1 -0
  258. package/packages/pi-tui/src/overlay-layout.ts +13 -1
  259. package/packages/pi-tui/src/tui.ts +34 -0
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
  262. package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
  263. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  264. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  266. package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
  267. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
  269. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  270. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  271. package/src/resources/extensions/gsd/auto-start.ts +38 -0
  272. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  273. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  274. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  275. package/src/resources/extensions/gsd/auto.ts +2 -1
  276. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  277. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
  278. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  279. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  280. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -1
  282. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
  283. package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
  284. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  285. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  286. package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
  287. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
  288. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  289. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  290. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  291. package/src/resources/extensions/gsd/detection.ts +1 -1
  292. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  293. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  294. package/src/resources/extensions/gsd/doctor.ts +2 -1
  295. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  296. package/src/resources/extensions/gsd/gsd-db.ts +13 -2
  297. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  298. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  299. package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
  300. package/src/resources/extensions/gsd/notification-store.ts +293 -0
  301. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  302. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  303. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  304. package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
  305. package/src/resources/extensions/gsd/preferences-types.ts +53 -0
  306. package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
  307. package/src/resources/extensions/gsd/preferences.ts +13 -2
  308. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  309. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  310. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  311. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  313. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  314. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  315. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  316. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  318. package/src/resources/extensions/gsd/quick.ts +20 -15
  319. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  320. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  321. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  322. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  323. package/src/resources/extensions/gsd/state.ts +101 -11
  324. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  325. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  326. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  327. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  328. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  329. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
  330. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  331. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  332. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  333. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  334. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  335. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  336. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  337. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  338. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  339. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  340. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  341. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  342. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  343. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  344. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  345. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  346. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +5 -3
  347. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  348. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  349. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  350. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  351. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  352. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  353. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  354. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +73 -0
  355. package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -0
  356. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  357. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  358. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  359. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  360. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  361. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  362. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +1197 -0
  363. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  364. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  365. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  366. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  367. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  368. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  369. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  370. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  373. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  374. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  375. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  376. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  377. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  378. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  379. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  380. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  381. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  382. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  383. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  384. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  385. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  386. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  387. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  388. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  389. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  390. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  391. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  392. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  393. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  394. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  395. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  396. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  397. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  398. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  399. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  400. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  401. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  402. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  403. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  404. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  405. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  406. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  407. package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
  408. package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
  409. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  410. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  411. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  412. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  413. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  414. package/src/resources/extensions/gsd/triage-resolution.ts +29 -10
  415. package/src/resources/extensions/gsd/types.ts +4 -0
  416. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  417. package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
  418. package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
  419. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
  420. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  421. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  422. package/src/resources/extensions/gsd/worktree.ts +10 -0
  423. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  424. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  425. package/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
  426. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  427. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  428. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  429. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  430. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  431. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  432. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  433. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  434. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  435. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  436. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  437. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  438. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  439. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  440. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  441. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  442. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  443. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  444. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  445. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  446. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  447. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  448. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  449. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  450. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  451. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  452. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  454. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  457. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  458. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  459. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  460. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  461. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  464. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  465. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  466. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  467. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  468. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  469. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  470. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  471. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  472. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  473. /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-coding-agent",
3
- "version": "2.64.0",
3
+ "version": "2.65.0",
4
4
  "description": "Coding agent CLI (vendored from pi-mono)",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -0,0 +1,64 @@
1
+ // GSD-2 — Regression tests for #3616: tool list persistence across newSession() calls
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ import test, { describe } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ const source = readFileSync(
10
+ join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
11
+ "utf-8",
12
+ );
13
+
14
+ describe("#3616 — newSession() must restore full tool set", () => {
15
+ test("newSession() calls _refreshToolRegistry with includeAllExtensionTools when cwd is unchanged", () => {
16
+ // Find the newSession method
17
+ const newSessionStart = source.indexOf("async newSession(options?:");
18
+ assert.ok(newSessionStart >= 0, "should find newSession method");
19
+
20
+ // Get the method body (up to the next top-level method)
21
+ const methodBody = source.slice(newSessionStart, newSessionStart + 3000);
22
+
23
+ // Verify the cwd-changed branch rebuilds tools
24
+ assert.ok(
25
+ methodBody.includes("if (this._cwd !== previousCwd)"),
26
+ "should have cwd-change guard",
27
+ );
28
+
29
+ // Verify the else branch exists and refreshes tools with includeAllExtensionTools
30
+ const elseIdx = methodBody.indexOf("} else {");
31
+ assert.ok(elseIdx >= 0, "should have else branch for cwd-unchanged case");
32
+
33
+ const elseBranch = methodBody.slice(elseIdx, elseIdx + 800);
34
+ assert.ok(
35
+ elseBranch.includes("_refreshToolRegistry"),
36
+ "else branch should call _refreshToolRegistry",
37
+ );
38
+ assert.ok(
39
+ elseBranch.includes("includeAllExtensionTools: true"),
40
+ "else branch should pass includeAllExtensionTools: true to restore narrowed tools",
41
+ );
42
+ });
43
+
44
+ test("newSession() references #3616 in the else-branch comment", () => {
45
+ const idx = source.indexOf("#3616");
46
+ assert.ok(idx >= 0, "source should reference issue #3616 for the tool restore fix");
47
+ });
48
+
49
+ test("agent.reset() does not clear _state.tools (tools persist across reset)", () => {
50
+ // This is a structural invariant — if reset() starts clearing tools,
51
+ // the newSession() refresh becomes the only defense against tool loss.
52
+ const agentSource = readFileSync(
53
+ join(process.cwd(), "packages/pi-agent-core/src/agent.ts"),
54
+ "utf-8",
55
+ );
56
+ const resetStart = agentSource.indexOf("reset()");
57
+ assert.ok(resetStart >= 0, "should find reset() method");
58
+ const resetBody = agentSource.slice(resetStart, resetStart + 400);
59
+ assert.ok(
60
+ !resetBody.includes("tools"),
61
+ "reset() should NOT touch _state.tools — tools are managed by agent-session",
62
+ );
63
+ });
64
+ });
@@ -1577,6 +1577,16 @@ export class AgentSession {
1577
1577
  activeToolNames: this.getActiveToolNames(),
1578
1578
  includeAllExtensionTools: true,
1579
1579
  });
1580
+ } else {
1581
+ // Even when cwd hasn't changed, restore the full tool set (#3616).
1582
+ // Extensions (e.g., discuss flows) may narrow the active tool list
1583
+ // via setActiveTools() during a session. Without this refresh, the
1584
+ // narrowed set persists into the next session — causing tools like
1585
+ // gsd_plan_slice to be missing from auto-mode subagent sessions.
1586
+ this._refreshToolRegistry({
1587
+ activeToolNames: this.getActiveToolNames(),
1588
+ includeAllExtensionTools: true,
1589
+ });
1580
1590
  }
1581
1591
 
1582
1592
  // Run setup callback if provided (e.g., to append initial messages)
@@ -0,0 +1,42 @@
1
+ // GSD-2 — Regression test for #3616: reload() must reset jiti extension loader cache
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ import test, { describe } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ const source = readFileSync(
10
+ join(process.cwd(), "packages/pi-coding-agent/src/core/resource-loader.ts"),
11
+ "utf-8",
12
+ );
13
+
14
+ describe("#3616 — reload() must invalidate jiti module cache", () => {
15
+ test("resource-loader imports resetExtensionLoaderCache from loader.js", () => {
16
+ assert.ok(
17
+ source.includes("resetExtensionLoaderCache"),
18
+ "resource-loader.ts should import resetExtensionLoaderCache",
19
+ );
20
+ assert.ok(
21
+ source.includes('from "./extensions/loader.js"'),
22
+ "resetExtensionLoaderCache should be imported from extensions/loader.js",
23
+ );
24
+ });
25
+
26
+ test("reload() calls resetExtensionLoaderCache before loadExtensions", () => {
27
+ const reloadStart = source.indexOf("async reload(): Promise<void>");
28
+ assert.ok(reloadStart >= 0, "should find reload() method");
29
+ const reloadBody = source.slice(reloadStart, reloadStart + 4000);
30
+
31
+ const resetIdx = reloadBody.indexOf("resetExtensionLoaderCache()");
32
+ assert.ok(resetIdx >= 0, "reload() should call resetExtensionLoaderCache()");
33
+
34
+ const loadIdx = reloadBody.indexOf("loadExtensions(");
35
+ assert.ok(loadIdx >= 0, "reload() should call loadExtensions");
36
+
37
+ assert.ok(
38
+ resetIdx < loadIdx,
39
+ "resetExtensionLoaderCache() must be called BEFORE loadExtensions to ensure fresh modules",
40
+ );
41
+ });
42
+ });
@@ -9,7 +9,7 @@ import type { ResourceCollision, ResourceDiagnostic } from "./diagnostics.js";
9
9
  export type { ResourceCollision, ResourceDiagnostic } from "./diagnostics.js";
10
10
 
11
11
  import { createEventBus, type EventBus } from "./event-bus.js";
12
- import { createExtensionRuntime, loadExtensionFromFactory, loadExtensions } from "./extensions/loader.js";
12
+ import { createExtensionRuntime, loadExtensionFromFactory, loadExtensions, resetExtensionLoaderCache } from "./extensions/loader.js";
13
13
  import type { Extension, ExtensionFactory, ExtensionRuntime, LoadExtensionsResult } from "./extensions/types.js";
14
14
  import { DefaultPackageManager, type PathMetadata } from "./package-manager.js";
15
15
  import type { PromptTemplate } from "./prompt-templates.js";
@@ -320,6 +320,10 @@ export class DefaultResourceLoader implements ResourceLoader {
320
320
  }
321
321
 
322
322
  async reload(): Promise<void> {
323
+ // Invalidate the shared jiti module cache so updated extension code
324
+ // on disk is re-compiled instead of served from the stale cache (#3616).
325
+ resetExtensionLoaderCache();
326
+
323
327
  const resolvedPaths = await this.packageManager.resolve();
324
328
  const cliExtensionPaths = await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths, {
325
329
  temporary: true,
@@ -278,5 +278,85 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
278
278
  const msg = errorMessage("Extra usage is required for long context requests.");
279
279
  assert.equal(handler.isRetryableError(msg), true);
280
280
  });
281
+
282
+ it("does NOT consider credential cooldown error as retryable (#3429)", () => {
283
+ // The credential cooldown message from getApiKey() must not re-enter
284
+ // the retry handler. Re-entry creates cascading empty error entries
285
+ // in the session file that break resume.
286
+ const { deps } = createMockDeps();
287
+ const handler = new RetryHandler(deps);
288
+ const msg = errorMessage(
289
+ 'All credentials for "anthropic" are in a cooldown window. ' +
290
+ 'Please wait a moment and try again, or switch to a different provider.',
291
+ );
292
+ assert.equal(handler.isRetryableError(msg), false);
293
+ });
294
+ });
295
+
296
+ describe("quota_exhausted credential backoff (#3430)", () => {
297
+ it("does NOT call markUsageLimitReached for quota_exhausted errors", async () => {
298
+ // "Extra usage is required" is an account-level billing gate.
299
+ // Backing off the credential for 30 minutes blocks all provider
300
+ // requests and has no effect on the billing condition.
301
+ const { deps, markUsageLimitReached } = createMockDeps({
302
+ model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
303
+ markUsageLimitReachedResult: false,
304
+ fallbackResult: null,
305
+ findModelResult: () => undefined,
306
+ });
307
+
308
+ const handler = new RetryHandler(deps);
309
+ const msg = errorMessage(
310
+ '429 {"type":"error","error":{"type":"rate_limit_error","message":"Extra usage is required for long context requests."}}',
311
+ );
312
+
313
+ await handler.handleRetryableError(msg);
314
+
315
+ assert.equal(
316
+ markUsageLimitReached.mock.calls.length,
317
+ 0,
318
+ "markUsageLimitReached must NOT be called for quota_exhausted errors",
319
+ );
320
+ });
321
+
322
+ it("still calls markUsageLimitReached for regular rate_limit errors", async () => {
323
+ const { deps, markUsageLimitReached } = createMockDeps({
324
+ model: createMockModel("anthropic", "claude-opus-4-6"),
325
+ markUsageLimitReachedResult: false,
326
+ fallbackResult: null,
327
+ });
328
+
329
+ const handler = new RetryHandler(deps);
330
+ const msg = errorMessage("429 Too Many Requests");
331
+
332
+ await handler.handleRetryableError(msg);
333
+
334
+ assert.equal(
335
+ markUsageLimitReached.mock.calls.length,
336
+ 1,
337
+ "markUsageLimitReached should be called for rate_limit errors",
338
+ );
339
+ });
340
+
341
+ it("still tries cross-provider fallback for quota_exhausted without credential backoff", async () => {
342
+ const fallbackModel = createMockModel("openai", "gpt-4o");
343
+ const { deps, markUsageLimitReached, continueFn } = createMockDeps({
344
+ model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
345
+ markUsageLimitReachedResult: false,
346
+ fallbackResult: { model: fallbackModel, reason: "cross-provider fallback" },
347
+ });
348
+
349
+ const handler = new RetryHandler(deps);
350
+ const msg = errorMessage("Extra usage is required for long context requests.");
351
+
352
+ const result = await handler.handleRetryableError(msg);
353
+
354
+ assert.equal(result, true, "should retry with fallback provider");
355
+ assert.equal(
356
+ markUsageLimitReached.mock.calls.length,
357
+ 0,
358
+ "should NOT back off credentials before trying fallback",
359
+ );
360
+ });
281
361
  });
282
362
  });
@@ -109,7 +109,11 @@ export class RetryHandler {
109
109
  if (isContextOverflow(message, contextWindow)) return false;
110
110
 
111
111
  const err = message.errorMessage;
112
- 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|temporarily backed off|extra usage is required/i.test(
112
+ // "temporarily backed off" is intentionally excluded: it is an internally-
113
+ // generated error from getApiKey() when credentials are in a backoff window.
114
+ // Re-entering the retry handler for that message creates a cascade of empty
115
+ // error entries in the session file, breaking resume (#3429).
116
+ 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/i.test(
113
117
  err,
114
118
  );
115
119
  }
@@ -139,34 +143,42 @@ export class RetryHandler {
139
143
  const retryGeneration = this._retryGeneration;
140
144
  if (this._deps.getModel() && message.errorMessage) {
141
145
  const errorType = this._classifyErrorType(message.errorMessage);
142
- const isCredentialError = errorType === "rate_limit" || errorType === "quota_exhausted";
143
- const hasAlternate =
144
- isCredentialError &&
145
- this._deps.modelRegistry.authStorage.markUsageLimitReached(
146
- this._deps.getModel()!.provider,
147
- this._deps.getSessionId(),
148
- { errorType },
149
- );
150
-
151
- if (hasAlternate) {
152
- this._removeLastAssistantError();
146
+ const isRateLimit = errorType === "rate_limit";
147
+ const isQuotaError = errorType === "quota_exhausted";
148
+
149
+ // Credential rotation — only for transient rate limits (#3430).
150
+ // Quota errors ("Extra usage is required") are account-level billing
151
+ // gates; rotating to another credential on the same account won't help
152
+ // and the 30-minute backoff blocks all provider requests needlessly.
153
+ if (isRateLimit) {
154
+ const hasAlternate =
155
+ this._deps.modelRegistry.authStorage.markUsageLimitReached(
156
+ this._deps.getModel()!.provider,
157
+ this._deps.getSessionId(),
158
+ { errorType },
159
+ );
160
+
161
+ if (hasAlternate) {
162
+ this._removeLastAssistantError();
153
163
 
154
- this._deps.emit({
155
- type: "auto_retry_start",
156
- attempt: this._retryAttempt + 1,
157
- maxAttempts: settings.maxRetries,
158
- delayMs: 0,
159
- errorMessage: `${message.errorMessage} (switching credential)`,
160
- });
164
+ this._deps.emit({
165
+ type: "auto_retry_start",
166
+ attempt: this._retryAttempt + 1,
167
+ maxAttempts: settings.maxRetries,
168
+ delayMs: 0,
169
+ errorMessage: `${message.errorMessage} (switching credential)`,
170
+ });
161
171
 
162
- // Retry immediately with the next credential - don't increment _retryAttempt
163
- this._scheduleContinue(retryGeneration);
172
+ // Retry immediately with the next credential - don't increment _retryAttempt
173
+ this._scheduleContinue(retryGeneration);
164
174
 
165
- return true;
175
+ return true;
176
+ }
166
177
  }
167
178
 
168
- // All credentials are backed off. Try cross-provider fallback before giving up.
169
- if (isCredentialError) {
179
+ // Cross-provider fallback for rate limits with all creds backed off,
180
+ // or quota errors (which skip credential backoff entirely).
181
+ if (isRateLimit || isQuotaError) {
170
182
  const fallbackResult = await this._deps.fallbackResolver.findFallback(
171
183
  this._deps.getModel()!,
172
184
  errorType,
@@ -200,7 +212,7 @@ export class RetryHandler {
200
212
  }
201
213
 
202
214
  // No fallback available either
203
- if (errorType === "quota_exhausted") {
215
+ if (isQuotaError) {
204
216
  // Try long-context model downgrade ([1m] → base) before giving up
205
217
  const downgraded = this._tryLongContextDowngrade(message, retryGeneration);
206
218
  if (downgraded) return true;
@@ -371,16 +371,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
371
371
  await new Promise(resolve => setTimeout(resolve, baseDelayMs * attempt));
372
372
  }
373
373
 
374
- // All retries exhausted — throw descriptive error
375
- // Check if credentials exist but are temporarily backed off
376
- // (e.g., after a 429 quota exhaustion). Provide a specific error
377
- // so the retry handler knows this is transient, not a permanent
378
- // auth failure.
374
+ // All retries exhausted — throw descriptive error.
375
+ // Check if credentials exist but are temporarily in a backoff window
376
+ // (e.g., after a 429). This message intentionally avoids phrases like
377
+ // "rate limit" / "429" to prevent isRetryableError() from re-entering
378
+ // the retry handler and creating cascading error entries (#3429).
379
379
  const hasAuth = modelRegistry.authStorage.hasAuth(resolvedProvider);
380
380
  if (hasAuth) {
381
381
  throw new Error(
382
- `All credentials for "${resolvedProvider}" are temporarily backed off due to rate limiting. ` +
383
- `The request will be retried automatically when backoff expires.`,
382
+ `All credentials for "${resolvedProvider}" are in a cooldown window. ` +
383
+ `Please wait a moment and try again, or switch to a different provider.`,
384
384
  );
385
385
  }
386
386
  const model = agent.state.model;
@@ -390,8 +390,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
390
390
  // surface a specific message instead of the misleading "Authentication failed".
391
391
  if (modelRegistry.authStorage.areAllCredentialsBackedOff(resolvedProvider)) {
392
392
  throw new Error(
393
- `Rate limit in effect for "${resolvedProvider}". ` +
394
- `Please wait before retrying or switch to a different model.`,
393
+ `All credentials for "${resolvedProvider}" are in a cooldown window. ` +
394
+ `Please wait a moment and try again, or switch to a different provider.`,
395
395
  );
396
396
  }
397
397
  throw new Error(
@@ -43,6 +43,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
43
43
  private modelsJsonWriter: ModelsJsonWriter;
44
44
  private onDone: () => void;
45
45
  private onDiscover: (provider: string) => void;
46
+ private onSetupAuth: (provider: string) => void;
46
47
  private confirmingRemove = false;
47
48
  private hintsContainer: Container;
48
49
 
@@ -52,6 +53,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
52
53
  modelRegistry: ModelRegistry,
53
54
  onDone: () => void,
54
55
  onDiscover: (provider: string) => void,
56
+ onSetupAuth?: (provider: string) => void,
55
57
  ) {
56
58
  super();
57
59
 
@@ -61,6 +63,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
61
63
  this.modelsJsonWriter = new ModelsJsonWriter(this.modelRegistry.modelsJsonPath);
62
64
  this.onDone = onDone;
63
65
  this.onDiscover = onDiscover;
66
+ this.onSetupAuth = onSetupAuth ?? (() => {});
64
67
 
65
68
  // Header
66
69
  this.addChild(new Text(theme.fg("accent", "Provider Manager"), 0, 0));
@@ -125,6 +128,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
125
128
  this.hintsContainer.addChild(new Text(hints, 0, 0));
126
129
  } else {
127
130
  const hints = [
131
+ rawKeyHint("enter", "setup auth"),
128
132
  rawKeyHint("d", "discover"),
129
133
  rawKeyHint("r", "remove auth"),
130
134
  rawKeyHint("esc", "close"),
@@ -203,6 +207,12 @@ export class ProviderManagerComponent extends Container implements Focusable {
203
207
  this.tui.requestRender();
204
208
  }
205
209
  }
210
+ } else if (kb.matches(keyData, "selectConfirm")) {
211
+ // Enter key → initiate auth setup for the selected provider (#3579)
212
+ const provider = this.providers[this.selectedIndex];
213
+ if (provider) {
214
+ this.onSetupAuth(provider.name);
215
+ }
206
216
  }
207
217
  }
208
218
  }
@@ -3,6 +3,7 @@ import {
3
3
  Container,
4
4
  getCapabilities,
5
5
  Image,
6
+ type ImageDimensions,
6
7
  imageFallback,
7
8
  Spacer,
8
9
  Text,
@@ -88,6 +89,9 @@ export class ToolExecutionComponent extends Container {
88
89
  private editDiffArgsKey?: string; // Track which args the preview is for
89
90
  // Cached converted images for Kitty protocol (which requires PNG), keyed by index
90
91
  private convertedImages: Map<number, { data: string; mimeType: string }> = new Map();
92
+ // Cached resolved image dimensions to avoid re-triggering async parsing
93
+ // when updateDisplay() recreates Image components (#3455).
94
+ private resolvedImageDimensions: Map<number, ImageDimensions> = new Map();
91
95
  // Incremental syntax highlighting cache for write tool call args
92
96
  private writeHighlightCache?: WriteHighlightCache;
93
97
  // When true, this component intentionally renders no lines
@@ -137,6 +141,15 @@ export class ToolExecutionComponent extends Container {
137
141
  return isBuiltInName && !hasCustomRenderers;
138
142
  }
139
143
 
144
+ dispose(): void {
145
+ this.convertedImages.clear();
146
+ this.imageComponents = [];
147
+ this.imageSpacers = [];
148
+ this.editDiffPreview = undefined;
149
+ this.writeHighlightCache = undefined;
150
+ this.result = undefined;
151
+ }
152
+
140
153
  updateArgs(args: any): void {
141
154
  this.args = args;
142
155
  if (this.toolName === "write" && this.isPartial) {
@@ -472,16 +485,28 @@ export class ToolExecutionComponent extends Container {
472
485
  const spacer = new Spacer(1);
473
486
  this.addChild(spacer);
474
487
  this.imageSpacers.push(spacer);
488
+ // Pass cached dimensions to avoid re-triggering async parsing
489
+ // when updateDisplay() recreates Image components (#3455).
490
+ const cachedDims = this.resolvedImageDimensions.get(i);
475
491
  const imageComponent = new Image(
476
492
  imageData,
477
493
  imageMimeType,
478
494
  { fallbackColor: (s: string) => theme.fg("toolOutput", s) },
479
495
  { maxWidthCells: 60 },
496
+ cachedDims,
480
497
  );
481
- imageComponent.setOnDimensionsResolved(() => {
482
- this.updateDisplay();
483
- this.ui.requestRender();
484
- });
498
+ if (!cachedDims) {
499
+ const imgIdx = i;
500
+ imageComponent.setOnDimensionsResolved(() => {
501
+ // Cache resolved dimensions so future updateDisplay() calls
502
+ // don't re-trigger async parsing → infinite loop (#3455).
503
+ const dims = imageComponent.getDimensions?.();
504
+ if (dims) this.resolvedImageDimensions.set(imgIdx, dims);
505
+ // Just re-render — don't call updateDisplay() which would
506
+ // destroy and recreate all Image components.
507
+ this.ui.requestRender();
508
+ });
509
+ }
485
510
  this.imageComponents.push(imageComponent);
486
511
  this.addChild(imageComponent);
487
512
  }
@@ -154,3 +154,30 @@ test("input-controller: truly unknown slash commands stop before session.prompt"
154
154
  );
155
155
  assert.equal(getEditorText(), "", "unknown slash commands should clear the editor after showing the error");
156
156
  });
157
+
158
+ test("input-controller: absolute file paths are not treated as slash commands (#3478)", async () => {
159
+ const { host, prompted, errors } = createHost();
160
+
161
+ await host.defaultEditor.onSubmit("/Users/name/Desktop/screenshot.png");
162
+
163
+ assert.deepEqual(errors, [], "file paths should not trigger unknown command error");
164
+ assert.deepEqual(prompted, ["/Users/name/Desktop/screenshot.png"], "file paths should be sent as plain input");
165
+ });
166
+
167
+ test("input-controller: Linux absolute paths are not treated as slash commands (#3478)", async () => {
168
+ const { host, prompted, errors } = createHost();
169
+
170
+ await host.defaultEditor.onSubmit("/home/user/documents/file.txt");
171
+
172
+ assert.deepEqual(errors, [], "Linux paths should not trigger unknown command error");
173
+ assert.deepEqual(prompted, ["/home/user/documents/file.txt"], "Linux paths should be sent as plain input");
174
+ });
175
+
176
+ test("input-controller: /tmp paths are not treated as slash commands (#3478)", async () => {
177
+ const { host, prompted, errors } = createHost();
178
+
179
+ await host.defaultEditor.onSubmit("/tmp/some-file.log");
180
+
181
+ assert.deepEqual(errors, []);
182
+ assert.deepEqual(prompted, ["/tmp/some-file.log"]);
183
+ });
@@ -18,7 +18,7 @@ export function setupEditorSubmitHandler(host: InteractiveModeStateHost & {
18
18
  text = text.trim();
19
19
  if (!text) return;
20
20
 
21
- if (text.startsWith("/")) {
21
+ if (text.startsWith("/") && !looksLikeFilePath(text)) {
22
22
  const handled = await dispatchSlashCommand(text, host.getSlashCommandContext());
23
23
  if (handled) {
24
24
  host.editor.setText("");
@@ -104,3 +104,18 @@ export function setupEditorSubmitHandler(host: InteractiveModeStateHost & {
104
104
  }
105
105
  };
106
106
  }
107
+
108
+ /**
109
+ * Distinguish absolute file paths from slash commands (#3478).
110
+ * Drag-and-drop inserts paths like "/Users/name/Desktop/file.png" which
111
+ * should be treated as plain text input, not a /Users command.
112
+ *
113
+ * Heuristic: a slash command is a single token like "/help" or "/gsd auto".
114
+ * File paths have a second "/" within the first token (e.g., "/Users/...").
115
+ */
116
+ function looksLikeFilePath(text: string): boolean {
117
+ const firstToken = text.split(/\s/)[0];
118
+ // Slash commands: /help, /gsd, /commit — single "/" at start only.
119
+ // File paths: /Users/name/file, /home/user/file, /tmp/x — contain "/" after position 0.
120
+ return firstToken.indexOf("/", 1) !== -1;
121
+ }
@@ -7,6 +7,7 @@ import * as crypto from "node:crypto";
7
7
  import * as fs from "node:fs";
8
8
  import * as os from "node:os";
9
9
  import * as path from "node:path";
10
+ import { listDescendants } from "@gsd/native";
10
11
  import type { AgentMessage } from "@gsd/pi-agent-core";
11
12
  import type { AssistantMessage, ImageContent, Message, Model, OAuthProviderId } from "@gsd/pi-ai";
12
13
  import type {
@@ -157,6 +158,10 @@ export interface InteractiveModeOptions {
157
158
  }
158
159
 
159
160
  export class InteractiveMode {
161
+ // Cap rendered chat components to prevent unbounded memory/CPU growth.
162
+ // Only render-components are removed — session transcript stays on disk.
163
+ private static readonly MAX_CHAT_COMPONENTS = 100;
164
+
160
165
  private session: AgentSession;
161
166
  private ui: TUI;
162
167
  private chatContainer: Container;
@@ -2138,6 +2143,18 @@ export class InteractiveMode {
2138
2143
  const _exhaustive: never = message;
2139
2144
  }
2140
2145
  }
2146
+ this.trimChatHistory();
2147
+ }
2148
+
2149
+ /**
2150
+ * Remove oldest components when chat exceeds MAX_CHAT_COMPONENTS.
2151
+ * Only render-components are removed — session data stays in SessionManager.
2152
+ */
2153
+ private trimChatHistory(): void {
2154
+ while (this.chatContainer.children.length > InteractiveMode.MAX_CHAT_COMPONENTS) {
2155
+ const oldest = this.chatContainer.children[0];
2156
+ this.chatContainer.removeChild(oldest);
2157
+ }
2141
2158
  }
2142
2159
 
2143
2160
  /**
@@ -2232,6 +2249,7 @@ export class InteractiveMode {
2232
2249
  }
2233
2250
 
2234
2251
  this.pendingTools.clear();
2252
+ this.trimChatHistory();
2235
2253
  this.ui.requestRender();
2236
2254
  }
2237
2255
 
@@ -2325,6 +2343,21 @@ export class InteractiveMode {
2325
2343
  if (shutdownBehavior === "stop_ui") {
2326
2344
  return;
2327
2345
  }
2346
+
2347
+ // Kill ALL descendant processes to prevent orphans (next-server, pnpm dev, etc.)
2348
+ try {
2349
+ const descendants = listDescendants(process.pid);
2350
+ for (const childPid of descendants) {
2351
+ try { process.kill(childPid, "SIGTERM"); } catch {}
2352
+ }
2353
+ if (descendants.length > 0) {
2354
+ await new Promise(resolve => setTimeout(resolve, 500));
2355
+ for (const childPid of descendants) {
2356
+ try { process.kill(childPid, "SIGKILL"); } catch {}
2357
+ }
2358
+ }
2359
+ } catch {}
2360
+
2328
2361
  process.exit(0);
2329
2362
  }
2330
2363
 
@@ -3378,6 +3411,11 @@ export class InteractiveMode {
3378
3411
  done();
3379
3412
  this.ui.requestRender();
3380
3413
  },
3414
+ async (provider: string) => {
3415
+ // Enter key → auth setup for selected provider (#3579)
3416
+ done();
3417
+ await this.showLoginDialog(provider);
3418
+ },
3381
3419
  );
3382
3420
  return { component, focus: component };
3383
3421
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=overlay-layout.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-layout.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/overlay-layout.test.ts"],"names":[],"mappings":""}