gsd-pi 2.44.0-dev.d25d507 → 2.45.0-dev.1afbdaa

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 (407) hide show
  1. package/dist/help-text.js +1 -1
  2. package/dist/loader.js +34 -0
  3. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  4. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  5. package/dist/resources/extensions/gsd/auto/phases.js +63 -77
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  7. package/dist/resources/extensions/gsd/auto/session.js +0 -11
  8. package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
  9. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
  10. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  11. package/dist/resources/extensions/gsd/auto-start.js +23 -5
  12. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  13. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  14. package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
  15. package/dist/resources/extensions/gsd/auto.js +42 -60
  16. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +170 -11
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
  18. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  19. package/dist/resources/extensions/gsd/commands/context.js +0 -4
  20. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  21. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  22. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
  23. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  24. package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
  25. package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
  26. package/dist/resources/extensions/gsd/db-writer.js +40 -22
  27. package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
  28. package/dist/resources/extensions/gsd/doctor.js +13 -3
  29. package/dist/resources/extensions/gsd/git-service.js +8 -3
  30. package/dist/resources/extensions/gsd/gsd-db.js +28 -4
  31. package/dist/resources/extensions/gsd/guided-flow.js +1 -2
  32. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  33. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  34. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
  35. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  36. package/dist/resources/extensions/gsd/preferences.js +8 -4
  37. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  38. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  39. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  40. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  42. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  43. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  47. package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
  48. package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
  49. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  50. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  51. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  52. package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/rethink.md +83 -0
  54. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  56. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  57. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  58. package/dist/resources/extensions/gsd/rethink.js +115 -0
  59. package/dist/resources/extensions/gsd/session-lock.js +1 -3
  60. package/dist/resources/extensions/gsd/state.js +48 -3
  61. package/dist/resources/extensions/gsd/sync-lock.js +89 -0
  62. package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
  63. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
  64. package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
  65. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
  66. package/dist/resources/extensions/gsd/tools/plan-slice.js +31 -1
  67. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -1
  68. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
  69. package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
  70. package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
  71. package/dist/resources/extensions/gsd/tools/replan-slice.js +34 -2
  72. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  73. package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
  74. package/dist/resources/extensions/gsd/workflow-events.js +102 -0
  75. package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
  76. package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
  77. package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
  78. package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
  79. package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
  80. package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
  81. package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
  82. package/dist/resources/extensions/gsd/write-intercept.js +84 -0
  83. package/dist/resources/extensions/mcp-client/index.js +14 -0
  84. package/dist/resources/extensions/voice/index.js +11 -16
  85. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  88. package/dist/web/standalone/.next/build-manifest.json +3 -3
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  91. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found/page.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/index.html +1 -1
  151. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  152. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  153. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  154. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  156. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  157. package/dist/web/standalone/.next/server/app/page.js +1 -1
  158. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  160. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  163. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  164. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  165. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  166. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  167. package/dist/web/standalone/.next/static/chunks/app/{page-b9367c5ae13b99c6.js → page-6654a8cca61a3d1c.js} +1 -1
  168. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  169. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  170. package/package.json +2 -1
  171. package/packages/native/dist/stream-process/index.js +2 -2
  172. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  173. package/packages/native/src/stream-process/index.ts +2 -2
  174. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  175. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  177. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  180. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  182. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  185. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  191. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  193. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  195. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  196. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  197. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
  199. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  201. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  205. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  207. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/main.js +17 -0
  210. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  222. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  226. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  227. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  234. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  236. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  237. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  238. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  239. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  240. package/packages/pi-coding-agent/package.json +1 -1
  241. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  242. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  243. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  244. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  245. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  246. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  247. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  248. package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
  249. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  250. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  251. package/packages/pi-coding-agent/src/main.ts +19 -0
  252. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  253. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  254. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  255. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  256. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  257. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  258. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  259. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  262. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  263. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
  264. package/src/resources/extensions/gsd/auto/phases.ts +69 -91
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  266. package/src/resources/extensions/gsd/auto/session.ts +0 -18
  267. package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
  268. package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
  269. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
  270. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  271. package/src/resources/extensions/gsd/auto-start.ts +26 -5
  272. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  273. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  274. package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
  275. package/src/resources/extensions/gsd/auto.ts +44 -86
  276. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +162 -11
  277. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  278. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  279. package/src/resources/extensions/gsd/commands/context.ts +0 -5
  280. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  281. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  282. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
  283. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  284. package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
  285. package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
  286. package/src/resources/extensions/gsd/db-writer.ts +41 -27
  287. package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
  288. package/src/resources/extensions/gsd/doctor-types.ts +7 -1
  289. package/src/resources/extensions/gsd/doctor.ts +13 -4
  290. package/src/resources/extensions/gsd/git-service.ts +6 -2
  291. package/src/resources/extensions/gsd/gsd-db.ts +32 -4
  292. package/src/resources/extensions/gsd/guided-flow.ts +1 -2
  293. package/src/resources/extensions/gsd/journal.ts +6 -1
  294. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  295. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  296. package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
  297. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  298. package/src/resources/extensions/gsd/preferences.ts +7 -3
  299. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  300. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  301. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  302. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
  303. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  304. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  305. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  306. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  307. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  308. package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  309. package/src/resources/extensions/gsd/prompts/queue.md +2 -2
  310. package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
  311. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  313. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  314. package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
  315. package/src/resources/extensions/gsd/prompts/rethink.md +83 -0
  316. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  318. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  319. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  320. package/src/resources/extensions/gsd/rethink.ts +154 -0
  321. package/src/resources/extensions/gsd/session-lock.ts +0 -4
  322. package/src/resources/extensions/gsd/state.ts +49 -1
  323. package/src/resources/extensions/gsd/sync-lock.ts +94 -0
  324. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
  325. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
  326. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  327. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
  328. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
  329. package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
  330. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  331. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
  332. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
  333. package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
  334. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  335. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +60 -0
  336. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  337. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  338. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
  339. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  340. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  341. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
  342. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  343. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  344. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  345. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  346. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  347. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
  348. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
  349. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
  350. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
  351. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
  352. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
  353. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
  354. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
  355. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  356. package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
  357. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
  358. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +26 -21
  359. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  360. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  361. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  362. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
  363. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  364. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
  365. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  366. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
  367. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  368. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  369. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
  370. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  371. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  372. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
  373. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
  374. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  375. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  376. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  377. package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
  378. package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
  379. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
  380. package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
  381. package/src/resources/extensions/gsd/tools/plan-slice.ts +40 -0
  382. package/src/resources/extensions/gsd/tools/plan-task.ts +37 -1
  383. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
  384. package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
  385. package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
  386. package/src/resources/extensions/gsd/tools/replan-slice.ts +41 -1
  387. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  388. package/src/resources/extensions/gsd/types.ts +8 -0
  389. package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
  390. package/src/resources/extensions/gsd/workflow-events.ts +154 -0
  391. package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
  392. package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
  393. package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
  394. package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
  395. package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
  396. package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
  397. package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
  398. package/src/resources/extensions/gsd/write-intercept.ts +90 -0
  399. package/src/resources/extensions/mcp-client/index.ts +20 -0
  400. package/src/resources/extensions/voice/index.ts +11 -21
  401. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  402. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  403. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  404. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  405. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  406. /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_buildManifest.js +0 -0
  407. /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-coding-agent",
3
- "version": "2.44.0",
3
+ "version": "2.45.0",
4
4
  "description": "Coding agent CLI (vendored from pi-mono)",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -744,7 +744,21 @@ export class AuthStorage {
744
744
  * @param providerId - The provider to get an API key for
745
745
  * @param sessionId - Optional session ID for sticky credential selection
746
746
  */
747
- async getApiKey(providerId: string, sessionId?: string): Promise<string | undefined> {
747
+ async getApiKey(providerId: string, sessionId?: string, options?: { baseUrl?: string }): Promise<string | undefined> {
748
+ // If the model has a local baseUrl, return a dummy key to avoid auth blocking
749
+ if (options?.baseUrl) {
750
+ try {
751
+ const hostname = new URL(options.baseUrl).hostname;
752
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
753
+ return "local-no-key-needed";
754
+ }
755
+ } catch {
756
+ if (options.baseUrl.startsWith("unix:")) {
757
+ return "local-no-key-needed";
758
+ }
759
+ }
760
+ }
761
+
748
762
  // Runtime override takes highest priority
749
763
  const runtimeKey = this.runtimeOverrides.get(providerId);
750
764
  if (runtimeKey) {
@@ -97,6 +97,7 @@ export class CompactionOrchestrator {
97
97
  if (!this._deps.modelRegistry.isProviderRequestReady(model.provider)) {
98
98
  throw new Error(`No API key for ${model.provider}`);
99
99
  }
100
+ // undefined for externalCli/none providers — stripped at the streamSimple boundary (model-registry.ts)
100
101
  const apiKey = await this._deps.modelRegistry.getApiKey(model, this._deps.getSessionId());
101
102
 
102
103
  const pathEntries = this._deps.sessionManager.getBranch();
@@ -303,6 +304,7 @@ export class CompactionOrchestrator {
303
304
  this._deps.emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
304
305
  return;
305
306
  }
307
+ // undefined for externalCli/none providers — stripped at the streamSimple boundary (model-registry.ts)
306
308
  const apiKey = await this._deps.modelRegistry.getApiKey(model, this._deps.getSessionId());
307
309
 
308
310
  const pathEntries = this._deps.sessionManager.getBranch();
@@ -1242,7 +1242,8 @@ export interface ExtensionAPI {
1242
1242
  export interface ProviderConfig {
1243
1243
  /** Auth behavior for provider availability and request key handling. Defaults to "apiKey". */
1244
1244
  authMode?: "apiKey" | "oauth" | "externalCli" | "none";
1245
- /** Optional readiness check. Return false if the provider cannot accept requests (e.g., CLI not authenticated, API key invalid). Called before default auth checks. */
1245
+ /** Optional readiness check. Return false if the provider cannot accept requests (e.g., CLI not authenticated, API key invalid).
1246
+ * Called before default auth checks. Trusted at the same level as extension code — extensions already have arbitrary code execution. */
1246
1247
  isReady?: () => boolean;
1247
1248
  /** Base URL for the API endpoint. Required when defining models. */
1248
1249
  baseUrl?: string;
@@ -0,0 +1,227 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync } from "node:fs";
3
+ import { homedir, tmpdir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+ import { describe, it } from "node:test";
6
+ import {
7
+ readManifestRuntimeDeps,
8
+ collectRuntimeDependencies,
9
+ verifyRuntimeDependencies,
10
+ resolveLocalSourcePath,
11
+ } from "./lifecycle-hooks.js";
12
+
13
+ function tmpDir(prefix: string, t: { after: (fn: () => void) => void }): string {
14
+ const dir = mkdtempSync(join(tmpdir(), `pi-lh-${prefix}-`));
15
+ t.after(() => rmSync(dir, { recursive: true, force: true }));
16
+ return dir;
17
+ }
18
+
19
+ // ─── readManifestRuntimeDeps ──────────────────────────────────────────────────
20
+
21
+ describe("readManifestRuntimeDeps", () => {
22
+ it("returns empty array when manifest file is missing", (t) => {
23
+ const dir = tmpDir("no-manifest", t);
24
+ assert.deepEqual(readManifestRuntimeDeps(dir), []);
25
+ });
26
+
27
+ it("returns empty array for malformed JSON", (t) => {
28
+ const dir = tmpDir("bad-json", t);
29
+ writeFileSync(join(dir, "extension-manifest.json"), "not json{{{", "utf-8");
30
+ assert.deepEqual(readManifestRuntimeDeps(dir), []);
31
+ });
32
+
33
+ it("returns runtime deps from valid manifest", (t) => {
34
+ const dir = tmpDir("valid", t);
35
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
36
+ dependencies: { runtime: ["claude", "node"] },
37
+ }), "utf-8");
38
+ assert.deepEqual(readManifestRuntimeDeps(dir), ["claude", "node"]);
39
+ });
40
+
41
+ it("returns empty array when dependencies exists but runtime is missing", (t) => {
42
+ const dir = tmpDir("no-runtime", t);
43
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
44
+ dependencies: {},
45
+ }), "utf-8");
46
+ assert.deepEqual(readManifestRuntimeDeps(dir), []);
47
+ });
48
+
49
+ it("returns empty array when runtime is empty", (t) => {
50
+ const dir = tmpDir("empty-runtime", t);
51
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
52
+ dependencies: { runtime: [] },
53
+ }), "utf-8");
54
+ assert.deepEqual(readManifestRuntimeDeps(dir), []);
55
+ });
56
+
57
+ it("filters out non-string entries in runtime array", (t) => {
58
+ const dir = tmpDir("mixed-types", t);
59
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
60
+ dependencies: { runtime: [123, null, "node", false, "python"] },
61
+ }), "utf-8");
62
+ assert.deepEqual(readManifestRuntimeDeps(dir), ["node", "python"]);
63
+ });
64
+
65
+ it("returns empty array when no dependencies field at all", (t) => {
66
+ const dir = tmpDir("no-deps-field", t);
67
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
68
+ id: "test",
69
+ name: "Test",
70
+ }), "utf-8");
71
+ assert.deepEqual(readManifestRuntimeDeps(dir), []);
72
+ });
73
+ });
74
+
75
+ // ─── collectRuntimeDependencies ───────────────────────────────────────────────
76
+
77
+ describe("collectRuntimeDependencies", () => {
78
+ it("aggregates deps from installedPath manifest", (t) => {
79
+ const dir = tmpDir("collect-installed", t);
80
+ writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
81
+ dependencies: { runtime: ["claude"] },
82
+ }), "utf-8");
83
+ assert.deepEqual(collectRuntimeDependencies(dir, []), ["claude"]);
84
+ });
85
+
86
+ it("aggregates deps from entry path directory manifests", (t) => {
87
+ const root = tmpDir("collect-entry", t);
88
+ const installedDir = join(root, "installed");
89
+ const entryDir = join(root, "entry");
90
+ mkdirSync(installedDir, { recursive: true });
91
+ mkdirSync(entryDir, { recursive: true });
92
+ writeFileSync(join(entryDir, "extension-manifest.json"), JSON.stringify({
93
+ dependencies: { runtime: ["python"] },
94
+ }), "utf-8");
95
+ const deps = collectRuntimeDependencies(installedDir, [join(entryDir, "index.ts")]);
96
+ assert.deepEqual(deps, ["python"]);
97
+ });
98
+
99
+ it("deduplicates across multiple directories", (t) => {
100
+ const root = tmpDir("collect-dedup", t);
101
+ const dir1 = join(root, "dir1");
102
+ const dir2 = join(root, "dir2");
103
+ mkdirSync(dir1, { recursive: true });
104
+ mkdirSync(dir2, { recursive: true });
105
+ writeFileSync(join(dir1, "extension-manifest.json"), JSON.stringify({
106
+ dependencies: { runtime: ["node", "python"] },
107
+ }), "utf-8");
108
+ writeFileSync(join(dir2, "extension-manifest.json"), JSON.stringify({
109
+ dependencies: { runtime: ["python", "claude"] },
110
+ }), "utf-8");
111
+ const deps = collectRuntimeDependencies(dir1, [join(dir2, "index.ts")]);
112
+ assert.equal(deps.length, 3);
113
+ assert.ok(deps.includes("node"));
114
+ assert.ok(deps.includes("python"));
115
+ assert.ok(deps.includes("claude"));
116
+ });
117
+
118
+ it("returns empty when no directories have manifests", (t) => {
119
+ const dir = tmpDir("collect-empty", t);
120
+ assert.deepEqual(collectRuntimeDependencies(dir, []), []);
121
+ });
122
+ });
123
+
124
+ // ─── verifyRuntimeDependencies ────────────────────────────────────────────────
125
+
126
+ describe("verifyRuntimeDependencies", () => {
127
+ it("does not throw for empty deps array", () => {
128
+ assert.doesNotThrow(() => verifyRuntimeDependencies([], "test-source", "pi"));
129
+ });
130
+
131
+ it("does not throw when all deps are present", () => {
132
+ assert.doesNotThrow(() => verifyRuntimeDependencies(["node"], "test-source", "pi"));
133
+ });
134
+
135
+ it("throws for missing dep with 'Missing runtime dependencies' message", () => {
136
+ assert.throws(
137
+ () => verifyRuntimeDependencies(["__nonexistent_dep_for_test__"], "test-source", "pi"),
138
+ (err: Error) => {
139
+ assert.ok(err.message.includes("Missing runtime dependencies"));
140
+ assert.ok(err.message.includes("__nonexistent_dep_for_test__"));
141
+ return true;
142
+ },
143
+ );
144
+ });
145
+
146
+ it("lists all missing deps in error message", () => {
147
+ assert.throws(
148
+ () => verifyRuntimeDependencies(["__missing_1__", "__missing_2__"], "test-source", "pi"),
149
+ (err: Error) => {
150
+ assert.ok(err.message.includes("__missing_1__"));
151
+ assert.ok(err.message.includes("__missing_2__"));
152
+ return true;
153
+ },
154
+ );
155
+ });
156
+
157
+ it("includes appName and source in error for retry hint", () => {
158
+ assert.throws(
159
+ () => verifyRuntimeDependencies(["__missing__"], "github:user/repo", "gsd"),
160
+ (err: Error) => {
161
+ assert.ok(err.message.includes("gsd"));
162
+ assert.ok(err.message.includes("github:user/repo"));
163
+ return true;
164
+ },
165
+ );
166
+ });
167
+ });
168
+
169
+ // ─── resolveLocalSourcePath ───────────────────────────────────────────────────
170
+
171
+ describe("resolveLocalSourcePath", () => {
172
+ it("returns undefined for empty string", () => {
173
+ assert.equal(resolveLocalSourcePath("", "/tmp"), undefined);
174
+ });
175
+
176
+ it("returns undefined for npm: source", () => {
177
+ assert.equal(resolveLocalSourcePath("npm:@foo/bar", "/tmp"), undefined);
178
+ });
179
+
180
+ it("returns undefined for git URL", () => {
181
+ assert.equal(resolveLocalSourcePath("git:github.com/user/repo", "/tmp"), undefined);
182
+ });
183
+
184
+ it("returns undefined for https git URL", () => {
185
+ assert.equal(resolveLocalSourcePath("https://github.com/user/repo", "/tmp"), undefined);
186
+ });
187
+
188
+ it("resolves ~ to homedir", () => {
189
+ const result = resolveLocalSourcePath("~", "/tmp");
190
+ if (existsSync(homedir())) {
191
+ assert.equal(result, homedir());
192
+ } else {
193
+ assert.equal(result, undefined);
194
+ }
195
+ });
196
+
197
+ it("resolves ~/path relative to homedir", () => {
198
+ const result = resolveLocalSourcePath("~/", "/tmp");
199
+ if (existsSync(homedir())) {
200
+ assert.equal(result, homedir());
201
+ } else {
202
+ assert.equal(result, undefined);
203
+ }
204
+ });
205
+
206
+ it("resolves relative path that exists", (t) => {
207
+ const dir = tmpDir("resolve-rel", t);
208
+ const sub = join(dir, "myext");
209
+ mkdirSync(sub, { recursive: true });
210
+ const result = resolveLocalSourcePath("myext", dir);
211
+ assert.equal(result, resolve(dir, "myext"));
212
+ });
213
+
214
+ it("returns undefined for relative path that does not exist", (t) => {
215
+ const dir = tmpDir("resolve-noexist", t);
216
+ assert.equal(resolveLocalSourcePath("nonexistent", dir), undefined);
217
+ });
218
+
219
+ it("resolves absolute path that exists", (t) => {
220
+ const dir = tmpDir("resolve-abs", t);
221
+ assert.equal(resolveLocalSourcePath(dir, "/irrelevant"), dir);
222
+ });
223
+
224
+ it("returns undefined for absolute path that does not exist", () => {
225
+ assert.equal(resolveLocalSourcePath("/tmp/__nonexistent_path_for_test__", "/tmp"), undefined);
226
+ });
227
+ });
@@ -62,7 +62,7 @@ function toScope(local: boolean): LifecycleHookScope {
62
62
  return local ? "project" : "user";
63
63
  }
64
64
 
65
- function readManifestRuntimeDeps(dir: string): string[] {
65
+ export function readManifestRuntimeDeps(dir: string): string[] {
66
66
  const manifestPath = join(dir, "extension-manifest.json");
67
67
  if (!existsSync(manifestPath)) return [];
68
68
  try {
@@ -73,7 +73,7 @@ function readManifestRuntimeDeps(dir: string): string[] {
73
73
  }
74
74
  }
75
75
 
76
- function collectRuntimeDependencies(installedPath: string, entryPaths: string[]): string[] {
76
+ export function collectRuntimeDependencies(installedPath: string, entryPaths: string[]): string[] {
77
77
  const deps = new Set<string>();
78
78
  const candidateDirs = new Set<string>([installedPath, ...entryPaths.map((entryPath) => dirname(entryPath))]);
79
79
  for (const dir of candidateDirs) {
@@ -84,7 +84,7 @@ function collectRuntimeDependencies(installedPath: string, entryPaths: string[])
84
84
  return Array.from(deps);
85
85
  }
86
86
 
87
- function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appName: string): void {
87
+ export function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appName: string): void {
88
88
  const missing: string[] = [];
89
89
  for (const dep of runtimeDeps) {
90
90
  const result = spawnSync(dep, ["--version"], { encoding: "utf-8", timeout: 5000 });
@@ -99,7 +99,7 @@ function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appNam
99
99
  );
100
100
  }
101
101
 
102
- function resolveLocalSourcePath(source: string, cwd: string): string | undefined {
102
+ export function resolveLocalSourcePath(source: string, cwd: string): string | undefined {
103
103
  const trimmed = source.trim();
104
104
  if (!trimmed) return undefined;
105
105
  if (trimmed.startsWith("npm:")) return undefined;
@@ -193,13 +193,19 @@ function getLegacyExportCandidates(phase: LifecycleHookPhase): string[] {
193
193
  return [phase];
194
194
  }
195
195
 
196
+ const _legacyModuleCache = new Map<string, Record<string, unknown>>();
197
+
196
198
  async function runLegacyExportHook(
197
199
  entryPath: string,
198
200
  phase: LifecycleHookPhase,
199
201
  context: LifecycleHookContext,
200
202
  ): Promise<LifecycleHookHandler | null> {
201
203
  try {
202
- const module = await importExtensionModule<Record<string, unknown>>(import.meta.url, pathToFileURL(entryPath).href);
204
+ let module = _legacyModuleCache.get(entryPath);
205
+ if (!module) {
206
+ module = await importExtensionModule<Record<string, unknown>>(import.meta.url, pathToFileURL(entryPath).href);
207
+ _legacyModuleCache.set(entryPath, module);
208
+ }
203
209
  for (const exportName of getLegacyExportCandidates(phase)) {
204
210
  const candidate = module[exportName];
205
211
  if (typeof candidate === "function") {
@@ -0,0 +1,45 @@
1
+ /**
2
+ * local-model-check.ts — Utility to detect if a model baseUrl is local.
3
+ *
4
+ * Leaf module with zero transitive dependencies on TypeScript parameter properties.
5
+ * Used by ModelRegistry and tests.
6
+ */
7
+
8
+ /**
9
+ * Check if a model's baseUrl points to a local endpoint.
10
+ * Returns true for localhost, 127.0.0.1, 0.0.0.0, ::1, or unix socket paths.
11
+ * Returns false if baseUrl is empty (cloud provider) or points to a remote host.
12
+ */
13
+ export function isLocalModel(model: { baseUrl: string }): boolean {
14
+ const url = model.baseUrl;
15
+ if (!url) return false;
16
+
17
+ // Unix socket paths
18
+ if (url.startsWith("unix://") || url.startsWith("unix:")) return true;
19
+
20
+ try {
21
+ const parsed = new URL(url);
22
+ const hostname = parsed.hostname;
23
+ if (
24
+ hostname === "localhost" ||
25
+ hostname === "127.0.0.1" ||
26
+ hostname === "0.0.0.0" ||
27
+ hostname === "::1" ||
28
+ hostname === "[::1]"
29
+ ) {
30
+ return true;
31
+ }
32
+ } catch {
33
+ // If URL parsing fails, check raw string for local patterns
34
+ if (
35
+ url.includes("localhost") ||
36
+ url.includes("127.0.0.1") ||
37
+ url.includes("0.0.0.0") ||
38
+ url.includes("[::1]")
39
+ ) {
40
+ return true;
41
+ }
42
+ }
43
+
44
+ return false;
45
+ }