gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.d4fc28e6b

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 (580) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.js +0 -19
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  6. package/dist/resources/extensions/github-sync/templates.js +39 -8
  7. package/dist/resources/extensions/gsd/auto/loop.js +119 -18
  8. package/dist/resources/extensions/gsd/auto/phases.js +212 -135
  9. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  10. package/dist/resources/extensions/gsd/auto/run-unit.js +41 -45
  11. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  12. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  15. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +26 -0
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +27 -14
  18. package/dist/resources/extensions/gsd/auto-prompts.js +214 -17
  19. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  20. package/dist/resources/extensions/gsd/auto-start.js +199 -9
  21. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  23. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  24. package/dist/resources/extensions/gsd/auto.js +95 -27
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -3
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +330 -55
  33. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  34. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  35. package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
  36. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  38. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  39. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  40. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  41. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  42. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  43. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  44. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  45. package/dist/resources/extensions/gsd/detection.js +106 -0
  46. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  47. package/dist/resources/extensions/gsd/git-service.js +36 -4
  48. package/dist/resources/extensions/gsd/graph.js +9 -3
  49. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  50. package/dist/resources/extensions/gsd/guided-flow.js +129 -44
  51. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  52. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  54. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  55. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  56. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  57. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  58. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  60. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  61. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  62. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  64. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  66. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  68. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  70. package/dist/resources/extensions/gsd/quick.js +34 -2
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  72. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  73. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  74. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  75. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  76. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  79. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  80. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  81. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  82. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  83. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  84. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  85. package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
  86. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  89. package/dist/web/standalone/.next/build-manifest.json +3 -3
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  117. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  118. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  121. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  122. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  123. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  124. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  125. package/dist/welcome-screen.d.ts +2 -0
  126. package/dist/welcome-screen.js +9 -7
  127. package/package.json +12 -8
  128. package/packages/contracts/package.json +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  133. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  134. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  135. package/packages/native/tsconfig.tsbuildinfo +1 -1
  136. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  137. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  138. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  139. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  140. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  141. package/packages/pi-agent-core/dist/agent.js +2 -0
  142. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  143. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  144. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  145. package/packages/pi-agent-core/dist/index.js +2 -0
  146. package/packages/pi-agent-core/dist/index.js.map +1 -1
  147. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  148. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  149. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  150. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  151. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  152. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  153. package/packages/pi-agent-core/dist/types.js.map +1 -1
  154. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  155. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  156. package/packages/pi-agent-core/src/agent.ts +8 -0
  157. package/packages/pi-agent-core/src/index.ts +2 -0
  158. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  159. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  160. package/packages/pi-agent-core/src/types.ts +14 -0
  161. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  162. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  163. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  164. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  165. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  166. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  167. package/packages/pi-ai/dist/models/index.js +8 -0
  168. package/packages/pi-ai/dist/models/index.js.map +1 -1
  169. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  170. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/providers/fake.js +319 -0
  172. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  173. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  175. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  176. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  177. package/packages/pi-ai/src/models/index.ts +9 -0
  178. package/packages/pi-ai/src/providers/fake.ts +376 -0
  179. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  180. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  181. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  182. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
  184. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
  186. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
  188. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  190. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  192. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  194. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  196. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  197. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  198. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  199. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  200. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  202. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  203. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  205. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  206. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  207. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  209. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -0
  211. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/extensions/runner.js +20 -7
  213. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +102 -3
  215. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
  217. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  220. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  225. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  226. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  227. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  228. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  229. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
  231. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  233. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  235. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  237. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  240. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  242. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  303. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  307. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  309. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  311. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  313. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  315. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  318. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  319. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  320. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
  321. package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
  322. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  323. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  324. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  325. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  326. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  327. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  328. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +113 -3
  329. package/packages/pi-coding-agent/src/core/extensions/runner.ts +24 -6
  330. package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
  331. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  332. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  333. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  334. package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
  335. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  336. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  337. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  338. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  339. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  340. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  341. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  345. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  347. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  351. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  352. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  353. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  354. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  355. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  356. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  357. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  358. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  360. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  361. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  364. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  365. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  366. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  367. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  368. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  369. package/packages/pi-tui/dist/index.d.ts +1 -0
  370. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/index.js +2 -0
  372. package/packages/pi-tui/dist/index.js.map +1 -1
  373. package/packages/pi-tui/dist/style.d.ts +41 -0
  374. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  375. package/packages/pi-tui/dist/style.js +158 -0
  376. package/packages/pi-tui/dist/style.js.map +1 -0
  377. package/packages/pi-tui/dist/tui.d.ts +0 -1
  378. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  379. package/packages/pi-tui/dist/tui.js +21 -16
  380. package/packages/pi-tui/dist/tui.js.map +1 -1
  381. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  382. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  383. package/packages/pi-tui/src/index.ts +9 -0
  384. package/packages/pi-tui/src/style.ts +225 -0
  385. package/packages/pi-tui/src/tui.ts +23 -16
  386. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  387. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  388. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  389. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  390. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  391. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  392. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  393. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  394. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  395. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  396. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  397. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  398. package/src/resources/GSD-WORKFLOW.md +2 -2
  399. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  400. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  401. package/src/resources/extensions/github-sync/templates.ts +38 -8
  402. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  403. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -2
  404. package/src/resources/extensions/gsd/auto/loop.ts +151 -26
  405. package/src/resources/extensions/gsd/auto/phases.ts +289 -196
  406. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  407. package/src/resources/extensions/gsd/auto/run-unit.ts +52 -44
  408. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  409. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  410. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  411. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  412. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  413. package/src/resources/extensions/gsd/auto-dispatch.ts +33 -0
  414. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -14
  415. package/src/resources/extensions/gsd/auto-prompts.ts +228 -16
  416. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  417. package/src/resources/extensions/gsd/auto-start.ts +237 -15
  418. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  419. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  420. package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
  421. package/src/resources/extensions/gsd/auto.ts +110 -22
  422. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +119 -2
  423. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
  424. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
  425. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
  426. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
  427. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
  428. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
  429. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +386 -55
  430. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  431. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  432. package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
  433. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  434. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  435. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  436. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  437. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  438. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  439. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  440. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  441. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  442. package/src/resources/extensions/gsd/detection.ts +128 -0
  443. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  444. package/src/resources/extensions/gsd/git-service.ts +46 -8
  445. package/src/resources/extensions/gsd/graph.ts +12 -5
  446. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  447. package/src/resources/extensions/gsd/guided-flow.ts +150 -51
  448. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  449. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  450. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  451. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  452. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  453. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  454. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  455. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  456. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  457. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  458. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  459. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  460. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  461. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  462. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  463. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  464. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  466. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  467. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  468. package/src/resources/extensions/gsd/quick.ts +37 -2
  469. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  470. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
  471. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  472. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +516 -15
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  476. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
  477. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
  478. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  479. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  480. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  481. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  482. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  484. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  485. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  486. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +117 -7
  487. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  488. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  489. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  490. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  492. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  493. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  494. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  495. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  496. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  497. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  498. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  499. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  500. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  501. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  502. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  503. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  504. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  505. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
  506. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
  507. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  508. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  509. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  510. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  511. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  512. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  513. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  514. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  515. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  516. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  517. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  518. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  519. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  520. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  521. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  522. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  523. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  524. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  525. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  526. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  527. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
  528. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  529. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
  530. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  531. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  533. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  534. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  535. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  536. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  537. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  538. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  539. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  540. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  541. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  542. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  543. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  544. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  545. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  546. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  547. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  548. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
  549. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  550. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  551. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  552. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  553. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  554. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  555. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  556. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  557. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  558. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  559. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  560. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  561. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
  562. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  563. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  564. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  565. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  566. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  567. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  568. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  569. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  570. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  571. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  572. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  573. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  574. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  575. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  576. package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
  577. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  578. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
  579. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
@@ -1,3 +1,4 @@
1
+ // GSD2 TUI Tests - Chat frame card visual contract coverage.
1
2
  import { test, describe } from "node:test";
2
3
  import assert from "node:assert/strict";
3
4
  import stripAnsi from "strip-ansi";
@@ -6,11 +7,11 @@ import { initTheme } from "../../theme/theme.js";
6
7
  initTheme("dark", false);
7
8
  // Regression tests for the "compaction" tone added to renderChatFrame.
8
9
  // The compaction notice shares the same visual frame as user / assistant
9
- // messages (top rule, `• label` header, `│ ` body prefix) but uses the
10
+ // messages (top rule, label header, `│ ` body prefix) but uses the
10
11
  // purple `customMessageLabel` color key so it is visually distinct from
11
12
  // conversation turns.
12
13
  describe("renderChatFrame — compaction tone", () => {
13
- test("produces a top rule, `• compaction` header row, and a │ body margin", () => {
14
+ test("produces a top rule, compaction header row, and a │ body margin", () => {
14
15
  const lines = renderChatFrame(["Compacted from 1,224,262 tokens (ctrl+o to expand)"], 60, {
15
16
  label: "compaction",
16
17
  tone: "compaction",
@@ -22,8 +23,9 @@ describe("renderChatFrame — compaction tone", () => {
22
23
  const plain = lines.map((line) => stripAnsi(line));
23
24
  // Top rule is a solid horizontal bar
24
25
  assert.match(plain[0], /^─+$/, "first line should be the solid top rule");
25
- // Header row contains `• compaction`
26
- assert.ok(plain[1].includes("compaction"), `expected header to contain "compaction", got ${JSON.stringify(plain[1])}`);
26
+ // Header row contains `compaction`
27
+ assert.ok(plain[1].includes("compaction"), `expected header to contain "compaction", got ${JSON.stringify(plain[1])}`);
28
+ assert.ok(!plain[1].includes("•"), `header should not render a bullet prefix, got ${JSON.stringify(plain[1])}`);
27
29
  // Body line(s) start with `│ `
28
30
  assert.ok(plain[2].startsWith("│ "), `expected body line to start with "│ ", got ${JSON.stringify(plain[2])}`);
29
31
  assert.ok(plain[2].includes("Compacted from 1,224,262 tokens"), "body line should include the original content");
@@ -1 +1 @@
1
- {"version":3,"file":"chat-frame-compaction-tone.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEzB,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,wEAAwE;AACxE,sBAAsB;AAEtB,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAClD,IAAI,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAChF,MAAM,KAAK,GAAG,eAAe,CAC5B,CAAC,oDAAoD,CAAC,EACtD,EAAE,EACF;YACC,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,YAAY;YAClB,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CACD,CAAC;QAEF,4CAA4C;QAC5C,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,wCAAwC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAErF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAEnD,qCAAqC;QACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,yCAAyC,CAAC,CAAC;QAE1E,qCAAqC;QACrC,MAAM,CAAC,EAAE,CACR,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,EACjC,kDAAkD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAC5E,CAAC;QAEF,+BAA+B;QAC/B,MAAM,CAAC,EAAE,CACR,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EACzB,8CAA8C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CACxE,CAAC;QACF,MAAM,CAAC,EAAE,CACR,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC,EACpD,+CAA+C,CAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAClF,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE;YAC3C,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,8DAA8D;QAC9D,MAAM,CAAC,EAAE,CACR,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAC3B,gEAAgE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACxF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACpE,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE;YACpD,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,WAAW;YACjB,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE;YACrD,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,YAAY;YAClB,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,uEAAuE;QACvE,qDAAqD;QACrD,MAAM,CAAC,EAAE,CACR,cAAc,KAAK,eAAe,EAClC,4EAA4E,CAC5E,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { test, describe } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\nimport { renderChatFrame } from \"../chat-frame.js\";\nimport { initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\", false);\n\n// Regression tests for the \"compaction\" tone added to renderChatFrame.\n// The compaction notice shares the same visual frame as user / assistant\n// messages (top rule, `• label` header, `│ ` body prefix) but uses the\n// purple `customMessageLabel` color key so it is visually distinct from\n// conversation turns.\n\ndescribe(\"renderChatFrame — compaction tone\", () => {\n\ttest(\"produces a top rule, `• compaction` header row, and a │ body margin\", () => {\n\t\tconst lines = renderChatFrame(\n\t\t\t[\"Compacted from 1,224,262 tokens (ctrl+o to expand)\"],\n\t\t\t60,\n\t\t\t{\n\t\t\t\tlabel: \"compaction\",\n\t\t\t\ttone: \"compaction\",\n\t\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\t\tshowTimestamp: false,\n\t\t\t},\n\t\t);\n\n\t\t// Structure: top rule, header, body line(s)\n\t\tassert.ok(lines.length >= 3, `expected at least 3 frame lines, got ${lines.length}`);\n\n\t\tconst plain = lines.map((line) => stripAnsi(line));\n\n\t\t// Top rule is a solid horizontal bar\n\t\tassert.match(plain[0], /^─+$/, \"first line should be the solid top rule\");\n\n\t\t// Header row contains `• compaction`\n\t\tassert.ok(\n\t\t\tplain[1].includes(\"compaction\"),\n\t\t\t`expected header to contain \"compaction\", got ${JSON.stringify(plain[1])}`,\n\t\t);\n\n\t\t// Body line(s) start with `│ `\n\t\tassert.ok(\n\t\t\tplain[2].startsWith(\"│ \"),\n\t\t\t`expected body line to start with \"│ \", got ${JSON.stringify(plain[2])}`,\n\t\t);\n\t\tassert.ok(\n\t\t\tplain[2].includes(\"Compacted from 1,224,262 tokens\"),\n\t\t\t\"body line should include the original content\",\n\t\t);\n\t});\n\n\ttest(\"does not render a right-aligned timestamp when showTimestamp is false\", () => {\n\t\tconst lines = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"compaction\",\n\t\t\ttone: \"compaction\",\n\t\t\ttimestamp: Date.now(),\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t});\n\n\t\tconst header = stripAnsi(lines[1]);\n\t\t// No four-digit year should appear anywhere in the header row\n\t\tassert.ok(\n\t\t\t!/\\b20\\d{2}\\b/.test(header),\n\t\t\t`timestamp should be suppressed when showTimestamp=false, got ${JSON.stringify(header)}`,\n\t\t);\n\t});\n\n\ttest(\"emits ANSI color codes distinct from the assistant tone\", () => {\n\t\tconst assistantFrame = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"claude\",\n\t\t\ttone: \"assistant\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t}).join(\"\\n\");\n\n\t\tconst compactionFrame = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"compaction\",\n\t\t\ttone: \"compaction\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t}).join(\"\\n\");\n\n\t\t// Both frames carry ANSI; the compaction frame should not be identical\n\t\t// to the assistant frame (different color mappings).\n\t\tassert.ok(\n\t\t\tassistantFrame !== compactionFrame,\n\t\t\t\"compaction tone must produce a different styled output than assistant tone\",\n\t\t);\n\t});\n});\n"]}
1
+ {"version":3,"file":"chat-frame-compaction-tone.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts"],"names":[],"mappings":"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","sourcesContent":["// GSD2 TUI Tests - Chat frame card visual contract coverage.\nimport { test, describe } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\nimport { renderChatFrame } from \"../chat-frame.js\";\nimport { initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\", false);\n\n// Regression tests for the \"compaction\" tone added to renderChatFrame.\n// The compaction notice shares the same visual frame as user / assistant\n// messages (top rule, label header, `│ ` body prefix) but uses the\n// purple `customMessageLabel` color key so it is visually distinct from\n// conversation turns.\n\ndescribe(\"renderChatFrame — compaction tone\", () => {\n\ttest(\"produces a top rule, compaction header row, and a │ body margin\", () => {\n\t\tconst lines = renderChatFrame(\n\t\t\t[\"Compacted from 1,224,262 tokens (ctrl+o to expand)\"],\n\t\t\t60,\n\t\t\t{\n\t\t\t\tlabel: \"compaction\",\n\t\t\t\ttone: \"compaction\",\n\t\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\t\tshowTimestamp: false,\n\t\t\t},\n\t\t);\n\n\t\t// Structure: top rule, header, body line(s)\n\t\tassert.ok(lines.length >= 3, `expected at least 3 frame lines, got ${lines.length}`);\n\n\t\tconst plain = lines.map((line) => stripAnsi(line));\n\n\t\t// Top rule is a solid horizontal bar\n\t\tassert.match(plain[0], /^─+$/, \"first line should be the solid top rule\");\n\n\t\t// Header row contains `compaction`\n\t\tassert.ok(\n\t\t\tplain[1].includes(\"compaction\"),\n\t\t\t`expected header to contain \"compaction\", got ${JSON.stringify(plain[1])}`,\n\t\t);\n\t\tassert.ok(!plain[1].includes(\"•\"), `header should not render a bullet prefix, got ${JSON.stringify(plain[1])}`);\n\n\t\t// Body line(s) start with `│ `\n\t\tassert.ok(\n\t\t\tplain[2].startsWith(\"│ \"),\n\t\t\t`expected body line to start with \"│ \", got ${JSON.stringify(plain[2])}`,\n\t\t);\n\t\tassert.ok(\n\t\t\tplain[2].includes(\"Compacted from 1,224,262 tokens\"),\n\t\t\t\"body line should include the original content\",\n\t\t);\n\t});\n\n\ttest(\"does not render a right-aligned timestamp when showTimestamp is false\", () => {\n\t\tconst lines = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"compaction\",\n\t\t\ttone: \"compaction\",\n\t\t\ttimestamp: Date.now(),\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t});\n\n\t\tconst header = stripAnsi(lines[1]);\n\t\t// No four-digit year should appear anywhere in the header row\n\t\tassert.ok(\n\t\t\t!/\\b20\\d{2}\\b/.test(header),\n\t\t\t`timestamp should be suppressed when showTimestamp=false, got ${JSON.stringify(header)}`,\n\t\t);\n\t});\n\n\ttest(\"emits ANSI color codes distinct from the assistant tone\", () => {\n\t\tconst assistantFrame = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"claude\",\n\t\t\ttone: \"assistant\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t}).join(\"\\n\");\n\n\t\tconst compactionFrame = renderChatFrame([\"body\"], 60, {\n\t\t\tlabel: \"compaction\",\n\t\t\ttone: \"compaction\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t}).join(\"\\n\");\n\n\t\t// Both frames carry ANSI; the compaction frame should not be identical\n\t\t// to the assistant frame (different color mappings).\n\t\tassert.ok(\n\t\t\tassistantFrame !== compactionFrame,\n\t\t\t\"compaction tone must produce a different styled output than assistant tone\",\n\t\t);\n\t});\n});\n"]}
@@ -1,7 +1,8 @@
1
+ // GSD-2 Interactive Tool Execution Rendering Tests
1
2
  import { describe, test } from "node:test";
2
3
  import assert from "node:assert/strict";
3
4
  import stripAnsi from "strip-ansi";
4
- import { ToolExecutionComponent } from "../tool-execution.js";
5
+ import { ToolExecutionComponent, ToolPhaseSummaryComponent } from "../tool-execution.js";
5
6
  import { initTheme } from "../../theme/theme.js";
6
7
  initTheme("dark", false);
7
8
  function renderTool(toolName, args, result, toolDefinition) {
@@ -18,17 +19,53 @@ function renderToolCollapsed(toolName, args, result, toolDefinition) {
18
19
  return stripAnsi(component.render(120).join("\n"));
19
20
  }
20
21
  describe("ToolExecutionComponent", () => {
21
- test("renders framed header with Running status while tool is partial", () => {
22
+ test("renders framed header with running status while tool is partial", () => {
22
23
  const rendered = renderToolCollapsed("mcp__demo__do_thing", { ok: true });
23
- assert.match(rendered, /Tool demo\u00b7do_thing/);
24
- assert.match(rendered, /Running/);
24
+ assert.match(rendered, /demo\u00b7do_thing/);
25
+ assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
26
+ assert.match(rendered, /running/);
27
+ assert.match(rendered, /running · \d+(ms|s)/);
25
28
  });
26
- test("renders framed header with Error status for failed tool result", () => {
29
+ test("renders framed header with failed status for failed tool result", () => {
27
30
  const rendered = renderTool("mcp__demo__do_thing", { ok: true }, { content: [{ type: "text", text: "boom" }], isError: true });
28
- assert.match(rendered, /Tool demo\u00b7do_thing/);
29
- assert.match(rendered, /Error/);
31
+ assert.match(rendered, /demo\u00b7do_thing/);
32
+ assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
33
+ assert.match(rendered, /failed/);
34
+ assert.match(rendered, /failed · \d+(ms|s)/);
30
35
  assert.match(rendered, /boom/);
31
36
  });
37
+ test("collapses successful low-signal tool cards by default", () => {
38
+ const rendered = renderToolCollapsed("mcp__demo__noop", { ok: true }, { content: [], isError: false });
39
+ assert.match(rendered, /success · \d+(ms|s)/);
40
+ assert.match(rendered, /demo\u00b7noop/);
41
+ assert.doesNotMatch(rendered, /Completed/);
42
+ assert.doesNotMatch(rendered, /ok=true/);
43
+ });
44
+ test("exposes phase metadata for successful low-signal tool rows", () => {
45
+ const component = new ToolExecutionComponent("gsd_requirement_update", { id: "R001" }, {}, { label: "Update Requirement" }, { requestRender() { } });
46
+ component.updateResult({ content: [], isError: false });
47
+ assert.deepEqual(component.getRollupPhase()?.label, "Requirement writes");
48
+ });
49
+ test("exposes phase metadata for collapsed output-bearing generic tools", () => {
50
+ const component = new ToolExecutionComponent("mcp__demo__do_thing", { ok: true }, {}, undefined, { requestRender() { } });
51
+ component.updateResult({ content: [{ type: "text", text: "important output" }], isError: false });
52
+ assert.deepEqual(component.getRollupPhase()?.label, "Other tool actions");
53
+ });
54
+ test("renders phase-based summaries for rolled-up tool executions", () => {
55
+ const phases = [
56
+ { label: "Setup / shell", count: 6, durationMs: 12 },
57
+ { label: "Context reads", count: 4, durationMs: 6 },
58
+ { label: "Requirement writes", count: 4, durationMs: 4 },
59
+ { label: "Memory lookups", count: 4, durationMs: 4 },
60
+ { label: "Finalization", count: 1, durationMs: 1 },
61
+ ];
62
+ const rendered = stripAnsi(new ToolPhaseSummaryComponent(phases).render(120).join("\n"));
63
+ assert.match(rendered, /Setup \/ shell 6 actions\s+success · 12ms/);
64
+ assert.match(rendered, /Context reads 4 actions\s+success · 6ms/);
65
+ assert.match(rendered, /Requirement writes 4 actions\s+success · 4ms/);
66
+ assert.match(rendered, /Memory lookups 4 actions\s+success · 4ms/);
67
+ assert.match(rendered, /Finalization 1 action\s+success · 1ms/);
68
+ });
32
69
  test("passes failed result status to custom result renderers", () => {
33
70
  const rendered = renderTool("gsd_requirement_save", { id: "R001" }, { content: [{ type: "text", text: "saved" }], isError: true }, {
34
71
  label: "Save Requirement",
@@ -39,7 +76,7 @@ describe("ToolExecutionComponent", () => {
39
76
  };
40
77
  },
41
78
  });
42
- assert.match(rendered, /Error/);
79
+ assert.match(rendered, /failed/);
43
80
  assert.match(rendered, /custom saw error/);
44
81
  assert.doesNotMatch(rendered, /custom saw success/);
45
82
  });
@@ -72,12 +109,14 @@ describe("ToolExecutionComponent", () => {
72
109
  });
73
110
  test("frame header prefers toolDefinition.label over raw tool name", () => {
74
111
  const rendered = renderToolCollapsed("gsd_slice_complete", { sliceId: "S03" }, undefined, { label: "Complete Slice" });
75
- assert.match(rendered, /Tool Complete Slice/);
112
+ assert.match(rendered, /Complete Slice/);
113
+ assert.doesNotMatch(rendered, /Tool Complete Slice/);
76
114
  assert.doesNotMatch(rendered, /gsd_slice_complete/);
77
115
  });
78
116
  test("frame header strips gsd_ prefix and title-cases when no label is registered", () => {
79
117
  const rendered = renderToolCollapsed("gsd_requirement_update", { id: "R005" });
80
- assert.match(rendered, /Tool Requirement Update/);
118
+ assert.match(rendered, /Requirement Update/);
119
+ assert.doesNotMatch(rendered, /Tool Requirement Update/);
81
120
  assert.doesNotMatch(rendered, /gsd_requirement_update/);
82
121
  });
83
122
  test("formatCompactArgs truncates long string values inline instead of dumping JSON", () => {
@@ -101,13 +140,13 @@ describe("ToolExecutionComponent", () => {
101
140
  assert.match(rendered, new RegExp(longPath.replace(/\//g, "\\/")));
102
141
  assert.doesNotMatch(rendered, /…/);
103
142
  });
104
- test("generic fallback truncates long output when collapsed", () => {
143
+ test("generic fallback collapses successful output rows until expanded", () => {
105
144
  const longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join("\n");
106
145
  const rendered = renderToolCollapsed("mcp__demo__do_thing", { ok: true }, { content: [{ type: "text", text: longOutput }], isError: false });
107
- assert.match(rendered, /line 1\b/);
108
- assert.match(rendered, /line 10\b/);
109
- assert.doesNotMatch(rendered, /line 20\b/);
110
- assert.match(rendered, /\(15 more lines/);
146
+ assert.match(rendered, /demo\u00b7do_thing/);
147
+ assert.match(rendered, /success · \d+(ms|s)/);
148
+ assert.doesNotMatch(rendered, /line 1\b/);
149
+ assert.doesNotMatch(rendered, /\(15 more lines/);
111
150
  });
112
151
  test("generic fallback falls back to truncated JSON for complex args", () => {
113
152
  const rendered = renderTool("mcp__demo__nested", { payload: { nested: { deeply: ["a", "b", "c"] } }, name: "x" });
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/components/__tests__/tool-execution.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\nimport { ToolExecutionComponent } from \"../tool-execution.js\";\nimport { initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\", false);\n\nfunction renderTool(\n\ttoolName: string,\n\targs: Record<string, unknown>,\n\tresult?: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: Record<string, unknown>;\n\t},\n\ttoolDefinition?: { label?: string; renderCall?: (...args: any[]) => any; renderResult?: (...args: any[]) => any },\n): string {\n\tconst component = new ToolExecutionComponent(\n\t\ttoolName,\n\t\targs,\n\t\t{},\n\t\ttoolDefinition as any,\n\t\t{ requestRender() {} } as any,\n\t);\n\tcomponent.setExpanded(true);\n\tif (result) component.updateResult(result);\n\treturn stripAnsi(component.render(120).join(\"\\n\"));\n}\n\nfunction renderToolCollapsed(\n\ttoolName: string,\n\targs: Record<string, unknown>,\n\tresult?: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: Record<string, unknown>;\n\t},\n\ttoolDefinition?: { label?: string; renderCall?: (...args: any[]) => any; renderResult?: (...args: any[]) => any },\n): string {\n\tconst component = new ToolExecutionComponent(\n\t\ttoolName,\n\t\targs,\n\t\t{},\n\t\ttoolDefinition as any,\n\t\t{ requestRender() {} } as any,\n\t);\n\tif (result) component.updateResult(result);\n\treturn stripAnsi(component.render(120).join(\"\\n\"));\n}\n\ndescribe(\"ToolExecutionComponent\", () => {\n\ttest(\"renders framed header with Running status while tool is partial\", () => {\n\t\tconst rendered = renderToolCollapsed(\"mcp__demo__do_thing\", { ok: true });\n\n\t\tassert.match(rendered, /Tool demo\\u00b7do_thing/);\n\t\tassert.match(rendered, /Running/);\n\t});\n\n\ttest(\"renders framed header with Error status for failed tool result\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__demo__do_thing\",\n\t\t\t{ ok: true },\n\t\t\t{ content: [{ type: \"text\", text: \"boom\" }], isError: true },\n\t\t);\n\n\t\tassert.match(rendered, /Tool demo\\u00b7do_thing/);\n\t\tassert.match(rendered, /Error/);\n\t\tassert.match(rendered, /boom/);\n\t});\n\n\ttest(\"passes failed result status to custom result renderers\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"gsd_requirement_save\",\n\t\t\t{ id: \"R001\" },\n\t\t\t{ content: [{ type: \"text\", text: \"saved\" }], isError: true },\n\t\t\t{\n\t\t\t\tlabel: \"Save Requirement\",\n\t\t\t\trenderResult(result: { isError?: boolean }) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\trender: () => [result.isError ? \"custom saw error\" : \"custom saw success\"],\n\t\t\t\t\t\tinvalidate() {},\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tassert.match(rendered, /Error/);\n\t\tassert.match(rendered, /custom saw error/);\n\t\tassert.doesNotMatch(rendered, /custom saw success/);\n\t});\n\n\ttest(\"renders capitalized Claude Code Bash tool names with bash output instead of generic args JSON\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"Bash\",\n\t\t\t{ command: \"pwd\" },\n\t\t\t{ content: [{ type: \"text\", text: \"/tmp/gsd-pr-fix\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /\\$ pwd/);\n\t\tassert.match(rendered, /\\/tmp\\/gsd-pr-fix/);\n\t\tassert.doesNotMatch(rendered, /^\\{\\s*\\}$/m);\n\t});\n\n\ttest(\"renders capitalized Claude Code Read tool names with read output\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"Read\",\n\t\t\t{ path: \"/tmp/demo.txt\" },\n\t\t\t{ content: [{ type: \"text\", text: \"hello\\nworld\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /read .*demo\\.txt/);\n\t\tassert.match(rendered, /hello/);\n\t\tassert.match(rendered, /world/);\n\t});\n\n\ttest(\"generic fallback strips mcp__<server>__ prefix and shows server·tool title\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__context7__resolve_library_id\",\n\t\t\t{ name: \"react\" },\n\t\t\t{ content: [{ type: \"text\", text: \"react@18.3.1\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /context7\\u00b7resolve_library_id/);\n\t\tassert.doesNotMatch(rendered, /mcp__/);\n\t\tassert.match(rendered, /name=\"react\"/);\n\t\tassert.match(rendered, /react@18\\.3\\.1/);\n\t});\n\n\ttest(\"generic fallback renders compact key=value args for primitive args\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"some_unknown_tool\",\n\t\t\t{ count: 3, enabled: true, label: \"hello\" },\n\t\t);\n\n\t\tassert.match(rendered, /Some Unknown Tool/);\n\t\tassert.match(rendered, /count=3/);\n\t\tassert.match(rendered, /enabled=true/);\n\t\tassert.match(rendered, /label=\"hello\"/);\n\t\tassert.doesNotMatch(rendered, /^\\{$/m);\n\t});\n\n\ttest(\"frame header prefers toolDefinition.label over raw tool name\", () => {\n\t\tconst rendered = renderToolCollapsed(\n\t\t\t\"gsd_slice_complete\",\n\t\t\t{ sliceId: \"S03\" },\n\t\t\tundefined,\n\t\t\t{ label: \"Complete Slice\" },\n\t\t);\n\n\t\tassert.match(rendered, /Tool Complete Slice/);\n\t\tassert.doesNotMatch(rendered, /gsd_slice_complete/);\n\t});\n\n\ttest(\"frame header strips gsd_ prefix and title-cases when no label is registered\", () => {\n\t\tconst rendered = renderToolCollapsed(\"gsd_requirement_update\", { id: \"R005\" });\n\n\t\tassert.match(rendered, /Tool Requirement Update/);\n\t\tassert.doesNotMatch(rendered, /gsd_requirement_update/);\n\t});\n\n\ttest(\"formatCompactArgs truncates long string values inline instead of dumping JSON\", () => {\n\t\tconst longPath = \"/Users/alice/.gsd/projects/4dce7b775013/worktrees/slice-S03-some-long-path-that-exceeds-limit\";\n\t\tconst rendered = renderToolCollapsed(\"gsd_slice_complete\", {\n\t\t\tsliceId: \"S03\",\n\t\t\tmilestoneId: \"M001\",\n\t\t\tworktree: longPath,\n\t\t});\n\n\t\tassert.match(rendered, /sliceId=\"S03\"/);\n\t\tassert.match(rendered, /milestoneId=\"M001\"/);\n\t\tassert.match(rendered, /worktree=\".*…\"/);\n\t\tassert.doesNotMatch(rendered, /\"sliceId\":\\s*\"S03\"/);\n\t});\n\n\ttest(\"formatCompactArgs shows full string values when expanded\", () => {\n\t\tconst longPath = \"/Users/alice/.gsd/projects/4dce7b775013/worktrees/slice-S03-some-long-path-that-exceeds-limit\";\n\t\tconst rendered = renderTool(\"gsd_slice_complete\", {\n\t\t\tsliceId: \"S03\",\n\t\t\tworktree: longPath,\n\t\t});\n\n\t\tassert.match(rendered, new RegExp(longPath.replace(/\\//g, \"\\\\/\")));\n\t\tassert.doesNotMatch(rendered, /…/);\n\t});\n\n\ttest(\"generic fallback truncates long output when collapsed\", () => {\n\t\tconst longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join(\"\\n\");\n\t\tconst rendered = renderToolCollapsed(\n\t\t\t\"mcp__demo__do_thing\",\n\t\t\t{ ok: true },\n\t\t\t{ content: [{ type: \"text\", text: longOutput }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /line 1\\b/);\n\t\tassert.match(rendered, /line 10\\b/);\n\t\tassert.doesNotMatch(rendered, /line 20\\b/);\n\t\tassert.match(rendered, /\\(15 more lines/);\n\t});\n\n\ttest(\"generic fallback falls back to truncated JSON for complex args\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__demo__nested\",\n\t\t\t{ payload: { nested: { deeply: [\"a\", \"b\", \"c\"] } }, name: \"x\" },\n\t\t);\n\n\t\tassert.match(rendered, /demo\\u00b7nested/);\n\t\t// Multi-line JSON dump for the complex payload\n\t\tassert.match(rendered, /\"payload\"/);\n\t\tassert.match(rendered, /\"nested\"/);\n\t});\n});\n"]}
1
+ {"version":3,"file":"tool-execution.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/components/__tests__/tool-execution.test.ts"],"names":[],"mappings":"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","sourcesContent":["// GSD-2 Interactive Tool Execution Rendering Tests\nimport { describe, test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\nimport { ToolExecutionComponent, ToolPhaseSummaryComponent, type ToolExecutionPhase } from \"../tool-execution.js\";\nimport { initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\", false);\n\nfunction renderTool(\n\ttoolName: string,\n\targs: Record<string, unknown>,\n\tresult?: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: Record<string, unknown>;\n\t},\n\ttoolDefinition?: { label?: string; renderCall?: (...args: any[]) => any; renderResult?: (...args: any[]) => any },\n): string {\n\tconst component = new ToolExecutionComponent(\n\t\ttoolName,\n\t\targs,\n\t\t{},\n\t\ttoolDefinition as any,\n\t\t{ requestRender() {} } as any,\n\t);\n\tcomponent.setExpanded(true);\n\tif (result) component.updateResult(result);\n\treturn stripAnsi(component.render(120).join(\"\\n\"));\n}\n\nfunction renderToolCollapsed(\n\ttoolName: string,\n\targs: Record<string, unknown>,\n\tresult?: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: Record<string, unknown>;\n\t},\n\ttoolDefinition?: { label?: string; renderCall?: (...args: any[]) => any; renderResult?: (...args: any[]) => any },\n): string {\n\tconst component = new ToolExecutionComponent(\n\t\ttoolName,\n\t\targs,\n\t\t{},\n\t\ttoolDefinition as any,\n\t\t{ requestRender() {} } as any,\n\t);\n\tif (result) component.updateResult(result);\n\treturn stripAnsi(component.render(120).join(\"\\n\"));\n}\n\ndescribe(\"ToolExecutionComponent\", () => {\n\ttest(\"renders framed header with running status while tool is partial\", () => {\n\t\tconst rendered = renderToolCollapsed(\"mcp__demo__do_thing\", { ok: true });\n\n\t\tassert.match(rendered, /demo\\u00b7do_thing/);\n\t\tassert.doesNotMatch(rendered, /Tool demo\\u00b7do_thing/);\n\t\tassert.match(rendered, /running/);\n\t\tassert.match(rendered, /running · \\d+(ms|s)/);\n\t});\n\n\ttest(\"renders framed header with failed status for failed tool result\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__demo__do_thing\",\n\t\t\t{ ok: true },\n\t\t\t{ content: [{ type: \"text\", text: \"boom\" }], isError: true },\n\t\t);\n\n\t\tassert.match(rendered, /demo\\u00b7do_thing/);\n\t\tassert.doesNotMatch(rendered, /Tool demo\\u00b7do_thing/);\n\t\tassert.match(rendered, /failed/);\n\t\tassert.match(rendered, /failed · \\d+(ms|s)/);\n\t\tassert.match(rendered, /boom/);\n\t});\n\n\ttest(\"collapses successful low-signal tool cards by default\", () => {\n\t\tconst rendered = renderToolCollapsed(\n\t\t\t\"mcp__demo__noop\",\n\t\t\t{ ok: true },\n\t\t\t{ content: [], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /success · \\d+(ms|s)/);\n\t\tassert.match(rendered, /demo\\u00b7noop/);\n\t\tassert.doesNotMatch(rendered, /Completed/);\n\t\tassert.doesNotMatch(rendered, /ok=true/);\n\t});\n\n\ttest(\"exposes phase metadata for successful low-signal tool rows\", () => {\n\t\tconst component = new ToolExecutionComponent(\n\t\t\t\"gsd_requirement_update\",\n\t\t\t{ id: \"R001\" },\n\t\t\t{},\n\t\t\t{ label: \"Update Requirement\" } as any,\n\t\t\t{ requestRender() {} } as any,\n\t\t);\n\t\tcomponent.updateResult({ content: [], isError: false });\n\n\t\tassert.deepEqual(component.getRollupPhase()?.label, \"Requirement writes\");\n\t});\n\n\ttest(\"exposes phase metadata for collapsed output-bearing generic tools\", () => {\n\t\tconst component = new ToolExecutionComponent(\n\t\t\t\"mcp__demo__do_thing\",\n\t\t\t{ ok: true },\n\t\t\t{},\n\t\t\tundefined,\n\t\t\t{ requestRender() {} } as any,\n\t\t);\n\t\tcomponent.updateResult({ content: [{ type: \"text\", text: \"important output\" }], isError: false });\n\n\t\tassert.deepEqual(component.getRollupPhase()?.label, \"Other tool actions\");\n\t});\n\n\ttest(\"renders phase-based summaries for rolled-up tool executions\", () => {\n\t\tconst phases: ToolExecutionPhase[] = [\n\t\t\t{ label: \"Setup / shell\", count: 6, durationMs: 12 },\n\t\t\t{ label: \"Context reads\", count: 4, durationMs: 6 },\n\t\t\t{ label: \"Requirement writes\", count: 4, durationMs: 4 },\n\t\t\t{ label: \"Memory lookups\", count: 4, durationMs: 4 },\n\t\t\t{ label: \"Finalization\", count: 1, durationMs: 1 },\n\t\t];\n\t\tconst rendered = stripAnsi(new ToolPhaseSummaryComponent(phases).render(120).join(\"\\n\"));\n\n\t\tassert.match(rendered, /Setup \\/ shell 6 actions\\s+success · 12ms/);\n\t\tassert.match(rendered, /Context reads 4 actions\\s+success · 6ms/);\n\t\tassert.match(rendered, /Requirement writes 4 actions\\s+success · 4ms/);\n\t\tassert.match(rendered, /Memory lookups 4 actions\\s+success · 4ms/);\n\t\tassert.match(rendered, /Finalization 1 action\\s+success · 1ms/);\n\t});\n\n\ttest(\"passes failed result status to custom result renderers\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"gsd_requirement_save\",\n\t\t\t{ id: \"R001\" },\n\t\t\t{ content: [{ type: \"text\", text: \"saved\" }], isError: true },\n\t\t\t{\n\t\t\t\tlabel: \"Save Requirement\",\n\t\t\t\trenderResult(result: { isError?: boolean }) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\trender: () => [result.isError ? \"custom saw error\" : \"custom saw success\"],\n\t\t\t\t\t\tinvalidate() {},\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tassert.match(rendered, /failed/);\n\t\tassert.match(rendered, /custom saw error/);\n\t\tassert.doesNotMatch(rendered, /custom saw success/);\n\t});\n\n\ttest(\"renders capitalized Claude Code Bash tool names with bash output instead of generic args JSON\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"Bash\",\n\t\t\t{ command: \"pwd\" },\n\t\t\t{ content: [{ type: \"text\", text: \"/tmp/gsd-pr-fix\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /\\$ pwd/);\n\t\tassert.match(rendered, /\\/tmp\\/gsd-pr-fix/);\n\t\tassert.doesNotMatch(rendered, /^\\{\\s*\\}$/m);\n\t});\n\n\ttest(\"renders capitalized Claude Code Read tool names with read output\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"Read\",\n\t\t\t{ path: \"/tmp/demo.txt\" },\n\t\t\t{ content: [{ type: \"text\", text: \"hello\\nworld\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /read .*demo\\.txt/);\n\t\tassert.match(rendered, /hello/);\n\t\tassert.match(rendered, /world/);\n\t});\n\n\ttest(\"generic fallback strips mcp__<server>__ prefix and shows server·tool title\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__context7__resolve_library_id\",\n\t\t\t{ name: \"react\" },\n\t\t\t{ content: [{ type: \"text\", text: \"react@18.3.1\" }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /context7\\u00b7resolve_library_id/);\n\t\tassert.doesNotMatch(rendered, /mcp__/);\n\t\tassert.match(rendered, /name=\"react\"/);\n\t\tassert.match(rendered, /react@18\\.3\\.1/);\n\t});\n\n\ttest(\"generic fallback renders compact key=value args for primitive args\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"some_unknown_tool\",\n\t\t\t{ count: 3, enabled: true, label: \"hello\" },\n\t\t);\n\n\t\tassert.match(rendered, /Some Unknown Tool/);\n\t\tassert.match(rendered, /count=3/);\n\t\tassert.match(rendered, /enabled=true/);\n\t\tassert.match(rendered, /label=\"hello\"/);\n\t\tassert.doesNotMatch(rendered, /^\\{$/m);\n\t});\n\n\ttest(\"frame header prefers toolDefinition.label over raw tool name\", () => {\n\t\tconst rendered = renderToolCollapsed(\n\t\t\t\"gsd_slice_complete\",\n\t\t\t{ sliceId: \"S03\" },\n\t\t\tundefined,\n\t\t\t{ label: \"Complete Slice\" },\n\t\t);\n\n\t\tassert.match(rendered, /Complete Slice/);\n\t\tassert.doesNotMatch(rendered, /Tool Complete Slice/);\n\t\tassert.doesNotMatch(rendered, /gsd_slice_complete/);\n\t});\n\n\ttest(\"frame header strips gsd_ prefix and title-cases when no label is registered\", () => {\n\t\tconst rendered = renderToolCollapsed(\"gsd_requirement_update\", { id: \"R005\" });\n\n\t\tassert.match(rendered, /Requirement Update/);\n\t\tassert.doesNotMatch(rendered, /Tool Requirement Update/);\n\t\tassert.doesNotMatch(rendered, /gsd_requirement_update/);\n\t});\n\n\ttest(\"formatCompactArgs truncates long string values inline instead of dumping JSON\", () => {\n\t\tconst longPath = \"/Users/alice/.gsd/projects/4dce7b775013/worktrees/slice-S03-some-long-path-that-exceeds-limit\";\n\t\tconst rendered = renderToolCollapsed(\"gsd_slice_complete\", {\n\t\t\tsliceId: \"S03\",\n\t\t\tmilestoneId: \"M001\",\n\t\t\tworktree: longPath,\n\t\t});\n\n\t\tassert.match(rendered, /sliceId=\"S03\"/);\n\t\tassert.match(rendered, /milestoneId=\"M001\"/);\n\t\tassert.match(rendered, /worktree=\".*…\"/);\n\t\tassert.doesNotMatch(rendered, /\"sliceId\":\\s*\"S03\"/);\n\t});\n\n\ttest(\"formatCompactArgs shows full string values when expanded\", () => {\n\t\tconst longPath = \"/Users/alice/.gsd/projects/4dce7b775013/worktrees/slice-S03-some-long-path-that-exceeds-limit\";\n\t\tconst rendered = renderTool(\"gsd_slice_complete\", {\n\t\t\tsliceId: \"S03\",\n\t\t\tworktree: longPath,\n\t\t});\n\n\t\tassert.match(rendered, new RegExp(longPath.replace(/\\//g, \"\\\\/\")));\n\t\tassert.doesNotMatch(rendered, /…/);\n\t});\n\n\ttest(\"generic fallback collapses successful output rows until expanded\", () => {\n\t\tconst longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join(\"\\n\");\n\t\tconst rendered = renderToolCollapsed(\n\t\t\t\"mcp__demo__do_thing\",\n\t\t\t{ ok: true },\n\t\t\t{ content: [{ type: \"text\", text: longOutput }], isError: false },\n\t\t);\n\n\t\tassert.match(rendered, /demo\\u00b7do_thing/);\n\t\tassert.match(rendered, /success · \\d+(ms|s)/);\n\t\tassert.doesNotMatch(rendered, /line 1\\b/);\n\t\tassert.doesNotMatch(rendered, /\\(15 more lines/);\n\t});\n\n\ttest(\"generic fallback falls back to truncated JSON for complex args\", () => {\n\t\tconst rendered = renderTool(\n\t\t\t\"mcp__demo__nested\",\n\t\t\t{ payload: { nested: { deeply: [\"a\", \"b\", \"c\"] } }, name: \"x\" },\n\t\t);\n\n\t\tassert.match(rendered, /demo\\u00b7nested/);\n\t\t// Multi-line JSON dump for the complex payload\n\t\tassert.match(rendered, /\"payload\"/);\n\t\tassert.match(rendered, /\"nested\"/);\n\t});\n});\n"]}
@@ -0,0 +1,26 @@
1
+ import { type Component } from "@gsd/pi-tui";
2
+ import type { TuiAdaptiveMode } from "../tui-mode.js";
3
+ export interface AdaptiveLayoutState {
4
+ override: TuiAdaptiveMode;
5
+ activeToolCount: number;
6
+ gsdPhase?: string;
7
+ lastError?: string;
8
+ sessionName?: string;
9
+ cwd: string;
10
+ }
11
+ export declare class AdaptiveLayoutComponent implements Component {
12
+ private readonly getState;
13
+ constructor(getState: () => AdaptiveLayoutState);
14
+ invalidate(): void;
15
+ render(width: number): string[];
16
+ private renderWorkflow;
17
+ private renderValidation;
18
+ private renderDebug;
19
+ private renderChat;
20
+ private renderCompact;
21
+ private frame;
22
+ private metric;
23
+ private columns;
24
+ private basename;
25
+ }
26
+ //# sourceMappingURL=adaptive-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-layout.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/adaptive-layout.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwC,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,KAAK,EAAE,eAAe,EAAW,MAAM,gBAAgB,CAAC;AAI/D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,uBAAwB,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,mBAAmB;IAEhE,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAqB/B,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,KAAK;IAYb,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,QAAQ;CAKhB"}
@@ -0,0 +1,112 @@
1
+ // GSD2 - Adaptive terminal mode dashboard for the interactive TUI
2
+ import { style, truncateToWidth, visibleWidth } from "@gsd/pi-tui";
3
+ import { resolveTuiMode } from "../tui-mode.js";
4
+ import { theme } from "../theme/theme.js";
5
+ export class AdaptiveLayoutComponent {
6
+ constructor(getState) {
7
+ this.getState = getState;
8
+ }
9
+ invalidate() { }
10
+ render(width) {
11
+ const state = this.getState();
12
+ const mode = resolveTuiMode({
13
+ terminalWidth: width,
14
+ override: state.override,
15
+ activeToolCount: state.activeToolCount,
16
+ gsdPhase: state.gsdPhase,
17
+ hasBlockingError: !!state.lastError,
18
+ });
19
+ if (state.override === "auto" && mode === "chat" && !state.gsdPhase && !state.lastError && state.activeToolCount === 0) {
20
+ return [];
21
+ }
22
+ if (mode === "compact" || width < 72)
23
+ return this.renderCompact(width, mode, state);
24
+ if (mode === "debug")
25
+ return this.renderDebug(width, state);
26
+ if (mode === "validation")
27
+ return this.renderValidation(width, state);
28
+ if (mode === "workflow")
29
+ return this.renderWorkflow(width, state);
30
+ return this.renderChat(width, state);
31
+ }
32
+ renderWorkflow(width, state) {
33
+ if (width < 112)
34
+ return this.renderCompact(width, "workflow", state);
35
+ const leftWidth = Math.max(44, Math.floor(width * 0.56));
36
+ const rightWidth = Math.max(32, width - leftWidth - 2);
37
+ const phase = state.gsdPhase ?? "Ready";
38
+ const left = this.frame([
39
+ this.metric("Active", phase, "modeWorkflow"),
40
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} running` : "idle", "toolRunning"),
41
+ this.metric("Mode", state.override === "auto" ? "auto workflow" : state.override, "modeWorkflow"),
42
+ ], leftWidth, "GSD Command Center", "workflow", "modeWorkflow");
43
+ const right = this.frame([
44
+ `Session ${state.sessionName ?? "current"}`,
45
+ `Path ${this.basename(state.cwd)}`,
46
+ `Next ${state.activeToolCount > 0 ? "watch tool output" : "continue from prompt"}`,
47
+ ], rightWidth, "signals", "inspector", "surfaceAccent");
48
+ return this.columns(left, right, leftWidth);
49
+ }
50
+ renderValidation(width, state) {
51
+ const phase = state.gsdPhase ?? "Validation pending";
52
+ return this.frame([
53
+ this.metric("Focus", phase, "modeValidation"),
54
+ this.metric("Checks", state.activeToolCount > 0 ? `${state.activeToolCount} active` : "waiting", "toolRunning"),
55
+ this.metric("Timeline", state.lastError ? "blocked" : "ready for completion evidence", state.lastError ? "toolError" : "toolSuccess"),
56
+ ], width, "validation", state.override === "auto" ? "auto" : state.override, "modeValidation");
57
+ }
58
+ renderDebug(width, state) {
59
+ const error = state.lastError ?? "Blocking error detected";
60
+ return this.frame([
61
+ this.metric("Failure", truncateToWidth(error, Math.max(20, width - 20), ""), "toolError"),
62
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} still running` : "none running", "toolRunning"),
63
+ this.metric("Next", "inspect the failed output, then retry the smallest step", "modeDebug"),
64
+ ], width, "blocking failure", "debug", "modeDebug");
65
+ }
66
+ renderChat(width, state) {
67
+ return this.frame([
68
+ this.metric("Mode", state.override === "auto" ? "auto chat" : state.override, "surfaceAccent"),
69
+ this.metric("Tools", state.activeToolCount > 0 ? `${state.activeToolCount} active` : "compact rows", "toolMuted"),
70
+ ], width, "chat", state.sessionName ?? "conversation", "surfaceAccent");
71
+ }
72
+ renderCompact(width, mode, state) {
73
+ const phase = state.lastError ?? state.gsdPhase ?? (state.activeToolCount > 0 ? `${state.activeToolCount} tools` : "ready");
74
+ const line = `${theme.fg("modeCompact", "GSD compact")} ${theme.fg("surfaceMuted", `${mode} · ${phase}`)}`;
75
+ return style()
76
+ .border("minimal")
77
+ .borderColor((text) => theme.fg("surfaceBorder", text))
78
+ .bodyGutter(" ")
79
+ .render([line], width);
80
+ }
81
+ frame(lines, width, title, rightTitle, accent) {
82
+ return style()
83
+ .border("rule")
84
+ .density("compact")
85
+ .toneColor((text) => theme.fg("surfaceMuted", text))
86
+ .borderColor((text) => theme.fg("surfaceBorder", text))
87
+ .title(theme.fg("surfaceTitle", title))
88
+ .rightTitle(theme.fg(accent, rightTitle))
89
+ .bodyGutter(theme.fg(accent, "│ "))
90
+ .render(lines, width);
91
+ }
92
+ metric(label, value, color) {
93
+ return `${theme.fg("surfaceMuted", `${label.padEnd(8)} `)}${theme.fg(color, value)}`;
94
+ }
95
+ columns(left, right, leftWidth) {
96
+ const rows = Math.max(left.length, right.length);
97
+ const output = [];
98
+ for (let i = 0; i < rows; i++) {
99
+ const leftLine = left[i] ?? "";
100
+ const rightLine = right[i] ?? "";
101
+ const gap = " ".repeat(Math.max(2, leftWidth - visibleWidth(leftLine) + 2));
102
+ output.push(`${leftLine}${gap}${rightLine}`);
103
+ }
104
+ return output;
105
+ }
106
+ basename(cwd) {
107
+ const trimmed = cwd.replace(/\/+$/, "");
108
+ const slash = trimmed.lastIndexOf("/");
109
+ return slash === -1 ? trimmed : trimmed.slice(slash + 1);
110
+ }
111
+ }
112
+ //# sourceMappingURL=adaptive-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-layout.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/adaptive-layout.ts"],"names":[],"mappings":"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","sourcesContent":["// GSD2 - Adaptive terminal mode dashboard for the interactive TUI\n\nimport { style, truncateToWidth, visibleWidth, type Component } from \"@gsd/pi-tui\";\nimport type { TuiAdaptiveMode, TuiMode } from \"../tui-mode.js\";\nimport { resolveTuiMode } from \"../tui-mode.js\";\nimport { theme, type ThemeColor } from \"../theme/theme.js\";\n\nexport interface AdaptiveLayoutState {\n\toverride: TuiAdaptiveMode;\n\tactiveToolCount: number;\n\tgsdPhase?: string;\n\tlastError?: string;\n\tsessionName?: string;\n\tcwd: string;\n}\n\nexport class AdaptiveLayoutComponent implements Component {\n\tconstructor(private readonly getState: () => AdaptiveLayoutState) {}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst state = this.getState();\n\t\tconst mode = resolveTuiMode({\n\t\t\tterminalWidth: width,\n\t\t\toverride: state.override,\n\t\t\tactiveToolCount: state.activeToolCount,\n\t\t\tgsdPhase: state.gsdPhase,\n\t\t\thasBlockingError: !!state.lastError,\n\t\t});\n\n\t\tif (state.override === \"auto\" && mode === \"chat\" && !state.gsdPhase && !state.lastError && state.activeToolCount === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (mode === \"compact\" || width < 72) return this.renderCompact(width, mode, state);\n\t\tif (mode === \"debug\") return this.renderDebug(width, state);\n\t\tif (mode === \"validation\") return this.renderValidation(width, state);\n\t\tif (mode === \"workflow\") return this.renderWorkflow(width, state);\n\t\treturn this.renderChat(width, state);\n\t}\n\n\tprivate renderWorkflow(width: number, state: AdaptiveLayoutState): string[] {\n\t\tif (width < 112) return this.renderCompact(width, \"workflow\", state);\n\n\t\tconst leftWidth = Math.max(44, Math.floor(width * 0.56));\n\t\tconst rightWidth = Math.max(32, width - leftWidth - 2);\n\t\tconst phase = state.gsdPhase ?? \"Ready\";\n\t\tconst left = this.frame(\n\t\t\t[\n\t\t\t\tthis.metric(\"Active\", phase, \"modeWorkflow\"),\n\t\t\t\tthis.metric(\"Tools\", state.activeToolCount > 0 ? `${state.activeToolCount} running` : \"idle\", \"toolRunning\"),\n\t\t\t\tthis.metric(\"Mode\", state.override === \"auto\" ? \"auto workflow\" : state.override, \"modeWorkflow\"),\n\t\t\t],\n\t\t\tleftWidth,\n\t\t\t\"GSD Command Center\",\n\t\t\t\"workflow\",\n\t\t\t\"modeWorkflow\",\n\t\t);\n\t\tconst right = this.frame(\n\t\t\t[\n\t\t\t\t`Session ${state.sessionName ?? \"current\"}`,\n\t\t\t\t`Path ${this.basename(state.cwd)}`,\n\t\t\t\t`Next ${state.activeToolCount > 0 ? \"watch tool output\" : \"continue from prompt\"}`,\n\t\t\t],\n\t\t\trightWidth,\n\t\t\t\"signals\",\n\t\t\t\"inspector\",\n\t\t\t\"surfaceAccent\",\n\t\t);\n\t\treturn this.columns(left, right, leftWidth);\n\t}\n\n\tprivate renderValidation(width: number, state: AdaptiveLayoutState): string[] {\n\t\tconst phase = state.gsdPhase ?? \"Validation pending\";\n\t\treturn this.frame(\n\t\t\t[\n\t\t\t\tthis.metric(\"Focus\", phase, \"modeValidation\"),\n\t\t\t\tthis.metric(\"Checks\", state.activeToolCount > 0 ? `${state.activeToolCount} active` : \"waiting\", \"toolRunning\"),\n\t\t\t\tthis.metric(\"Timeline\", state.lastError ? \"blocked\" : \"ready for completion evidence\", state.lastError ? \"toolError\" : \"toolSuccess\"),\n\t\t\t],\n\t\t\twidth,\n\t\t\t\"validation\",\n\t\t\tstate.override === \"auto\" ? \"auto\" : state.override,\n\t\t\t\"modeValidation\",\n\t\t);\n\t}\n\n\tprivate renderDebug(width: number, state: AdaptiveLayoutState): string[] {\n\t\tconst error = state.lastError ?? \"Blocking error detected\";\n\t\treturn this.frame(\n\t\t\t[\n\t\t\t\tthis.metric(\"Failure\", truncateToWidth(error, Math.max(20, width - 20), \"\"), \"toolError\"),\n\t\t\t\tthis.metric(\"Tools\", state.activeToolCount > 0 ? `${state.activeToolCount} still running` : \"none running\", \"toolRunning\"),\n\t\t\t\tthis.metric(\"Next\", \"inspect the failed output, then retry the smallest step\", \"modeDebug\"),\n\t\t\t],\n\t\t\twidth,\n\t\t\t\"blocking failure\",\n\t\t\t\"debug\",\n\t\t\t\"modeDebug\",\n\t\t);\n\t}\n\n\tprivate renderChat(width: number, state: AdaptiveLayoutState): string[] {\n\t\treturn this.frame(\n\t\t\t[\n\t\t\t\tthis.metric(\"Mode\", state.override === \"auto\" ? \"auto chat\" : state.override, \"surfaceAccent\"),\n\t\t\t\tthis.metric(\"Tools\", state.activeToolCount > 0 ? `${state.activeToolCount} active` : \"compact rows\", \"toolMuted\"),\n\t\t\t],\n\t\t\twidth,\n\t\t\t\"chat\",\n\t\t\tstate.sessionName ?? \"conversation\",\n\t\t\t\"surfaceAccent\",\n\t\t);\n\t}\n\n\tprivate renderCompact(width: number, mode: TuiMode, state: AdaptiveLayoutState): string[] {\n\t\tconst phase = state.lastError ?? state.gsdPhase ?? (state.activeToolCount > 0 ? `${state.activeToolCount} tools` : \"ready\");\n\t\tconst line = `${theme.fg(\"modeCompact\", \"GSD compact\")} ${theme.fg(\"surfaceMuted\", `${mode} · ${phase}`)}`;\n\t\treturn style()\n\t\t\t.border(\"minimal\")\n\t\t\t.borderColor((text) => theme.fg(\"surfaceBorder\", text))\n\t\t\t.bodyGutter(\" \")\n\t\t\t.render([line], width);\n\t}\n\n\tprivate frame(lines: string[], width: number, title: string, rightTitle: string, accent: ThemeColor): string[] {\n\t\treturn style()\n\t\t\t.border(\"rule\")\n\t\t\t.density(\"compact\")\n\t\t\t.toneColor((text) => theme.fg(\"surfaceMuted\", text))\n\t\t\t.borderColor((text) => theme.fg(\"surfaceBorder\", text))\n\t\t\t.title(theme.fg(\"surfaceTitle\", title))\n\t\t\t.rightTitle(theme.fg(accent, rightTitle))\n\t\t\t.bodyGutter(theme.fg(accent, \"│ \"))\n\t\t\t.render(lines, width);\n\t}\n\n\tprivate metric(label: string, value: string, color: ThemeColor): string {\n\t\treturn `${theme.fg(\"surfaceMuted\", `${label.padEnd(8)} `)}${theme.fg(color, value)}`;\n\t}\n\n\tprivate columns(left: string[], right: string[], leftWidth: number): string[] {\n\t\tconst rows = Math.max(left.length, right.length);\n\t\tconst output: string[] = [];\n\t\tfor (let i = 0; i < rows; i++) {\n\t\t\tconst leftLine = left[i] ?? \"\";\n\t\t\tconst rightLine = right[i] ?? \"\";\n\t\t\tconst gap = \" \".repeat(Math.max(2, leftWidth - visibleWidth(leftLine) + 2));\n\t\t\toutput.push(`${leftLine}${gap}${rightLine}`);\n\t\t}\n\t\treturn output;\n\t}\n\n\tprivate basename(cwd: string): string {\n\t\tconst trimmed = cwd.replace(/\\/+$/, \"\");\n\t\tconst slash = trimmed.lastIndexOf(\"/\");\n\t\treturn slash === -1 ? trimmed : trimmed.slice(slash + 1);\n\t}\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adaptive-layout.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-layout.test.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/adaptive-layout.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ // GSD2 - Runtime tests for adaptive terminal layout rendering
2
+ import assert from "node:assert/strict";
3
+ import { describe, it, before } from "node:test";
4
+ import stripAnsi from "strip-ansi";
5
+ import { AdaptiveLayoutComponent } from "./adaptive-layout.js";
6
+ import { initTheme } from "../theme/theme.js";
7
+ before(() => {
8
+ initTheme("dark", false);
9
+ });
10
+ function render(component, width) {
11
+ return component.render(width).map(stripAnsi).join("\n");
12
+ }
13
+ describe("AdaptiveLayoutComponent", () => {
14
+ it("renders workflow command center and inspector on wide terminals", () => {
15
+ const component = new AdaptiveLayoutComponent(() => ({
16
+ override: "workflow",
17
+ activeToolCount: 2,
18
+ gsdPhase: "executing milestone M001",
19
+ sessionName: "demo",
20
+ cwd: "/tmp/demo",
21
+ }));
22
+ const output = render(component, 132);
23
+ assert.match(output, /GSD Command Center/);
24
+ assert.match(output, /signals/);
25
+ assert.match(output, /2 running/);
26
+ });
27
+ it("falls back to a single compact row for narrow workflow terminals", () => {
28
+ const component = new AdaptiveLayoutComponent(() => ({
29
+ override: "workflow",
30
+ activeToolCount: 1,
31
+ gsdPhase: "executing milestone M001",
32
+ cwd: "/tmp/demo",
33
+ }));
34
+ const output = render(component, 68);
35
+ assert.match(output, /GSD compact/);
36
+ assert.doesNotMatch(output, /signals/);
37
+ });
38
+ it("renders blocking failure context in debug mode", () => {
39
+ const component = new AdaptiveLayoutComponent(() => ({
40
+ override: "auto",
41
+ activeToolCount: 0,
42
+ lastError: "Cannot find module @gsd/native",
43
+ cwd: "/tmp/demo",
44
+ }));
45
+ const output = render(component, 120);
46
+ assert.match(output, /blocking failure/);
47
+ assert.match(output, /Cannot find module/);
48
+ assert.match(output, /inspect the failed output/);
49
+ });
50
+ });
51
+ //# sourceMappingURL=adaptive-layout.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-layout.test.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/adaptive-layout.test.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAE9D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,CAAC,GAAG,EAAE;IACX,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,SAAS,MAAM,CAAC,SAAkC,EAAE,KAAa;IAChE,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC1E,MAAM,SAAS,GAAG,IAAI,uBAAuB,CAAC,GAAG,EAAE,CAAC,CAAC;YACpD,QAAQ,EAAE,UAAU;YACpB,eAAe,EAAE,CAAC;YAClB,QAAQ,EAAE,0BAA0B;YACpC,WAAW,EAAE,MAAM;YACnB,GAAG,EAAE,WAAW;SAChB,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC3E,MAAM,SAAS,GAAG,IAAI,uBAAuB,CAAC,GAAG,EAAE,CAAC,CAAC;YACpD,QAAQ,EAAE,UAAU;YACpB,eAAe,EAAE,CAAC;YAClB,QAAQ,EAAE,0BAA0B;YACpC,GAAG,EAAE,WAAW;SAChB,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACzD,MAAM,SAAS,GAAG,IAAI,uBAAuB,CAAC,GAAG,EAAE,CAAC,CAAC;YACpD,QAAQ,EAAE,MAAM;YAChB,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,gCAAgC;YAC3C,GAAG,EAAE,WAAW;SAChB,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["// GSD2 - Runtime tests for adaptive terminal layout rendering\n\nimport assert from \"node:assert/strict\";\nimport { describe, it, before } from \"node:test\";\nimport stripAnsi from \"strip-ansi\";\nimport { AdaptiveLayoutComponent } from \"./adaptive-layout.js\";\nimport { initTheme } from \"../theme/theme.js\";\n\nbefore(() => {\n\tinitTheme(\"dark\", false);\n});\n\nfunction render(component: AdaptiveLayoutComponent, width: number): string {\n\treturn component.render(width).map(stripAnsi).join(\"\\n\");\n}\n\ndescribe(\"AdaptiveLayoutComponent\", () => {\n\tit(\"renders workflow command center and inspector on wide terminals\", () => {\n\t\tconst component = new AdaptiveLayoutComponent(() => ({\n\t\t\toverride: \"workflow\",\n\t\t\tactiveToolCount: 2,\n\t\t\tgsdPhase: \"executing milestone M001\",\n\t\t\tsessionName: \"demo\",\n\t\t\tcwd: \"/tmp/demo\",\n\t\t}));\n\n\t\tconst output = render(component, 132);\n\t\tassert.match(output, /GSD Command Center/);\n\t\tassert.match(output, /signals/);\n\t\tassert.match(output, /2 running/);\n\t});\n\n\tit(\"falls back to a single compact row for narrow workflow terminals\", () => {\n\t\tconst component = new AdaptiveLayoutComponent(() => ({\n\t\t\toverride: \"workflow\",\n\t\t\tactiveToolCount: 1,\n\t\t\tgsdPhase: \"executing milestone M001\",\n\t\t\tcwd: \"/tmp/demo\",\n\t\t}));\n\n\t\tconst output = render(component, 68);\n\t\tassert.match(output, /GSD compact/);\n\t\tassert.doesNotMatch(output, /signals/);\n\t});\n\n\tit(\"renders blocking failure context in debug mode\", () => {\n\t\tconst component = new AdaptiveLayoutComponent(() => ({\n\t\t\toverride: \"auto\",\n\t\t\tactiveToolCount: 0,\n\t\t\tlastError: \"Cannot find module @gsd/native\",\n\t\t\tcwd: \"/tmp/demo\",\n\t\t}));\n\n\t\tconst output = render(component, 120);\n\t\tassert.match(output, /blocking failure/);\n\t\tassert.match(output, /Cannot find module/);\n\t\tassert.match(output, /inspect the failed output/);\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,aAAa,CAAC;AAEpF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,YAAY,CAAU;gBAG7B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,eAAe,GAAE,eAAiC,EAClD,KAAK,CAAC,EAAE,YAAY;IAsBrB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAO/C,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAO3B,UAAU,IAAI,IAAI;IAO3B,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIzC,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAqFrC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAiBxC"}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,aAAa,CAAC;AAEpF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,YAAY,CAAU;gBAG7B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,eAAe,GAAE,eAAiC,EAClD,KAAK,CAAC,EAAE,YAAY;IAsBrB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAO/C,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAO3B,UAAU,IAAI,IAAI;IAO3B,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIzC,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAqFrC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAiBxC"}
@@ -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 { 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"]}
1
+ {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["// GSD2 TUI - Assistant message card renderer for interactive terminal sessions.\nimport 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"]}
@@ -1 +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,GAAG,YAAY,GAAG,OAAO,CAAC;AAU/D,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,CA8DV"}
1
+ {"version":3,"file":"chat-frame.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEvE,KAAK,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;AAU/D,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,CA8DV"}