gsd-pi 2.74.0-dev.28a6415 → 2.74.0-dev.658744a

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 (303) hide show
  1. package/dist/resources/extensions/gsd/auto/phases.js +51 -6
  2. package/dist/resources/extensions/gsd/auto-model-selection.js +3 -3
  3. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -3
  4. package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
  5. package/dist/resources/extensions/gsd/auto-worktree.js +2 -0
  6. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -3
  7. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  8. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
  9. package/dist/resources/extensions/gsd/cache.js +16 -5
  10. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  11. package/dist/resources/extensions/gsd/commands/handlers/core.js +5 -1
  12. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +50 -3
  13. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -0
  14. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  15. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  16. package/dist/resources/extensions/gsd/guided-flow.js +8 -6
  17. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  18. package/dist/resources/extensions/gsd/preferences-validation.js +10 -0
  19. package/dist/resources/extensions/gsd/preferences.js +5 -0
  20. package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
  21. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  22. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  23. package/dist/web/standalone/.next/BUILD_ID +1 -1
  24. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  25. package/dist/web/standalone/.next/build-manifest.json +2 -2
  26. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  27. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/index.html +1 -1
  49. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  56. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  57. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  59. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  60. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  61. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  62. package/package.json +1 -1
  63. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  64. package/packages/mcp-server/dist/workflow-tools.js +88 -6
  65. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  66. package/packages/mcp-server/src/workflow-tools.ts +95 -10
  67. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  68. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  69. package/packages/pi-ai/dist/index.d.ts +1 -9
  70. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  71. package/packages/pi-ai/dist/index.js +1 -9
  72. package/packages/pi-ai/dist/index.js.map +1 -1
  73. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  74. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  75. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  76. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  77. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  78. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  79. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  80. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  81. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  82. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  83. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  84. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  85. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  86. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  87. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  88. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  89. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  90. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  91. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  92. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  93. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  94. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  95. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  96. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  97. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  98. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  99. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  100. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  101. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  102. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  103. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  104. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  105. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  106. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  107. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  108. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  109. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  110. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  111. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  112. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  113. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  114. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  115. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  116. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  117. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  118. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  120. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  121. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  122. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  123. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  124. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  125. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  126. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  127. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  128. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  129. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  130. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  131. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  132. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  133. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  134. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  135. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  136. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  137. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  138. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  139. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  140. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  141. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  142. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  143. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  144. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  145. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  146. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  147. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  148. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  149. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  150. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  151. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  152. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  153. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  154. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  155. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  156. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  157. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  158. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  159. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  160. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  161. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  162. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  163. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  164. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  165. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  166. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  167. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  168. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  169. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  170. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  172. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  173. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  174. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  175. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  176. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  177. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  178. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  179. package/packages/pi-ai/dist/models/index.js +80 -0
  180. package/packages/pi-ai/dist/models/index.js.map +1 -0
  181. package/packages/pi-ai/dist/models.d.ts +1 -36
  182. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  183. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  184. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  185. package/packages/pi-ai/dist/models.js +3 -112
  186. package/packages/pi-ai/dist/models.js.map +1 -1
  187. package/packages/pi-ai/dist/models.test.js +6 -5
  188. package/packages/pi-ai/dist/models.test.js.map +1 -1
  189. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  190. package/packages/pi-ai/src/index.ts +1 -9
  191. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  192. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  193. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  194. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  195. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  196. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  197. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  198. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  199. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  200. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  201. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  202. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  203. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  204. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  205. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  206. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  207. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  208. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  209. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  210. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  211. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  212. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  213. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  214. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  215. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  216. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  217. package/packages/pi-ai/src/models/index.ts +106 -0
  218. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  219. package/packages/pi-ai/src/models.test.ts +6 -5
  220. package/packages/pi-ai/src/models.ts +3 -153
  221. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  222. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  224. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +214 -0
  226. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +18 -8
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  235. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  237. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  238. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
  240. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  243. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +115 -4
  246. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
  249. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
  252. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  253. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
  254. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  255. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  256. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +273 -0
  257. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
  258. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +20 -9
  259. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
  260. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
  261. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  262. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +176 -40
  263. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
  265. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  266. package/src/resources/extensions/gsd/auto/phases.ts +70 -6
  267. package/src/resources/extensions/gsd/auto-model-selection.ts +3 -3
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -3
  269. package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
  270. package/src/resources/extensions/gsd/auto-worktree.ts +1 -0
  271. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +5 -3
  272. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  273. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
  274. package/src/resources/extensions/gsd/cache.ts +16 -5
  275. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  276. package/src/resources/extensions/gsd/commands/handlers/core.ts +5 -1
  277. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +57 -3
  278. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -0
  279. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  280. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  281. package/src/resources/extensions/gsd/guided-flow.ts +4 -2
  282. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  283. package/src/resources/extensions/gsd/preferences-validation.ts +10 -0
  284. package/src/resources/extensions/gsd/preferences.ts +6 -0
  285. package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
  286. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  287. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
  288. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
  289. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +117 -0
  290. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  291. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +3 -3
  292. package/src/resources/extensions/gsd/tests/preferences.test.ts +145 -0
  293. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +57 -2
  294. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  295. package/src/resources/extensions/gsd/types.ts +13 -0
  296. package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
  297. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  298. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  299. package/packages/pi-ai/dist/models.generated.js +0 -14343
  300. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  301. package/packages/pi-ai/src/models.generated.ts +0 -14345
  302. /package/dist/web/standalone/.next/static/{fMaWScj7m6EsI3DbaNv2_ → Es_JWCfFZjIvYZShmjyye}/_buildManifest.js +0 -0
  303. /package/dist/web/standalone/.next/static/{fMaWScj7m6EsI3DbaNv2_ → Es_JWCfFZjIvYZShmjyye}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@gsd/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@gsd/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.js\";\nimport { formatTimestamp, type TimestampFormat } from \"./timestamp.js\";\n\nexport interface ContentRange {\n\tstartIndex: number;\n\tendIndex: number;\n}\n\n/**\n * Component that renders a complete assistant message, or a sub-range of its content[].\n * When `range` is provided, only content[startIndex..endIndex] (inclusive) is rendered.\n * Non-text/thinking blocks within the range are silently skipped.\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate timestampFormat: TimestampFormat;\n\tprivate range?: ContentRange;\n\tprivate showMetadata: boolean;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\ttimestampFormat: TimestampFormat = \"date-time-iso\",\n\t\trange?: ContentRange,\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.timestampFormat = timestampFormat;\n\t\tthis.range = range;\n\t\t// No range = legacy full-message rendering; show metadata by default.\n\t\t// Ranged (interleaved) instances start with metadata hidden; chat-controller\n\t\t// calls setShowMetadata(true) on the last segment at message_end.\n\t\tthis.showMetadata = !range;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\tsetRange(range: ContentRange | undefined): void {\n\t\tthis.range = range;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetShowMetadata(show: boolean): void {\n\t\tthis.showMetadata = show;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst start = this.range?.startIndex ?? 0;\n\t\tconst end = this.range?.endIndex ?? message.content.length - 1;\n\t\tconst slice = message.content.slice(start, end + 1);\n\n\t\tconst hasVisibleContent = slice.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\t\tconst hasTextContent = message.content.some((c) => c.type === \"text\" && c.text.trim().length > 0);\n\t\tconst hasToolContent = message.content.some((c) => c.type === \"toolCall\" || c.type === \"serverToolUse\");\n\t\t// Claude Code often emits long reasoning blocks ahead of user-visible text/tool\n\t\t// output in the same lifecycle. Keep chat output visible without requiring a\n\t\t// manual thinking toggle every turn.\n\t\tconst shouldCapThinking = hasTextContent || hasToolContent || message.provider === \"claude-code\";\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order; non-text/thinking blocks are silently skipped\n\t\tfor (let i = 0; i < slice.length; i++) {\n\t\t\tconst content = slice[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = slice\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static \"Thinking...\" label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.italic(theme.fg(\"thinkingText\", \"Thinking...\")), 1, 0));\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tconst thinkingMarkdown = new Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\titalic: true,\n\t\t\t\t\t});\n\t\t\t\t\t// Keep visible chat output readable when thinking traces are long.\n\t\t\t\t\t// Tool-bearing turns can stream text in a later assistant message.\n\t\t\t\t\tif (shouldCapThinking) {\n\t\t\t\t\t\tthinkingMarkdown.maxLines = 8;\n\t\t\t\t\t}\n\t\t\t\t\tthis.contentContainer.addChild(thinkingMarkdown);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Metadata (errors, timestamp): gated on showMetadata so ranged instances stay clean\n\t\t// until chat-controller explicitly enables it on the last segment at message_end.\n\t\tif (this.showMetadata) {\n\t\t\t// Check if aborted - show after partial content\n\t\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\t\tif (!hasToolCalls) {\n\t\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\t\tconst abortMessage =\n\t\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (message.stopReason && message.timestamp) {\n\t\t\t\tconst timeStr = formatTimestamp(message.timestamp, this.timestampFormat);\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", timeStr), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@gsd/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@gsd/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.js\";\nimport { type TimestampFormat } from \"./timestamp.js\";\nimport { renderChatFrame } from \"./chat-frame.js\";\n\nexport interface ContentRange {\n\tstartIndex: number;\n\tendIndex: number;\n}\n\n/**\n * Component that renders a complete assistant message, or a sub-range of its content[].\n * When `range` is provided, only content[startIndex..endIndex] (inclusive) is rendered.\n * Non-text/thinking blocks within the range are silently skipped.\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate timestampFormat: TimestampFormat;\n\tprivate range?: ContentRange;\n\tprivate showMetadata: boolean;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\ttimestampFormat: TimestampFormat = \"date-time-iso\",\n\t\trange?: ContentRange,\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.timestampFormat = timestampFormat;\n\t\tthis.range = range;\n\t\t// No range = legacy full-message rendering; show metadata by default.\n\t\t// Ranged (interleaved) instances start with metadata hidden; chat-controller\n\t\t// calls setShowMetadata(true) on the last segment at message_end.\n\t\tthis.showMetadata = !range;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\tsetRange(range: ContentRange | undefined): void {\n\t\tthis.range = range;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetShowMetadata(show: boolean): void {\n\t\tthis.showMetadata = show;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst start = this.range?.startIndex ?? 0;\n\t\tconst end = this.range?.endIndex ?? message.content.length - 1;\n\t\tconst slice = message.content.slice(start, end + 1);\n\n\t\tconst hasVisibleContent = slice.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\t\tconst hasTextContent = message.content.some((c) => c.type === \"text\" && c.text.trim().length > 0);\n\t\tconst hasToolContent = message.content.some((c) => c.type === \"toolCall\" || c.type === \"serverToolUse\");\n\t\t// Claude Code often emits long reasoning blocks ahead of user-visible text/tool\n\t\t// output in the same lifecycle. Keep chat output visible without requiring a\n\t\t// manual thinking toggle every turn.\n\t\tconst shouldCapThinking = hasTextContent || hasToolContent || message.provider === \"claude-code\";\n\n\t\t// Render content in order; non-text/thinking blocks are silently skipped\n\t\tfor (let i = 0; i < slice.length; i++) {\n\t\t\tconst content = slice[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = slice\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static \"Thinking...\" label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.italic(theme.fg(\"thinkingText\", \"Thinking...\")), 1, 0));\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tconst thinkingMarkdown = new Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\titalic: true,\n\t\t\t\t\t});\n\t\t\t\t\t// Keep visible chat output readable when thinking traces are long.\n\t\t\t\t\t// Tool-bearing turns can stream text in a later assistant message.\n\t\t\t\t\tif (shouldCapThinking) {\n\t\t\t\t\t\tthinkingMarkdown.maxLines = 8;\n\t\t\t\t\t}\n\t\t\t\t\tthis.contentContainer.addChild(thinkingMarkdown);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Metadata (errors, timestamp): gated on showMetadata so ranged instances stay clean\n\t\t// until chat-controller explicitly enables it on the last segment at message_end.\n\t\tif (this.showMetadata) {\n\t\t\t// Check if aborted - show after partial content\n\t\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\t\tif (!hasToolCalls) {\n\t\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\t\tconst abortMessage =\n\t\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst frameWidth = Math.max(20, width);\n\t\tconst contentWidth = Math.max(1, frameWidth - 4);\n\t\tconst lines = super.render(contentWidth);\n\t\tconst headerLabel = this.lastMessage?.model ? `GSD - ${this.lastMessage.model}` : \"GSD\";\n\t\tconst framed = renderChatFrame(lines, frameWidth, {\n\t\t\tlabel: headerLabel,\n\t\t\ttone: \"assistant\",\n\t\t\ttimestamp: this.lastMessage?.timestamp,\n\t\t\ttimestampFormat: this.timestampFormat,\n\t\t\tshowTimestamp: this.showMetadata,\n\t\t});\n\t\tif (framed.length === 0) {\n\t\t\treturn framed;\n\t\t}\n\t\treturn [\"\", ...framed];\n\t}\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { type TimestampFormat } from "./timestamp.js";
2
+ type FrameTone = "assistant" | "user";
3
+ export declare function renderChatFrame(contentLines: string[], width: number, opts: {
4
+ label: string;
5
+ tone: FrameTone;
6
+ timestamp?: number;
7
+ timestampFormat: TimestampFormat;
8
+ showTimestamp?: boolean;
9
+ }): string[];
10
+ export {};
11
+ //# sourceMappingURL=chat-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-frame.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEvE,KAAK,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;AAUtC,wBAAgB,eAAe,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;IACL,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB,GACC,MAAM,EAAE,CA0CV"}
@@ -0,0 +1,47 @@
1
+ import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
2
+ import { theme } from "../theme/theme.js";
3
+ import { formatTimestamp } from "./timestamp.js";
4
+ function trimOuterBlankLines(lines) {
5
+ let start = 0;
6
+ let end = lines.length;
7
+ while (start < end && lines[start].trim().length === 0)
8
+ start++;
9
+ while (end > start && lines[end - 1].trim().length === 0)
10
+ end--;
11
+ return lines.slice(start, end);
12
+ }
13
+ export function renderChatFrame(contentLines, width, opts) {
14
+ const outerWidth = Math.max(20, width);
15
+ const contentWidth = Math.max(1, outerWidth - 2); // "│ " + content
16
+ const borderColor = opts.tone === "user" ? "borderAccent" : "border";
17
+ const borderMuted = opts.tone === "user" ? "borderMuted" : "borderMuted";
18
+ const border = (s) => theme.fg(borderColor, s);
19
+ const leftRaw = `• ${opts.label}`;
20
+ const rightRaw = opts.showTimestamp === false || !opts.timestamp
21
+ ? ""
22
+ : formatTimestamp(opts.timestamp, opts.timestampFormat);
23
+ const leftBudget = rightRaw
24
+ ? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)
25
+ : outerWidth;
26
+ const left = truncateToWidth(leftRaw, leftBudget, "");
27
+ const leftStyled = opts.tone === "user"
28
+ ? theme.fg("accent", theme.bold(left))
29
+ : theme.fg("muted", theme.bold(left));
30
+ const rightStyled = rightRaw ? theme.fg("dim", rightRaw) : "";
31
+ const gap = rightRaw.length > 0
32
+ ? Math.max(1, outerWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled))
33
+ : Math.max(0, outerWidth - visibleWidth(leftStyled));
34
+ const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
35
+ const headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));
36
+ const sourceLines = trimOuterBlankLines(contentLines);
37
+ const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
38
+ const clipped = truncateToWidth(line, contentWidth, "");
39
+ return border("│ ") + clipped;
40
+ });
41
+ return [
42
+ theme.fg(borderMuted, "─".repeat(outerWidth)),
43
+ headerRow + " ".repeat(headerPad),
44
+ ...bodyLines,
45
+ ];
46
+ }
47
+ //# sourceMappingURL=chat-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-frame.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { formatTimestamp, type TimestampFormat } from \"./timestamp.js\";\n\ntype FrameTone = \"assistant\" | \"user\";\n\nfunction trimOuterBlankLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim().length === 0) start++;\n\twhile (end > start && lines[end - 1].trim().length === 0) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function renderChatFrame(\n\tcontentLines: string[],\n\twidth: number,\n\topts: {\n\t\tlabel: string;\n\t\ttone: FrameTone;\n\t\ttimestamp?: number;\n\t\ttimestampFormat: TimestampFormat;\n\t\tshowTimestamp?: boolean;\n\t},\n): string[] {\n\tconst outerWidth = Math.max(20, width);\n\tconst contentWidth = Math.max(1, outerWidth - 2); // \"│ \" + content\n\tconst borderColor = opts.tone === \"user\" ? \"borderAccent\" : \"border\";\n\tconst borderMuted = opts.tone === \"user\" ? \"borderMuted\" : \"borderMuted\";\n\tconst border = (s: string) => theme.fg(borderColor, s);\n\tconst leftRaw = `• ${opts.label}`;\n\tconst rightRaw =\n\t\topts.showTimestamp === false || !opts.timestamp\n\t\t\t? \"\"\n\t\t\t: formatTimestamp(opts.timestamp, opts.timestampFormat);\n\n\tconst leftBudget = rightRaw\n\t\t? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)\n\t\t: outerWidth;\n\tconst left = truncateToWidth(leftRaw, leftBudget, \"\");\n\tconst leftStyled =\n\t\topts.tone === \"user\"\n\t\t\t? theme.fg(\"accent\", theme.bold(left))\n\t\t\t: theme.fg(\"muted\", theme.bold(left));\n\tconst rightStyled = rightRaw ? theme.fg(\"dim\", rightRaw) : \"\";\n\tconst gap =\n\t\trightRaw.length > 0\n\t\t\t? Math.max(\n\t\t\t\t\t1,\n\t\t\t\t\touterWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled),\n\t\t\t\t)\n\t\t\t: Math.max(0, outerWidth - visibleWidth(leftStyled));\n\tconst headerRow = `${leftStyled}${\" \".repeat(gap)}${rightStyled}`;\n\tconst headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));\n\n\tconst sourceLines = trimOuterBlankLines(contentLines);\n\tconst bodyLines = (sourceLines.length > 0 ? sourceLines : [\"\"]).map((line) => {\n\t\tconst clipped = truncateToWidth(line, contentWidth, \"\");\n\t\treturn border(\"│ \") + clipped;\n\t});\n\n\treturn [\n\t\ttheme.fg(borderMuted, \"─\".repeat(outerWidth)),\n\t\theaderRow + \" \".repeat(headerPad),\n\t\t...bodyLines,\n\t];\n}\n"]}
@@ -60,6 +60,14 @@ export declare class ToolExecutionComponent extends Container {
60
60
  details?: any;
61
61
  isError: boolean;
62
62
  }, isPartial?: boolean): void;
63
+ /**
64
+ * Mark a tool call as historical when replaying from session context and
65
+ * no matching tool result is available. Happens after compaction squashes
66
+ * tool_result messages out of history — the tool call block survives but
67
+ * the result is gone. Without this, the component stays in "Running" state
68
+ * forever even though the tool completed long ago.
69
+ */
70
+ markHistoricalNoResult(): void;
63
71
  /**
64
72
  * Finalize a pending tool call as failed/interrupted while preserving any streamed partial output.
65
73
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,SAAS,EAOT,KAAK,GAAG,EAER,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AA8FxE,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAC,CAIb;IAEF,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,OAAO,CAAC,eAAe,CAAC,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA8D;IAGrF,OAAO,CAAC,uBAAuB,CAA2C;IAE1E,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAElD,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,KAAK,kBAAkB,GAE7B;gBAGA,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,oBAAoB,YAAK,EAClC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,EAAE,EAAE,GAAG,EACP,GAAG,GAAE,MAAsB;IA2B5B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAOhC,OAAO,IAAI,IAAI;IASf,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAQ3B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,8BAA8B;IAkBtC,OAAO,CAAC,oCAAoC;IAyD5C;;;OAGG;IACH,eAAe,IAAI,IAAI;IAWvB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA6B5B,YAAY,CACX,MAAM,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClF,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;KACjB,EACD,SAAS,UAAQ,GACf,IAAI;IAeP;;OAEG;IACH,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAoBzC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IA2BlC,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAKpC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAKzB,UAAU,IAAI,IAAI;IAKlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAOxC,OAAO,CAAC,aAAa;IAiJrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+EzB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,mBAAmB;CAoX3B"}
1
+ {"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,SAAS,EAOT,KAAK,GAAG,EAGR,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AA6IxE,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAC,CAIb;IAEF,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,OAAO,CAAC,eAAe,CAAC,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA8D;IAGrF,OAAO,CAAC,uBAAuB,CAA2C;IAE1E,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAElD,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,KAAK,kBAAkB,GAE7B;gBAGA,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,oBAAoB,YAAK,EAClC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,EAAE,EAAE,GAAG,EACP,GAAG,GAAE,MAAsB;IA2B5B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAOhC,OAAO,IAAI,IAAI;IASf,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAQ3B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,8BAA8B;IAkBtC,OAAO,CAAC,oCAAoC;IAyD5C;;;OAGG;IACH,eAAe,IAAI,IAAI;IAWvB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA6B5B,YAAY,CACX,MAAM,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClF,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;KACjB,EACD,SAAS,UAAQ,GACf,IAAI;IAeP;;;;;;OAMG;IACH,sBAAsB,IAAI,IAAI;IAU9B;;OAEG;IACH,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAoBzC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IA2BlC,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAKpC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAKzB,UAAU,IAAI,IAAI;IAKlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAsBxC,OAAO,CAAC,aAAa;IA6IrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+EzB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,mBAAmB;CAoX3B"}
@@ -1,4 +1,4 @@
1
- import { Box, Container, getCapabilities, Image, imageFallback, Spacer, Text, truncateToWidth, } from "@gsd/pi-tui";
1
+ import { Box, Container, getCapabilities, Image, imageFallback, Spacer, Text, truncateToWidth, visibleWidth, } from "@gsd/pi-tui";
2
2
  import stripAnsi from "strip-ansi";
3
3
  import { computeEditDiff } from "../../../core/tools/edit-diff.js";
4
4
  import { allTools } from "../../../core/tools/index.js";
@@ -51,6 +51,39 @@ function parseMcpToolName(name) {
51
51
  return null;
52
52
  return { server: rest.slice(0, delim), tool: rest.slice(delim + 2) };
53
53
  }
54
+ function trimOuterBlankLines(lines) {
55
+ let start = 0;
56
+ let end = lines.length;
57
+ while (start < end && lines[start].trim().length === 0)
58
+ start++;
59
+ while (end > start && lines[end - 1].trim().length === 0)
60
+ end--;
61
+ return lines.slice(start, end);
62
+ }
63
+ function renderToolFrame(contentLines, width, opts) {
64
+ const outerWidth = Math.max(20, width);
65
+ const contentWidth = Math.max(1, outerWidth - 2); // "│ " + content
66
+ const borderColor = opts.tone === "error" ? "error" : "toolTitle";
67
+ const topColor = opts.tone === "error" ? "error" : "toolTitle";
68
+ const labelColor = opts.tone === "error" ? "error" : "toolTitle";
69
+ const statusColor = opts.tone === "error" ? "error" : opts.tone === "pending" ? "warning" : "success";
70
+ const border = (s) => theme.fg(borderColor, s);
71
+ const leftStyled = theme.fg(labelColor, theme.bold(`• ${opts.label}`));
72
+ const rightStyled = theme.fg(statusColor, opts.status);
73
+ const gap = Math.max(1, outerWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled));
74
+ const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
75
+ const headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));
76
+ const sourceLines = trimOuterBlankLines(contentLines);
77
+ const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
78
+ const clipped = truncateToWidth(line, contentWidth, "");
79
+ return border("│ ") + clipped;
80
+ });
81
+ return [
82
+ theme.fg(topColor, "─".repeat(outerWidth)),
83
+ headerRow + " ".repeat(headerPad),
84
+ ...bodyLines,
85
+ ];
86
+ }
54
87
  const COMPACT_ARG_VALUE_LIMIT = 60;
55
88
  const GENERIC_OUTPUT_PREVIEW_LINES = 10;
56
89
  const GENERIC_ARGS_JSON_PREVIEW_LINES = 10;
@@ -293,6 +326,23 @@ export class ToolExecutionComponent extends Container {
293
326
  // Convert non-PNG images to PNG for Kitty protocol (async)
294
327
  this.maybeConvertImagesForKitty();
295
328
  }
329
+ /**
330
+ * Mark a tool call as historical when replaying from session context and
331
+ * no matching tool result is available. Happens after compaction squashes
332
+ * tool_result messages out of history — the tool call block survives but
333
+ * the result is gone. Without this, the component stays in "Running" state
334
+ * forever even though the tool completed long ago.
335
+ */
336
+ markHistoricalNoResult() {
337
+ if (this.result)
338
+ return; // real result already set, nothing to do
339
+ this.isPartial = false;
340
+ this.result = {
341
+ content: [],
342
+ isError: false,
343
+ };
344
+ this.updateDisplay();
345
+ }
296
346
  /**
297
347
  * Finalize a pending tool call as failed/interrupted while preserving any streamed partial output.
298
348
  */
@@ -364,15 +414,25 @@ export class ToolExecutionComponent extends Container {
364
414
  if (this.hideComponent) {
365
415
  return [];
366
416
  }
367
- return super.render(width);
417
+ const frameWidth = Math.max(20, width);
418
+ const contentWidth = Math.max(1, frameWidth - 4);
419
+ const lines = super.render(contentWidth);
420
+ const frameTone = this.result?.isError ? "error" : this.isPartial || !this.result ? "pending" : "success";
421
+ const frameStatus = this.isPartial || !this.result ? "Running" : this.result.isError ? "Error" : "Done";
422
+ const parsed = parseMcpToolName(this.toolName);
423
+ const frameLabel = parsed
424
+ ? `Tool ${parsed.server}·${parsed.tool}`
425
+ : `Tool ${this.normalizedToolName || this.toolName || "unknown"}`;
426
+ const framed = renderToolFrame(lines, frameWidth, {
427
+ label: frameLabel,
428
+ status: frameStatus,
429
+ tone: frameTone,
430
+ });
431
+ return framed.length > 0 ? ["", ...framed] : framed;
368
432
  }
369
433
  updateDisplay() {
370
- // Set background based on state
371
- const bgFn = this.isPartial
372
- ? (text) => theme.bg("toolPendingBg", text)
373
- : this.result?.isError
374
- ? (text) => theme.bg("toolErrorBg", text)
375
- : (text) => theme.bg("toolSuccessBg", text);
434
+ // Tool body now uses transparent background; status is conveyed in the frame header.
435
+ const bgFn = (text) => text;
376
436
  const useBuiltInRenderer = this.shouldUseBuiltInRenderer();
377
437
  let customRendererHasContent = false;
378
438
  this.hideComponent = false;