gsd-pi 2.76.0-dev.fe143342a → 2.77.0-dev.1d17f366c

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 (597) hide show
  1. package/README.md +17 -35
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +38 -2
  6. package/dist/extension-discovery.d.ts +6 -0
  7. package/dist/extension-discovery.js +37 -0
  8. package/dist/extension-registry.d.ts +3 -0
  9. package/dist/extension-sort.d.ts +18 -0
  10. package/dist/extension-sort.js +114 -0
  11. package/dist/extension-validator.d.ts +47 -0
  12. package/dist/extension-validator.js +127 -0
  13. package/dist/loader.js +35 -7
  14. package/dist/onboarding.js +45 -0
  15. package/dist/provider-migrations.d.ts +18 -0
  16. package/dist/provider-migrations.js +14 -0
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +78 -59
  19. package/dist/resources/extensions/cmux/index.js +20 -0
  20. package/dist/resources/extensions/github-sync/templates.js +103 -0
  21. package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
  22. package/dist/resources/extensions/google-search/index.js +3 -375
  23. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +90 -2
  25. package/dist/resources/extensions/gsd/auto/phases.js +95 -21
  26. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  27. package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
  28. package/dist/resources/extensions/gsd/auto/session.js +18 -1
  29. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  30. package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
  31. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
  33. package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
  34. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  35. package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
  36. package/dist/resources/extensions/gsd/auto-start.js +45 -39
  37. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  38. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  39. package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
  40. package/dist/resources/extensions/gsd/auto.js +97 -31
  41. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +27 -1
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -6
  45. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
  46. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  47. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  49. package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
  50. package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  52. package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
  53. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  54. package/dist/resources/extensions/gsd/git-service.js +1 -0
  55. package/dist/resources/extensions/gsd/gitignore.js +2 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +90 -30
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +212 -9
  59. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  60. package/dist/resources/extensions/gsd/journal.js +17 -2
  61. package/dist/resources/extensions/gsd/key-manager.js +22 -0
  62. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  63. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  64. package/dist/resources/extensions/gsd/model-router.js +36 -3
  65. package/dist/resources/extensions/gsd/notifications.js +30 -16
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +31 -6
  67. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  68. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  69. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  70. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/reports.js +5 -4
  73. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  74. package/dist/resources/extensions/gsd/safety/file-change-validator.js +12 -4
  75. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  76. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  77. package/dist/resources/extensions/gsd/state.js +25 -25
  78. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  79. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  80. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  81. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  82. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  83. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  84. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  85. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  86. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  87. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  88. package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
  89. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  90. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  91. package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
  92. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  93. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  94. package/dist/resources/extensions/mcp-client/index.js +118 -9
  95. package/dist/resources/extensions/shared/cmux-events.js +12 -0
  96. package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
  97. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  98. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  99. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  100. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  101. package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
  102. package/dist/resources/skills/write-docs/SKILL.md +2 -1
  103. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/index.html +1 -1
  190. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  193. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  194. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  197. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  198. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  201. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  206. package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
  207. package/dist/welcome-screen.js +6 -1
  208. package/dist/wizard.js +2 -0
  209. package/package.json +16 -14
  210. package/packages/daemon/package.json +2 -2
  211. package/packages/mcp-server/README.md +3 -3
  212. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  213. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  214. package/packages/mcp-server/dist/env-writer.js +74 -6
  215. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  216. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  217. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  218. package/packages/mcp-server/dist/remote-questions.js +732 -0
  219. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  220. package/packages/mcp-server/dist/server.d.ts +7 -0
  221. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/server.js +95 -10
  223. package/packages/mcp-server/dist/server.js.map +1 -1
  224. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  225. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/session-manager.js +49 -1
  227. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/package.json +9 -3
  232. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  233. package/packages/mcp-server/src/env-writer.ts +76 -6
  234. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  235. package/packages/mcp-server/src/readers/readers.test.ts +5 -1
  236. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  237. package/packages/mcp-server/src/remote-questions.ts +916 -0
  238. package/packages/mcp-server/src/server.ts +118 -16
  239. package/packages/mcp-server/src/session-manager.ts +43 -1
  240. package/packages/mcp-server/src/workflow-tools.test.ts +44 -0
  241. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  242. package/packages/mcp-server/tsconfig.test.json +19 -0
  243. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  244. package/packages/native/package.json +6 -1
  245. package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
  246. package/packages/native/tsconfig.tsbuildinfo +1 -1
  247. package/packages/pi-agent-core/package.json +6 -1
  248. package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
  249. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  250. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models/custom.js +41 -0
  252. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  255. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  257. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  258. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  262. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  263. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  264. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  265. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  266. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  268. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  269. package/packages/pi-ai/package.json +6 -1
  270. package/packages/pi-ai/src/models/custom.ts +42 -0
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  272. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  273. package/packages/pi-ai/src/providers/anthropic.ts +9 -3
  274. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  275. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  276. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  278. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +7 -0
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
  284. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
  286. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
  288. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
  290. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
  292. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
  296. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  298. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  299. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  300. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  301. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
  302. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
  304. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
  306. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
  308. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
  310. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
  312. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
  314. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/extensions/loader.js +24 -8
  316. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  318. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +14 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
  324. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  330. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
  333. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
  335. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  337. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  339. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  341. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/session-manager.js +1 -1
  343. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/session-manager.test.js +21 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
  347. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
  349. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  351. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
  360. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  363. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  364. package/packages/pi-coding-agent/package.json +6 -1
  365. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  366. package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
  367. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
  368. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
  369. package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
  370. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  371. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
  372. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
  373. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
  374. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  375. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  376. package/packages/pi-coding-agent/src/core/extensions/loader.ts +24 -11
  377. package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
  378. package/packages/pi-coding-agent/src/core/extensions/types.ts +15 -0
  379. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
  380. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
  381. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  382. package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
  383. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
  384. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  385. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  386. package/packages/pi-coding-agent/src/core/session-manager.test.ts +30 -1
  387. package/packages/pi-coding-agent/src/core/session-manager.ts +1 -1
  388. package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
  389. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
  390. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  391. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  392. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  393. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
  394. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  395. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  396. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
  397. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  398. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
  399. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  400. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  401. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  403. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  404. package/packages/pi-tui/package.json +6 -1
  405. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
  406. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
  407. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  408. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  409. package/packages/rpc-client/package.json +6 -1
  410. package/pkg/package.json +1 -1
  411. package/scripts/install.js +512 -0
  412. package/scripts/lib/workspace-manifest.cjs +86 -0
  413. package/scripts/link-workspace-packages.cjs +5 -17
  414. package/scripts/postinstall.js +9 -178
  415. package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
  416. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +91 -63
  417. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +114 -12
  418. package/src/resources/extensions/cmux/index.ts +35 -10
  419. package/src/resources/extensions/github-sync/templates.ts +151 -0
  420. package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
  421. package/src/resources/extensions/google-search/extension-manifest.json +5 -4
  422. package/src/resources/extensions/google-search/index.ts +9 -470
  423. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  424. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -1
  425. package/src/resources/extensions/gsd/auto/loop.ts +104 -2
  426. package/src/resources/extensions/gsd/auto/phases.ts +123 -21
  427. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  428. package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
  429. package/src/resources/extensions/gsd/auto/session.ts +28 -1
  430. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  431. package/src/resources/extensions/gsd/auto/types.ts +1 -1
  432. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
  433. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  434. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
  435. package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
  436. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  437. package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
  438. package/src/resources/extensions/gsd/auto-start.ts +48 -52
  439. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  440. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  441. package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
  442. package/src/resources/extensions/gsd/auto.ts +105 -35
  443. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
  444. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
  445. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
  446. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  447. package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
  448. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  449. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  450. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  451. package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
  452. package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
  453. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  454. package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
  455. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  456. package/src/resources/extensions/gsd/git-service.ts +1 -0
  457. package/src/resources/extensions/gsd/gitignore.ts +2 -1
  458. package/src/resources/extensions/gsd/gsd-db.ts +92 -32
  459. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  460. package/src/resources/extensions/gsd/guided-flow.ts +259 -10
  461. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  462. package/src/resources/extensions/gsd/journal.ts +29 -3
  463. package/src/resources/extensions/gsd/key-manager.ts +22 -0
  464. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  465. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  466. package/src/resources/extensions/gsd/model-router.ts +42 -1
  467. package/src/resources/extensions/gsd/notifications.ts +27 -15
  468. package/src/resources/extensions/gsd/pre-execution-checks.ts +33 -7
  469. package/src/resources/extensions/gsd/preferences-types.ts +8 -0
  470. package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  471. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  472. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  473. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  474. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  475. package/src/resources/extensions/gsd/reports.ts +5 -4
  476. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  477. package/src/resources/extensions/gsd/safety/file-change-validator.ts +16 -3
  478. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  479. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  480. package/src/resources/extensions/gsd/state.ts +35 -30
  481. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
  482. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  483. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  484. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
  485. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  486. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
  487. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  488. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  489. package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
  490. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
  491. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  492. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  493. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  494. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
  495. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
  497. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
  498. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  499. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  500. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  501. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
  502. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
  504. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  505. package/src/resources/extensions/gsd/tests/exec-history.test.ts +113 -0
  506. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  507. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +38 -0
  508. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  509. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
  510. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +296 -1
  511. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  512. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  513. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
  514. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  515. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  516. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
  517. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  518. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +66 -0
  519. package/src/resources/extensions/gsd/tests/key-manager.test.ts +2 -0
  520. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
  521. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  522. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  523. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  524. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
  525. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  526. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
  527. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
  528. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  529. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
  530. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  531. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  532. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +337 -0
  533. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  534. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
  535. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
  536. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  537. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  538. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  539. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  540. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  541. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  542. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  543. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  544. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  545. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  546. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  547. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
  548. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  549. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  550. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  551. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  552. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  553. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  554. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  555. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  556. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  557. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  558. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
  559. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  560. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  561. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +138 -5
  562. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
  563. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  564. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  566. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  567. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  568. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  569. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  570. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  571. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  572. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  573. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  574. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  575. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  576. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  577. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  578. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  579. package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
  580. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  581. package/src/resources/extensions/gsd/workflow-logger.ts +23 -3
  582. package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
  583. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  584. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  585. package/src/resources/extensions/mcp-client/index.ts +129 -10
  586. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  587. package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
  588. package/src/resources/skills/create-skill/SKILL.md +2 -2
  589. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  590. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  591. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  592. package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
  593. package/src/resources/skills/write-docs/SKILL.md +2 -1
  594. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  595. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
  596. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
  597. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Regression tests for #4563:
3
+ * Bug 1 — custom/Anthropic-compatible models were hard-capped to 32 k output tokens
4
+ * Bug 2 — custom models in models.json could not declare capabilities.supportsXhigh
5
+ */
6
+ import assert from "node:assert/strict";
7
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { afterEach, beforeEach, describe, it } from "node:test";
11
+ import { AuthStorage } from "./auth-storage.js";
12
+ import { ModelRegistry } from "./model-registry.js";
13
+
14
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
15
+
16
+ let testDir: string;
17
+
18
+ beforeEach(() => {
19
+ testDir = join(
20
+ tmpdir(),
21
+ `model-registry-custom-caps-${Date.now()}-${Math.random().toString(36).slice(2)}`,
22
+ );
23
+ mkdirSync(testDir, { recursive: true });
24
+ });
25
+
26
+ afterEach(() => {
27
+ try {
28
+ rmSync(testDir, { recursive: true, force: true });
29
+ } catch {
30
+ // best-effort cleanup
31
+ }
32
+ });
33
+
34
+ function createRegistry(modelsJson: object): ModelRegistry {
35
+ const path = join(testDir, "models.json");
36
+ writeFileSync(path, JSON.stringify(modelsJson));
37
+ return new ModelRegistry(AuthStorage.inMemory(), path);
38
+ }
39
+
40
+ function writeModelsJson(obj: object): string {
41
+ const path = join(testDir, "models.json");
42
+ writeFileSync(path, JSON.stringify(obj));
43
+ return path;
44
+ }
45
+
46
+ // ─── Bug 1: 32 k cap must not apply to custom/OpenAI-compatible models ────────
47
+
48
+ describe("Bug 1 — maxTokens cap (#4563)", () => {
49
+ it("custom openai-completions model with maxTokens > 32 k is not capped", () => {
50
+ const registry = createRegistry({
51
+ providers: {
52
+ "kimi-custom": {
53
+ baseUrl: "https://api.example.com/v1",
54
+ apiKey: "sk-test",
55
+ api: "openai-completions",
56
+ models: [
57
+ {
58
+ id: "kimi-k2.6-code-preview",
59
+ name: "Kimi K2.6 Code Preview",
60
+ maxTokens: 131072,
61
+ contextWindow: 262144,
62
+ },
63
+ ],
64
+ },
65
+ },
66
+ });
67
+
68
+ const model = registry.getAll().find((m) => m.id === "kimi-k2.6-code-preview");
69
+ assert.ok(model, "model should be registered");
70
+ assert.equal(
71
+ model.maxTokens,
72
+ 131072,
73
+ "maxTokens must be preserved as declared — not capped to 32 000",
74
+ );
75
+ });
76
+
77
+ it("custom model with maxTokens exactly 32 k is not affected", () => {
78
+ const registry = createRegistry({
79
+ providers: {
80
+ "custom-provider": {
81
+ baseUrl: "https://api.example.com/v1",
82
+ apiKey: "sk-test",
83
+ api: "openai-completions",
84
+ models: [{ id: "model-32k", maxTokens: 32000, contextWindow: 128000 }],
85
+ },
86
+ },
87
+ });
88
+
89
+ const model = registry.getAll().find((m) => m.id === "model-32k");
90
+ assert.ok(model);
91
+ assert.equal(model.maxTokens, 32000);
92
+ });
93
+
94
+ it("custom model with maxTokens 65 k is stored at full value", () => {
95
+ const registry = createRegistry({
96
+ providers: {
97
+ "dashscope-custom": {
98
+ baseUrl: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
99
+ apiKey: "sk-test",
100
+ api: "openai-completions",
101
+ models: [
102
+ {
103
+ id: "qwen3.5-plus",
104
+ name: "Qwen3.5 Plus",
105
+ maxTokens: 65536,
106
+ contextWindow: 1000000,
107
+ },
108
+ ],
109
+ },
110
+ },
111
+ });
112
+
113
+ const model = registry.getAll().find((m) => m.id === "qwen3.5-plus" && m.provider === "dashscope-custom");
114
+ assert.ok(model);
115
+ assert.equal(model.maxTokens, 65536);
116
+ });
117
+ });
118
+
119
+ // ─── Bug 2: capabilities.supportsXhigh must be declarable in models.json ──────
120
+
121
+ describe("Bug 2 — capabilities.supportsXhigh in models.json (#4563)", () => {
122
+ it("model with capabilities.supportsXhigh: true surfaces the flag", () => {
123
+ const registry = createRegistry({
124
+ providers: {
125
+ "kimi-custom": {
126
+ baseUrl: "https://api.example.com/v1",
127
+ apiKey: "sk-test",
128
+ api: "anthropic-messages",
129
+ models: [
130
+ {
131
+ id: "kimi-k2.6-code-preview",
132
+ name: "Kimi K2.6 Code Preview",
133
+ maxTokens: 131072,
134
+ contextWindow: 262144,
135
+ capabilities: { supportsXhigh: true },
136
+ },
137
+ ],
138
+ },
139
+ },
140
+ });
141
+
142
+ const model = registry.getAll().find((m) => m.id === "kimi-k2.6-code-preview");
143
+ assert.ok(model, "model should be registered");
144
+ assert.equal(
145
+ model.capabilities?.supportsXhigh,
146
+ true,
147
+ "supportsXhigh must be true as declared in models.json",
148
+ );
149
+ });
150
+
151
+ it("model without capabilities declaration has no supportsXhigh", () => {
152
+ const registry = createRegistry({
153
+ providers: {
154
+ "plain-provider": {
155
+ baseUrl: "https://api.example.com/v1",
156
+ apiKey: "sk-test",
157
+ api: "openai-completions",
158
+ models: [{ id: "plain-model", maxTokens: 16384, contextWindow: 128000 }],
159
+ },
160
+ },
161
+ });
162
+
163
+ const model = registry.getAll().find((m) => m.id === "plain-model");
164
+ assert.ok(model);
165
+ // supportsXhigh should be absent or explicitly false — never implicitly true
166
+ assert.ok(
167
+ !model.capabilities?.supportsXhigh,
168
+ "supportsXhigh must not be set for models that don't declare it",
169
+ );
170
+ });
171
+
172
+ it("capabilities.supportsXhigh: false is respected", () => {
173
+ const registry = createRegistry({
174
+ providers: {
175
+ "explicit-provider": {
176
+ baseUrl: "https://api.example.com/v1",
177
+ apiKey: "sk-test",
178
+ api: "openai-completions",
179
+ models: [
180
+ {
181
+ id: "no-xhigh-model",
182
+ capabilities: { supportsXhigh: false },
183
+ },
184
+ ],
185
+ },
186
+ },
187
+ });
188
+
189
+ const model = registry.getAll().find((m) => m.id === "no-xhigh-model");
190
+ assert.ok(model);
191
+ assert.equal(model.capabilities?.supportsXhigh, false);
192
+ });
193
+
194
+ it("supportsXhigh declared in models.json is not overwritten by capability patches", () => {
195
+ // The capability-patches system must not overwrite an explicit declaration in models.json.
196
+ // applyCapabilityPatches uses spread: { ...patch.caps, ...model.capabilities }
197
+ // so model.capabilities wins. This test verifies the precedence end-to-end.
198
+ const registry = createRegistry({
199
+ providers: {
200
+ "compat-provider": {
201
+ baseUrl: "https://api.example.com/v1",
202
+ apiKey: "sk-test",
203
+ api: "openai-completions",
204
+ models: [
205
+ {
206
+ id: "custom-xhigh-model",
207
+ capabilities: { supportsXhigh: true },
208
+ },
209
+ ],
210
+ },
211
+ },
212
+ });
213
+
214
+ const model = registry.getAll().find((m) => m.id === "custom-xhigh-model");
215
+ assert.ok(model);
216
+ assert.equal(model.capabilities?.supportsXhigh, true);
217
+ });
218
+
219
+ it("modelOverrides can set capabilities.supportsXhigh on built-in models", () => {
220
+ // A user-facing override in models.json should be able to add supportsXhigh
221
+ // to a built-in model that doesn't declare it.
222
+ const path = writeModelsJson({
223
+ providers: {
224
+ anthropic: {
225
+ modelOverrides: {
226
+ "claude-3-5-haiku-20241022": {
227
+ capabilities: { supportsXhigh: true },
228
+ },
229
+ },
230
+ },
231
+ },
232
+ });
233
+
234
+ const registry = new ModelRegistry(AuthStorage.inMemory(), path);
235
+ const model = registry.getAll().find(
236
+ (m) => m.provider === "anthropic" && m.id === "claude-3-5-haiku-20241022",
237
+ );
238
+ assert.ok(model, "built-in model must still be present");
239
+ assert.equal(
240
+ model.capabilities?.supportsXhigh,
241
+ true,
242
+ "modelOverrides must be able to set capabilities.supportsXhigh",
243
+ );
244
+ });
245
+ });
@@ -48,6 +48,14 @@ const VercelGatewayRoutingSchema = Type.Object({
48
48
  order: Type.Optional(Type.Array(Type.String())),
49
49
  });
50
50
 
51
+ // Schema for model capability declarations (mirrors ModelCapabilities in pi-ai types)
52
+ const ModelCapabilitiesSchema = Type.Object({
53
+ supportsXhigh: Type.Optional(Type.Boolean()),
54
+ requiresToolCallId: Type.Optional(Type.Boolean()),
55
+ supportsServiceTier: Type.Optional(Type.Boolean()),
56
+ charsPerToken: Type.Optional(Type.Number()),
57
+ });
58
+
51
59
  // Schema for OpenAI compatibility settings
52
60
  const OpenAICompletionsCompatSchema = Type.Object({
53
61
  supportsStore: Type.Optional(Type.Boolean()),
@@ -91,6 +99,7 @@ const ModelDefinitionSchema = Type.Object({
91
99
  maxTokens: Type.Optional(Type.Number()),
92
100
  headers: Type.Optional(Type.Record(Type.String(), Type.String())),
93
101
  compat: Type.Optional(OpenAICompatSchema),
102
+ capabilities: Type.Optional(ModelCapabilitiesSchema),
94
103
  });
95
104
 
96
105
  // Schema for per-model overrides (all fields optional, merged with built-in model)
@@ -110,6 +119,7 @@ const ModelOverrideSchema = Type.Object({
110
119
  maxTokens: Type.Optional(Type.Number()),
111
120
  headers: Type.Optional(Type.Record(Type.String(), Type.String())),
112
121
  compat: Type.Optional(OpenAICompatSchema),
122
+ capabilities: Type.Optional(ModelCapabilitiesSchema),
113
123
  });
114
124
 
115
125
  type ModelOverride = Static<typeof ModelOverrideSchema>;
@@ -219,6 +229,11 @@ function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<A
219
229
  // Deep merge compat
220
230
  result.compat = mergeCompat(model.compat, override.compat);
221
231
 
232
+ // Merge capabilities (override wins per-field)
233
+ if (override.capabilities) {
234
+ result.capabilities = { ...model.capabilities, ...override.capabilities };
235
+ }
236
+
222
237
  return result;
223
238
  }
224
239
 
@@ -514,6 +529,7 @@ export class ModelRegistry {
514
529
  maxTokens: modelDef.maxTokens ?? 16384,
515
530
  headers,
516
531
  compat: modelDef.compat,
532
+ capabilities: modelDef.capabilities,
517
533
  } as Model<Api>);
518
534
  }
519
535
  }
@@ -242,7 +242,7 @@ export class DefaultResourceLoader implements ResourceLoader {
242
242
  this.systemPromptOverride = options.systemPromptOverride;
243
243
  this.appendSystemPromptOverride = options.appendSystemPromptOverride;
244
244
 
245
- this.extensionsResult = { extensions: [], errors: [], runtime: createExtensionRuntime() };
245
+ this.extensionsResult = { extensions: [], errors: [], warnings: [], runtime: createExtensionRuntime() };
246
246
  this.skills = [];
247
247
  this.skillDiagnostics = [];
248
248
  this.prompts = [];
@@ -3,7 +3,8 @@
3
3
 
4
4
  import { describe, it } from "node:test";
5
5
  import assert from "node:assert/strict";
6
- import { CredentialCooldownError } from "./sdk.js";
6
+ import { canRestoreSessionModel, CredentialCooldownError } from "./sdk.js";
7
+ import type { Model } from "@gsd/pi-ai";
7
8
 
8
9
  // ─── CredentialCooldownError ──────────────────────────────────────────────────
9
10
 
@@ -87,3 +88,26 @@ describe("CredentialCooldownError", () => {
87
88
  assert.equal(plain.retryAfterMs, 15_000);
88
89
  });
89
90
  });
91
+
92
+ describe("canRestoreSessionModel", () => {
93
+ const model = {
94
+ provider: "claude-code",
95
+ id: "claude-sonnet",
96
+ } as Model<any>;
97
+
98
+ it("allows keyless external providers when the provider is request-ready", () => {
99
+ const registry = {
100
+ isProviderRequestReady: (provider: string) => provider === "claude-code",
101
+ };
102
+
103
+ assert.equal(canRestoreSessionModel(registry, model), true);
104
+ });
105
+
106
+ it("blocks restore when the provider is not request-ready", () => {
107
+ const registry = {
108
+ isProviderRequestReady: () => false,
109
+ };
110
+
111
+ assert.equal(canRestoreSessionModel(registry, model), false);
112
+ });
113
+ });
@@ -31,6 +31,13 @@ export class CredentialCooldownError extends Error {
31
31
  this.retryAfterMs = retryAfterMs;
32
32
  }
33
33
  }
34
+
35
+ export function canRestoreSessionModel(
36
+ modelRegistry: Pick<ModelRegistry, "isProviderRequestReady">,
37
+ model: Model<any>,
38
+ ): boolean {
39
+ return modelRegistry.isProviderRequestReady(model.provider);
40
+ }
34
41
  import { Agent, type AgentMessage, type ThinkingLevel } from "@gsd/pi-agent-core";
35
42
  import type { Message, Model } from "@gsd/pi-ai";
36
43
  import { getAgentDir, getDocsPath } from "../config.js";
@@ -262,9 +269,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
262
269
  // If session has data, try to restore model from it
263
270
  if (!model && hasExistingSession && existingSession.model) {
264
271
  const restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);
265
- if (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {
266
- model = restoredModel;
267
- }
272
+ if (restoredModel && canRestoreSessionModel(modelRegistry, restoredModel)) {
273
+ model = restoredModel;
274
+ }
268
275
  if (!model) {
269
276
  modelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;
270
277
  }
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it, afterEach } from "node:test";
3
- import { mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
@@ -97,4 +97,33 @@ describe("SessionManager secret redaction on persistence", () => {
97
97
  "redaction placeholder must appear in persisted JSONL",
98
98
  );
99
99
  });
100
+
101
+ it("scrubs secrets from JSONL rewritten by _rewriteFile() during migration", () => {
102
+ // Write a v1 session file (no id/parentId on entries) containing a secret.
103
+ // setSessionFile() will detect version < 3, run migration, and call _rewriteFile()
104
+ // which previously serialised entries without passing them through redaction.
105
+ dir = mkdtempSync(join(tmpdir(), "gsd-session-rewrite-redact-test-"));
106
+ const leakedKey = "sk-ant-api03-abcDEF1234567890abcDEF1234567890xYz";
107
+ const v1Header = JSON.stringify({ type: "session", version: 1, id: "test-session-id", timestamp: new Date().toISOString(), cwd: dir });
108
+ const v1UserMsg = JSON.stringify({ type: "message", message: { role: "user", content: [{ type: "text", text: `secret: ${leakedKey}` }] } });
109
+ const v1AssistantMsg = JSON.stringify({ type: "message", message: { role: "assistant", content: [{ type: "text", text: "ok" }], usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, total: 2, cost: { total: 0 } } } });
110
+ const sessionFile = join(dir, "test-session.jsonl");
111
+ writeFileSync(sessionFile, [v1Header, v1UserMsg, v1AssistantMsg].join("\n") + "\n", "utf8");
112
+
113
+ // Loading this file triggers migrateToCurrentVersion() which returns true (v1 → v3),
114
+ // causing _rewriteFile() to rewrite the file. The bug: _rewriteFile() called
115
+ // JSON.stringify(e) without redaction, so the secret would survive on disk.
116
+ const manager = SessionManager.create(dir, dir);
117
+ manager.setSessionFile(sessionFile);
118
+
119
+ const contents = readFileSync(sessionFile, "utf8");
120
+ assert.ok(
121
+ !contents.includes(leakedKey),
122
+ "raw secret must not appear in JSONL rewritten by _rewriteFile()",
123
+ );
124
+ assert.ok(
125
+ contents.includes("[REDACTED:anthropic]"),
126
+ "redaction placeholder must appear in JSONL rewritten by _rewriteFile()",
127
+ );
128
+ });
100
129
  });
@@ -959,7 +959,7 @@ export class SessionManager {
959
959
 
960
960
  private _rewriteFile(): void {
961
961
  if (!this.persist || !this.sessionFile) return;
962
- const content = `${this.fileEntries.map((e) => JSON.stringify(e)).join("\n")}\n`;
962
+ const content = `${this.fileEntries.map((e) => JSON.stringify(prepareForPersistence(e, this.blobStore))).join("\n")}\n`;
963
963
  let release: (() => void) | undefined;
964
964
  try {
965
965
  release = tryAcquireLockSync(this.sessionFile);
@@ -109,9 +109,9 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
109
109
  }
110
110
 
111
111
  // Get absolute paths to documentation and examples
112
- const readmePath = getReadmePath();
113
- const docsPath = getDocsPath();
114
- const examplesPath = getExamplesPath();
112
+ const readmePath = toPosixPath(getReadmePath());
113
+ const docsPath = toPosixPath(getDocsPath());
114
+ const examplesPath = toPosixPath(getExamplesPath());
115
115
 
116
116
  // Build tools list based on selected tools.
117
117
  // Built-ins use toolDescriptions. Custom tools can provide one-line snippets.
@@ -1,11 +1,12 @@
1
1
  import { describe, it, mock, afterEach } from "node:test";
2
2
  import assert from "node:assert/strict";
3
+ import { resolve as resolvePath } from "node:path";
3
4
  import { resolveToCwd, expandPath } from "./path-utils.js";
4
5
 
5
6
  describe("resolveToCwd", () => {
6
7
  it("resolves relative paths against cwd", () => {
7
8
  const result = resolveToCwd("foo/bar.txt", "/home/user/project");
8
- assert.equal(result, "/home/user/project/foo/bar.txt");
9
+ assert.equal(result, resolvePath("/home/user/project", "foo/bar.txt"));
9
10
  });
10
11
 
11
12
  it("returns absolute paths unchanged", () => {
@@ -1,14 +1,11 @@
1
- // GSD-2 — Provider display name mapping tests
1
+ // GSD-2 — Provider display name + auth badge tests
2
2
  import { test, describe } from "node:test";
3
3
  import assert from "node:assert/strict";
4
- import { providerDisplayName } from "../model-selector.js";
4
+ import { providerAuthBadge, providerDisplayName } from "../model-selector.js";
5
5
 
6
6
  describe("providerDisplayName", () => {
7
- test("renames 'anthropic' to 'anthropic-api'", () => {
8
- assert.equal(providerDisplayName("anthropic"), "anthropic-api");
9
- });
10
-
11
- test("passes through unmapped providers unchanged", () => {
7
+ test("passes providers through unchanged", () => {
8
+ assert.equal(providerDisplayName("anthropic"), "anthropic");
12
9
  assert.equal(providerDisplayName("claude-code"), "claude-code");
13
10
  assert.equal(providerDisplayName("openai"), "openai");
14
11
  assert.equal(providerDisplayName("bedrock"), "bedrock");
@@ -16,3 +13,16 @@ describe("providerDisplayName", () => {
16
13
  assert.equal(providerDisplayName("openrouter"), "openrouter");
17
14
  });
18
15
  });
16
+
17
+ describe("providerAuthBadge", () => {
18
+ test("returns human-readable labels for each auth mode", () => {
19
+ assert.equal(providerAuthBadge("apiKey"), "API key");
20
+ assert.equal(providerAuthBadge("oauth"), "OAuth");
21
+ assert.equal(providerAuthBadge("externalCli"), "CLI");
22
+ });
23
+
24
+ test("returns empty string for 'none' and undefined", () => {
25
+ assert.equal(providerAuthBadge("none"), "");
26
+ assert.equal(providerAuthBadge(undefined), "");
27
+ });
28
+ });
@@ -2,7 +2,7 @@ import { type Component, truncateToWidth, visibleWidth } from "@gsd/pi-tui";
2
2
  import type { AgentSession } from "../../../core/agent-session.js";
3
3
  import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.js";
4
4
  import { theme } from "../theme/theme.js";
5
- import { providerDisplayName } from "./model-selector.js";
5
+ import { providerAuthBadge, providerDisplayName } from "./model-selector.js";
6
6
 
7
7
  /**
8
8
  * Sanitize text for display in a single-line status.
@@ -199,13 +199,22 @@ export class FooterComponent implements Component {
199
199
  thinkingLevel === "off" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;
200
200
  }
201
201
 
202
- // Prepend the provider in parentheses if there are multiple providers and there's enough room
202
+ // Prepend the provider in parentheses if there are multiple providers and there's enough room.
203
+ // Include the auth mode so users can tell at a glance whether the active model is
204
+ // API-key-backed, OAuth-backed, or delegated to a third-party CLI.
203
205
  let rightSide = rightSideWithoutProvider;
204
206
  if (this.footerData.getAvailableProviderCount() > 1 && displayModel) {
205
- rightSide = `(${providerDisplayName(displayModel.provider)}) ${rightSideWithoutProvider}`;
207
+ const authMode = this.session.modelRegistry.getProviderAuthMode(displayModel.provider);
208
+ const authLabel = providerAuthBadge(authMode);
209
+ const providerLabel = providerDisplayName(displayModel.provider);
210
+ const parenthetical = authLabel ? `${providerLabel} · ${authLabel}` : providerLabel;
211
+ rightSide = `(${parenthetical}) ${rightSideWithoutProvider}`;
206
212
  if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
207
- // Too wide, fall back
208
- rightSide = rightSideWithoutProvider;
213
+ // Too wide: drop the auth suffix first, then fall back to no parenthetical.
214
+ rightSide = `(${providerLabel}) ${rightSideWithoutProvider}`;
215
+ if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
216
+ rightSide = rightSideWithoutProvider;
217
+ }
209
218
  }
210
219
  }
211
220
 
@@ -9,19 +9,32 @@ import {
9
9
  Text,
10
10
  type TUI,
11
11
  } from "@gsd/pi-tui";
12
- import type { ModelRegistry } from "../../../core/model-registry.js";
12
+ import type { ModelRegistry, ProviderAuthMode } from "../../../core/model-registry.js";
13
13
  import type { SettingsManager } from "../../../core/settings-manager.js";
14
14
  import { theme } from "../theme/theme.js";
15
15
  import { DynamicBorder } from "./dynamic-border.js";
16
16
  import { keyHint } from "./keybinding-hints.js";
17
17
 
18
- /** Display names for providers in the model selector UI. */
19
- const PROVIDER_DISPLAY_NAMES: Record<string, string> = {
20
- anthropic: "anthropic-api",
21
- };
22
-
23
18
  export function providerDisplayName(provider: string): string {
24
- return PROVIDER_DISPLAY_NAMES[provider] ?? provider;
19
+ return provider;
20
+ }
21
+
22
+ /**
23
+ * Short, user-facing label for a provider's auth mode. Returned strings are
24
+ * suitable for use as a suffix/badge alongside the provider name.
25
+ * Returns an empty string for modes that don't need a badge (e.g. "none").
26
+ */
27
+ export function providerAuthBadge(authMode?: ProviderAuthMode): string {
28
+ switch (authMode) {
29
+ case "apiKey":
30
+ return "API key";
31
+ case "oauth":
32
+ return "OAuth";
33
+ case "externalCli":
34
+ return "CLI";
35
+ default:
36
+ return "";
37
+ }
25
38
  }
26
39
 
27
40
  function formatTokenCount(count: number): string {
@@ -140,7 +153,8 @@ export class ModelSelectorComponent extends Container implements Focusable {
140
153
  this.scopeHintText = new Text(this.getScopeHintText(), 0, 0);
141
154
  this.addChild(this.scopeHintText);
142
155
  } else {
143
- const hintText = "Only showing models with configured API keys (see README for details)";
156
+ const hintText =
157
+ "Only showing models with configured credentials (API key, OAuth, or CLI). See README for details.";
144
158
  this.addChild(new Text(theme.fg("warning", hintText), 0, 0));
145
159
  }
146
160
  this.addChild(new Spacer(1));
@@ -409,7 +423,12 @@ export class ModelSelectorComponent extends Container implements Focusable {
409
423
 
410
424
  const ctx = formatTokenCount(item.model.contextWindow);
411
425
  const ctxBadge = theme.fg("muted", `${ctx}`);
412
- const providerBadge = theme.fg("muted", `[${providerDisplayName(item.provider)}]`);
426
+ const authMode = this.modelRegistry.getProviderAuthMode(item.provider);
427
+ const authLabel = providerAuthBadge(authMode);
428
+ const providerBadgeText = authLabel
429
+ ? `[${providerDisplayName(item.provider)} · ${authLabel}]`
430
+ : `[${providerDisplayName(item.provider)}]`;
431
+ const providerBadge = theme.fg("muted", providerBadgeText);
413
432
  const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
414
433
 
415
434
  let line: string;
@@ -445,7 +464,19 @@ export class ModelSelectorComponent extends Container implements Focusable {
445
464
  const maxVisible = 12;
446
465
 
447
466
  if (this.groupedRows.length === 0) {
448
- this.listContainer.addChild(new Text(theme.fg("muted", " No models available"), 0, 0));
467
+ this.listContainer.addChild(
468
+ new Text(theme.fg("muted", " No providers configured."), 0, 0),
469
+ );
470
+ this.listContainer.addChild(
471
+ new Text(
472
+ theme.fg(
473
+ "muted",
474
+ " Run /login (OAuth), set an API key, or install a CLI provider. See README.",
475
+ ),
476
+ 0,
477
+ 0,
478
+ ),
479
+ );
449
480
  return;
450
481
  }
451
482
 
@@ -467,11 +498,14 @@ export class ModelSelectorComponent extends Container implements Focusable {
467
498
  // Provider group header — always unselectable
468
499
  const providerLabel = theme.fg("borderAccent", providerDisplayName(row.provider));
469
500
  const count = theme.fg("muted", ` (${row.count})`);
501
+ const authMode = this.modelRegistry.getProviderAuthMode(row.provider);
502
+ const authLabel = providerAuthBadge(authMode);
503
+ const authText = authLabel ? theme.fg("muted", ` · via ${authLabel}`) : "";
470
504
  // Add blank line before header if not the very first visible row
471
505
  if (i > startIndex) {
472
506
  this.listContainer.addChild(new Text("", 0, 0));
473
507
  }
474
- this.listContainer.addChild(new Text(` ${providerLabel}${count}`, 0, 0));
508
+ this.listContainer.addChild(new Text(` ${providerLabel}${count}${authText}`, 0, 0));
475
509
  } else {
476
510
  // Model row
477
511
  const isSelected = i === this.selectedGroupIndex;
@@ -17,6 +17,7 @@ function createHost(options: HostOptions = {}) {
17
17
  const prompted: string[] = [];
18
18
  const errors: string[] = [];
19
19
  const warnings: string[] = [];
20
+ const tips: string[] = [];
20
21
  const history: string[] = [];
21
22
  const knownSlashCommands = new Set(options.knownSlashCommands ?? []);
22
23
  let editorText = "";
@@ -60,6 +61,9 @@ function createHost(options: HostOptions = {}) {
60
61
  showError(message: string) {
61
62
  errors.push(message);
62
63
  },
64
+ showTip(message: string) {
65
+ tips.push(message);
66
+ },
63
67
  updateEditorBorderColor() {},
64
68
  isExtensionCommand() {
65
69
  return false;
@@ -70,6 +74,15 @@ function createHost(options: HostOptions = {}) {
70
74
  queueCompactionMessage() {},
71
75
  updatePendingMessagesDisplay() {},
72
76
  flushPendingBashComponents() {},
77
+ contextualTips: {
78
+ recordBashIncluded() {},
79
+ evaluate() {
80
+ return undefined;
81
+ },
82
+ },
83
+ getContextPercent() {
84
+ return undefined;
85
+ },
73
86
  };
74
87
 
75
88
  setupEditorSubmitHandler(host as any);
@@ -79,6 +92,7 @@ function createHost(options: HostOptions = {}) {
79
92
  prompted,
80
93
  errors,
81
94
  warnings,
95
+ tips,
82
96
  history,
83
97
  getEditorText: () => editorText,
84
98
  getSettingsOpened: () => settingsOpened,