gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.ffbcc03

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 (403) hide show
  1. package/dist/resources/extensions/gsd/activity-log.js +16 -0
  2. package/dist/resources/extensions/gsd/auto/loop.js +147 -10
  3. package/dist/resources/extensions/gsd/auto/phases.js +113 -3
  4. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  5. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
  6. package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
  8. package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
  9. package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
  10. package/dist/resources/extensions/gsd/auto-verification.js +100 -2
  11. package/dist/resources/extensions/gsd/auto.js +28 -2
  12. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  13. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
  14. package/dist/resources/extensions/gsd/cache.js +16 -5
  15. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  16. package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
  17. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  18. package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  19. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  20. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  21. package/dist/resources/extensions/gsd/git-service.js +49 -1
  22. package/dist/resources/extensions/gsd/graph-context.js +98 -7
  23. package/dist/resources/extensions/gsd/gsd-db.js +260 -2
  24. package/dist/resources/extensions/gsd/guided-flow.js +24 -1
  25. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  26. package/dist/resources/extensions/gsd/journal.js +27 -0
  27. package/dist/resources/extensions/gsd/metrics.js +19 -0
  28. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  29. package/dist/resources/extensions/gsd/preferences-models.js +20 -3
  30. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  31. package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
  32. package/dist/resources/extensions/gsd/preferences.js +26 -0
  33. package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
  34. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  35. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  36. package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
  37. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  38. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  39. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  40. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  41. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  42. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  43. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  44. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  45. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  46. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  47. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  48. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  49. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  50. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  51. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  52. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  53. package/dist/web/standalone/.next/BUILD_ID +1 -1
  54. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  55. package/dist/web/standalone/.next/build-manifest.json +2 -2
  56. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/index.html +1 -1
  79. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  86. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  87. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  89. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  90. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  91. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  92. package/package.json +1 -1
  93. package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
  94. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
  95. package/packages/mcp-server/dist/readers/graph.js +107 -0
  96. package/packages/mcp-server/dist/readers/graph.js.map +1 -1
  97. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  98. package/packages/mcp-server/dist/workflow-tools.js +88 -6
  99. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  100. package/packages/mcp-server/src/readers/graph.test.ts +178 -0
  101. package/packages/mcp-server/src/readers/graph.ts +148 -1
  102. package/packages/mcp-server/src/workflow-tools.ts +95 -10
  103. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  104. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  105. package/packages/pi-ai/dist/index.d.ts +1 -9
  106. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  107. package/packages/pi-ai/dist/index.js +1 -9
  108. package/packages/pi-ai/dist/index.js.map +1 -1
  109. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  110. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  111. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  112. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  113. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  114. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  115. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  116. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  117. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  118. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  120. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  121. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  122. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  123. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  124. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  125. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  126. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  127. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  128. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  129. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  130. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  131. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  132. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  133. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  134. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  135. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  136. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  137. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  138. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  139. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  140. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  141. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  142. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  143. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  144. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  145. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  146. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  147. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  148. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  149. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  150. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  151. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  152. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  153. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  154. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  155. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  156. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  157. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  158. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  159. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  160. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  161. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  162. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  163. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  164. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  165. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  166. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  167. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  168. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  169. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  170. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  172. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  173. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  174. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  175. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  176. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  177. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  178. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  179. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  180. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  181. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  182. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  184. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  185. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  186. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  187. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  188. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  189. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  190. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  191. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  192. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  193. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  194. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  195. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  196. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  197. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  198. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  199. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  200. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  201. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  202. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  203. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  204. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  205. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  206. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  207. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  208. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  209. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  210. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  212. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  213. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  214. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  215. package/packages/pi-ai/dist/models/index.js +80 -0
  216. package/packages/pi-ai/dist/models/index.js.map +1 -0
  217. package/packages/pi-ai/dist/models.d.ts +1 -36
  218. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  219. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  220. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  221. package/packages/pi-ai/dist/models.js +3 -112
  222. package/packages/pi-ai/dist/models.js.map +1 -1
  223. package/packages/pi-ai/dist/models.test.js +6 -5
  224. package/packages/pi-ai/dist/models.test.js.map +1 -1
  225. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  226. package/packages/pi-ai/src/index.ts +1 -9
  227. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  228. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  229. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  230. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  231. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  232. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  233. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  234. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  235. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  236. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  237. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  238. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  239. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  240. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  241. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  242. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  243. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  244. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  245. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  246. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  247. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  248. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  249. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  250. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  251. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  252. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  253. package/packages/pi-ai/src/models/index.ts +106 -0
  254. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  255. package/packages/pi-ai/src/models.test.ts +6 -5
  256. package/packages/pi-ai/src/models.ts +3 -153
  257. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  258. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  260. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
  262. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  264. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  265. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  266. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  267. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  269. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  288. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
  289. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
  297. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  298. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  299. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
  300. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  301. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  302. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
  303. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
  304. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
  305. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
  306. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  307. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
  308. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
  309. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
  310. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  311. package/packages/pi-coding-agent/tsconfig.json +2 -2
  312. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  313. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  314. package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
  315. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  316. package/src/resources/extensions/gsd/auto/phases.ts +123 -3
  317. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  318. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
  319. package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
  320. package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
  321. package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
  322. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  323. package/src/resources/extensions/gsd/auto-verification.ts +129 -2
  324. package/src/resources/extensions/gsd/auto.ts +34 -2
  325. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  326. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
  327. package/src/resources/extensions/gsd/cache.ts +16 -5
  328. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  329. package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
  330. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  331. package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  332. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  333. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  334. package/src/resources/extensions/gsd/git-service.ts +68 -0
  335. package/src/resources/extensions/gsd/graph-context.ts +139 -12
  336. package/src/resources/extensions/gsd/gsd-db.ts +321 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +33 -1
  338. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  339. package/src/resources/extensions/gsd/journal.ts +30 -0
  340. package/src/resources/extensions/gsd/metrics.ts +26 -0
  341. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  342. package/src/resources/extensions/gsd/preferences-models.ts +20 -3
  343. package/src/resources/extensions/gsd/preferences-types.ts +32 -0
  344. package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
  345. package/src/resources/extensions/gsd/preferences.ts +28 -0
  346. package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
  347. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  348. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  349. package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  350. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
  351. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
  352. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  353. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  354. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
  355. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  356. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
  357. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  358. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  359. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  360. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  361. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  362. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  363. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  364. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  365. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  366. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  367. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  368. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
  369. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  370. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  372. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  373. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  374. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  375. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  376. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  377. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  378. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  379. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  380. package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
  381. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  382. package/src/resources/extensions/gsd/types.ts +14 -1
  383. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  384. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  385. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  386. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  387. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  388. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  389. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  390. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  391. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  392. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  393. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  394. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  395. package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
  396. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  397. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  398. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  399. package/packages/pi-ai/dist/models.generated.js +0 -14343
  400. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  401. package/packages/pi-ai/src/models.generated.ts +0 -14345
  402. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
  403. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
@@ -0,0 +1,59 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import type { AuthStorage } from "./auth-storage.js";
4
+ import { ModelRegistry } from "./model-registry.js";
5
+
6
+ function createRegistryWithCapturedResolver() {
7
+ let capturedResolver: ((provider: string) => string | undefined) | undefined;
8
+ const authStorage = {
9
+ setFallbackResolver: (resolver: (provider: string) => string | undefined) => {
10
+ capturedResolver = resolver;
11
+ },
12
+ onCredentialChange: () => {},
13
+ getOAuthProviders: () => [],
14
+ get: () => undefined,
15
+ hasAuth: () => false,
16
+ getApiKey: async () => undefined,
17
+ } as unknown as AuthStorage;
18
+
19
+ new ModelRegistry(authStorage, undefined);
20
+ assert.ok(capturedResolver, "ModelRegistry should register a fallback resolver");
21
+ return capturedResolver!;
22
+ }
23
+
24
+ describe("ModelRegistry env fallback resolver (#3782)", () => {
25
+ it("falls back to built-in provider env vars when models.json has no custom key", () => {
26
+ const prev = process.env.MINIMAX_API_KEY;
27
+ process.env.MINIMAX_API_KEY = "minimax-env-test-key";
28
+
29
+ try {
30
+ const resolver = createRegistryWithCapturedResolver();
31
+ assert.equal(
32
+ resolver("minimax"),
33
+ "minimax-env-test-key",
34
+ "fallback resolver should return built-in provider env keys",
35
+ );
36
+ } finally {
37
+ if (prev === undefined) {
38
+ delete process.env.MINIMAX_API_KEY;
39
+ } else {
40
+ process.env.MINIMAX_API_KEY = prev;
41
+ }
42
+ }
43
+ });
44
+
45
+ it("still returns undefined when no custom or built-in env key exists", () => {
46
+ const prev = process.env.MINIMAX_API_KEY;
47
+ delete process.env.MINIMAX_API_KEY;
48
+
49
+ try {
50
+ const resolver = createRegistryWithCapturedResolver();
51
+ assert.equal(resolver("minimax"), undefined);
52
+ assert.equal(resolver("totally-unknown-provider"), undefined);
53
+ } finally {
54
+ if (prev !== undefined) {
55
+ process.env.MINIMAX_API_KEY = prev;
56
+ }
57
+ }
58
+ });
59
+ });
@@ -8,6 +8,7 @@ import {
8
8
  type AssistantMessageEventStream,
9
9
  type Context,
10
10
  getApiProvider,
11
+ getEnvApiKey,
11
12
  getModels,
12
13
  getProviders,
13
14
  type KnownProvider,
@@ -245,7 +246,7 @@ export class ModelRegistry {
245
246
  if (keyConfig) {
246
247
  return resolveConfigValue(keyConfig);
247
248
  }
248
- return undefined;
249
+ return getEnvApiKey(provider);
249
250
  });
250
251
 
251
252
  // Refresh models when credentials change (e.g., OAuth token refresh with new model limits)
@@ -48,6 +48,25 @@ function renderToolCollapsed(
48
48
  }
49
49
 
50
50
  describe("ToolExecutionComponent", () => {
51
+ test("renders framed header with Running status while tool is partial", () => {
52
+ const rendered = renderToolCollapsed("mcp__demo__do_thing", { ok: true });
53
+
54
+ assert.match(rendered, /Tool demo\u00b7do_thing/);
55
+ assert.match(rendered, /Running/);
56
+ });
57
+
58
+ test("renders framed header with Error status for failed tool result", () => {
59
+ const rendered = renderTool(
60
+ "mcp__demo__do_thing",
61
+ { ok: true },
62
+ { content: [{ type: "text", text: "boom" }], isError: true },
63
+ );
64
+
65
+ assert.match(rendered, /Tool demo\u00b7do_thing/);
66
+ assert.match(rendered, /Error/);
67
+ assert.match(rendered, /boom/);
68
+ });
69
+
51
70
  test("renders capitalized Claude Code Bash tool names with bash output instead of generic args JSON", () => {
52
71
  const rendered = renderTool(
53
72
  "Bash",
@@ -1,7 +1,8 @@
1
1
  import type { AssistantMessage } from "@gsd/pi-ai";
2
2
  import { Container, Markdown, type MarkdownTheme, Spacer, Text } from "@gsd/pi-tui";
3
3
  import { getMarkdownTheme, theme } from "../theme/theme.js";
4
- import { formatTimestamp, type TimestampFormat } from "./timestamp.js";
4
+ import { type TimestampFormat } from "./timestamp.js";
5
+ import { renderChatFrame } from "./chat-frame.js";
5
6
 
6
7
  export interface ContentRange {
7
8
  startIndex: number;
@@ -89,10 +90,10 @@ export class AssistantMessageComponent extends Container {
89
90
  );
90
91
  const hasTextContent = message.content.some((c) => c.type === "text" && c.text.trim().length > 0);
91
92
  const hasToolContent = message.content.some((c) => c.type === "toolCall" || c.type === "serverToolUse");
92
-
93
- if (hasVisibleContent) {
94
- this.contentContainer.addChild(new Spacer(1));
95
- }
93
+ // Claude Code often emits long reasoning blocks ahead of user-visible text/tool
94
+ // output in the same lifecycle. Keep chat output visible without requiring a
95
+ // manual thinking toggle every turn.
96
+ const shouldCapThinking = hasTextContent || hasToolContent || message.provider === "claude-code";
96
97
 
97
98
  // Render content in order; non-text/thinking blocks are silently skipped
98
99
  for (let i = 0; i < slice.length; i++) {
@@ -122,7 +123,7 @@ export class AssistantMessageComponent extends Container {
122
123
  });
123
124
  // Keep visible chat output readable when thinking traces are long.
124
125
  // Tool-bearing turns can stream text in a later assistant message.
125
- if (hasTextContent || hasToolContent) {
126
+ if (shouldCapThinking) {
126
127
  thinkingMarkdown.maxLines = 8;
127
128
  }
128
129
  this.contentContainer.addChild(thinkingMarkdown);
@@ -156,10 +157,24 @@ export class AssistantMessageComponent extends Container {
156
157
  }
157
158
  }
158
159
 
159
- if (message.stopReason && message.timestamp) {
160
- const timeStr = formatTimestamp(message.timestamp, this.timestampFormat);
161
- this.contentContainer.addChild(new Text(theme.fg("dim", timeStr), 1, 0));
162
- }
163
160
  }
164
161
  }
162
+
163
+ override render(width: number): string[] {
164
+ const frameWidth = Math.max(20, width);
165
+ const contentWidth = Math.max(1, frameWidth - 4);
166
+ const lines = super.render(contentWidth);
167
+ const headerLabel = this.lastMessage?.model ? `GSD - ${this.lastMessage.model}` : "GSD";
168
+ const framed = renderChatFrame(lines, frameWidth, {
169
+ label: headerLabel,
170
+ tone: "assistant",
171
+ timestamp: this.lastMessage?.timestamp,
172
+ timestampFormat: this.timestampFormat,
173
+ showTimestamp: this.showMetadata,
174
+ });
175
+ if (framed.length === 0) {
176
+ return framed;
177
+ }
178
+ return ["", ...framed];
179
+ }
165
180
  }
@@ -0,0 +1,67 @@
1
+ import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
2
+ import { theme } from "../theme/theme.js";
3
+ import { formatTimestamp, type TimestampFormat } from "./timestamp.js";
4
+
5
+ type FrameTone = "assistant" | "user";
6
+
7
+ function trimOuterBlankLines(lines: string[]): string[] {
8
+ let start = 0;
9
+ let end = lines.length;
10
+ while (start < end && lines[start].trim().length === 0) start++;
11
+ while (end > start && lines[end - 1].trim().length === 0) end--;
12
+ return lines.slice(start, end);
13
+ }
14
+
15
+ export function renderChatFrame(
16
+ contentLines: string[],
17
+ width: number,
18
+ opts: {
19
+ label: string;
20
+ tone: FrameTone;
21
+ timestamp?: number;
22
+ timestampFormat: TimestampFormat;
23
+ showTimestamp?: boolean;
24
+ },
25
+ ): string[] {
26
+ const outerWidth = Math.max(20, width);
27
+ const contentWidth = Math.max(1, outerWidth - 2); // "│ " + content
28
+ const borderColor = opts.tone === "user" ? "borderAccent" : "border";
29
+ const borderMuted = opts.tone === "user" ? "borderMuted" : "borderMuted";
30
+ const border = (s: string) => theme.fg(borderColor, s);
31
+ const leftRaw = `• ${opts.label}`;
32
+ const rightRaw =
33
+ opts.showTimestamp === false || !opts.timestamp
34
+ ? ""
35
+ : formatTimestamp(opts.timestamp, opts.timestampFormat);
36
+
37
+ const leftBudget = rightRaw
38
+ ? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)
39
+ : outerWidth;
40
+ const left = truncateToWidth(leftRaw, leftBudget, "");
41
+ const leftStyled =
42
+ opts.tone === "user"
43
+ ? theme.fg("accent", theme.bold(left))
44
+ : theme.fg("muted", theme.bold(left));
45
+ const rightStyled = rightRaw ? theme.fg("dim", rightRaw) : "";
46
+ const gap =
47
+ rightRaw.length > 0
48
+ ? Math.max(
49
+ 1,
50
+ outerWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled),
51
+ )
52
+ : Math.max(0, outerWidth - visibleWidth(leftStyled));
53
+ const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
54
+ const headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));
55
+
56
+ const sourceLines = trimOuterBlankLines(contentLines);
57
+ const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
58
+ const clipped = truncateToWidth(line, contentWidth, "");
59
+ return border("│ ") + clipped;
60
+ });
61
+
62
+ return [
63
+ theme.fg(borderMuted, "─".repeat(outerWidth)),
64
+ headerRow + " ".repeat(headerPad),
65
+ ...bodyLines,
66
+ ];
67
+ }
@@ -9,6 +9,7 @@ import {
9
9
  Text,
10
10
  type TUI,
11
11
  truncateToWidth,
12
+ visibleWidth,
12
13
  } from "@gsd/pi-tui";
13
14
  import stripAnsi from "strip-ansi";
14
15
  import type { ToolDefinition } from "../../../core/extensions/types.js";
@@ -65,6 +66,53 @@ function parseMcpToolName(name: string): { server: string; tool: string } | null
65
66
  return { server: rest.slice(0, delim), tool: rest.slice(delim + 2) };
66
67
  }
67
68
 
69
+ type ToolFrameTone = "pending" | "success" | "error";
70
+
71
+ function trimOuterBlankLines(lines: string[]): string[] {
72
+ let start = 0;
73
+ let end = lines.length;
74
+ while (start < end && lines[start].trim().length === 0) start++;
75
+ while (end > start && lines[end - 1].trim().length === 0) end--;
76
+ return lines.slice(start, end);
77
+ }
78
+
79
+ function renderToolFrame(
80
+ contentLines: string[],
81
+ width: number,
82
+ opts: {
83
+ label: string;
84
+ status: string;
85
+ tone: ToolFrameTone;
86
+ },
87
+ ): string[] {
88
+ const outerWidth = Math.max(20, width);
89
+ const contentWidth = Math.max(1, outerWidth - 2); // "│ " + content
90
+
91
+ const borderColor = opts.tone === "error" ? "error" : "toolTitle";
92
+ const topColor = opts.tone === "error" ? "error" : "toolTitle";
93
+ const labelColor = opts.tone === "error" ? "error" : "toolTitle";
94
+ const statusColor = opts.tone === "error" ? "error" : opts.tone === "pending" ? "warning" : "success";
95
+ const border = (s: string) => theme.fg(borderColor, s);
96
+
97
+ const leftStyled = theme.fg(labelColor, theme.bold(`• ${opts.label}`));
98
+ const rightStyled = theme.fg(statusColor, opts.status);
99
+ const gap = Math.max(1, outerWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled));
100
+ const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
101
+ const headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));
102
+
103
+ const sourceLines = trimOuterBlankLines(contentLines);
104
+ const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
105
+ const clipped = truncateToWidth(line, contentWidth, "");
106
+ return border("│ ") + clipped;
107
+ });
108
+
109
+ return [
110
+ theme.fg(topColor, "─".repeat(outerWidth)),
111
+ headerRow + " ".repeat(headerPad),
112
+ ...bodyLines,
113
+ ];
114
+ }
115
+
68
116
  const COMPACT_ARG_VALUE_LIMIT = 60;
69
117
  const GENERIC_OUTPUT_PREVIEW_LINES = 10;
70
118
  const GENERIC_ARGS_JSON_PREVIEW_LINES = 10;
@@ -379,6 +427,23 @@ export class ToolExecutionComponent extends Container {
379
427
  this.maybeConvertImagesForKitty();
380
428
  }
381
429
 
430
+ /**
431
+ * Mark a tool call as historical when replaying from session context and
432
+ * no matching tool result is available. Happens after compaction squashes
433
+ * tool_result messages out of history — the tool call block survives but
434
+ * the result is gone. Without this, the component stays in "Running" state
435
+ * forever even though the tool completed long ago.
436
+ */
437
+ markHistoricalNoResult(): void {
438
+ if (this.result) return; // real result already set, nothing to do
439
+ this.isPartial = false;
440
+ this.result = {
441
+ content: [],
442
+ isError: false,
443
+ };
444
+ this.updateDisplay();
445
+ }
446
+
382
447
  /**
383
448
  * Finalize a pending tool call as failed/interrupted while preserving any streamed partial output.
384
449
  */
@@ -452,16 +517,27 @@ export class ToolExecutionComponent extends Container {
452
517
  if (this.hideComponent) {
453
518
  return [];
454
519
  }
455
- return super.render(width);
520
+ const frameWidth = Math.max(20, width);
521
+ const contentWidth = Math.max(1, frameWidth - 4);
522
+ const lines = super.render(contentWidth);
523
+ const frameTone: ToolFrameTone =
524
+ this.result?.isError ? "error" : this.isPartial || !this.result ? "pending" : "success";
525
+ const frameStatus = this.isPartial || !this.result ? "Running" : this.result.isError ? "Error" : "Done";
526
+ const parsed = parseMcpToolName(this.toolName);
527
+ const frameLabel = parsed
528
+ ? `Tool ${parsed.server}·${parsed.tool}`
529
+ : `Tool ${this.normalizedToolName || this.toolName || "unknown"}`;
530
+ const framed = renderToolFrame(lines, frameWidth, {
531
+ label: frameLabel,
532
+ status: frameStatus,
533
+ tone: frameTone,
534
+ });
535
+ return framed.length > 0 ? ["", ...framed] : framed;
456
536
  }
457
537
 
458
538
  private updateDisplay(): void {
459
- // Set background based on state
460
- const bgFn = this.isPartial
461
- ? (text: string) => theme.bg("toolPendingBg", text)
462
- : this.result?.isError
463
- ? (text: string) => theme.bg("toolErrorBg", text)
464
- : (text: string) => theme.bg("toolSuccessBg", text);
539
+ // Tool body now uses transparent background; status is conveyed in the frame header.
540
+ const bgFn = (text: string) => text;
465
541
 
466
542
  const useBuiltInRenderer = this.shouldUseBuiltInRenderer();
467
543
  let customRendererHasContent = false;
@@ -1,6 +1,7 @@
1
- import { Container, Markdown, type MarkdownTheme, Spacer, Text } from "@gsd/pi-tui";
2
- import { getMarkdownTheme, theme } from "../theme/theme.js";
3
- import { formatTimestamp, type TimestampFormat } from "./timestamp.js";
1
+ import { Container, Markdown, type MarkdownTheme } from "@gsd/pi-tui";
2
+ import { getMarkdownTheme } from "../theme/theme.js";
3
+ import { type TimestampFormat } from "./timestamp.js";
4
+ import { renderChatFrame } from "./chat-frame.js";
4
5
 
5
6
  const OSC133_ZONE_START = "\x1b]133;A\x07";
6
7
  const OSC133_ZONE_END = "\x1b]133;B\x07";
@@ -16,32 +17,28 @@ export class UserMessageComponent extends Container {
16
17
  super();
17
18
  this.timestamp = timestamp;
18
19
  this.timestampFormat = timestampFormat;
19
- this.addChild(new Spacer(1));
20
- this.addChild(
21
- new Markdown(text, 1, 1, markdownTheme, {
22
- bgColor: (text: string) => theme.bg("userMessageBg", text),
23
- color: (text: string) => theme.fg("userMessageText", text),
24
- }),
25
- );
20
+ this.addChild(new Markdown(text, 0, 0, markdownTheme));
26
21
  }
27
22
 
28
23
  override render(width: number): string[] {
29
- const lines = super.render(width);
30
- if (lines.length === 0) {
31
- return lines;
24
+ const frameWidth = Math.max(20, width);
25
+ const contentWidth = Math.max(1, frameWidth - 4);
26
+ const lines = super.render(contentWidth);
27
+ const framed = renderChatFrame(lines, frameWidth, {
28
+ label: "You",
29
+ tone: "user",
30
+ timestamp: this.timestamp,
31
+ timestampFormat: this.timestampFormat,
32
+ showTimestamp: true,
33
+ });
34
+ if (framed.length === 0) {
35
+ return framed;
32
36
  }
33
-
34
- // Insert right-aligned timestamp above the message content
35
- if (this.timestamp) {
36
- const timeStr = formatTimestamp(this.timestamp, this.timestampFormat);
37
- const label = theme.fg("dim", timeStr);
38
- const padding = Math.max(0, width - timeStr.length - 1);
39
- const timestampLine = " ".repeat(padding) + label;
40
- lines.splice(0, 0, timestampLine);
41
- }
42
-
43
- lines[0] = OSC133_ZONE_START + lines[0];
44
- lines[lines.length - 1] = lines[lines.length - 1] + OSC133_ZONE_END;
45
- return lines;
37
+ const out = ["", ...framed];
38
+ const firstFrameLine = 1;
39
+ const lastFrameLine = out.length - 1;
40
+ out[firstFrameLine] = OSC133_ZONE_START + out[firstFrameLine];
41
+ out[lastFrameLine] = out[lastFrameLine] + OSC133_ZONE_END;
42
+ return out;
46
43
  }
47
44
  }