gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac

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 (643) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +49 -35
  3. package/dist/headless-ui.d.ts +17 -0
  4. package/dist/headless-ui.js +97 -3
  5. package/dist/headless.js +67 -6
  6. package/dist/help-text.js +1 -0
  7. package/dist/onboarding.js +44 -0
  8. package/dist/resource-loader.js +16 -1
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +16 -3
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +8 -5
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +2 -1
  20. package/dist/resources/extensions/gsd/auto/phases.js +25 -21
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
  28. package/dist/resources/extensions/gsd/auto-start.js +35 -22
  29. package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
  30. package/dist/resources/extensions/gsd/auto.js +4 -0
  31. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
  33. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
  37. package/dist/resources/extensions/gsd/captures.js +56 -4
  38. package/dist/resources/extensions/gsd/db-writer.js +116 -8
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
  40. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
  42. package/dist/resources/extensions/gsd/doctor.js +3 -1
  43. package/dist/resources/extensions/gsd/error-classifier.js +13 -10
  44. package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
  45. package/dist/resources/extensions/gsd/forensics.js +123 -20
  46. package/dist/resources/extensions/gsd/git-service.js +23 -1
  47. package/dist/resources/extensions/gsd/gitignore.js +33 -0
  48. package/dist/resources/extensions/gsd/gsd-db.js +36 -9
  49. package/dist/resources/extensions/gsd/guided-flow.js +106 -44
  50. package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
  51. package/dist/resources/extensions/gsd/health-widget.js +17 -0
  52. package/dist/resources/extensions/gsd/index.js +1 -1
  53. package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
  54. package/dist/resources/extensions/gsd/migrate-external.js +8 -1
  55. package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
  56. package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
  57. package/dist/resources/extensions/gsd/model-router.js +35 -1
  58. package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
  59. package/dist/resources/extensions/gsd/notifications.js +16 -1
  60. package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
  61. package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
  62. package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
  63. package/dist/resources/extensions/gsd/paths.js +43 -0
  64. package/dist/resources/extensions/gsd/preferences-models.js +14 -1
  65. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  66. package/dist/resources/extensions/gsd/preferences.js +13 -16
  67. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  74. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  77. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  79. package/dist/resources/extensions/gsd/repo-identity.js +205 -11
  80. package/dist/resources/extensions/gsd/rethink.js +5 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
  82. package/dist/resources/extensions/gsd/state.js +85 -27
  83. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
  85. package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
  86. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
  87. package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
  88. package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
  89. package/dist/resources/extensions/gsd/undo.js +2 -2
  90. package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
  91. package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
  92. package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
  93. package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
  94. package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
  95. package/dist/resources/extensions/gsd/workspace-index.js +24 -0
  96. package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
  97. package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
  98. package/dist/resources/extensions/mcp-client/index.js +11 -7
  99. package/dist/resources/extensions/ollama/index.js +112 -0
  100. package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
  101. package/dist/resources/extensions/ollama/ollama-client.js +168 -0
  102. package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
  103. package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
  104. package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
  105. package/dist/resources/extensions/ollama/types.js +2 -0
  106. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  107. package/dist/resources/extensions/shared/interview-ui.js +11 -1
  108. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
  109. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  110. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  111. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  112. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  113. package/dist/startup-model-validation.d.ts +39 -0
  114. package/dist/startup-model-validation.js +50 -0
  115. package/dist/web/standalone/.next/BUILD_ID +1 -1
  116. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  117. package/dist/web/standalone/.next/build-manifest.json +3 -3
  118. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  119. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  138. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  201. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  202. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  205. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  206. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  207. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
  208. package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
  209. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
  210. package/dist/web-mode.js +2 -1
  211. package/package.json +2 -2
  212. package/packages/daemon/src/cli.ts +49 -0
  213. package/packages/daemon/src/daemon.test.ts +104 -1
  214. package/packages/daemon/src/daemon.ts +24 -1
  215. package/packages/daemon/src/discord-bot.ts +73 -3
  216. package/packages/daemon/src/event-bridge.ts +15 -9
  217. package/packages/daemon/src/event-formatter.ts +30 -2
  218. package/packages/daemon/src/index.ts +9 -0
  219. package/packages/daemon/src/launchd.test.ts +356 -0
  220. package/packages/daemon/src/launchd.ts +242 -0
  221. package/packages/daemon/src/message-batcher.test.ts +2 -2
  222. package/packages/daemon/src/message-batcher.ts +9 -3
  223. package/packages/daemon/src/orchestrator.test.ts +1 -0
  224. package/packages/daemon/src/orchestrator.ts +106 -2
  225. package/packages/native/dist/ast/index.js +9 -5
  226. package/packages/native/dist/ast/types.js +2 -1
  227. package/packages/native/dist/clipboard/index.js +12 -7
  228. package/packages/native/dist/clipboard/types.js +2 -1
  229. package/packages/native/dist/diff/index.js +12 -7
  230. package/packages/native/dist/diff/types.js +2 -1
  231. package/packages/native/dist/fd/index.js +6 -3
  232. package/packages/native/dist/fd/types.js +2 -1
  233. package/packages/native/dist/glob/index.js +9 -5
  234. package/packages/native/dist/glob/types.js +2 -1
  235. package/packages/native/dist/grep/index.js +9 -5
  236. package/packages/native/dist/grep/types.js +2 -1
  237. package/packages/native/dist/gsd-parser/index.js +18 -11
  238. package/packages/native/dist/gsd-parser/types.js +2 -1
  239. package/packages/native/dist/highlight/index.js +12 -7
  240. package/packages/native/dist/highlight/types.js +2 -1
  241. package/packages/native/dist/html/index.js +6 -3
  242. package/packages/native/dist/html/types.js +2 -1
  243. package/packages/native/dist/image/index.js +10 -5
  244. package/packages/native/dist/image/types.js +7 -4
  245. package/packages/native/dist/index.js +70 -17
  246. package/packages/native/dist/json-parse/index.js +13 -8
  247. package/packages/native/dist/native.js +47 -10
  248. package/packages/native/dist/ps/index.js +15 -9
  249. package/packages/native/dist/ps/types.js +2 -1
  250. package/packages/native/dist/stream-process/index.js +12 -7
  251. package/packages/native/dist/text/index.js +24 -14
  252. package/packages/native/dist/text/types.js +5 -2
  253. package/packages/native/dist/truncate/index.js +12 -7
  254. package/packages/native/dist/ttsr/index.js +12 -7
  255. package/packages/native/dist/ttsr/types.js +2 -1
  256. package/packages/native/dist/xxhash/index.js +9 -5
  257. package/packages/native/package.json +19 -19
  258. package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
  259. package/packages/native/src/native.ts +9 -8
  260. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  261. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  262. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  263. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  264. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  265. package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
  266. package/packages/pi-agent-core/src/agent-loop.ts +3 -2
  267. package/packages/pi-agent-core/src/proxy.ts +1 -1
  268. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  269. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  270. package/packages/pi-ai/dist/index.d.ts +1 -0
  271. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/index.js +1 -0
  273. package/packages/pi-ai/dist/index.js.map +1 -1
  274. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  275. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
  276. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  277. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
  278. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
  279. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
  280. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
  281. package/packages/pi-ai/dist/types.d.ts +3 -3
  282. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  283. package/packages/pi-ai/dist/types.js.map +1 -1
  284. package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
  285. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  286. package/packages/pi-ai/dist/utils/json-parse.js +24 -1
  287. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  288. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
  289. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
  290. package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
  291. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
  292. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
  293. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
  294. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
  295. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
  296. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  297. package/packages/pi-ai/src/index.ts +1 -0
  298. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
  299. package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
  300. package/packages/pi-ai/src/types.ts +3 -2
  301. package/packages/pi-ai/src/utils/json-parse.ts +28 -1
  302. package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
  303. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
  304. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  305. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
  307. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
  309. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
  311. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
  313. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
  315. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/exec.js +3 -1
  318. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
  320. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
  322. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
  324. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
  325. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
  326. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
  327. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
  328. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
  330. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
  334. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
  336. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
  338. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  340. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  341. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  342. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
  344. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
  346. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
  351. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  352. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  354. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
  357. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  359. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
  360. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/messages.js +31 -2
  363. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
  365. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
  367. package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  370. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
  372. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
  374. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
  376. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
  378. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
  380. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
  381. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
  382. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
  385. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
  388. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  389. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
  390. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
  391. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
  392. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
  393. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  394. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/index.js +1 -1
  396. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
  399. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
  401. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
  403. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  404. package/packages/pi-coding-agent/package.json +1 -1
  405. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
  406. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
  407. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
  408. package/packages/pi-coding-agent/src/core/exec.ts +3 -1
  409. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  410. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  411. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  412. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  413. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  414. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  415. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  416. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  417. package/packages/pi-coding-agent/src/core/index.ts +6 -0
  418. package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
  419. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
  420. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  421. package/packages/pi-coding-agent/src/core/messages.ts +29 -2
  422. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  423. package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
  424. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
  425. package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
  426. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
  427. package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
  428. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
  429. package/packages/pi-coding-agent/src/index.ts +6 -0
  430. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
  431. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
  432. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  433. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  434. package/packages/pi-tui/dist/terminal.js +9 -0
  435. package/packages/pi-tui/dist/terminal.js.map +1 -1
  436. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  437. package/packages/pi-tui/dist/tui.js +9 -0
  438. package/packages/pi-tui/dist/tui.js.map +1 -1
  439. package/packages/pi-tui/src/terminal.ts +14 -0
  440. package/packages/pi-tui/src/tui.ts +8 -0
  441. package/pkg/package.json +1 -1
  442. package/scripts/ensure-workspace-builds.cjs +45 -14
  443. package/src/resources/agents/researcher.md +1 -1
  444. package/src/resources/extensions/ask-user-questions.ts +21 -3
  445. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  446. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  447. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  448. package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
  449. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
  450. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
  451. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
  452. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  453. package/src/resources/extensions/get-secrets-from-user.ts +8 -5
  454. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  455. package/src/resources/extensions/google-search/index.ts +2 -1
  456. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  457. package/src/resources/extensions/gsd/auto/phases.ts +43 -34
  458. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  459. package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
  460. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
  461. package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
  462. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  463. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  464. package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
  465. package/src/resources/extensions/gsd/auto-start.ts +35 -26
  466. package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
  467. package/src/resources/extensions/gsd/auto.ts +5 -0
  468. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
  469. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
  470. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
  471. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
  472. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
  473. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
  474. package/src/resources/extensions/gsd/captures.ts +63 -3
  475. package/src/resources/extensions/gsd/db-writer.ts +140 -7
  476. package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
  477. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  478. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
  479. package/src/resources/extensions/gsd/doctor.ts +3 -1
  480. package/src/resources/extensions/gsd/error-classifier.ts +14 -11
  481. package/src/resources/extensions/gsd/extension-manifest.json +16 -1
  482. package/src/resources/extensions/gsd/forensics.ts +144 -20
  483. package/src/resources/extensions/gsd/git-service.ts +26 -3
  484. package/src/resources/extensions/gsd/gitignore.ts +33 -0
  485. package/src/resources/extensions/gsd/gsd-db.ts +43 -7
  486. package/src/resources/extensions/gsd/guided-flow.ts +114 -45
  487. package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
  488. package/src/resources/extensions/gsd/health-widget.ts +17 -0
  489. package/src/resources/extensions/gsd/index.ts +1 -0
  490. package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
  491. package/src/resources/extensions/gsd/migrate-external.ts +9 -1
  492. package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
  493. package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
  494. package/src/resources/extensions/gsd/model-router.ts +35 -1
  495. package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
  496. package/src/resources/extensions/gsd/notifications.ts +16 -0
  497. package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
  498. package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
  499. package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
  500. package/src/resources/extensions/gsd/paths.ts +42 -0
  501. package/src/resources/extensions/gsd/preferences-models.ts +14 -1
  502. package/src/resources/extensions/gsd/preferences-types.ts +2 -1
  503. package/src/resources/extensions/gsd/preferences.ts +13 -15
  504. package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
  505. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  506. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  507. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  508. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  509. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  510. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  511. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  512. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  513. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  514. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  515. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  516. package/src/resources/extensions/gsd/repo-identity.ts +186 -11
  517. package/src/resources/extensions/gsd/rethink.ts +6 -0
  518. package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
  519. package/src/resources/extensions/gsd/state.ts +84 -32
  520. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
  521. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  522. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
  523. package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
  524. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  525. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
  527. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  528. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
  529. package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
  530. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
  531. package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  533. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
  534. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
  535. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  536. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
  537. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  538. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
  539. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  540. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
  541. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
  542. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
  543. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
  544. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
  545. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  546. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
  547. package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
  548. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
  549. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
  550. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
  551. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
  552. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  553. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  554. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
  555. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  556. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
  557. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
  558. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
  559. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  560. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
  561. package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
  562. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
  563. package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
  564. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
  565. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
  566. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
  567. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
  568. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  569. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
  570. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  571. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  572. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
  573. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
  574. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
  575. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
  576. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  577. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
  578. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
  579. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
  580. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
  581. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
  582. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  583. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
  584. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
  585. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
  586. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
  587. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  588. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
  589. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  590. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
  591. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  592. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
  593. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  594. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
  595. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
  596. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
  597. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
  598. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
  599. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
  600. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
  601. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
  602. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
  603. package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
  604. package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
  605. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
  606. package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
  607. package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
  608. package/src/resources/extensions/gsd/types.ts +4 -2
  609. package/src/resources/extensions/gsd/undo.ts +2 -2
  610. package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
  611. package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
  612. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  613. package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
  614. package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
  615. package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
  616. package/src/resources/extensions/gsd/workspace-index.ts +30 -0
  617. package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
  618. package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
  619. package/src/resources/extensions/mcp-client/index.ts +13 -7
  620. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
  621. package/src/resources/extensions/ollama/index.ts +130 -0
  622. package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
  623. package/src/resources/extensions/ollama/ollama-client.ts +196 -0
  624. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  625. package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
  626. package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
  627. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
  628. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  629. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
  630. package/src/resources/extensions/ollama/types.ts +130 -0
  631. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  632. package/src/resources/extensions/shared/interview-ui.ts +12 -1
  633. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
  634. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
  635. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  636. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  637. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  638. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  639. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
  640. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
  641. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
  642. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
  643. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
@@ -0,0 +1,112 @@
1
+ // GSD2 — Ollama Extension: First-class local LLM support
2
+ /**
3
+ * Ollama Extension
4
+ *
5
+ * Auto-detects a running Ollama instance, discovers locally pulled models,
6
+ * and registers them as a first-class provider. No configuration required —
7
+ * if Ollama is running, models appear automatically.
8
+ *
9
+ * Features:
10
+ * - Auto-discovery of local models via /api/tags
11
+ * - Capability detection (vision, reasoning, context window)
12
+ * - /ollama slash commands for model management
13
+ * - ollama_manage tool for LLM-driven model operations
14
+ * - Zero-cost model registration (local inference)
15
+ *
16
+ * Respects OLLAMA_HOST env var for non-default endpoints.
17
+ */
18
+ import { importExtensionModule } from "@gsd/pi-coding-agent";
19
+ import * as client from "./ollama-client.js";
20
+ import { discoverModels, getOllamaOpenAIBaseUrl } from "./ollama-discovery.js";
21
+ import { registerOllamaCommands } from "./ollama-commands.js";
22
+ /** Default compat settings for Ollama models via OpenAI-compat endpoint */
23
+ const OLLAMA_COMPAT = {
24
+ supportsDeveloperRole: false,
25
+ supportsReasoningEffort: false,
26
+ supportsUsageInStreaming: false,
27
+ maxTokensField: "max_tokens",
28
+ supportsStore: false,
29
+ };
30
+ let toolsPromise = null;
31
+ async function registerOllamaTools(pi) {
32
+ if (!toolsPromise) {
33
+ toolsPromise = (async () => {
34
+ const { registerOllamaTool } = await importExtensionModule(import.meta.url, "./ollama-tool.js");
35
+ registerOllamaTool(pi);
36
+ })().catch((error) => {
37
+ toolsPromise = null;
38
+ throw error;
39
+ });
40
+ }
41
+ return toolsPromise;
42
+ }
43
+ /** Track whether we've registered models so we can clean up on shutdown */
44
+ let providerRegistered = false;
45
+ /**
46
+ * Probe Ollama and register discovered models.
47
+ * Safe to call multiple times — re-discovers and re-registers.
48
+ */
49
+ async function probeAndRegister(pi) {
50
+ const running = await client.isRunning();
51
+ if (!running) {
52
+ if (providerRegistered) {
53
+ pi.unregisterProvider("ollama");
54
+ providerRegistered = false;
55
+ }
56
+ return false;
57
+ }
58
+ const models = await discoverModels();
59
+ if (models.length === 0)
60
+ return true; // Running but no models pulled
61
+ const baseUrl = getOllamaOpenAIBaseUrl();
62
+ pi.registerProvider("ollama", {
63
+ authMode: "none",
64
+ baseUrl,
65
+ api: "openai-completions",
66
+ isReady: () => true,
67
+ models: models.map((m) => ({
68
+ id: m.id,
69
+ name: m.name,
70
+ reasoning: m.reasoning,
71
+ input: m.input,
72
+ cost: m.cost,
73
+ contextWindow: m.contextWindow,
74
+ maxTokens: m.maxTokens,
75
+ compat: OLLAMA_COMPAT,
76
+ })),
77
+ });
78
+ providerRegistered = true;
79
+ return true;
80
+ }
81
+ export default function ollama(pi) {
82
+ // Register slash commands immediately (they check Ollama availability themselves)
83
+ registerOllamaCommands(pi);
84
+ pi.on("session_start", async (_event, ctx) => {
85
+ // Register tool (deferred to avoid blocking startup)
86
+ if (ctx.hasUI) {
87
+ void registerOllamaTools(pi).catch((error) => {
88
+ ctx.ui.notify(`Ollama tool failed to load: ${error instanceof Error ? error.message : String(error)}`, "warning");
89
+ });
90
+ }
91
+ else {
92
+ await registerOllamaTools(pi);
93
+ }
94
+ // Async probe — don't block startup
95
+ probeAndRegister(pi)
96
+ .then((found) => {
97
+ if (found && ctx.hasUI) {
98
+ ctx.ui.setStatus("ollama", "Ollama");
99
+ }
100
+ })
101
+ .catch(() => {
102
+ // Silently ignore probe failures
103
+ });
104
+ });
105
+ pi.on("session_shutdown", async () => {
106
+ if (providerRegistered) {
107
+ pi.unregisterProvider("ollama");
108
+ providerRegistered = false;
109
+ }
110
+ toolsPromise = null;
111
+ });
112
+ }
@@ -0,0 +1,115 @@
1
+ // GSD2 — Known model capability table for Ollama models
2
+ /**
3
+ * Known model family capabilities.
4
+ * Keys are matched as prefixes against the model name (before the colon/tag).
5
+ * More specific entries should appear first.
6
+ */
7
+ const KNOWN_MODELS = [
8
+ // ─── Reasoning models ───────────────────────────────────────────────
9
+ ["deepseek-r1", { contextWindow: 131072, reasoning: true }],
10
+ ["qwq", { contextWindow: 131072, reasoning: true }],
11
+ // ─── Vision models ──────────────────────────────────────────────────
12
+ ["llava", { contextWindow: 4096, input: ["text", "image"] }],
13
+ ["bakllava", { contextWindow: 4096, input: ["text", "image"] }],
14
+ ["moondream", { contextWindow: 8192, input: ["text", "image"] }],
15
+ ["llama3.2-vision", { contextWindow: 131072, input: ["text", "image"] }],
16
+ ["minicpm-v", { contextWindow: 4096, input: ["text", "image"] }],
17
+ // ─── Code models ────────────────────────────────────────────────────
18
+ ["codestral", { contextWindow: 262144, maxTokens: 32768 }],
19
+ ["qwen2.5-coder", { contextWindow: 131072, maxTokens: 32768 }],
20
+ ["deepseek-coder-v2", { contextWindow: 131072, maxTokens: 16384 }],
21
+ ["starcoder2", { contextWindow: 16384, maxTokens: 8192 }],
22
+ ["codegemma", { contextWindow: 8192, maxTokens: 8192 }],
23
+ ["codellama", { contextWindow: 16384, maxTokens: 8192 }],
24
+ ["devstral", { contextWindow: 131072, maxTokens: 32768 }],
25
+ // ─── Llama family ───────────────────────────────────────────────────
26
+ ["llama3.3", { contextWindow: 131072, maxTokens: 16384 }],
27
+ ["llama3.2", { contextWindow: 131072, maxTokens: 16384 }],
28
+ ["llama3.1", { contextWindow: 131072, maxTokens: 16384 }],
29
+ ["llama3", { contextWindow: 8192, maxTokens: 8192 }],
30
+ ["llama2", { contextWindow: 4096, maxTokens: 4096 }],
31
+ // ─── Qwen family ────────────────────────────────────────────────────
32
+ ["qwen3", { contextWindow: 131072, maxTokens: 32768 }],
33
+ ["qwen2.5", { contextWindow: 131072, maxTokens: 32768 }],
34
+ ["qwen2", { contextWindow: 131072, maxTokens: 32768 }],
35
+ // ─── Gemma family ───────────────────────────────────────────────────
36
+ ["gemma3", { contextWindow: 131072, maxTokens: 16384 }],
37
+ ["gemma2", { contextWindow: 8192, maxTokens: 8192 }],
38
+ // ─── Mistral family ─────────────────────────────────────────────────
39
+ ["mistral-large", { contextWindow: 131072, maxTokens: 16384 }],
40
+ ["mistral-small", { contextWindow: 131072, maxTokens: 16384 }],
41
+ ["mistral-nemo", { contextWindow: 131072, maxTokens: 16384 }],
42
+ ["mistral", { contextWindow: 32768, maxTokens: 8192 }],
43
+ ["mixtral", { contextWindow: 32768, maxTokens: 8192 }],
44
+ // ─── Phi family ─────────────────────────────────────────────────────
45
+ ["phi4", { contextWindow: 16384, maxTokens: 16384 }],
46
+ ["phi3.5", { contextWindow: 131072, maxTokens: 16384 }],
47
+ ["phi3", { contextWindow: 131072, maxTokens: 4096 }],
48
+ // ─── Command R ──────────────────────────────────────────────────────
49
+ ["command-r-plus", { contextWindow: 131072, maxTokens: 16384 }],
50
+ ["command-r", { contextWindow: 131072, maxTokens: 16384 }],
51
+ ];
52
+ /**
53
+ * Look up capabilities for a model by name.
54
+ * Matches the longest prefix from the known models table.
55
+ */
56
+ export function getModelCapabilities(modelName) {
57
+ // Strip tag (everything after the colon) for matching
58
+ const baseName = modelName.split(":")[0].toLowerCase();
59
+ for (const [pattern, caps] of KNOWN_MODELS) {
60
+ if (baseName === pattern || baseName.startsWith(pattern)) {
61
+ return caps;
62
+ }
63
+ }
64
+ return {};
65
+ }
66
+ /**
67
+ * Estimate context window from parameter size string (e.g. "7B", "70B", "1.5B").
68
+ * Used as fallback when model isn't in the known table.
69
+ */
70
+ export function estimateContextFromParams(parameterSize) {
71
+ const match = parameterSize.match(/([\d.]+)\s*([BbMm])/);
72
+ if (!match)
73
+ return 8192;
74
+ const size = parseFloat(match[1]);
75
+ const unit = match[2].toUpperCase();
76
+ // Convert to billions
77
+ const billions = unit === "M" ? size / 1000 : size;
78
+ // Rough heuristics: larger models tend to support larger contexts
79
+ if (billions >= 70)
80
+ return 131072;
81
+ if (billions >= 30)
82
+ return 65536;
83
+ if (billions >= 13)
84
+ return 32768;
85
+ if (billions >= 7)
86
+ return 16384;
87
+ return 8192;
88
+ }
89
+ /**
90
+ * Humanize a model name for display (e.g. "llama3.1:8b" → "Llama 3.1 8B").
91
+ */
92
+ export function humanizeModelName(modelName) {
93
+ const [base, tag] = modelName.split(":");
94
+ // Capitalize first letter, add spaces around version numbers
95
+ let name = base
96
+ .replace(/([a-z])(\d)/g, "$1 $2")
97
+ .replace(/(\d)([a-z])/g, "$1 $2")
98
+ .replace(/^./, (c) => c.toUpperCase());
99
+ // Clean up common patterns
100
+ name = name.replace(/\s*-\s*/g, " ");
101
+ if (tag && tag !== "latest") {
102
+ name += ` ${tag.toUpperCase()}`;
103
+ }
104
+ return name;
105
+ }
106
+ /**
107
+ * Format byte size for display (e.g. 4700000000 → "4.7 GB").
108
+ */
109
+ export function formatModelSize(bytes) {
110
+ if (bytes >= 1e9)
111
+ return `${(bytes / 1e9).toFixed(1)} GB`;
112
+ if (bytes >= 1e6)
113
+ return `${(bytes / 1e6).toFixed(1)} MB`;
114
+ return `${(bytes / 1e3).toFixed(0)} KB`;
115
+ }
@@ -0,0 +1,168 @@
1
+ // GSD2 — HTTP client for Ollama REST API
2
+ const DEFAULT_HOST = "http://localhost:11434";
3
+ const PROBE_TIMEOUT_MS = 1500;
4
+ const REQUEST_TIMEOUT_MS = 10000;
5
+ /**
6
+ * Get the Ollama host URL from OLLAMA_HOST or default.
7
+ */
8
+ export function getOllamaHost() {
9
+ const host = process.env.OLLAMA_HOST;
10
+ if (!host)
11
+ return DEFAULT_HOST;
12
+ // OLLAMA_HOST can be just a host:port without scheme
13
+ if (host.startsWith("http://") || host.startsWith("https://"))
14
+ return host;
15
+ return `http://${host}`;
16
+ }
17
+ async function fetchWithTimeout(url, options = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
18
+ const controller = new AbortController();
19
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
20
+ try {
21
+ return await fetch(url, { ...options, signal: controller.signal });
22
+ }
23
+ finally {
24
+ clearTimeout(timeout);
25
+ }
26
+ }
27
+ /**
28
+ * Check if Ollama is running and reachable.
29
+ */
30
+ export async function isRunning() {
31
+ try {
32
+ const response = await fetchWithTimeout(`${getOllamaHost()}/`, {}, PROBE_TIMEOUT_MS);
33
+ return response.ok;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ /**
40
+ * Get Ollama version.
41
+ */
42
+ export async function getVersion() {
43
+ try {
44
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/version`);
45
+ if (!response.ok)
46
+ return null;
47
+ const data = (await response.json());
48
+ return data.version;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ /**
55
+ * List all locally available models.
56
+ */
57
+ export async function listModels() {
58
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/tags`);
59
+ if (!response.ok) {
60
+ throw new Error(`Ollama /api/tags returned ${response.status}: ${response.statusText}`);
61
+ }
62
+ return (await response.json());
63
+ }
64
+ /**
65
+ * Get detailed information about a specific model.
66
+ */
67
+ export async function showModel(name) {
68
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/show`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ name }),
72
+ });
73
+ if (!response.ok) {
74
+ throw new Error(`Ollama /api/show returned ${response.status}: ${response.statusText}`);
75
+ }
76
+ return (await response.json());
77
+ }
78
+ /**
79
+ * List currently loaded/running models.
80
+ */
81
+ export async function getRunningModels() {
82
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/ps`);
83
+ if (!response.ok) {
84
+ throw new Error(`Ollama /api/ps returned ${response.status}: ${response.statusText}`);
85
+ }
86
+ return (await response.json());
87
+ }
88
+ /**
89
+ * Pull a model with streaming progress.
90
+ * Calls onProgress for each progress update.
91
+ * Returns when the pull is complete.
92
+ */
93
+ export async function pullModel(name, onProgress, signal) {
94
+ const response = await fetch(`${getOllamaHost()}/api/pull`, {
95
+ method: "POST",
96
+ headers: { "Content-Type": "application/json" },
97
+ body: JSON.stringify({ name, stream: true }),
98
+ signal,
99
+ });
100
+ if (!response.ok) {
101
+ const text = await response.text();
102
+ throw new Error(`Ollama /api/pull returned ${response.status}: ${text}`);
103
+ }
104
+ if (!response.body) {
105
+ throw new Error("Ollama /api/pull returned no body");
106
+ }
107
+ const reader = response.body.getReader();
108
+ const decoder = new TextDecoder();
109
+ let buffer = "";
110
+ while (true) {
111
+ const { done, value } = await reader.read();
112
+ if (done)
113
+ break;
114
+ buffer += decoder.decode(value, { stream: true });
115
+ const lines = buffer.split("\n");
116
+ buffer = lines.pop() ?? "";
117
+ for (const line of lines) {
118
+ const trimmed = line.trim();
119
+ if (!trimmed)
120
+ continue;
121
+ try {
122
+ const progress = JSON.parse(trimmed);
123
+ onProgress?.(progress);
124
+ }
125
+ catch {
126
+ // Skip malformed lines
127
+ }
128
+ }
129
+ }
130
+ // Process remaining buffer
131
+ if (buffer.trim()) {
132
+ try {
133
+ const progress = JSON.parse(buffer.trim());
134
+ onProgress?.(progress);
135
+ }
136
+ catch {
137
+ // Ignore
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Delete a local model.
143
+ */
144
+ export async function deleteModel(name) {
145
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/delete`, {
146
+ method: "DELETE",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: JSON.stringify({ name }),
149
+ });
150
+ if (!response.ok) {
151
+ const text = await response.text();
152
+ throw new Error(`Ollama /api/delete returned ${response.status}: ${text}`);
153
+ }
154
+ }
155
+ /**
156
+ * Copy a model to a new name.
157
+ */
158
+ export async function copyModel(source, destination) {
159
+ const response = await fetchWithTimeout(`${getOllamaHost()}/api/copy`, {
160
+ method: "POST",
161
+ headers: { "Content-Type": "application/json" },
162
+ body: JSON.stringify({ source, destination }),
163
+ });
164
+ if (!response.ok) {
165
+ const text = await response.text();
166
+ throw new Error(`Ollama /api/copy returned ${response.status}: ${text}`);
167
+ }
168
+ }
@@ -0,0 +1,194 @@
1
+ // GSD2 — Ollama slash commands
2
+ import { Text } from "@gsd/pi-tui";
3
+ import * as client from "./ollama-client.js";
4
+ import { discoverModels, formatModelForDisplay } from "./ollama-discovery.js";
5
+ import { formatModelSize } from "./model-capabilities.js";
6
+ export function registerOllamaCommands(pi) {
7
+ pi.registerCommand("ollama", {
8
+ description: "Manage local Ollama models — list | pull | remove | ps",
9
+ async handler(args, ctx) {
10
+ const parts = (args ?? "").trim().split(/\s+/);
11
+ const subcommand = parts[0] || "status";
12
+ const modelArg = parts.slice(1).join(" ");
13
+ switch (subcommand) {
14
+ case "status":
15
+ return await handleStatus(ctx);
16
+ case "list":
17
+ case "ls":
18
+ return await handleList(ctx);
19
+ case "pull":
20
+ return await handlePull(modelArg, ctx);
21
+ case "remove":
22
+ case "rm":
23
+ case "delete":
24
+ return await handleRemove(modelArg, ctx);
25
+ case "ps":
26
+ return await handlePs(ctx);
27
+ default:
28
+ ctx.ui.notify(`Unknown subcommand: ${subcommand}. Use: status, list, pull, remove, ps`, "warning");
29
+ }
30
+ },
31
+ });
32
+ }
33
+ async function handleStatus(ctx) {
34
+ const running = await client.isRunning();
35
+ if (!running) {
36
+ ctx.ui.notify("Ollama is not running. Install from https://ollama.com and run 'ollama serve'", "warning");
37
+ return;
38
+ }
39
+ const version = await client.getVersion();
40
+ const lines = [];
41
+ lines.push(`Ollama${version ? ` v${version}` : ""} — running (${client.getOllamaHost()})`);
42
+ // Show loaded models
43
+ try {
44
+ const ps = await client.getRunningModels();
45
+ if (ps.models && ps.models.length > 0) {
46
+ lines.push("");
47
+ lines.push("Loaded:");
48
+ for (const m of ps.models) {
49
+ const vram = m.size_vram > 0 ? formatModelSize(m.size_vram) + " VRAM" : "CPU";
50
+ const expiresAt = new Date(m.expires_at);
51
+ const idleMs = expiresAt.getTime() - Date.now();
52
+ const idleMin = Math.max(0, Math.floor(idleMs / 60000));
53
+ lines.push(` ${m.name} ${vram} expires in ${idleMin}m`);
54
+ }
55
+ }
56
+ }
57
+ catch {
58
+ // ps endpoint may not be available on older versions
59
+ }
60
+ // Show available models
61
+ try {
62
+ const models = await discoverModels();
63
+ if (models.length > 0) {
64
+ lines.push("");
65
+ lines.push("Available:");
66
+ for (const m of models) {
67
+ lines.push(` ${formatModelForDisplay(m)}`);
68
+ }
69
+ }
70
+ else {
71
+ lines.push("");
72
+ lines.push("No models pulled. Use /ollama pull <model> to get started.");
73
+ }
74
+ }
75
+ catch (err) {
76
+ lines.push("");
77
+ lines.push(`Error listing models: ${err instanceof Error ? err.message : String(err)}`);
78
+ }
79
+ await ctx.ui.custom((tui, theme, _kb, done) => {
80
+ const text = new Text(lines.map((l) => theme.fg("fg", l)).join("\n"), 0, 0);
81
+ setTimeout(() => done(undefined), 0);
82
+ return text;
83
+ });
84
+ }
85
+ async function handleList(ctx) {
86
+ const running = await client.isRunning();
87
+ if (!running) {
88
+ ctx.ui.notify("Ollama is not running", "warning");
89
+ return;
90
+ }
91
+ const models = await discoverModels();
92
+ if (models.length === 0) {
93
+ ctx.ui.notify("No models available. Use /ollama pull <model> to download one.", "info");
94
+ return;
95
+ }
96
+ const lines = ["Local Ollama models:", ""];
97
+ for (const m of models) {
98
+ lines.push(` ${formatModelForDisplay(m)}`);
99
+ }
100
+ await ctx.ui.custom((tui, theme, _kb, done) => {
101
+ const text = new Text(lines.map((l) => theme.fg("fg", l)).join("\n"), 0, 0);
102
+ setTimeout(() => done(undefined), 0);
103
+ return text;
104
+ });
105
+ }
106
+ async function handlePull(modelName, ctx) {
107
+ if (!modelName) {
108
+ ctx.ui.notify("Usage: /ollama pull <model> (e.g. /ollama pull llama3.1:8b)", "warning");
109
+ return;
110
+ }
111
+ const running = await client.isRunning();
112
+ if (!running) {
113
+ ctx.ui.notify("Ollama is not running", "warning");
114
+ return;
115
+ }
116
+ ctx.ui.setWidget("ollama-pull", [`Pulling ${modelName}...`]);
117
+ try {
118
+ let lastPercent = -1;
119
+ await client.pullModel(modelName, (progress) => {
120
+ if (progress.total && progress.completed) {
121
+ const percent = Math.floor((progress.completed / progress.total) * 100);
122
+ if (percent !== lastPercent) {
123
+ lastPercent = percent;
124
+ const completed = formatModelSize(progress.completed);
125
+ const total = formatModelSize(progress.total);
126
+ ctx.ui.setWidget("ollama-pull", [
127
+ `Pulling ${modelName}... ${percent}% (${completed} / ${total})`,
128
+ ]);
129
+ }
130
+ }
131
+ else if (progress.status) {
132
+ ctx.ui.setWidget("ollama-pull", [`${modelName}: ${progress.status}`]);
133
+ }
134
+ });
135
+ ctx.ui.setWidget("ollama-pull", undefined);
136
+ ctx.ui.notify(`${modelName} pulled successfully`, "success");
137
+ }
138
+ catch (err) {
139
+ ctx.ui.setWidget("ollama-pull", undefined);
140
+ ctx.ui.notify(`Failed to pull ${modelName}: ${err instanceof Error ? err.message : String(err)}`, "error");
141
+ }
142
+ }
143
+ async function handleRemove(modelName, ctx) {
144
+ if (!modelName) {
145
+ ctx.ui.notify("Usage: /ollama remove <model>", "warning");
146
+ return;
147
+ }
148
+ const running = await client.isRunning();
149
+ if (!running) {
150
+ ctx.ui.notify("Ollama is not running", "warning");
151
+ return;
152
+ }
153
+ const confirmed = await ctx.ui.confirm("Delete model", `Are you sure you want to delete ${modelName}?`);
154
+ if (!confirmed)
155
+ return;
156
+ try {
157
+ await client.deleteModel(modelName);
158
+ ctx.ui.notify(`${modelName} deleted`, "success");
159
+ }
160
+ catch (err) {
161
+ ctx.ui.notify(`Failed to delete ${modelName}: ${err instanceof Error ? err.message : String(err)}`, "error");
162
+ }
163
+ }
164
+ async function handlePs(ctx) {
165
+ const running = await client.isRunning();
166
+ if (!running) {
167
+ ctx.ui.notify("Ollama is not running", "warning");
168
+ return;
169
+ }
170
+ try {
171
+ const ps = await client.getRunningModels();
172
+ if (!ps.models || ps.models.length === 0) {
173
+ ctx.ui.notify("No models currently loaded in memory", "info");
174
+ return;
175
+ }
176
+ const lines = ["Running models:", ""];
177
+ for (const m of ps.models) {
178
+ const vram = m.size_vram > 0 ? formatModelSize(m.size_vram) + " VRAM" : "CPU only";
179
+ const totalSize = formatModelSize(m.size);
180
+ const expiresAt = new Date(m.expires_at);
181
+ const idleMs = expiresAt.getTime() - Date.now();
182
+ const idleMin = Math.max(0, Math.floor(idleMs / 60000));
183
+ lines.push(` ${m.name} ${totalSize} ${vram} expires in ${idleMin}m`);
184
+ }
185
+ await ctx.ui.custom((tui, theme, _kb, done) => {
186
+ const text = new Text(lines.map((l) => theme.fg("fg", l)).join("\n"), 0, 0);
187
+ setTimeout(() => done(undefined), 0);
188
+ return text;
189
+ });
190
+ }
191
+ catch (err) {
192
+ ctx.ui.notify(`Failed to get running models: ${err instanceof Error ? err.message : String(err)}`, "error");
193
+ }
194
+ }
@@ -0,0 +1,69 @@
1
+ // GSD2 — Ollama model discovery and capability detection
2
+ /**
3
+ * Discovers locally available Ollama models and enriches them with
4
+ * capability metadata (context window, vision, reasoning) from the
5
+ * known model table and /api/show responses.
6
+ *
7
+ * Returns models in the format expected by pi.registerProvider().
8
+ */
9
+ import { listModels, getOllamaHost } from "./ollama-client.js";
10
+ import { estimateContextFromParams, formatModelSize, getModelCapabilities, humanizeModelName, } from "./model-capabilities.js";
11
+ const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
12
+ function enrichModel(info) {
13
+ const caps = getModelCapabilities(info.name);
14
+ const parameterSize = info.details?.parameter_size ?? "";
15
+ // Determine context window: known table > estimate from param size > default
16
+ const contextWindow = caps.contextWindow ??
17
+ (parameterSize ? estimateContextFromParams(parameterSize) : 8192);
18
+ // Determine max tokens: known table > fraction of context > default
19
+ const maxTokens = caps.maxTokens ?? Math.min(Math.floor(contextWindow / 4), 16384);
20
+ // Detect vision from families or known table
21
+ const hasVision = caps.input?.includes("image") ??
22
+ (info.details?.families?.some((f) => f === "clip" || f === "mllama") ?? false);
23
+ // Detect reasoning from known table
24
+ const reasoning = caps.reasoning ?? false;
25
+ return {
26
+ id: info.name,
27
+ name: humanizeModelName(info.name),
28
+ reasoning,
29
+ input: hasVision ? ["text", "image"] : ["text"],
30
+ cost: ZERO_COST,
31
+ contextWindow,
32
+ maxTokens,
33
+ sizeBytes: info.size,
34
+ parameterSize,
35
+ };
36
+ }
37
+ /**
38
+ * Discover all locally available Ollama models with enriched capabilities.
39
+ */
40
+ export async function discoverModels() {
41
+ const tags = await listModels();
42
+ if (!tags.models || tags.models.length === 0)
43
+ return [];
44
+ return tags.models.map(enrichModel);
45
+ }
46
+ /**
47
+ * Format a discovered model for display in model list.
48
+ */
49
+ export function formatModelForDisplay(model) {
50
+ const parts = [model.id];
51
+ if (model.sizeBytes > 0) {
52
+ parts.push(`(${formatModelSize(model.sizeBytes)})`);
53
+ }
54
+ const flags = [];
55
+ if (model.reasoning)
56
+ flags.push("reasoning");
57
+ if (model.input.includes("image"))
58
+ flags.push("vision");
59
+ if (flags.length > 0) {
60
+ parts.push(`[${flags.join(", ")}]`);
61
+ }
62
+ return parts.join(" ");
63
+ }
64
+ /**
65
+ * Build the OpenAI-compat base URL for Ollama.
66
+ */
67
+ export function getOllamaOpenAIBaseUrl() {
68
+ return `${getOllamaHost()}/v1`;
69
+ }