gsd-pi 2.75.0-dev.063e5a3 → 2.75.0-dev.96d4bb599

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 (760) hide show
  1. package/README.md +186 -149
  2. package/dist/claude-cli-check.d.ts +10 -0
  3. package/dist/claude-cli-check.js +13 -3
  4. package/dist/headless-events.d.ts +1 -1
  5. package/dist/headless-events.js +5 -2
  6. package/dist/headless.js +5 -6
  7. package/dist/loader.js +0 -0
  8. package/dist/onboarding.d.ts +20 -1
  9. package/dist/onboarding.js +99 -39
  10. package/dist/resources/extensions/ask-user-questions.js +17 -5
  11. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +12 -2
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +76 -4
  14. package/dist/resources/extensions/gsd/auto/detect-stuck.js +9 -0
  15. package/dist/resources/extensions/gsd/auto/loop.js +67 -4
  16. package/dist/resources/extensions/gsd/auto/phases.js +70 -47
  17. package/dist/resources/extensions/gsd/auto/resolve.js +1 -1
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -1
  19. package/dist/resources/extensions/gsd/auto/session.js +5 -0
  20. package/dist/resources/extensions/gsd/auto-artifact-paths.js +20 -0
  21. package/dist/resources/extensions/gsd/auto-dashboard.js +15 -7
  22. package/dist/resources/extensions/gsd/auto-dispatch.js +112 -6
  23. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +11 -3
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +10 -8
  26. package/dist/resources/extensions/gsd/auto-prompts.js +173 -39
  27. package/dist/resources/extensions/gsd/auto-recovery.js +57 -0
  28. package/dist/resources/extensions/gsd/auto-start.js +5 -3
  29. package/dist/resources/extensions/gsd/auto-verification.js +3 -3
  30. package/dist/resources/extensions/gsd/auto-worktree.js +55 -1
  31. package/dist/resources/extensions/gsd/auto.js +57 -25
  32. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +8 -21
  33. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +45 -23
  34. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +128 -0
  35. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +29 -0
  36. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  37. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +22 -0
  38. package/dist/resources/extensions/gsd/bootstrap/system-context.js +17 -4
  39. package/dist/resources/extensions/gsd/commands/catalog.js +81 -9
  40. package/dist/resources/extensions/gsd/commands/handlers/core.js +64 -24
  41. package/dist/resources/extensions/gsd/commands/handlers/escalate.js +171 -0
  42. package/dist/resources/extensions/gsd/commands/handlers/onboarding.js +159 -0
  43. package/dist/resources/extensions/gsd/commands/handlers/ops.js +21 -0
  44. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +228 -29
  45. package/dist/resources/extensions/gsd/commands-cmux.js +5 -2
  46. package/dist/resources/extensions/gsd/commands-config.js +5 -0
  47. package/dist/resources/extensions/gsd/commands-debug.js +388 -0
  48. package/dist/resources/extensions/gsd/commands-do.js +1 -0
  49. package/dist/resources/extensions/gsd/commands-extract-learnings.js +233 -75
  50. package/dist/resources/extensions/gsd/commands-handlers.js +21 -2
  51. package/dist/resources/extensions/gsd/commands-memory.js +462 -0
  52. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +40 -12
  53. package/dist/resources/extensions/gsd/commands-scan.js +94 -0
  54. package/dist/resources/extensions/gsd/commands-workflow-templates.js +101 -2
  55. package/dist/resources/extensions/gsd/custom-workflow-engine.js +74 -54
  56. package/dist/resources/extensions/gsd/db-writer.js +1 -0
  57. package/dist/resources/extensions/gsd/debug-session-store.js +238 -0
  58. package/dist/resources/extensions/gsd/definition-loader.js +7 -0
  59. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -9
  60. package/dist/resources/extensions/gsd/doctor-environment.js +2 -1
  61. package/dist/resources/extensions/gsd/doctor-git-checks.js +5 -1
  62. package/dist/resources/extensions/gsd/doctor-proactive.js +4 -1
  63. package/dist/resources/extensions/gsd/doctor-providers.js +48 -20
  64. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +22 -4
  65. package/dist/resources/extensions/gsd/doctor.js +7 -1
  66. package/dist/resources/extensions/gsd/error-classifier.js +6 -3
  67. package/dist/resources/extensions/gsd/escalation.js +321 -0
  68. package/dist/resources/extensions/gsd/forensics.js +26 -29
  69. package/dist/resources/extensions/gsd/git-service.js +0 -1
  70. package/dist/resources/extensions/gsd/graph.js +26 -2
  71. package/dist/resources/extensions/gsd/gsd-db.js +490 -32
  72. package/dist/resources/extensions/gsd/health-widget-core.js +42 -14
  73. package/dist/resources/extensions/gsd/health-widget.js +7 -4
  74. package/dist/resources/extensions/gsd/init-wizard.js +86 -45
  75. package/dist/resources/extensions/gsd/markdown-renderer.js +5 -5
  76. package/dist/resources/extensions/gsd/memory-embeddings.js +219 -0
  77. package/dist/resources/extensions/gsd/memory-extractor.js +78 -27
  78. package/dist/resources/extensions/gsd/memory-ingest.js +218 -0
  79. package/dist/resources/extensions/gsd/memory-relations.js +189 -0
  80. package/dist/resources/extensions/gsd/memory-source-store.js +113 -0
  81. package/dist/resources/extensions/gsd/memory-store.js +299 -6
  82. package/dist/resources/extensions/gsd/metrics.js +1 -0
  83. package/dist/resources/extensions/gsd/model-cost-table.js +3 -1
  84. package/dist/resources/extensions/gsd/model-router.js +16 -6
  85. package/dist/resources/extensions/gsd/native-git-bridge.js +137 -5
  86. package/dist/resources/extensions/gsd/notification-overlay.js +7 -22
  87. package/dist/resources/extensions/gsd/notification-widget.js +24 -39
  88. package/dist/resources/extensions/gsd/notifications.js +4 -0
  89. package/dist/resources/extensions/gsd/onboarding-state.js +133 -0
  90. package/dist/resources/extensions/gsd/post-execution-checks.js +27 -11
  91. package/dist/resources/extensions/gsd/pre-execution-checks.js +97 -4
  92. package/dist/resources/extensions/gsd/preferences-models.js +1 -0
  93. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  94. package/dist/resources/extensions/gsd/preferences-validation.js +42 -8
  95. package/dist/resources/extensions/gsd/preferences.js +10 -10
  96. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +4 -1
  97. package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +25 -0
  98. package/dist/resources/extensions/gsd/prompts/debug-session-manager.md +80 -0
  99. package/dist/resources/extensions/gsd/prompts/execute-task.md +12 -0
  100. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +12 -0
  101. package/dist/resources/extensions/gsd/prompts/refine-slice.md +69 -0
  102. package/dist/resources/extensions/gsd/prompts/scan.md +79 -0
  103. package/dist/resources/extensions/gsd/prompts/workflow-oneshot.md +26 -0
  104. package/dist/resources/extensions/gsd/python-resolver.js +70 -0
  105. package/dist/resources/extensions/gsd/run-manager.js +37 -17
  106. package/dist/resources/extensions/gsd/setup-catalog.js +75 -0
  107. package/dist/resources/extensions/gsd/state.js +47 -3
  108. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +7 -7
  109. package/dist/resources/extensions/gsd/tools/complete-task.js +80 -0
  110. package/dist/resources/extensions/gsd/tools/memory-tools.js +306 -0
  111. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -12
  112. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -2
  113. package/dist/resources/extensions/gsd/tools/skip-slice.js +78 -0
  114. package/dist/resources/extensions/gsd/uok/flags.js +7 -7
  115. package/dist/resources/extensions/gsd/uok/kernel.js +8 -3
  116. package/dist/resources/extensions/gsd/verification-gate.js +2 -1
  117. package/dist/resources/extensions/gsd/workflow-dispatch.js +64 -0
  118. package/dist/resources/extensions/gsd/workflow-install.js +327 -0
  119. package/dist/resources/extensions/gsd/workflow-manifest.js +8 -0
  120. package/dist/resources/extensions/gsd/workflow-mcp.js +1 -6
  121. package/dist/resources/extensions/gsd/workflow-plugins.js +346 -0
  122. package/dist/resources/extensions/gsd/workflow-projections.js +17 -15
  123. package/dist/resources/extensions/gsd/workflow-templates/accessibility-audit.md +88 -0
  124. package/dist/resources/extensions/gsd/workflow-templates/api-breaking-change.md +117 -0
  125. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +1 -0
  126. package/dist/resources/extensions/gsd/workflow-templates/changelog-gen.md +82 -0
  127. package/dist/resources/extensions/gsd/workflow-templates/ci-bootstrap.md +144 -0
  128. package/dist/resources/extensions/gsd/workflow-templates/dead-code.md +81 -0
  129. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +1 -0
  130. package/dist/resources/extensions/gsd/workflow-templates/docs-sync.yaml +76 -0
  131. package/dist/resources/extensions/gsd/workflow-templates/env-audit.yaml +88 -0
  132. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +1 -0
  133. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +1 -0
  134. package/dist/resources/extensions/gsd/workflow-templates/issue-triage.md +84 -0
  135. package/dist/resources/extensions/gsd/workflow-templates/observability-setup.md +133 -0
  136. package/dist/resources/extensions/gsd/workflow-templates/onboarding-check.md +74 -0
  137. package/dist/resources/extensions/gsd/workflow-templates/performance-audit.md +125 -0
  138. package/dist/resources/extensions/gsd/workflow-templates/pr-review.md +67 -0
  139. package/dist/resources/extensions/gsd/workflow-templates/pr-triage.md +83 -0
  140. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +1 -0
  141. package/dist/resources/extensions/gsd/workflow-templates/registry.json +184 -0
  142. package/dist/resources/extensions/gsd/workflow-templates/release.md +118 -0
  143. package/dist/resources/extensions/gsd/workflow-templates/rename-symbol.yaml +99 -0
  144. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +1 -0
  145. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +1 -0
  146. package/dist/resources/extensions/gsd/workflow-templates/spike.md +1 -0
  147. package/dist/resources/extensions/gsd/workflow-templates/test-backfill.yaml +73 -0
  148. package/dist/resources/extensions/gsd/worktree-resolver.js +42 -1
  149. package/dist/resources/extensions/remote-questions/commands.js +380 -0
  150. package/dist/resources/extensions/remote-questions/manager.js +39 -5
  151. package/dist/resources/extensions/remote-questions/telegram-adapter.js +79 -4
  152. package/dist/resources/extensions/shared/interview-ui.js +189 -1
  153. package/dist/resources/extensions/shared/layout-utils.js +17 -0
  154. package/dist/resources/extensions/shared/rtk-shared.js +47 -0
  155. package/dist/resources/extensions/shared/rtk.js +3 -46
  156. package/dist/resources/skills/create-workflow/SKILL.md +33 -6
  157. package/dist/rtk-shared.d.ts +10 -0
  158. package/dist/rtk-shared.js +47 -0
  159. package/dist/rtk.d.ts +2 -6
  160. package/dist/rtk.js +3 -48
  161. package/dist/shared/workspace-types.d.ts +52 -0
  162. package/dist/shared/workspace-types.js +1 -0
  163. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  164. package/dist/update-check.d.ts +10 -0
  165. package/dist/update-check.js +24 -3
  166. package/dist/web/standalone/.next/BUILD_ID +1 -1
  167. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  168. package/dist/web/standalone/.next/build-manifest.json +3 -3
  169. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  170. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  171. package/dist/web/standalone/.next/required-server-files.json +1 -1
  172. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  174. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  180. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  181. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  183. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  184. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  185. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  187. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  190. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  197. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  206. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  210. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  212. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  216. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  218. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  220. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  222. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  223. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  224. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  226. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  228. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  230. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  232. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  234. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  235. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  236. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  238. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  239. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  240. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  241. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  242. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  243. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  244. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  245. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  246. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  247. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  248. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  249. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  250. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  252. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  253. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  254. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  255. package/dist/web/standalone/.next/server/app/index.html +1 -1
  256. package/dist/web/standalone/.next/server/app/index.rsc +3 -3
  257. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  258. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  259. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  260. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  261. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  262. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  263. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  264. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  265. package/dist/web/standalone/.next/server/chunks/7461.js +1 -0
  266. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  267. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  268. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  269. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  270. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  271. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  272. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +9 -0
  273. package/dist/web/standalone/.next/static/chunks/{2008.71ee9230ad78df21.js → 3621.fc7480022c972438.js} +2 -2
  274. package/dist/web/standalone/.next/static/chunks/app/{page-f1e30ab6bb269149.js → page-5b113fd32bc2a1c3.js} +1 -1
  275. package/dist/web/standalone/.next/static/chunks/{webpack-b868033a5834586d.js → webpack-5fc74f13a25fa1bb.js} +1 -1
  276. package/dist/web/standalone/.next/static/css/632cd626b1731d88.css +1 -0
  277. package/dist/web/standalone/server.js +1 -1
  278. package/dist/welcome-screen.js +48 -24
  279. package/dist/wizard.js +2 -2
  280. package/dist/worktree-cli.d.ts +6 -5
  281. package/dist/worktree-cli.js +23 -7
  282. package/package.json +3 -3
  283. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  284. package/packages/mcp-server/dist/server.js +12 -10
  285. package/packages/mcp-server/dist/server.js.map +1 -1
  286. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  287. package/packages/mcp-server/dist/session-manager.js +8 -1
  288. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  289. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -0
  290. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  291. package/packages/mcp-server/dist/workflow-tools.js +113 -14
  292. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  293. package/packages/mcp-server/src/mcp-server.test.ts +40 -4
  294. package/packages/mcp-server/src/server.ts +12 -10
  295. package/packages/mcp-server/src/session-manager.ts +10 -3
  296. package/packages/mcp-server/src/workflow-tools.test.ts +91 -1
  297. package/packages/mcp-server/src/workflow-tools.ts +128 -18
  298. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  299. package/packages/native/tsconfig.tsbuildinfo +1 -1
  300. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  301. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/models/capability-patches.js +3 -2
  303. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  304. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +68 -0
  305. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -1
  306. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +68 -0
  307. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -1
  308. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +17 -0
  309. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -1
  310. package/packages/pi-ai/dist/models/generated/anthropic.js +17 -0
  311. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -1
  312. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +17 -0
  313. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -1
  314. package/packages/pi-ai/dist/models/generated/google-antigravity.js +17 -0
  315. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -1
  316. package/packages/pi-ai/dist/models/generated/groq.d.ts +0 -153
  317. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -1
  318. package/packages/pi-ai/dist/models/generated/groq.js +0 -153
  319. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -1
  320. package/packages/pi-ai/dist/models/generated/index.d.ts +136 -153
  321. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  322. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  323. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  324. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  325. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  326. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +17 -0
  327. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -1
  328. package/packages/pi-ai/dist/models/generated/openrouter.js +17 -0
  329. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -1
  330. package/packages/pi-ai/dist/models.generated.test.js +17 -0
  331. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  332. package/packages/pi-ai/dist/providers/amazon-bedrock.d.ts +22 -1
  333. package/packages/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  334. package/packages/pi-ai/dist/providers/amazon-bedrock.js +40 -6
  335. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  336. package/packages/pi-ai/dist/providers/amazon-bedrock.test.d.ts +2 -0
  337. package/packages/pi-ai/dist/providers/amazon-bedrock.test.d.ts.map +1 -0
  338. package/packages/pi-ai/dist/providers/amazon-bedrock.test.js +106 -0
  339. package/packages/pi-ai/dist/providers/amazon-bedrock.test.js.map +1 -0
  340. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +42 -1
  341. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  342. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +20 -1
  343. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  344. package/packages/pi-ai/dist/providers/anthropic-shared.js +32 -2
  345. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  346. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +12 -1
  347. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  348. package/packages/pi-ai/dist/providers/anthropic.d.ts +11 -0
  349. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  350. package/packages/pi-ai/dist/providers/anthropic.js +18 -1
  351. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  352. package/packages/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  353. package/packages/pi-ai/dist/utils/oauth/openai-codex.js +12 -0
  354. package/packages/pi-ai/dist/utils/oauth/openai-codex.js.map +1 -1
  355. package/packages/pi-ai/package.json +1 -1
  356. package/packages/pi-ai/scripts/generate-models.ts +50 -0
  357. package/packages/pi-ai/src/models/capability-patches.ts +5 -2
  358. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +68 -0
  359. package/packages/pi-ai/src/models/generated/anthropic.ts +17 -0
  360. package/packages/pi-ai/src/models/generated/google-antigravity.ts +17 -0
  361. package/packages/pi-ai/src/models/generated/groq.ts +0 -153
  362. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  363. package/packages/pi-ai/src/models/generated/openrouter.ts +17 -0
  364. package/packages/pi-ai/src/models.generated.test.ts +17 -0
  365. package/packages/pi-ai/src/providers/amazon-bedrock.test.ts +164 -0
  366. package/packages/pi-ai/src/providers/amazon-bedrock.ts +41 -7
  367. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +47 -1
  368. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +15 -1
  369. package/packages/pi-ai/src/providers/anthropic-shared.ts +36 -3
  370. package/packages/pi-ai/src/providers/anthropic.ts +19 -1
  371. package/packages/pi-ai/src/utils/oauth/openai-codex.ts +15 -0
  372. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  373. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.d.ts +2 -0
  374. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.d.ts.map +1 -0
  375. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +38 -0
  376. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -0
  377. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +14 -0
  378. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/auth-storage.js +34 -0
  380. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +74 -0
  382. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  383. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +4 -1
  384. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  385. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +32 -0
  386. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/sdk.js +32 -0
  389. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  390. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +2 -2
  391. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  392. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  393. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +17 -7
  394. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  395. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  396. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +48 -34
  397. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +4 -0
  399. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +83 -33
  401. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  402. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +70 -0
  403. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
  404. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +77 -0
  405. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -0
  406. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -66
  407. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  408. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +1 -75
  409. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  410. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts +1 -1
  411. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  412. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +192 -24
  413. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  414. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +56 -0
  415. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +83 -0
  416. package/packages/pi-coding-agent/src/core/auth-storage.ts +35 -0
  417. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +4 -1
  418. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +37 -1
  419. package/packages/pi-coding-agent/src/core/sdk.ts +41 -0
  420. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +2 -2
  421. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +19 -7
  422. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +53 -31
  423. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +88 -36
  424. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +83 -0
  425. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +2 -83
  426. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +208 -27
  427. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  428. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  429. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  430. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +70 -0
  431. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
  432. package/pkg/dist/modes/interactive/theme/theme-schema.js +77 -0
  433. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -0
  434. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -66
  435. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  436. package/pkg/dist/modes/interactive/theme/theme.js +1 -75
  437. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  438. package/pkg/dist/modes/interactive/theme/themes.d.ts +1 -1
  439. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  440. package/pkg/dist/modes/interactive/theme/themes.js +192 -24
  441. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  442. package/src/resources/extensions/ask-user-questions.ts +24 -6
  443. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  444. package/src/resources/extensions/claude-code-cli/readiness.ts +13 -2
  445. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +94 -4
  446. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +84 -0
  447. package/src/resources/extensions/gsd/auto/detect-stuck.ts +10 -0
  448. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  449. package/src/resources/extensions/gsd/auto/loop.ts +109 -3
  450. package/src/resources/extensions/gsd/auto/phases.ts +94 -60
  451. package/src/resources/extensions/gsd/auto/resolve.ts +1 -1
  452. package/src/resources/extensions/gsd/auto/run-unit.ts +11 -1
  453. package/src/resources/extensions/gsd/auto/session.ts +7 -0
  454. package/src/resources/extensions/gsd/auto-artifact-paths.ts +20 -0
  455. package/src/resources/extensions/gsd/auto-dashboard.ts +21 -4
  456. package/src/resources/extensions/gsd/auto-dispatch.ts +123 -5
  457. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  458. package/src/resources/extensions/gsd/auto-model-selection.ts +14 -3
  459. package/src/resources/extensions/gsd/auto-post-unit.ts +10 -8
  460. package/src/resources/extensions/gsd/auto-prompts.ts +201 -40
  461. package/src/resources/extensions/gsd/auto-recovery.ts +63 -1
  462. package/src/resources/extensions/gsd/auto-start.ts +8 -6
  463. package/src/resources/extensions/gsd/auto-verification.ts +3 -3
  464. package/src/resources/extensions/gsd/auto-worktree.ts +65 -0
  465. package/src/resources/extensions/gsd/auto.ts +61 -28
  466. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +8 -21
  467. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +46 -24
  468. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +158 -0
  469. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +31 -0
  470. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  471. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  472. package/src/resources/extensions/gsd/bootstrap/system-context.ts +20 -4
  473. package/src/resources/extensions/gsd/commands/catalog.ts +74 -9
  474. package/src/resources/extensions/gsd/commands/handlers/core.ts +69 -27
  475. package/src/resources/extensions/gsd/commands/handlers/escalate.ts +216 -0
  476. package/src/resources/extensions/gsd/commands/handlers/onboarding.ts +196 -0
  477. package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
  478. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +279 -29
  479. package/src/resources/extensions/gsd/commands-cmux.ts +6 -2
  480. package/src/resources/extensions/gsd/commands-config.ts +10 -0
  481. package/src/resources/extensions/gsd/commands-debug.ts +484 -0
  482. package/src/resources/extensions/gsd/commands-do.ts +1 -0
  483. package/src/resources/extensions/gsd/commands-extract-learnings.ts +295 -76
  484. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  485. package/src/resources/extensions/gsd/commands-memory.ts +551 -0
  486. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +49 -12
  487. package/src/resources/extensions/gsd/commands-scan.ts +125 -0
  488. package/src/resources/extensions/gsd/commands-workflow-templates.ts +129 -2
  489. package/src/resources/extensions/gsd/custom-workflow-engine.ts +85 -60
  490. package/src/resources/extensions/gsd/db-writer.ts +3 -0
  491. package/src/resources/extensions/gsd/debug-session-store.ts +377 -0
  492. package/src/resources/extensions/gsd/definition-loader.ts +7 -0
  493. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -9
  494. package/src/resources/extensions/gsd/doctor-environment.ts +2 -1
  495. package/src/resources/extensions/gsd/doctor-git-checks.ts +5 -1
  496. package/src/resources/extensions/gsd/doctor-proactive.ts +4 -1
  497. package/src/resources/extensions/gsd/doctor-providers.ts +52 -22
  498. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +23 -4
  499. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  500. package/src/resources/extensions/gsd/doctor.ts +7 -1
  501. package/src/resources/extensions/gsd/error-classifier.ts +6 -3
  502. package/src/resources/extensions/gsd/escalation.ts +367 -0
  503. package/src/resources/extensions/gsd/forensics.ts +25 -29
  504. package/src/resources/extensions/gsd/git-service.ts +0 -1
  505. package/src/resources/extensions/gsd/graph.ts +33 -3
  506. package/src/resources/extensions/gsd/gsd-db.ts +578 -32
  507. package/src/resources/extensions/gsd/health-widget-core.ts +43 -14
  508. package/src/resources/extensions/gsd/health-widget.ts +7 -3
  509. package/src/resources/extensions/gsd/init-wizard.ts +87 -54
  510. package/src/resources/extensions/gsd/markdown-renderer.ts +5 -5
  511. package/src/resources/extensions/gsd/memory-embeddings.ts +235 -0
  512. package/src/resources/extensions/gsd/memory-extractor.ts +100 -34
  513. package/src/resources/extensions/gsd/memory-ingest.ts +286 -0
  514. package/src/resources/extensions/gsd/memory-relations.ts +240 -0
  515. package/src/resources/extensions/gsd/memory-source-store.ts +138 -0
  516. package/src/resources/extensions/gsd/memory-store.ts +351 -7
  517. package/src/resources/extensions/gsd/metrics.ts +1 -0
  518. package/src/resources/extensions/gsd/model-cost-table.ts +3 -1
  519. package/src/resources/extensions/gsd/model-router.ts +25 -6
  520. package/src/resources/extensions/gsd/native-git-bridge.ts +134 -6
  521. package/src/resources/extensions/gsd/notification-overlay.ts +9 -19
  522. package/src/resources/extensions/gsd/notification-widget.ts +25 -43
  523. package/src/resources/extensions/gsd/notifications.ts +6 -0
  524. package/src/resources/extensions/gsd/onboarding-state.ts +146 -0
  525. package/src/resources/extensions/gsd/post-execution-checks.ts +37 -14
  526. package/src/resources/extensions/gsd/pre-execution-checks.ts +98 -8
  527. package/src/resources/extensions/gsd/preferences-models.ts +1 -0
  528. package/src/resources/extensions/gsd/preferences-types.ts +10 -2
  529. package/src/resources/extensions/gsd/preferences-validation.ts +33 -7
  530. package/src/resources/extensions/gsd/preferences.ts +10 -10
  531. package/src/resources/extensions/gsd/prompts/complete-milestone.md +4 -1
  532. package/src/resources/extensions/gsd/prompts/debug-diagnose.md +25 -0
  533. package/src/resources/extensions/gsd/prompts/debug-session-manager.md +80 -0
  534. package/src/resources/extensions/gsd/prompts/execute-task.md +12 -0
  535. package/src/resources/extensions/gsd/prompts/plan-milestone.md +12 -0
  536. package/src/resources/extensions/gsd/prompts/refine-slice.md +69 -0
  537. package/src/resources/extensions/gsd/prompts/scan.md +79 -0
  538. package/src/resources/extensions/gsd/prompts/workflow-oneshot.md +26 -0
  539. package/src/resources/extensions/gsd/python-resolver.ts +76 -0
  540. package/src/resources/extensions/gsd/run-manager.ts +53 -19
  541. package/src/resources/extensions/gsd/setup-catalog.ts +105 -0
  542. package/src/resources/extensions/gsd/state.ts +50 -2
  543. package/src/resources/extensions/gsd/templates/PREFERENCES.md +7 -7
  544. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +1 -34
  545. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +7 -0
  546. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +45 -31
  547. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +63 -0
  548. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +12 -0
  549. package/src/resources/extensions/gsd/tests/auto-prompts-fallback.test.ts +35 -0
  550. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +123 -1
  551. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +39 -0
  552. package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +39 -0
  553. package/src/resources/extensions/gsd/tests/commands-do.test.ts +48 -0
  554. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +333 -21
  555. package/src/resources/extensions/gsd/tests/commands-scan.test.ts +351 -0
  556. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +8 -6
  557. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +6 -8
  558. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  559. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +63 -0
  560. package/src/resources/extensions/gsd/tests/debug-command-handler.test.ts +905 -0
  561. package/src/resources/extensions/gsd/tests/debug-command-lifecycle.integration.test.ts +1229 -0
  562. package/src/resources/extensions/gsd/tests/debug-session-store.test.ts +565 -0
  563. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +64 -0
  564. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +67 -0
  565. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +62 -18
  566. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +5 -0
  567. package/src/resources/extensions/gsd/tests/escalation.test.ts +818 -0
  568. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +29 -12
  569. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +106 -0
  570. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +74 -0
  571. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +0 -4
  572. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -1
  573. package/src/resources/extensions/gsd/tests/health-widget.test.ts +8 -2
  574. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +190 -0
  575. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +39 -0
  576. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +44 -0
  577. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +68 -1
  578. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +109 -11
  579. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +51 -0
  580. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +2 -2
  581. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  582. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +171 -1
  583. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  584. package/src/resources/extensions/gsd/tests/memory-embeddings.test.ts +213 -0
  585. package/src/resources/extensions/gsd/tests/memory-ingest.test.ts +153 -0
  586. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +107 -0
  587. package/src/resources/extensions/gsd/tests/memory-relations.test.ts +175 -0
  588. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  589. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +295 -0
  590. package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +3 -2
  591. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +2 -2
  592. package/src/resources/extensions/gsd/tests/model-router.test.ts +51 -1
  593. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +59 -0
  594. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +56 -37
  595. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +1 -1
  596. package/src/resources/extensions/gsd/tests/onboarding-state.test.ts +105 -0
  597. package/src/resources/extensions/gsd/tests/plan-milestone-boundary-map-preservation.test.ts +114 -0
  598. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +4 -5
  599. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +17 -0
  600. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +105 -1
  601. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +275 -6
  602. package/src/resources/extensions/gsd/tests/preferences.test.ts +69 -1
  603. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +539 -0
  604. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +11 -2
  605. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +7 -0
  606. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +27 -0
  607. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +24 -0
  608. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +1 -1
  609. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +33 -0
  610. package/src/resources/extensions/gsd/tests/python-resolver.test.ts +131 -0
  611. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +67 -0
  612. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +107 -0
  613. package/src/resources/extensions/gsd/tests/requirements.test.ts +9 -0
  614. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +153 -0
  615. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +125 -0
  616. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +16 -4
  617. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +3 -0
  618. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +15 -0
  619. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +5 -0
  620. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +2 -1
  621. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +31 -1
  622. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +166 -0
  623. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +35 -0
  624. package/src/resources/extensions/gsd/tests/workflow-install.test.ts +113 -0
  625. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +15 -6
  626. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  627. package/src/resources/extensions/gsd/tests/workflow-plugins.test.ts +310 -0
  628. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +7 -0
  629. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +8 -2
  630. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +2 -1
  631. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +77 -2
  632. package/src/resources/extensions/gsd/tools/complete-task.ts +87 -0
  633. package/src/resources/extensions/gsd/tools/memory-tools.ts +380 -0
  634. package/src/resources/extensions/gsd/tools/plan-milestone.ts +42 -8
  635. package/src/resources/extensions/gsd/tools/plan-slice.ts +6 -1
  636. package/src/resources/extensions/gsd/tools/skip-slice.ts +133 -0
  637. package/src/resources/extensions/gsd/types.ts +62 -0
  638. package/src/resources/extensions/gsd/unit-runtime.ts +1 -0
  639. package/src/resources/extensions/gsd/uok/contracts.ts +2 -1
  640. package/src/resources/extensions/gsd/uok/flags.ts +7 -7
  641. package/src/resources/extensions/gsd/uok/kernel.ts +16 -4
  642. package/src/resources/extensions/gsd/verification-gate.ts +2 -1
  643. package/src/resources/extensions/gsd/workflow-dispatch.ts +106 -0
  644. package/src/resources/extensions/gsd/workflow-install.ts +423 -0
  645. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  646. package/src/resources/extensions/gsd/workflow-manifest.ts +8 -0
  647. package/src/resources/extensions/gsd/workflow-mcp.ts +1 -6
  648. package/src/resources/extensions/gsd/workflow-plugins.ts +403 -0
  649. package/src/resources/extensions/gsd/workflow-projections.ts +18 -16
  650. package/src/resources/extensions/gsd/workflow-templates/accessibility-audit.md +88 -0
  651. package/src/resources/extensions/gsd/workflow-templates/api-breaking-change.md +117 -0
  652. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +1 -0
  653. package/src/resources/extensions/gsd/workflow-templates/changelog-gen.md +82 -0
  654. package/src/resources/extensions/gsd/workflow-templates/ci-bootstrap.md +144 -0
  655. package/src/resources/extensions/gsd/workflow-templates/dead-code.md +81 -0
  656. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +1 -0
  657. package/src/resources/extensions/gsd/workflow-templates/docs-sync.yaml +76 -0
  658. package/src/resources/extensions/gsd/workflow-templates/env-audit.yaml +88 -0
  659. package/src/resources/extensions/gsd/workflow-templates/full-project.md +1 -0
  660. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +1 -0
  661. package/src/resources/extensions/gsd/workflow-templates/issue-triage.md +84 -0
  662. package/src/resources/extensions/gsd/workflow-templates/observability-setup.md +133 -0
  663. package/src/resources/extensions/gsd/workflow-templates/onboarding-check.md +74 -0
  664. package/src/resources/extensions/gsd/workflow-templates/performance-audit.md +125 -0
  665. package/src/resources/extensions/gsd/workflow-templates/pr-review.md +67 -0
  666. package/src/resources/extensions/gsd/workflow-templates/pr-triage.md +83 -0
  667. package/src/resources/extensions/gsd/workflow-templates/refactor.md +1 -0
  668. package/src/resources/extensions/gsd/workflow-templates/registry.json +184 -0
  669. package/src/resources/extensions/gsd/workflow-templates/release.md +118 -0
  670. package/src/resources/extensions/gsd/workflow-templates/rename-symbol.yaml +99 -0
  671. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +1 -0
  672. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +1 -0
  673. package/src/resources/extensions/gsd/workflow-templates/spike.md +1 -0
  674. package/src/resources/extensions/gsd/workflow-templates/test-backfill.yaml +73 -0
  675. package/src/resources/extensions/gsd/workflow-templates.ts +7 -0
  676. package/src/resources/extensions/gsd/workspace-index.ts +9 -4
  677. package/src/resources/extensions/gsd/worktree-resolver.ts +47 -1
  678. package/src/resources/extensions/remote-questions/commands.ts +480 -0
  679. package/src/resources/extensions/remote-questions/manager.ts +49 -4
  680. package/src/resources/extensions/remote-questions/telegram-adapter.ts +86 -4
  681. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +246 -0
  682. package/src/resources/extensions/remote-questions/tests/remote-answer-normalization.test.ts +92 -0
  683. package/src/resources/extensions/remote-questions/tests/telegram-commands.test.ts +267 -0
  684. package/src/resources/extensions/shared/interview-ui.ts +195 -1
  685. package/src/resources/extensions/shared/layout-utils.ts +26 -0
  686. package/src/resources/extensions/shared/rtk-shared.ts +58 -0
  687. package/src/resources/extensions/shared/rtk.ts +12 -52
  688. package/src/resources/extensions/shared/tests/interview-preview.test.ts +177 -0
  689. package/src/resources/extensions/shared/tests/preview-layout.test.ts +120 -0
  690. package/src/resources/skills/create-workflow/SKILL.md +33 -6
  691. package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +0 -9
  692. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +0 -1
  693. package/packages/native/dist/ps/types.d.ts +0 -5
  694. package/packages/native/dist/ps/types.js +0 -2
  695. package/packages/native/src/ps/types.ts +0 -5
  696. package/packages/pi-ai/node_modules/@smithy/node-http-handler/LICENSE +0 -201
  697. package/packages/pi-ai/node_modules/@smithy/node-http-handler/README.md +0 -9
  698. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-cjs/index.js +0 -762
  699. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js +0 -19
  700. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/constants.js +0 -1
  701. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js +0 -9
  702. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/index.js +0 -3
  703. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +0 -230
  704. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js +0 -87
  705. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js +0 -32
  706. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +0 -169
  707. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/readable.mock.js +0 -21
  708. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/server.mock.js +0 -88
  709. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js +0 -36
  710. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js +0 -21
  711. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js +0 -22
  712. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js +0 -23
  713. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js +0 -8
  714. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js +0 -41
  715. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/readable.mock.js +0 -21
  716. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/timing.js +0 -4
  717. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/write-request-body.js +0 -63
  718. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/build-abort-error.d.ts +0 -10
  719. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/constants.d.ts +0 -5
  720. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/get-transformed-headers.d.ts +0 -4
  721. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/index.d.ts +0 -3
  722. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +0 -46
  723. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-manager.d.ts +0 -24
  724. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-pool.d.ts +0 -12
  725. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +0 -63
  726. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/readable.mock.d.ts +0 -13
  727. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/server.mock.d.ts +0 -12
  728. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-connection-timeout.d.ts +0 -2
  729. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-request-timeout.d.ts +0 -6
  730. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-keep-alive.d.ts +0 -6
  731. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-timeout.d.ts +0 -2
  732. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/collector.d.ts +0 -5
  733. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/index.d.ts +0 -6
  734. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/readable.mock.d.ts +0 -13
  735. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/timing.d.ts +0 -8
  736. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/build-abort-error.d.ts +0 -10
  737. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/constants.d.ts +0 -5
  738. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/get-transformed-headers.d.ts +0 -4
  739. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/index.d.ts +0 -3
  740. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http-handler.d.ts +0 -46
  741. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-manager.d.ts +0 -24
  742. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-pool.d.ts +0 -12
  743. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-handler.d.ts +0 -63
  744. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/readable.mock.d.ts +0 -13
  745. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/server.mock.d.ts +0 -12
  746. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-connection-timeout.d.ts +0 -2
  747. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-request-timeout.d.ts +0 -6
  748. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-keep-alive.d.ts +0 -6
  749. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-timeout.d.ts +0 -2
  750. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/collector.d.ts +0 -5
  751. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/index.d.ts +0 -6
  752. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/readable.mock.d.ts +0 -13
  753. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/timing.d.ts +0 -8
  754. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/write-request-body.d.ts +0 -12
  755. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/write-request-body.d.ts +0 -12
  756. package/packages/pi-ai/node_modules/@smithy/node-http-handler/package.json +0 -68
  757. package/packages/pi-ai/oauth.d.ts +0 -1
  758. package/packages/pi-ai/oauth.js +0 -1
  759. /package/dist/web/standalone/.next/static/{j7IBD35UgrL2b298GLK3V → o61X3klsB6C0UE0X1x3PA}/_buildManifest.js +0 -0
  760. /package/dist/web/standalone/.next/static/{j7IBD35UgrL2b298GLK3V → o61X3klsB6C0UE0X1x3PA}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"chat-frame.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { formatTimestamp, type TimestampFormat } from \"./timestamp.js\";\n\ntype FrameTone = \"assistant\" | \"user\" | \"compaction\";\n\nfunction trimOuterBlankLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim().length === 0) start++;\n\twhile (end > start && lines[end - 1].trim().length === 0) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function renderChatFrame(\n\tcontentLines: string[],\n\twidth: number,\n\topts: {\n\t\tlabel: string;\n\t\ttone: FrameTone;\n\t\ttimestamp?: number;\n\t\ttimestampFormat: TimestampFormat;\n\t\tshowTimestamp?: boolean;\n\t},\n): string[] {\n\tconst outerWidth = Math.max(20, width);\n\tconst contentWidth = Math.max(1, outerWidth - 2); // \"│ \" + content\n\tconst borderColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"borderAccent\"\n\t\t\t: opts.tone === \"compaction\"\n\t\t\t\t? \"customMessageLabel\"\n\t\t\t\t: \"border\";\n\tconst borderMuted =\n\t\topts.tone === \"compaction\" ? \"customMessageLabel\" : \"borderMuted\";\n\tconst border = (s: string) => theme.fg(borderColor, s);\n\tconst leftRaw = `• ${opts.label}`;\n\tconst rightRaw =\n\t\topts.showTimestamp === false || !opts.timestamp\n\t\t\t? \"\"\n\t\t\t: formatTimestamp(opts.timestamp, opts.timestampFormat);\n\n\tconst leftBudget = rightRaw\n\t\t? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)\n\t\t: outerWidth;\n\tconst left = truncateToWidth(leftRaw, leftBudget, \"\");\n\tconst leftStyled =\n\t\topts.tone === \"user\"\n\t\t\t? theme.fg(\"accent\", theme.bold(left))\n\t\t\t: opts.tone === \"compaction\"\n\t\t\t\t? theme.fg(\"customMessageLabel\", theme.bold(left))\n\t\t\t\t: theme.fg(\"muted\", theme.bold(left));\n\tconst rightStyled = rightRaw ? theme.fg(\"dim\", rightRaw) : \"\";\n\tconst gap =\n\t\trightRaw.length > 0\n\t\t\t? Math.max(\n\t\t\t\t\t1,\n\t\t\t\t\touterWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled),\n\t\t\t\t)\n\t\t\t: Math.max(0, outerWidth - visibleWidth(leftStyled));\n\tconst headerRow = `${leftStyled}${\" \".repeat(gap)}${rightStyled}`;\n\tconst headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));\n\n\tconst sourceLines = trimOuterBlankLines(contentLines);\n\tconst bodyLines = (sourceLines.length > 0 ? sourceLines : [\"\"]).map((line) => {\n\t\tconst clipped = truncateToWidth(line, contentWidth, \"\");\n\t\treturn border(\"│ \") + clipped;\n\t});\n\n\treturn [\n\t\ttheme.fg(borderMuted, \"─\".repeat(outerWidth)),\n\t\theaderRow + \" \".repeat(headerPad),\n\t\t...bodyLines,\n\t];\n}\n"]}
1
+ {"version":3,"file":"chat-frame.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { formatTimestamp, type TimestampFormat } from \"./timestamp.js\";\n\ntype FrameTone = \"assistant\" | \"user\" | \"compaction\";\n\nfunction trimOuterBlankLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim().length === 0) start++;\n\twhile (end > start && lines[end - 1].trim().length === 0) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function renderChatFrame(\n\tcontentLines: string[],\n\twidth: number,\n\topts: {\n\t\tlabel: string;\n\t\ttone: FrameTone;\n\t\ttimestamp?: number;\n\t\ttimestampFormat: TimestampFormat;\n\t\tshowTimestamp?: boolean;\n\t},\n): string[] {\n\tconst outerWidth = Math.max(20, width);\n\tconst contentWidth = Math.max(1, outerWidth - 2); // \"│ \" + content\n\tconst borderColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"border\"\n\t\t\t: opts.tone === \"compaction\"\n\t\t\t\t? \"customMessageLabel\"\n\t\t\t\t: \"borderAccent\";\n\tconst borderMuted =\n\t\topts.tone === \"compaction\" ? \"customMessageLabel\" : \"borderMuted\";\n\tconst border = (s: string) => theme.fg(borderColor, s);\n\tconst leftRaw = `• ${opts.label}`;\n\tconst rightRaw =\n\t\topts.showTimestamp === false || !opts.timestamp\n\t\t\t? \"\"\n\t\t\t: formatTimestamp(opts.timestamp, opts.timestampFormat);\n\n\tconst leftBudget = rightRaw\n\t\t? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)\n\t\t: outerWidth;\n\tconst left = truncateToWidth(leftRaw, leftBudget, \"\");\n\tconst labelColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"border\"\n\t\t\t: opts.tone === \"compaction\"\n\t\t\t\t? \"customMessageLabel\"\n\t\t\t\t: \"borderAccent\";\n\tconst dashIdx = left.indexOf(\" - \");\n\tconst leftStyled =\n\t\tdashIdx >= 0\n\t\t\t? theme.fg(labelColor, theme.bold(left.slice(0, dashIdx))) +\n\t\t\t\ttheme.fg(\"dim\", left.slice(dashIdx))\n\t\t\t: theme.fg(labelColor, theme.bold(left));\n\tconst rightStyled = rightRaw ? theme.fg(\"dim\", rightRaw) : \"\";\n\tconst gap =\n\t\trightRaw.length > 0\n\t\t\t? Math.max(\n\t\t\t\t\t1,\n\t\t\t\t\touterWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled),\n\t\t\t\t)\n\t\t\t: Math.max(0, outerWidth - visibleWidth(leftStyled));\n\tconst headerRow = `${leftStyled}${\" \".repeat(gap)}${rightStyled}`;\n\tconst headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));\n\n\tconst sourceLines = trimOuterBlankLines(contentLines);\n\tconst bodyColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"userMessageText\"\n\t\t\t: opts.tone === \"compaction\"\n\t\t\t\t? \"customMessageText\"\n\t\t\t\t: \"assistantMessageText\";\n\tconst bodyLines = (sourceLines.length > 0 ? sourceLines : [\"\"]).map((line) => {\n\t\tconst clipped = truncateToWidth(line, contentWidth, \"\");\n\t\treturn border(\"│ \") + theme.fg(bodyColor, clipped);\n\t});\n\n\treturn [\n\t\ttheme.fg(borderMuted, \"─\".repeat(outerWidth)),\n\t\theaderRow + \" \".repeat(headerPad),\n\t\t...bodyLines,\n\t];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AA2BxF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAI/C,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IAJnB,OAAO,CAAC,kBAAkB,CAAQ;gBAGzB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,0BAA0B;IAG/C,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI7C;;;OAGG;IACH,UAAU,IAAI,IAAI;IAIlB;;;OAGG;IACH,OAAO,IAAI,IAAI;IAIf,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA4K/B"}
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AA2BxF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAI/C,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IAJnB,OAAO,CAAC,kBAAkB,CAAQ;gBAGzB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,0BAA0B;IAG/C,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI7C;;;OAGG;IACH,UAAU,IAAI,IAAI;IAIlB;;;OAGG;IACH,OAAO,IAAI,IAAI;IAIf,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkM/B"}
@@ -102,18 +102,20 @@ export class FooterComponent {
102
102
  }
103
103
  // Build stats line as separate groups joined by a dim middle-dot separator
104
104
  const sep = ` ${theme.fg("dim", "\u00B7")} `;
105
- // Group 1: token I/O
105
+ // Group 1: total tokens.
106
106
  const tokenGroup = [];
107
- if (totalInput)
108
- tokenGroup.push(`↑${formatTokens(totalInput)}`);
109
- if (totalOutput)
110
- tokenGroup.push(`↓${formatTokens(totalOutput)}`);
111
- // Group 2: cache metrics
107
+ const totalTokens = totalInput + totalOutput + totalCacheRead + totalCacheWrite;
108
+ if (totalTokens > 0)
109
+ tokenGroup.push(formatTokens(totalTokens));
110
+ // Group 2: cache efficiency — cacheRead / all input-side tokens.
111
+ // Collapses the old cr/cw pair into a single "how much was served
112
+ // from cache" signal. cr/cw breakdown moved to `/stats`.
112
113
  const cacheGroup = [];
113
- if (totalCacheRead)
114
- cacheGroup.push(`cr:${formatTokens(totalCacheRead)}`);
115
- if (totalCacheWrite)
116
- cacheGroup.push(`cw:${formatTokens(totalCacheWrite)}`);
114
+ const inputSide = totalInput + totalCacheRead + totalCacheWrite;
115
+ if (totalCacheRead > 0 && inputSide > 0) {
116
+ const cachedPct = Math.round((totalCacheRead / inputSide) * 100);
117
+ cacheGroup.push(`${cachedPct}% cached`);
118
+ }
117
119
  // Group 3: cost
118
120
  const costGroup = [];
119
121
  const usingSubscription = displayModel ? this.session.modelRegistry.isUsingOAuth(displayModel) : false;
@@ -128,21 +130,24 @@ export class FooterComponent {
128
130
  costGroup.push(`(last: ${formatPromptCost(lastTurnCost)})`);
129
131
  }
130
132
  }
131
- // Group 4: context percentage (colorized)
132
- let contextPercentStr;
133
+ // Group 4: context bar + percentage (mirrors /gsd auto dashboard style).
134
+ // Bar colors track the same thresholds as the percent text.
133
135
  const autoIndicator = this.autoCompactEnabled ? " (auto)" : "";
134
- const contextPercentDisplay = contextPercent === "?"
135
- ? `?/${formatTokens(contextWindow)}${autoIndicator}`
136
- : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
137
- if (contextPercentValue > 90) {
138
- contextPercentStr = theme.fg("error", contextPercentDisplay);
139
- }
140
- else if (contextPercentValue > 70) {
141
- contextPercentStr = theme.fg("warning", contextPercentDisplay);
142
- }
143
- else {
144
- contextPercentStr = contextPercentDisplay;
145
- }
136
+ const barColor = contextPercentValue > 90 ? "error" : contextPercentValue > 70 ? "warning" : "success";
137
+ const BAR_WIDTH = 8;
138
+ const filled = contextUsage?.percent !== null
139
+ ? Math.max(0, Math.min(BAR_WIDTH, Math.round((contextPercentValue / 100) * BAR_WIDTH)))
140
+ : 0;
141
+ const bar = theme.fg(barColor, "━".repeat(filled)) +
142
+ theme.fg("dim", "─".repeat(Math.max(0, BAR_WIDTH - filled)));
143
+ const pctText = contextPercent === "?" ? "?" : `${contextPercent}%`;
144
+ const suffix = `/${formatTokens(contextWindow)}${autoIndicator}`;
145
+ const colorizedPct = contextPercentValue > 90
146
+ ? theme.fg("error", pctText)
147
+ : contextPercentValue > 70
148
+ ? theme.fg("warning", pctText)
149
+ : pctText;
150
+ const contextPercentStr = `${bar} ${colorizedPct}${suffix}`;
146
151
  // Assemble groups: items within a group are space-separated,
147
152
  // groups are separated by a dim middle-dot
148
153
  const groups = [];
@@ -208,19 +213,28 @@ export class FooterComponent {
208
213
  const dimStatsLeft = theme.fg("dim", statsLeft);
209
214
  const remainder = statsLine.slice(statsLeft.length); // padding + rightSide
210
215
  const dimRemainder = theme.fg("dim", remainder);
211
- const pwdLine = truncateToWidth(theme.fg("dim", pwd), width, theme.fg("dim", "..."));
212
- const lines = [pwdLine, dimStatsLeft + dimRemainder];
213
- // Add extension statuses on a single line, sorted by key alphabetically
216
+ // Extension statuses right-aligned on the pwd line (sorted by key).
217
+ // Keeps the footer compact by avoiding a dedicated row when the content
218
+ // fits alongside pwd. Falls back to pwd-only if the combined line would
219
+ // exceed width.
214
220
  const extensionStatuses = this.footerData.getExtensionStatuses();
215
- if (extensionStatuses.size > 0) {
216
- const sortedStatuses = Array.from(extensionStatuses.entries())
221
+ const extStatusText = extensionStatuses.size > 0
222
+ ? Array.from(extensionStatuses.entries())
217
223
  .sort(([a], [b]) => a.localeCompare(b))
218
- .map(([, text]) => sanitizeStatusText(text));
219
- const statusLine = sortedStatuses.join(" ");
220
- // Match the rest of the footer styling: extension statuses should render
221
- // in the same dim color as pwd/stats, with a dim ellipsis on truncation.
222
- lines.push(truncateToWidth(theme.fg("dim", statusLine), width, theme.fg("dim", "...")));
224
+ .map(([, text]) => sanitizeStatusText(text))
225
+ .join(" ")
226
+ : "";
227
+ const pwdWidth = visibleWidth(pwd);
228
+ const extWidth = visibleWidth(extStatusText);
229
+ let pwdLine;
230
+ if (extStatusText && pwdWidth + 2 + extWidth <= width) {
231
+ const padding = " ".repeat(width - pwdWidth - extWidth);
232
+ pwdLine = theme.fg("dim", pwd + padding + extStatusText);
233
+ }
234
+ else {
235
+ pwdLine = truncateToWidth(theme.fg("dim", pwd), width, theme.fg("dim", "..."));
223
236
  }
237
+ const lines = [pwdLine, dimStatsLeft + dimRemainder];
224
238
  return lines;
225
239
  }
226
240
  }
@@ -1 +1 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.js\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { providerDisplayName } from \"./model-selector.js\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts (similar to web-ui)\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/**\n * Format a cost value for compact display.\n * Uses fewer decimal places for larger amounts.\n * @internal Exported for testing only.\n */\nexport function formatPromptCost(cost: number): string {\n\tif (cost < 0.001) return `$${cost.toFixed(4)}`;\n\tif (cost < 0.01) return `$${cost.toFixed(3)}`;\n\tif (cost < 1) return `$${cost.toFixed(3)}`;\n\treturn `$${cost.toFixed(2)}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(\n\t\tprivate session: AgentSession,\n\t\tprivate footerData: ReadonlyFooterDataProvider,\n\t) {}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\tconst usageTotals = this.session.sessionManager.getUsageTotals();\n\t\tconst totalInput = usageTotals.input;\n\t\tconst totalOutput = usageTotals.output;\n\t\tconst totalCacheRead = usageTotals.cacheRead;\n\t\tconst totalCacheWrite = usageTotals.cacheWrite;\n\t\tconst totalCost = usageTotals.cost;\n\n\t\t// Use activeInferenceModel during streaming to show the model actually\n\t\t// being used, not the configured model which may have been switched mid-turn.\n\t\tconst displayModel = state.activeInferenceModel ?? state.model;\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? displayModel?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = process.cwd();\n\t\tconst home = process.env.HOME || process.env.USERPROFILE;\n\t\tif (home && pwd.startsWith(home)) {\n\t\t\tpwd = `~${pwd.slice(home.length)}`;\n\t\t}\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line as separate groups joined by a dim middle-dot separator\n\t\tconst sep = ` ${theme.fg(\"dim\", \"\\u00B7\")} `;\n\n\t\t// Group 1: token I/O\n\t\tconst tokenGroup: string[] = [];\n\t\tif (totalInput) tokenGroup.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) tokenGroup.push(`↓${formatTokens(totalOutput)}`);\n\n\t\t// Group 2: cache metrics\n\t\tconst cacheGroup: string[] = [];\n\t\tif (totalCacheRead) cacheGroup.push(`cr:${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) cacheGroup.push(`cw:${formatTokens(totalCacheWrite)}`);\n\n\t\t// Group 3: cost\n\t\tconst costGroup: string[] = [];\n\t\tconst usingSubscription = displayModel ? this.session.modelRegistry.isUsingOAuth(displayModel) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tcostGroup.push(costStr);\n\t\t}\n\n\t\t// Per-prompt cost annotation (opt-in via show_token_cost preference, #1515)\n\t\tif (process.env.GSD_SHOW_TOKEN_COST === \"1\") {\n\t\t\tconst lastTurnCost = this.session.getLastTurnCost();\n\t\t\tif (lastTurnCost > 0) {\n\t\t\t\tcostGroup.push(`(last: ${formatPromptCost(lastTurnCost)})`);\n\t\t\t}\n\t\t}\n\n\t\t// Group 4: context percentage (colorized)\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\n\t\t// Assemble groups: items within a group are space-separated,\n\t\t// groups are separated by a dim middle-dot\n\t\tconst groups: string[] = [];\n\t\tif (tokenGroup.length > 0) groups.push(tokenGroup.join(\" \"));\n\t\tif (cacheGroup.length > 0) groups.push(cacheGroup.join(\" \"));\n\t\tif (costGroup.length > 0) groups.push(costGroup.join(\" \"));\n\t\tgroups.push(contextPercentStr);\n\n\t\tlet statsLeft = groups.join(sep);\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = displayModel?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (displayModel?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && displayModel) {\n\t\t\trightSide = `(${providerDisplayName(displayModel.provider)}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Match the rest of the footer styling: extension statuses should render\n\t\t\t// in the same dim color as pwd/stats, with a dim ellipsis on truncation.\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", statusLine), width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.js\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { providerDisplayName } from \"./model-selector.js\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts (similar to web-ui)\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/**\n * Format a cost value for compact display.\n * Uses fewer decimal places for larger amounts.\n * @internal Exported for testing only.\n */\nexport function formatPromptCost(cost: number): string {\n\tif (cost < 0.001) return `$${cost.toFixed(4)}`;\n\tif (cost < 0.01) return `$${cost.toFixed(3)}`;\n\tif (cost < 1) return `$${cost.toFixed(3)}`;\n\treturn `$${cost.toFixed(2)}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(\n\t\tprivate session: AgentSession,\n\t\tprivate footerData: ReadonlyFooterDataProvider,\n\t) {}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\tconst usageTotals = this.session.sessionManager.getUsageTotals();\n\t\tconst totalInput = usageTotals.input;\n\t\tconst totalOutput = usageTotals.output;\n\t\tconst totalCacheRead = usageTotals.cacheRead;\n\t\tconst totalCacheWrite = usageTotals.cacheWrite;\n\t\tconst totalCost = usageTotals.cost;\n\n\t\t// Use activeInferenceModel during streaming to show the model actually\n\t\t// being used, not the configured model which may have been switched mid-turn.\n\t\tconst displayModel = state.activeInferenceModel ?? state.model;\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? displayModel?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = process.cwd();\n\t\tconst home = process.env.HOME || process.env.USERPROFILE;\n\t\tif (home && pwd.startsWith(home)) {\n\t\t\tpwd = `~${pwd.slice(home.length)}`;\n\t\t}\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line as separate groups joined by a dim middle-dot separator\n\t\tconst sep = ` ${theme.fg(\"dim\", \"\\u00B7\")} `;\n\n\t\t// Group 1: total tokens.\n\t\tconst tokenGroup: string[] = [];\n\t\tconst totalTokens = totalInput + totalOutput + totalCacheRead + totalCacheWrite;\n\t\tif (totalTokens > 0) tokenGroup.push(formatTokens(totalTokens));\n\n\t\t// Group 2: cache efficiency — cacheRead / all input-side tokens.\n\t\t// Collapses the old cr/cw pair into a single \"how much was served\n\t\t// from cache\" signal. cr/cw breakdown moved to `/stats`.\n\t\tconst cacheGroup: string[] = [];\n\t\tconst inputSide = totalInput + totalCacheRead + totalCacheWrite;\n\t\tif (totalCacheRead > 0 && inputSide > 0) {\n\t\t\tconst cachedPct = Math.round((totalCacheRead / inputSide) * 100);\n\t\t\tcacheGroup.push(`${cachedPct}% cached`);\n\t\t}\n\n\t\t// Group 3: cost\n\t\tconst costGroup: string[] = [];\n\t\tconst usingSubscription = displayModel ? this.session.modelRegistry.isUsingOAuth(displayModel) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tcostGroup.push(costStr);\n\t\t}\n\n\t\t// Per-prompt cost annotation (opt-in via show_token_cost preference, #1515)\n\t\tif (process.env.GSD_SHOW_TOKEN_COST === \"1\") {\n\t\t\tconst lastTurnCost = this.session.getLastTurnCost();\n\t\t\tif (lastTurnCost > 0) {\n\t\t\t\tcostGroup.push(`(last: ${formatPromptCost(lastTurnCost)})`);\n\t\t\t}\n\t\t}\n\n\t\t// Group 4: context bar + percentage (mirrors /gsd auto dashboard style).\n\t\t// Bar colors track the same thresholds as the percent text.\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst barColor: \"error\" | \"warning\" | \"success\" =\n\t\t\tcontextPercentValue > 90 ? \"error\" : contextPercentValue > 70 ? \"warning\" : \"success\";\n\t\tconst BAR_WIDTH = 8;\n\t\tconst filled = contextUsage?.percent !== null\n\t\t\t? Math.max(0, Math.min(BAR_WIDTH, Math.round((contextPercentValue / 100) * BAR_WIDTH)))\n\t\t\t: 0;\n\t\tconst bar =\n\t\t\ttheme.fg(barColor, \"━\".repeat(filled)) +\n\t\t\ttheme.fg(\"dim\", \"─\".repeat(Math.max(0, BAR_WIDTH - filled)));\n\t\tconst pctText = contextPercent === \"?\" ? \"?\" : `${contextPercent}%`;\n\t\tconst suffix = `/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tconst colorizedPct =\n\t\t\tcontextPercentValue > 90\n\t\t\t\t? theme.fg(\"error\", pctText)\n\t\t\t\t: contextPercentValue > 70\n\t\t\t\t\t? theme.fg(\"warning\", pctText)\n\t\t\t\t\t: pctText;\n\t\tconst contextPercentStr = `${bar} ${colorizedPct}${suffix}`;\n\n\t\t// Assemble groups: items within a group are space-separated,\n\t\t// groups are separated by a dim middle-dot\n\t\tconst groups: string[] = [];\n\t\tif (tokenGroup.length > 0) groups.push(tokenGroup.join(\" \"));\n\t\tif (cacheGroup.length > 0) groups.push(cacheGroup.join(\" \"));\n\t\tif (costGroup.length > 0) groups.push(costGroup.join(\" \"));\n\t\tgroups.push(contextPercentStr);\n\n\t\tlet statsLeft = groups.join(sep);\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = displayModel?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (displayModel?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && displayModel) {\n\t\t\trightSide = `(${providerDisplayName(displayModel.provider)}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\t// Extension statuses right-aligned on the pwd line (sorted by key).\n\t\t// Keeps the footer compact by avoiding a dedicated row when the content\n\t\t// fits alongside pwd. Falls back to pwd-only if the combined line would\n\t\t// exceed width.\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tconst extStatusText =\n\t\t\textensionStatuses.size > 0\n\t\t\t\t? Array.from(extensionStatuses.entries())\n\t\t\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t\t\t.map(([, text]) => sanitizeStatusText(text))\n\t\t\t\t\t\t.join(\" \")\n\t\t\t\t: \"\";\n\n\t\tconst pwdWidth = visibleWidth(pwd);\n\t\tconst extWidth = visibleWidth(extStatusText);\n\t\tlet pwdLine: string;\n\t\tif (extStatusText && pwdWidth + 2 + extWidth <= width) {\n\t\t\tconst padding = \" \".repeat(width - pwdWidth - extWidth);\n\t\t\tpwdLine = theme.fg(\"dim\", pwd + padding + extStatusText);\n\t\t} else {\n\t\t\tpwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\t}\n\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\treturn lines;\n\t}\n}\n"]}
@@ -1,4 +1,8 @@
1
1
  import type { InteractiveModeEvent, InteractiveModeStateHost } from "../interactive-mode-state.js";
2
+ export declare function findLatestPinnableCandidates(contentBlocks: Array<any>): Array<{
3
+ text: string;
4
+ contentIndex: number;
5
+ }>;
2
6
  export declare function findLatestPinnableText(contentBlocks: Array<any>): string;
3
7
  export declare function handleAgentEvent(host: InteractiveModeStateHost & {
4
8
  init: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"chat-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/chat-controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AA+CnG,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAgBxE;AAWD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,4BAA4B,EAAE,MAAM,GAAG,CAAC;IACxC,gBAAgB,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACxD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IACpD,2BAA2B,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,CAAC;IACvD,sBAAsB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,oBAAoB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,4BAA4B,EAAE,MAAM,IAAI,CAAC;IACzC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAChD,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8zB7C"}
1
+ {"version":3,"file":"chat-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/chat-controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AA8CnG,wBAAgB,4BAA4B,CAC3C,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,GACvB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB/C;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAExE;AA+BD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,4BAA4B,EAAE,MAAM,GAAG,CAAC;IACxC,gBAAgB,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACxD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IACpD,2BAA2B,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,CAAC;IACvD,sBAAsB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,oBAAoB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,4BAA4B,EAAE,MAAM,IAAI,CAAC;IACzC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAChD,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAw1B7C"}
@@ -21,11 +21,10 @@ function hasVisibleAssistantContent(message) {
21
21
  function hasAssistantToolBlocks(message) {
22
22
  return message.content.some((c) => c.type === "toolCall" || c.type === "serverToolUse");
23
23
  }
24
- // Pick the latest non-empty text block that appears strictly before the most
25
- // recent tool call. Text blocks that come after the last tool call are still
26
- // streaming live into the chat container, so mirroring them into the pinned
27
- // "Latest Output" zone would render the same tokens twice.
28
- export function findLatestPinnableText(contentBlocks) {
24
+ // Pinnable text candidates: non-empty text blocks that appear strictly before
25
+ // the most recent tool call, returned newest-first. Text blocks after the last
26
+ // tool call are still streaming live into the chat container.
27
+ export function findLatestPinnableCandidates(contentBlocks) {
29
28
  let lastToolIdx = -1;
30
29
  for (let i = contentBlocks.length - 1; i >= 0; i--) {
31
30
  const c = contentBlocks[i];
@@ -34,13 +33,38 @@ export function findLatestPinnableText(contentBlocks) {
34
33
  break;
35
34
  }
36
35
  }
36
+ const out = [];
37
37
  for (let i = lastToolIdx - 1; i >= 0; i--) {
38
38
  const c = contentBlocks[i];
39
39
  if (c?.type === "text" && typeof c.text === "string" && c.text.trim()) {
40
- return c.text.trim();
40
+ out.push({ text: c.text.trim(), contentIndex: i });
41
+ }
42
+ }
43
+ return out;
44
+ }
45
+ export function findLatestPinnableText(contentBlocks) {
46
+ return findLatestPinnableCandidates(contentBlocks)[0]?.text ?? "";
47
+ }
48
+ // Sum rendered line counts of segments that appear strictly after the given
49
+ // content-block index. Used to decide whether a pinnable text block has
50
+ // scrolled out of the viewport and therefore warrants mirroring.
51
+ function rowsRenderedAfterContentIndex(contentIndex, width) {
52
+ let rows = 0;
53
+ for (const seg of renderedSegments) {
54
+ try {
55
+ if (seg.kind === "text-run" && seg.startIndex > contentIndex) {
56
+ rows += seg.component.render(width).length;
57
+ }
58
+ else if (seg.kind === "tool" && seg.contentIndex > contentIndex) {
59
+ rows += seg.component.render(width).length;
60
+ }
61
+ }
62
+ catch {
63
+ // Defensive: a component that throws during measurement shouldn't
64
+ // destabilize pinned-zone logic. Skip it.
41
65
  }
42
66
  }
43
- return "";
67
+ return rows;
44
68
  }
45
69
  // Tracks the latest assistant text for the pinned message zone
46
70
  let lastPinnedText = "";
@@ -437,36 +461,62 @@ export async function handleAgentEvent(host, event) {
437
461
  if (hasTools)
438
462
  hasToolsInTurn = true;
439
463
  if (hasToolsInTurn) {
440
- const latestText = findLatestPinnableText(contentBlocks);
441
- if (latestText && latestText !== lastPinnedText) {
442
- lastPinnedText = latestText;
443
- if (!pinnedBorder) {
444
- // First time: create border + text component
445
- host.pinnedMessageContainer.clear();
446
- pinnedBorder = new DynamicBorder((str) => theme.fg("dim", str), "Working · Latest Output");
447
- pinnedBorder.startSpinner(host.ui, (str) => theme.fg("accent", str));
448
- host.pinnedMessageContainer.addChild(pinnedBorder);
449
- pinnedTextComponent = new Markdown(latestText, 1, 0, host.getMarkdownThemeWithSettings());
450
- // Cap pinned content to ~40% of terminal height so tall output
451
- // doesn't exceed the viewport and cause render flashing.
452
- pinnedTextComponent.maxLines = Math.max(3, Math.floor(host.ui.terminal.rows * 0.4));
453
- host.pinnedMessageContainer.addChild(pinnedTextComponent);
454
- // Hide the separate status loader — the pinned zone replaces it
455
- if (host.loadingAnimation) {
456
- host.loadingAnimation.stop();
457
- host.loadingAnimation = undefined;
458
- }
459
- host.statusContainer.clear();
464
+ const candidates = findLatestPinnableCandidates(contentBlocks);
465
+ const termRows = host.ui.terminal.rows;
466
+ const termCols = host.ui.terminal.columns;
467
+ const pinnedMax = Math.max(3, Math.floor(termRows * 0.4));
468
+ // Reserve rows for pinned zone + its border + editor + footer chrome.
469
+ // Anything below this row budget is still in the viewport.
470
+ const offscreenThreshold = Math.max(1, termRows - pinnedMax - 8);
471
+ // Walk candidates newest→oldest; pick the first whose following
472
+ // segments have pushed enough rows to scroll it off-screen.
473
+ let picked;
474
+ for (const c of candidates) {
475
+ if (rowsRenderedAfterContentIndex(c.contentIndex, termCols) >= offscreenThreshold) {
476
+ picked = c;
477
+ break;
460
478
  }
461
- else {
462
- // Update existing markdown component in-place
463
- pinnedTextComponent?.setText(latestText);
464
- // Refresh maxLines in case terminal was resized
465
- if (pinnedTextComponent) {
466
- pinnedTextComponent.maxLines = Math.max(3, Math.floor(host.ui.terminal.rows * 0.4));
479
+ }
480
+ if (picked) {
481
+ if (picked.text !== lastPinnedText) {
482
+ lastPinnedText = picked.text;
483
+ if (!pinnedBorder) {
484
+ // First time: create border + text component
485
+ host.pinnedMessageContainer.clear();
486
+ pinnedBorder = new DynamicBorder((str) => theme.fg("dim", str), "Working · Latest Output");
487
+ pinnedBorder.startSpinner(host.ui, (str) => theme.fg("accent", str));
488
+ host.pinnedMessageContainer.addChild(pinnedBorder);
489
+ pinnedTextComponent = new Markdown(picked.text, 1, 0, host.getMarkdownThemeWithSettings());
490
+ // Cap pinned content to ~40% of terminal height so tall output
491
+ // doesn't exceed the viewport and cause render flashing.
492
+ pinnedTextComponent.maxLines = pinnedMax;
493
+ host.pinnedMessageContainer.addChild(pinnedTextComponent);
494
+ // Hide the separate status loader — the pinned zone replaces it
495
+ if (host.loadingAnimation) {
496
+ host.loadingAnimation.stop();
497
+ host.loadingAnimation = undefined;
498
+ }
499
+ host.statusContainer.clear();
500
+ }
501
+ else {
502
+ // Update existing markdown component in-place
503
+ pinnedTextComponent?.setText(picked.text);
504
+ // Refresh maxLines in case terminal was resized
505
+ if (pinnedTextComponent) {
506
+ pinnedTextComponent.maxLines = pinnedMax;
507
+ }
467
508
  }
468
509
  }
469
510
  }
511
+ else if (pinnedBorder) {
512
+ // Every candidate is still visible in the chat scrollback —
513
+ // tear down the pinned zone so we don't duplicate on-screen text.
514
+ pinnedBorder.stopSpinner();
515
+ pinnedBorder = undefined;
516
+ pinnedTextComponent = undefined;
517
+ host.pinnedMessageContainer.clear();
518
+ lastPinnedText = "";
519
+ }
470
520
  }
471
521
  host.ui.requestRender();
472
522
  }