gsd-pi 2.70.0 → 2.70.1-dev.366a872

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 (315) hide show
  1. package/dist/loader.js +4 -0
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +270 -23
  3. package/dist/resources/extensions/get-secrets-from-user.js +17 -1
  4. package/dist/resources/extensions/gsd/auto-model-selection.js +33 -19
  5. package/dist/resources/extensions/gsd/auto-prompts.js +7 -3
  6. package/dist/resources/extensions/gsd/auto-start.js +28 -12
  7. package/dist/resources/extensions/gsd/auto.js +12 -8
  8. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -0
  9. package/dist/resources/extensions/gsd/commands-handlers.js +22 -8
  10. package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
  11. package/dist/resources/extensions/gsd/doctor-engine-checks.js +12 -0
  12. package/dist/resources/extensions/gsd/doctor-format.js +2 -0
  13. package/dist/resources/extensions/gsd/file-lock.js +60 -0
  14. package/dist/resources/extensions/gsd/guided-flow.js +33 -20
  15. package/dist/resources/extensions/gsd/init-wizard.js +3 -11
  16. package/dist/resources/extensions/gsd/pre-execution-checks.js +5 -3
  17. package/dist/resources/extensions/gsd/prompts/discuss.md +31 -13
  18. package/dist/resources/extensions/gsd/state.js +234 -332
  19. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +34 -0
  20. package/dist/resources/extensions/gsd/validate-directory.js +30 -12
  21. package/dist/resources/extensions/gsd/workflow-events.js +25 -13
  22. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
  23. package/dist/resources/extensions/gsd/workflow-mcp.js +12 -1
  24. package/dist/resources/extensions/slash-commands/audit.js +2 -1
  25. package/dist/resources/extensions/subagent/isolation.js +4 -2
  26. package/dist/update-check.d.ts +1 -0
  27. package/dist/update-check.js +30 -27
  28. package/dist/update-cmd.js +3 -11
  29. package/dist/web/standalone/.next/BUILD_ID +1 -1
  30. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  31. package/dist/web/standalone/.next/build-manifest.json +4 -4
  32. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  33. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  34. package/dist/web/standalone/.next/required-server-files.json +3 -3
  35. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  36. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  46. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  50. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  52. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  62. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  74. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  94. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  104. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  110. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  130. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/index.html +1 -1
  140. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  141. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  142. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  143. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  145. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/page.js +2 -2
  147. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  149. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  150. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  151. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/middleware.js +2 -2
  154. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  156. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  157. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  158. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  159. package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
  160. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  161. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  162. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  163. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  164. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  165. package/dist/web/standalone/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
  166. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  167. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  168. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  169. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  170. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  171. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  172. package/dist/web/standalone/server.js +1 -1
  173. package/dist/web-mode.js +4 -0
  174. package/package.json +11 -11
  175. package/packages/mcp-server/dist/env-writer.d.ts +39 -0
  176. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
  177. package/packages/mcp-server/dist/env-writer.js +158 -0
  178. package/packages/mcp-server/dist/env-writer.js.map +1 -0
  179. package/packages/mcp-server/dist/server.d.ts +11 -2
  180. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  181. package/packages/mcp-server/dist/server.js +102 -2
  182. package/packages/mcp-server/dist/server.js.map +1 -1
  183. package/packages/mcp-server/dist/workflow-tools.d.ts +2 -0
  184. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  185. package/packages/mcp-server/dist/workflow-tools.js +35 -3
  186. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  187. package/packages/mcp-server/src/env-writer.test.ts +280 -0
  188. package/packages/mcp-server/src/env-writer.ts +183 -0
  189. package/packages/mcp-server/src/import-candidates.test.ts +48 -0
  190. package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
  191. package/packages/mcp-server/src/server.ts +137 -3
  192. package/packages/mcp-server/src/workflow-tools.ts +34 -1
  193. package/packages/pi-agent-core/dist/agent.d.ts +8 -0
  194. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  195. package/packages/pi-agent-core/dist/agent.js +3 -0
  196. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  197. package/packages/pi-agent-core/src/agent.test.ts +82 -0
  198. package/packages/pi-agent-core/src/agent.ts +12 -0
  199. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
  200. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +348 -0
  202. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
  203. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  205. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +1 -0
  207. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/lsp/config.js +38 -15
  209. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/sdk.js +10 -0
  212. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
  218. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  219. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +158 -23
  223. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  228. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +58 -2
  230. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +3 -1
  233. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  234. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  235. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  237. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  238. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  239. package/packages/pi-coding-agent/package.json +1 -1
  240. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +418 -0
  241. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  242. package/packages/pi-coding-agent/src/core/lsp/config.ts +43 -17
  243. package/packages/pi-coding-agent/src/core/sdk.ts +8 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
  245. package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
  246. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +189 -29
  247. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  248. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +66 -2
  249. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +7 -5
  250. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
  251. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
  252. package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
  253. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  254. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
  255. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
  256. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
  257. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
  258. package/packages/pi-tui/dist/components/input.d.ts +2 -0
  259. package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
  260. package/packages/pi-tui/dist/components/input.js +7 -4
  261. package/packages/pi-tui/dist/components/input.js.map +1 -1
  262. package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
  263. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  264. package/packages/pi-tui/dist/components/markdown.js +17 -1
  265. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  266. package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
  267. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
  268. package/packages/pi-tui/src/components/input.ts +7 -4
  269. package/packages/pi-tui/src/components/markdown.ts +22 -1
  270. package/pkg/package.json +1 -1
  271. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +384 -24
  272. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +317 -0
  273. package/src/resources/extensions/get-secrets-from-user.ts +24 -1
  274. package/src/resources/extensions/gsd/auto-model-selection.ts +39 -25
  275. package/src/resources/extensions/gsd/auto-prompts.ts +7 -3
  276. package/src/resources/extensions/gsd/auto-start.ts +37 -14
  277. package/src/resources/extensions/gsd/auto.ts +12 -8
  278. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -0
  279. package/src/resources/extensions/gsd/commands-handlers.ts +22 -7
  280. package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
  281. package/src/resources/extensions/gsd/doctor-engine-checks.ts +14 -0
  282. package/src/resources/extensions/gsd/doctor-format.ts +1 -0
  283. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  284. package/src/resources/extensions/gsd/file-lock.ts +59 -0
  285. package/src/resources/extensions/gsd/guided-flow.ts +36 -17
  286. package/src/resources/extensions/gsd/init-wizard.ts +3 -13
  287. package/src/resources/extensions/gsd/pre-execution-checks.ts +6 -3
  288. package/src/resources/extensions/gsd/prompts/discuss.md +31 -13
  289. package/src/resources/extensions/gsd/state.ts +274 -344
  290. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
  291. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
  292. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
  293. package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
  294. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +207 -0
  295. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +48 -1
  296. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +8 -7
  297. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
  298. package/src/resources/extensions/gsd/tests/validate-directory.test.ts +33 -1
  299. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +87 -1
  300. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
  301. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +180 -1
  302. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
  303. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +60 -25
  304. package/src/resources/extensions/gsd/validate-directory.ts +33 -11
  305. package/src/resources/extensions/gsd/workflow-events.ts +34 -25
  306. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
  307. package/src/resources/extensions/gsd/workflow-mcp.ts +16 -1
  308. package/src/resources/extensions/slash-commands/audit.ts +2 -1
  309. package/src/resources/extensions/subagent/isolation.ts +4 -3
  310. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
  311. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  312. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  313. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  314. /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → eMly3KqfZihJJAHQGmxvO}/_buildManifest.js +0 -0
  315. /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → eMly3KqfZihJJAHQGmxvO}/_ssgManifest.js +0 -0
@@ -16,10 +16,12 @@ import type {
16
16
  SimpleStreamOptions,
17
17
  ToolCall,
18
18
  } from "@gsd/pi-ai";
19
+ import type { ExtensionUIContext } from "@gsd/pi-coding-agent";
19
20
  import { EventStream } from "@gsd/pi-ai";
20
21
  import { execSync } from "node:child_process";
21
22
  import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
22
23
  import { buildWorkflowMcpServers } from "../gsd/workflow-mcp.js";
24
+ import { showInterviewRound, type Question, type RoundResult } from "../shared/tui.js";
23
25
  import type {
24
26
  SDKAssistantMessage,
25
27
  SDKMessage,
@@ -45,6 +47,58 @@ type ToolCallWithExternalResult = ToolCall & {
45
47
  externalResult?: ExternalToolResultPayload;
46
48
  };
47
49
 
50
+ interface ClaudeCodeStreamOptions extends SimpleStreamOptions {
51
+ extensionUIContext?: ExtensionUIContext;
52
+ }
53
+
54
+ interface SdkElicitationRequestOption {
55
+ const?: string;
56
+ title?: string;
57
+ }
58
+
59
+ interface SdkElicitationFieldSchema {
60
+ type?: string;
61
+ title?: string;
62
+ description?: string;
63
+ format?: string;
64
+ writeOnly?: boolean;
65
+ oneOf?: SdkElicitationRequestOption[];
66
+ items?: {
67
+ anyOf?: SdkElicitationRequestOption[];
68
+ };
69
+ }
70
+
71
+ interface SdkElicitationRequest {
72
+ serverName: string;
73
+ message: string;
74
+ mode?: "form" | "url";
75
+ requestedSchema?: {
76
+ type?: string;
77
+ properties?: Record<string, SdkElicitationFieldSchema>;
78
+ required?: string[];
79
+ };
80
+ }
81
+
82
+ interface SdkElicitationResult {
83
+ action: "accept" | "decline" | "cancel";
84
+ content?: Record<string, string | string[]>;
85
+ }
86
+
87
+ interface ParsedElicitationQuestion extends Question {
88
+ noteFieldId?: string;
89
+ }
90
+
91
+ interface ParsedTextInputField {
92
+ id: string;
93
+ title: string;
94
+ description: string;
95
+ required: boolean;
96
+ secure: boolean;
97
+ }
98
+
99
+ const OTHER_OPTION_LABEL = "None of the above";
100
+ const SENSITIVE_FIELD_PATTERN = /(password|passphrase|secret|token|api[_\s-]*key|private[_\s-]*key|credential)/i;
101
+
48
102
  // ---------------------------------------------------------------------------
49
103
  // Stream factory
50
104
  // ---------------------------------------------------------------------------
@@ -172,6 +226,286 @@ export function makeStreamExhaustedErrorMessage(model: string, lastTextContent:
172
226
  return message;
173
227
  }
174
228
 
229
+ function readElicitationChoices(options: SdkElicitationRequestOption[] | undefined): string[] {
230
+ if (!Array.isArray(options)) return [];
231
+ return options
232
+ .map((option) => (typeof option?.const === "string" ? option.const : typeof option?.title === "string" ? option.title : ""))
233
+ .filter((option): option is string => option.length > 0);
234
+ }
235
+
236
+ export function parseAskUserQuestionsElicitation(
237
+ request: Pick<SdkElicitationRequest, "mode" | "requestedSchema">,
238
+ ): ParsedElicitationQuestion[] | null {
239
+ if (request.mode && request.mode !== "form") return null;
240
+ const properties = request.requestedSchema?.properties;
241
+ if (!properties || typeof properties !== "object") return null;
242
+
243
+ const questions: ParsedElicitationQuestion[] = [];
244
+
245
+ for (const [fieldId, rawField] of Object.entries(properties)) {
246
+ if (fieldId.endsWith("__note")) continue;
247
+ if (!rawField || typeof rawField !== "object") return null;
248
+
249
+ const header = typeof rawField.title === "string" && rawField.title.length > 0 ? rawField.title : fieldId;
250
+ const question = typeof rawField.description === "string" ? rawField.description : "";
251
+
252
+ if (rawField.type === "array") {
253
+ const options = readElicitationChoices(rawField.items?.anyOf).map((label) => ({ label, description: "" }));
254
+ if (options.length === 0) return null;
255
+ questions.push({
256
+ id: fieldId,
257
+ header,
258
+ question,
259
+ options,
260
+ allowMultiple: true,
261
+ });
262
+ continue;
263
+ }
264
+
265
+ if (rawField.type === "string") {
266
+ const noteFieldId = Object.prototype.hasOwnProperty.call(properties, `${fieldId}__note`)
267
+ ? `${fieldId}__note`
268
+ : undefined;
269
+ const options = readElicitationChoices(rawField.oneOf)
270
+ .filter((label) => label !== OTHER_OPTION_LABEL)
271
+ .map((label) => ({ label, description: "" }));
272
+ if (options.length === 0) return null;
273
+ questions.push({
274
+ id: fieldId,
275
+ header,
276
+ question,
277
+ options,
278
+ noteFieldId,
279
+ });
280
+ continue;
281
+ }
282
+
283
+ return null;
284
+ }
285
+
286
+ return questions.length > 0 ? questions : null;
287
+ }
288
+
289
+ function isSecureElicitationField(
290
+ requestMessage: string,
291
+ fieldId: string,
292
+ field: SdkElicitationFieldSchema,
293
+ ): boolean {
294
+ if (field.format === "password") return true;
295
+ if (field.writeOnly === true) return true;
296
+
297
+ const rawField = field as Record<string, unknown>;
298
+ if (rawField.sensitive === true || rawField["x-sensitive"] === true) return true;
299
+
300
+ const haystack = [
301
+ requestMessage,
302
+ fieldId.replace(/[_-]+/g, " "),
303
+ typeof field.title === "string" ? field.title : "",
304
+ typeof field.description === "string" ? field.description : "",
305
+ ]
306
+ .join(" ")
307
+ .toLowerCase();
308
+
309
+ return SENSITIVE_FIELD_PATTERN.test(haystack);
310
+ }
311
+
312
+ export function parseTextInputElicitation(
313
+ request: Pick<SdkElicitationRequest, "message" | "mode" | "requestedSchema">,
314
+ ): ParsedTextInputField[] | null {
315
+ if (request.mode && request.mode !== "form") return null;
316
+ const schema = request.requestedSchema as
317
+ | ({ properties?: Record<string, SdkElicitationFieldSchema>; keys?: Record<string, SdkElicitationFieldSchema> } & Record<string, unknown>)
318
+ | undefined;
319
+ const fieldsSource = schema?.properties && typeof schema.properties === "object"
320
+ ? schema.properties
321
+ : schema?.keys && typeof schema.keys === "object"
322
+ ? schema.keys
323
+ : undefined;
324
+ if (!fieldsSource) return null;
325
+
326
+ const requiredSet = new Set(
327
+ Array.isArray(request.requestedSchema?.required)
328
+ ? request.requestedSchema.required.filter((value): value is string => typeof value === "string")
329
+ : [],
330
+ );
331
+
332
+ const fields: ParsedTextInputField[] = [];
333
+ for (const [fieldId, field] of Object.entries(fieldsSource)) {
334
+ if (!field || typeof field !== "object") continue;
335
+ if (field.type !== "string") continue;
336
+ if (Array.isArray(field.oneOf) && field.oneOf.length > 0) continue;
337
+
338
+ fields.push({
339
+ id: fieldId,
340
+ title: typeof field.title === "string" && field.title.length > 0 ? field.title : fieldId,
341
+ description: typeof field.description === "string" ? field.description : "",
342
+ required: requiredSet.has(fieldId),
343
+ secure: isSecureElicitationField(request.message, fieldId, field),
344
+ });
345
+ }
346
+
347
+ return fields.length > 0 ? fields : null;
348
+ }
349
+
350
+ export function roundResultToElicitationContent(
351
+ questions: ParsedElicitationQuestion[],
352
+ result: RoundResult,
353
+ ): Record<string, string | string[]> {
354
+ const content: Record<string, string | string[]> = {};
355
+
356
+ for (const question of questions) {
357
+ const answer = result.answers[question.id];
358
+ if (!answer) continue;
359
+
360
+ if (question.allowMultiple) {
361
+ const selected = Array.isArray(answer.selected) ? answer.selected : [answer.selected];
362
+ content[question.id] = selected;
363
+ continue;
364
+ }
365
+
366
+ const selected = Array.isArray(answer.selected) ? answer.selected[0] ?? "" : answer.selected;
367
+ content[question.id] = selected;
368
+ if (question.noteFieldId && selected === OTHER_OPTION_LABEL && answer.notes.trim().length > 0) {
369
+ content[question.noteFieldId] = answer.notes.trim();
370
+ }
371
+ }
372
+
373
+ return content;
374
+ }
375
+
376
+ function buildElicitationPromptTitle(request: SdkElicitationRequest, question: ParsedElicitationQuestion): string {
377
+ const parts = [
378
+ request.serverName ? `[${request.serverName}]` : "",
379
+ question.header,
380
+ question.question,
381
+ ].filter((part) => part && part.trim().length > 0);
382
+ return parts.join("\n\n");
383
+ }
384
+
385
+ async function promptElicitationWithDialogs(
386
+ request: SdkElicitationRequest,
387
+ questions: ParsedElicitationQuestion[],
388
+ ui: ExtensionUIContext,
389
+ signal: AbortSignal,
390
+ ): Promise<SdkElicitationResult> {
391
+ const content: Record<string, string | string[]> = {};
392
+
393
+ for (const question of questions) {
394
+ const title = buildElicitationPromptTitle(request, question);
395
+
396
+ if (question.allowMultiple) {
397
+ const selected = await ui.select(title, question.options.map((option) => option.label), {
398
+ allowMultiple: true,
399
+ signal,
400
+ });
401
+ if (Array.isArray(selected)) {
402
+ if (selected.length === 0) return { action: "cancel" };
403
+ content[question.id] = selected;
404
+ continue;
405
+ }
406
+ if (typeof selected === "string" && selected.length > 0) {
407
+ content[question.id] = [selected];
408
+ continue;
409
+ }
410
+ return { action: "cancel" };
411
+ }
412
+
413
+ const selected = await ui.select(title, [...question.options.map((option) => option.label), OTHER_OPTION_LABEL], { signal });
414
+ if (typeof selected !== "string" || selected.length === 0) {
415
+ return { action: "cancel" };
416
+ }
417
+
418
+ content[question.id] = selected;
419
+ if (question.noteFieldId && selected === OTHER_OPTION_LABEL) {
420
+ const note = await ui.input(`${question.header} note`, "Explain your answer", { signal });
421
+ if (note === undefined) return { action: "cancel" };
422
+ if (note.trim().length > 0) {
423
+ content[question.noteFieldId] = note.trim();
424
+ }
425
+ }
426
+ }
427
+
428
+ return { action: "accept", content };
429
+ }
430
+
431
+ function buildTextInputPromptTitle(request: SdkElicitationRequest, field: ParsedTextInputField): string {
432
+ const parts = [
433
+ request.serverName ? `[${request.serverName}]` : "",
434
+ field.title,
435
+ field.description,
436
+ ].filter((part) => typeof part === "string" && part.trim().length > 0);
437
+ return parts.join("\n\n");
438
+ }
439
+
440
+ function buildTextInputPlaceholder(field: ParsedTextInputField): string | undefined {
441
+ const desc = field.description.trim();
442
+ if (!desc) return field.required ? "Required" : "Leave empty to skip";
443
+
444
+ const formatLine = desc
445
+ .split(/\r?\n/)
446
+ .map((line) => line.trim())
447
+ .find((line) => /^format:/i.test(line));
448
+
449
+ if (!formatLine) return field.required ? "Required" : "Leave empty to skip";
450
+ const hint = formatLine.replace(/^format:\s*/i, "").trim();
451
+ return hint.length > 0 ? hint : field.required ? "Required" : "Leave empty to skip";
452
+ }
453
+
454
+ async function promptTextInputElicitation(
455
+ request: SdkElicitationRequest,
456
+ fields: ParsedTextInputField[],
457
+ ui: ExtensionUIContext,
458
+ signal: AbortSignal,
459
+ ): Promise<SdkElicitationResult> {
460
+ const content: Record<string, string | string[]> = {};
461
+
462
+ for (const field of fields) {
463
+ const value = await ui.input(
464
+ buildTextInputPromptTitle(request, field),
465
+ buildTextInputPlaceholder(field),
466
+ { signal, ...(field.secure ? { secure: true } : {}) },
467
+ );
468
+ if (value === undefined) {
469
+ return { action: "cancel" };
470
+ }
471
+ content[field.id] = value;
472
+ }
473
+
474
+ return { action: "accept", content };
475
+ }
476
+
477
+ export function createClaudeCodeElicitationHandler(
478
+ ui: ExtensionUIContext | undefined,
479
+ ): ((request: SdkElicitationRequest, options: { signal: AbortSignal }) => Promise<SdkElicitationResult>) | undefined {
480
+ if (!ui) return undefined;
481
+
482
+ return async (request, { signal }) => {
483
+ if (request.mode === "url") {
484
+ return { action: "decline" };
485
+ }
486
+
487
+ const questions = parseAskUserQuestionsElicitation(request);
488
+ if (questions) {
489
+ const interviewResult = await showInterviewRound(questions, { signal }, { ui } as any).catch(() => undefined);
490
+ if (interviewResult && Object.keys(interviewResult.answers).length > 0) {
491
+ return {
492
+ action: "accept",
493
+ content: roundResultToElicitationContent(questions, interviewResult),
494
+ };
495
+ }
496
+
497
+ return promptElicitationWithDialogs(request, questions, ui, signal);
498
+ }
499
+
500
+ const textFields = parseTextInputElicitation(request);
501
+ if (textFields) {
502
+ return promptTextInputElicitation(request, textFields, ui, signal);
503
+ }
504
+
505
+ return { action: "decline" };
506
+ };
507
+ }
508
+
175
509
  // ---------------------------------------------------------------------------
176
510
  // SDK options builder
177
511
  // ---------------------------------------------------------------------------
@@ -182,8 +516,13 @@ export function makeStreamExhaustedErrorMessage(model: string, lastTextContent:
182
516
  * Extracted for testability — callers can verify session persistence,
183
517
  * beta flags, and other configuration without mocking the full SDK.
184
518
  */
185
- export function buildSdkOptions(modelId: string, prompt: string): Record<string, unknown> {
519
+ export function buildSdkOptions(
520
+ modelId: string,
521
+ prompt: string,
522
+ extraOptions: Record<string, unknown> = {},
523
+ ): Record<string, unknown> {
186
524
  const mcpServers = buildWorkflowMcpServers();
525
+ const disallowedTools = ["AskUserQuestion"];
187
526
  return {
188
527
  pathToClaudeCodeExecutable: getClaudePath(),
189
528
  model: modelId,
@@ -194,8 +533,10 @@ export function buildSdkOptions(modelId: string, prompt: string): Record<string,
194
533
  allowDangerouslySkipPermissions: true,
195
534
  settingSources: ["project"],
196
535
  systemPrompt: { type: "preset", preset: "claude_code" },
536
+ disallowedTools,
197
537
  ...(mcpServers ? { mcpServers } : {}),
198
538
  betas: modelId.includes("sonnet") ? ["context-1m-2025-08-07"] : [],
539
+ ...extraOptions,
199
540
  };
200
541
  }
201
542
 
@@ -291,15 +632,15 @@ export function extractToolResultsFromSdkUserMessage(message: SDKUserMessage): A
291
632
  return extracted;
292
633
  }
293
634
 
294
- function attachExternalResultsToToolCalls(
295
- toolCalls: AssistantMessage["content"],
635
+ function attachExternalResultsToToolBlocks(
636
+ toolBlocks: AssistantMessage["content"],
296
637
  toolResultsById: ReadonlyMap<string, ExternalToolResultPayload>,
297
638
  ): void {
298
- for (const block of toolCalls) {
299
- if (block.type !== "toolCall") continue;
639
+ for (const block of toolBlocks) {
640
+ if (block.type !== "toolCall" && block.type !== "serverToolUse") continue;
300
641
  const externalResult = toolResultsById.get(block.id);
301
642
  if (!externalResult) continue;
302
- (block as ToolCallWithExternalResult).externalResult = externalResult;
643
+ (block as ToolCallWithExternalResult & { id: string }).externalResult = externalResult;
303
644
  }
304
645
  }
305
646
 
@@ -337,8 +678,8 @@ async function pumpSdkMessages(
337
678
  /** Track the last text content seen across all assistant turns for the final message. */
338
679
  let lastTextContent = "";
339
680
  let lastThinkingContent = "";
340
- /** Collect tool calls from intermediate SDK turns for tool_execution events. */
341
- const intermediateToolCalls: AssistantMessage["content"] = [];
681
+ /** Collect tool blocks from intermediate SDK turns for tool execution rendering. */
682
+ const intermediateToolBlocks: AssistantMessage["content"] = [];
342
683
  /** Preserve real external tool results from Claude Code's synthetic user messages. */
343
684
  const toolResultsById = new Map<string, ExternalToolResultPayload>();
344
685
 
@@ -359,7 +700,17 @@ async function pumpSdkMessages(
359
700
  }
360
701
 
361
702
  const prompt = buildPromptFromContext(context);
362
- const sdkOpts = buildSdkOptions(modelId, prompt);
703
+ const sdkOpts = buildSdkOptions(
704
+ modelId,
705
+ prompt,
706
+ typeof (options as ClaudeCodeStreamOptions | undefined)?.extensionUIContext === "object"
707
+ ? {
708
+ onElicitation: createClaudeCodeElicitationHandler(
709
+ (options as ClaudeCodeStreamOptions | undefined)?.extensionUIContext,
710
+ ),
711
+ }
712
+ : {},
713
+ );
363
714
 
364
715
  const queryResult = sdk.query({
365
716
  prompt,
@@ -439,9 +790,9 @@ async function pumpSdkMessages(
439
790
  lastTextContent = block.text;
440
791
  } else if (block.type === "thinking" && block.thinking) {
441
792
  lastThinkingContent = block.thinking;
442
- } else if (block.type === "toolCall") {
443
- // Collect tool calls for externalToolExecution rendering
444
- intermediateToolCalls.push(block);
793
+ } else if (block.type === "toolCall" || block.type === "serverToolUse") {
794
+ // Collect tool blocks for externalToolExecution rendering
795
+ intermediateToolBlocks.push(block);
445
796
  }
446
797
  }
447
798
  }
@@ -451,24 +802,33 @@ async function pumpSdkMessages(
451
802
  for (const { toolUseId, result } of extractToolResultsFromSdkUserMessage(msg as SDKUserMessage)) {
452
803
  toolResultsById.set(toolUseId, result);
453
804
  }
454
- attachExternalResultsToToolCalls(intermediateToolCalls, toolResultsById);
805
+ attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
455
806
 
456
807
  // Push a synthetic toolcall_end for each tool call from this turn
457
808
  // so the TUI can render tool results in real-time during the SDK
458
809
  // session instead of waiting until the entire session completes.
459
810
  if (builder) {
460
811
  for (const block of builder.message.content) {
461
- if (block.type !== "toolCall") continue;
462
812
  const extResult = (block as ToolCallWithExternalResult).externalResult;
463
813
  if (!extResult) continue;
464
- // Push a toolcall_end with result attached so the chat-controller
465
- // can call updateResult on the pending ToolExecutionComponent.
466
- stream.push({
467
- type: "toolcall_end",
468
- contentIndex: builder.message.content.indexOf(block),
469
- toolCall: block,
470
- partial: builder.message,
471
- });
814
+ const contentIndex = builder.message.content.indexOf(block);
815
+ if (contentIndex < 0) continue;
816
+ // Push synthetic completion events with result attached so the
817
+ // chat-controller can update pending ToolExecutionComponents.
818
+ if (block.type === "toolCall") {
819
+ stream.push({
820
+ type: "toolcall_end",
821
+ contentIndex,
822
+ toolCall: block,
823
+ partial: builder.message,
824
+ });
825
+ } else if (block.type === "serverToolUse") {
826
+ stream.push({
827
+ type: "server_tool_use",
828
+ contentIndex,
829
+ partial: builder.message,
830
+ });
831
+ }
472
832
  }
473
833
  }
474
834
 
@@ -486,8 +846,8 @@ async function pumpSdkMessages(
486
846
  const finalContent: AssistantMessage["content"] = [];
487
847
 
488
848
  // Add tool calls from intermediate turns first (renders above text)
489
- attachExternalResultsToToolCalls(intermediateToolCalls, toolResultsById);
490
- finalContent.push(...intermediateToolCalls);
849
+ attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
850
+ finalContent.push(...intermediateToolBlocks);
491
851
 
492
852
  // Add text/thinking from the last turn
493
853
  if (builder && builder.message.content.length > 0) {