gsd-pi 2.74.0-dev.16f2f3b → 2.74.0-dev.20f79a8

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 (246) hide show
  1. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -3
  2. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  3. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +45 -4
  4. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  5. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  6. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  7. package/dist/web/standalone/.next/BUILD_ID +1 -1
  8. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  9. package/dist/web/standalone/.next/build-manifest.json +2 -2
  10. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  11. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  12. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  28. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  29. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  30. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  31. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  32. package/dist/web/standalone/.next/server/app/index.html +1 -1
  33. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  40. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  41. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  42. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  43. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  44. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  45. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  46. package/package.json +1 -1
  47. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  48. package/packages/pi-ai/dist/index.d.ts +1 -9
  49. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  50. package/packages/pi-ai/dist/index.js +1 -9
  51. package/packages/pi-ai/dist/index.js.map +1 -1
  52. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  53. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  54. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  55. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  56. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  57. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  58. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  59. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  60. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  61. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  62. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  63. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  64. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  65. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  66. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  67. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  68. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  69. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  70. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  71. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  72. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  73. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  74. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  75. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  76. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  77. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  78. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  79. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  80. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  81. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  82. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  83. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  84. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  85. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  86. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  87. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  88. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  89. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  90. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  91. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  92. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  93. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  94. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  95. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  96. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  97. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  98. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  99. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  100. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  101. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  102. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  103. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  104. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  105. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  106. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  107. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  108. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  109. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  110. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  111. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  112. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  113. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  114. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  115. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  116. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  117. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  118. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  119. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  120. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  121. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  122. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  123. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  124. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  125. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  126. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  127. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  128. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  129. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  130. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  131. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  132. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  133. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  134. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  135. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  136. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  137. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  138. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  139. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  140. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  141. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  142. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  143. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  144. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  145. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  146. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  147. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  148. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  149. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  150. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  151. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  152. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  153. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  154. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  155. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  156. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  157. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  158. package/packages/pi-ai/dist/models/index.js +80 -0
  159. package/packages/pi-ai/dist/models/index.js.map +1 -0
  160. package/packages/pi-ai/dist/models.d.ts +1 -36
  161. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  162. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  163. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  164. package/packages/pi-ai/dist/models.js +3 -112
  165. package/packages/pi-ai/dist/models.js.map +1 -1
  166. package/packages/pi-ai/dist/models.test.js +6 -5
  167. package/packages/pi-ai/dist/models.test.js.map +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  169. package/packages/pi-ai/src/index.ts +1 -9
  170. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  171. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  172. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  173. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  174. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  175. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  176. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  177. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  178. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  179. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  180. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  181. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  182. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  183. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  184. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  185. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  186. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  187. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  188. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  189. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  190. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  191. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  192. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  193. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  194. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  195. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  196. package/packages/pi-ai/src/models/index.ts +106 -0
  197. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  198. package/packages/pi-ai/src/models.test.ts +6 -5
  199. package/packages/pi-ai/src/models.ts +3 -153
  200. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  201. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  203. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +214 -0
  205. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  207. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +18 -8
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  216. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +115 -4
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +6 -4
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  223. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  224. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +273 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +20 -9
  226. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
  227. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  228. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +176 -40
  229. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -4
  230. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  231. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -3
  232. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  233. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +56 -3
  234. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  235. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  236. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  237. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  238. package/src/resources/extensions/gsd/types.ts +13 -0
  239. package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
  240. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  241. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  242. package/packages/pi-ai/dist/models.generated.js +0 -14343
  243. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  244. package/packages/pi-ai/src/models.generated.ts +0 -14345
  245. /package/dist/web/standalone/.next/static/{C7qugsXHwdw4-b4ROHvOE → ZDXqgjuglsRoazETSKw1J}/_buildManifest.js +0 -0
  246. /package/dist/web/standalone/.next/static/{C7qugsXHwdw4-b4ROHvOE → ZDXqgjuglsRoazETSKw1J}/_ssgManifest.js +0 -0
@@ -95,6 +95,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
95
95
  }
96
96
 
97
97
  host.footer.invalidate();
98
+ const timestampFormat = host.settingsManager.getTimestampFormat();
98
99
 
99
100
  // Reset content index tracker and pinned state when a new assistant message starts
100
101
  if (event.type === "message_start" && event.message.role === "assistant") {
@@ -238,7 +239,10 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
238
239
  // content (#4144 regression). Prior sub-turn children stay in
239
240
  // chatContainer as frozen history; new segments append after them.
240
241
  if (contentBlocks.length < lastContentLength) {
241
- orphanedSegments = [...renderedSegments];
242
+ // Accumulate across successive shrinks — overwriting would drop
243
+ // segments displaced by an earlier shrink, leaving them stranded
244
+ // in chatContainer once the prune pass finally runs.
245
+ orphanedSegments = [...orphanedSegments, ...renderedSegments];
242
246
  renderedSegments = [];
243
247
  lastPinnedText = "";
244
248
  lastProcessedContentIndex = 0;
@@ -341,29 +345,35 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
341
345
  type DesiredSegment =
342
346
  | { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
343
347
  | { kind: "tool"; contentIndex: number; toolId: string };
344
- const desired: DesiredSegment[] = [];
345
- let runStart = -1;
346
- let runEnd = -1;
347
- let runType: "text" | "thinking" | undefined;
348
- const closeRun = () => {
349
- if (runStart !== -1 && runType) {
350
- desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
351
- runStart = -1;
352
- runEnd = -1;
353
- runType = undefined;
348
+ const desired: DesiredSegment[] = [];
349
+ let runStart = -1;
350
+ let runEnd = -1;
351
+ let runType: "text" | "thinking" | undefined;
352
+ const closeRun = () => {
353
+ if (runStart !== -1 && runType) {
354
+ desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
355
+ runStart = -1;
356
+ runEnd = -1;
357
+ runType = undefined;
354
358
  }
355
359
  };
356
- for (let i = 0; i < blocks.length; i++) {
357
- const b = blocks[i];
358
- const blockType = b.type === "text" || b.type === "thinking" ? b.type : undefined;
359
- const isTextLike = blockType === "text" || blockType === "thinking";
360
- const isTool = b.type === "toolCall" || b.type === "serverToolUse";
361
- // For Claude Code MCP turns, prune only pre-tool prose, never thinking.
362
- const shouldSkipProse = shouldDropPreToolProse && firstToolIdx >= 0 && i < firstToolIdx && blockType === "text";
363
- if (shouldSkipProse) {
364
- closeRun();
365
- continue;
366
- }
360
+ for (let i = 0; i < blocks.length; i++) {
361
+ const b = blocks[i];
362
+ const blockType = b.type === "text" || b.type === "thinking" ? b.type : undefined;
363
+ const isTextLike = blockType === "text" || blockType === "thinking";
364
+ const isTool = b.type === "toolCall" || b.type === "serverToolUse";
365
+ // For Claude Code MCP turns, prune only pre-tool prose, never thinking.
366
+ const textValue = blockType === "text" && typeof b?.text === "string" ? b.text : "";
367
+ const isLikelyQuestion = blockType === "text" && typeof textValue === "string" && /\?\s*$/.test(textValue.trim());
368
+ const shouldSkipProse = shouldDropPreToolProse
369
+ && firstToolIdx >= 0
370
+ && i < firstToolIdx
371
+ && blockType === "text"
372
+ && !isLikelyQuestion;
373
+ if (shouldSkipProse) {
374
+ closeRun();
375
+ continue;
376
+ }
367
377
  if (isTextLike) {
368
378
  if (runStart === -1) {
369
379
  runStart = i;
@@ -459,7 +469,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
459
469
  undefined,
460
470
  host.hideThinkingBlock,
461
471
  host.getMarkdownThemeWithSettings(),
462
- host.settingsManager.getTimestampFormat(),
472
+ timestampFormat,
463
473
  { startIndex: seg.startIndex, endIndex: seg.endIndex },
464
474
  );
465
475
  host.chatContainer.addChild(comp);
@@ -553,11 +563,11 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
553
563
  }
554
564
  break;
555
565
 
556
- case "message_end":
557
- if (event.message.role === "user") break;
558
- if (event.message.role === "assistant") {
559
- host.streamingMessage = event.message;
560
- let errorMessage: string | undefined;
566
+ case "message_end":
567
+ if (event.message.role === "user") break;
568
+ if (event.message.role === "assistant") {
569
+ host.streamingMessage = event.message;
570
+ let errorMessage: string | undefined;
561
571
  if (host.streamingMessage.stopReason === "aborted") {
562
572
  const retryAttempt = host.session.retryAttempt;
563
573
  errorMessage = retryAttempt > 0
@@ -566,18 +576,144 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
566
576
  host.streamingMessage.errorMessage = errorMessage;
567
577
  }
568
578
 
569
- const shouldRenderAssistant = hasVisibleAssistantContent(host.streamingMessage)
570
- || (
571
- (host.streamingMessage.stopReason === "aborted" || host.streamingMessage.stopReason === "error")
572
- && !hasAssistantToolBlocks(host.streamingMessage)
573
- );
574
- if (!host.streamingComponent && shouldRenderAssistant) {
575
- host.streamingComponent = new AssistantMessageComponent(
576
- undefined,
577
- host.hideThinkingBlock,
578
- host.getMarkdownThemeWithSettings(),
579
- host.settingsManager.getTimestampFormat(),
580
- );
579
+ const shouldRenderAssistant = hasVisibleAssistantContent(host.streamingMessage)
580
+ || (
581
+ (host.streamingMessage.stopReason === "aborted" || host.streamingMessage.stopReason === "error")
582
+ && !hasAssistantToolBlocks(host.streamingMessage)
583
+ );
584
+
585
+ // The final message_end payload can contain additional text/thinking
586
+ // blocks that never arrived via message_update (e.g. SDK result
587
+ // aggregation). Rebuild this in-flight turn from final content so
588
+ // ranges/components don't keep stale partial indices.
589
+ if (renderedSegments.length > 0) {
590
+ const finalBlocks = host.streamingMessage.content;
591
+ type DesiredSegment =
592
+ | { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
593
+ | { kind: "tool"; contentIndex: number; toolId: string };
594
+ const desired: DesiredSegment[] = [];
595
+ let runStart = -1;
596
+ let runEnd = -1;
597
+ let runType: "text" | "thinking" | undefined;
598
+ const closeRun = () => {
599
+ if (runStart !== -1 && runType) {
600
+ desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
601
+ runStart = -1;
602
+ runEnd = -1;
603
+ runType = undefined;
604
+ }
605
+ };
606
+
607
+ for (let i = 0; i < finalBlocks.length; i++) {
608
+ const block = finalBlocks[i] as any;
609
+ const blockType = block?.type === "text" || block?.type === "thinking" ? block.type : undefined;
610
+ const isTextLike = blockType === "text" || blockType === "thinking";
611
+ const isTool = block?.type === "toolCall" || block?.type === "serverToolUse";
612
+
613
+ if (isTextLike) {
614
+ if (runStart === -1) {
615
+ runStart = i;
616
+ runEnd = i;
617
+ runType = blockType;
618
+ } else if (runType !== blockType) {
619
+ closeRun();
620
+ runStart = i;
621
+ runEnd = i;
622
+ runType = blockType;
623
+ } else {
624
+ runEnd = i;
625
+ }
626
+ } else {
627
+ closeRun();
628
+ if (isTool) {
629
+ desired.push({ kind: "tool", contentIndex: i, toolId: block.id });
630
+ }
631
+ }
632
+ }
633
+ closeRun();
634
+
635
+ const toolComponentsById = new Map<string, ToolExecutionComponent>();
636
+ for (const [toolId, component] of host.pendingTools.entries()) {
637
+ toolComponentsById.set(toolId, component);
638
+ }
639
+
640
+ for (const seg of renderedSegments) {
641
+ host.chatContainer.removeChild(seg.component);
642
+ if (seg.kind === "tool") {
643
+ const priorBlocks = host.streamingMessage.content;
644
+ const priorBlock = priorBlocks[seg.contentIndex] as any;
645
+ if (priorBlock?.id && !toolComponentsById.has(priorBlock.id)) {
646
+ toolComponentsById.set(priorBlock.id, seg.component);
647
+ }
648
+ }
649
+ }
650
+ renderedSegments = [];
651
+ host.streamingComponent = undefined;
652
+
653
+ for (const seg of desired) {
654
+ if (seg.kind === "tool") {
655
+ const finalBlock = finalBlocks[seg.contentIndex] as any;
656
+ let component = toolComponentsById.get(seg.toolId);
657
+ if (!component && finalBlock?.id) {
658
+ component = host.pendingTools.get(finalBlock.id);
659
+ }
660
+ if (!component && finalBlock?.type === "toolCall") {
661
+ component = new ToolExecutionComponent(
662
+ finalBlock.name,
663
+ finalBlock.arguments,
664
+ { showImages: host.settingsManager.getShowImages() },
665
+ host.getRegisteredToolDefinition(finalBlock.name),
666
+ host.ui,
667
+ );
668
+ component.setExpanded(host.toolOutputExpanded);
669
+ host.pendingTools.set(finalBlock.id, component);
670
+ toolComponentsById.set(finalBlock.id, component);
671
+ } else if (!component && finalBlock?.type === "serverToolUse") {
672
+ component = new ToolExecutionComponent(
673
+ finalBlock.name,
674
+ finalBlock.input ?? {},
675
+ { showImages: host.settingsManager.getShowImages() },
676
+ undefined,
677
+ host.ui,
678
+ );
679
+ component.setExpanded(host.toolOutputExpanded);
680
+ host.pendingTools.set(finalBlock.id, component);
681
+ toolComponentsById.set(finalBlock.id, component);
682
+ }
683
+ if (component) {
684
+ host.chatContainer.addChild(component);
685
+ renderedSegments.push({ kind: "tool", contentIndex: seg.contentIndex, component });
686
+ }
687
+ continue;
688
+ }
689
+
690
+ const comp = new AssistantMessageComponent(
691
+ undefined,
692
+ host.hideThinkingBlock,
693
+ host.getMarkdownThemeWithSettings(),
694
+ timestampFormat,
695
+ { startIndex: seg.startIndex, endIndex: seg.endIndex },
696
+ );
697
+ comp.updateContent(host.streamingMessage);
698
+ host.chatContainer.addChild(comp);
699
+ renderedSegments.push({
700
+ kind: "text-run",
701
+ startIndex: seg.startIndex,
702
+ endIndex: seg.endIndex,
703
+ contentType: seg.contentType,
704
+ component: comp,
705
+ });
706
+ host.streamingComponent = comp;
707
+ }
708
+ }
709
+
710
+ if (!host.streamingComponent && shouldRenderAssistant) {
711
+ host.streamingComponent = new AssistantMessageComponent(
712
+ undefined,
713
+ host.hideThinkingBlock,
714
+ host.getMarkdownThemeWithSettings(),
715
+ timestampFormat,
716
+ );
581
717
  host.chatContainer.addChild(host.streamingComponent);
582
718
  }
583
719
  if (host.streamingComponent) {
@@ -2117,6 +2117,7 @@ export class InteractiveMode {
2117
2117
  }
2118
2118
 
2119
2119
  private addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): void {
2120
+ const timestampFormat = this.settingsManager.getTimestampFormat();
2120
2121
  switch (message.role) {
2121
2122
  case "bashExecution": {
2122
2123
  const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext);
@@ -2174,12 +2175,12 @@ export class InteractiveMode {
2174
2175
  skillBlock.userMessage,
2175
2176
  this.getMarkdownThemeWithSettings(),
2176
2177
  message.timestamp,
2177
- this.settingsManager.getTimestampFormat(),
2178
+ timestampFormat,
2178
2179
  );
2179
2180
  this.chatContainer.addChild(userComponent);
2180
2181
  }
2181
2182
  } else {
2182
- const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), message.timestamp, this.settingsManager.getTimestampFormat());
2183
+ const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), message.timestamp, timestampFormat);
2183
2184
  this.chatContainer.addChild(userComponent);
2184
2185
  }
2185
2186
  if (options?.populateHistory) {
@@ -2193,7 +2194,7 @@ export class InteractiveMode {
2193
2194
  message,
2194
2195
  this.hideThinkingBlock,
2195
2196
  this.getMarkdownThemeWithSettings(),
2196
- this.settingsManager.getTimestampFormat(),
2197
+ timestampFormat,
2197
2198
  );
2198
2199
  this.chatContainer.addChild(assistantComponent);
2199
2200
  break;
@@ -2231,6 +2232,7 @@ export class InteractiveMode {
2231
2232
  options: { updateFooter?: boolean; populateHistory?: boolean } = {},
2232
2233
  ): void {
2233
2234
  this.pendingTools.clear();
2235
+ const timestampFormat = this.settingsManager.getTimestampFormat();
2234
2236
 
2235
2237
  if (options.updateFooter) {
2236
2238
  this.footer.invalidate();
@@ -2255,7 +2257,7 @@ export class InteractiveMode {
2255
2257
  message,
2256
2258
  this.hideThinkingBlock,
2257
2259
  this.getMarkdownThemeWithSettings(),
2258
- this.settingsManager.getTimestampFormat(),
2260
+ timestampFormat,
2259
2261
  { startIndex: segment.startIndex, endIndex: segment.endIndex },
2260
2262
  );
2261
2263
  this.chatContainer.addChild(assistantComponent);