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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (580) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.js +0 -19
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  6. package/dist/resources/extensions/github-sync/templates.js +39 -8
  7. package/dist/resources/extensions/gsd/auto/loop.js +119 -18
  8. package/dist/resources/extensions/gsd/auto/phases.js +212 -135
  9. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  10. package/dist/resources/extensions/gsd/auto/run-unit.js +41 -45
  11. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  12. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  15. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +26 -0
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +27 -14
  18. package/dist/resources/extensions/gsd/auto-prompts.js +214 -17
  19. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  20. package/dist/resources/extensions/gsd/auto-start.js +199 -9
  21. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  23. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  24. package/dist/resources/extensions/gsd/auto.js +95 -27
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -3
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +330 -55
  33. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  34. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  35. package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
  36. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  38. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  39. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  40. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  41. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  42. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  43. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  44. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  45. package/dist/resources/extensions/gsd/detection.js +106 -0
  46. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  47. package/dist/resources/extensions/gsd/git-service.js +36 -4
  48. package/dist/resources/extensions/gsd/graph.js +9 -3
  49. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  50. package/dist/resources/extensions/gsd/guided-flow.js +129 -44
  51. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  52. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  54. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  55. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  56. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  57. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  58. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  60. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  61. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  62. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  64. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  66. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  68. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  70. package/dist/resources/extensions/gsd/quick.js +34 -2
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  72. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  73. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  74. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  75. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  76. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  79. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  80. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  81. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  82. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  83. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  84. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  85. package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
  86. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  89. package/dist/web/standalone/.next/build-manifest.json +3 -3
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  117. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  118. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  121. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  122. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  123. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  124. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  125. package/dist/welcome-screen.d.ts +2 -0
  126. package/dist/welcome-screen.js +9 -7
  127. package/package.json +12 -8
  128. package/packages/contracts/package.json +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  133. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  134. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  135. package/packages/native/tsconfig.tsbuildinfo +1 -1
  136. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  137. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  138. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  139. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  140. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  141. package/packages/pi-agent-core/dist/agent.js +2 -0
  142. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  143. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  144. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  145. package/packages/pi-agent-core/dist/index.js +2 -0
  146. package/packages/pi-agent-core/dist/index.js.map +1 -1
  147. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  148. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  149. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  150. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  151. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  152. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  153. package/packages/pi-agent-core/dist/types.js.map +1 -1
  154. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  155. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  156. package/packages/pi-agent-core/src/agent.ts +8 -0
  157. package/packages/pi-agent-core/src/index.ts +2 -0
  158. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  159. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  160. package/packages/pi-agent-core/src/types.ts +14 -0
  161. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  162. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  163. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  164. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  165. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  166. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  167. package/packages/pi-ai/dist/models/index.js +8 -0
  168. package/packages/pi-ai/dist/models/index.js.map +1 -1
  169. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  170. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/providers/fake.js +319 -0
  172. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  173. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  175. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  176. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  177. package/packages/pi-ai/src/models/index.ts +9 -0
  178. package/packages/pi-ai/src/providers/fake.ts +376 -0
  179. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  180. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  181. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  182. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
  184. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
  186. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
  188. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  190. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  192. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  194. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  196. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  197. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  198. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  199. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  200. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  202. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  203. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  205. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  206. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  207. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  209. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -0
  211. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/extensions/runner.js +20 -7
  213. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +102 -3
  215. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
  217. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  220. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  225. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  226. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  227. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  228. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  229. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
  231. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  233. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  235. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  237. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  240. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  242. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  303. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  307. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  309. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  311. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  313. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  315. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  318. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  319. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  320. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
  321. package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
  322. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  323. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  324. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  325. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  326. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  327. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  328. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +113 -3
  329. package/packages/pi-coding-agent/src/core/extensions/runner.ts +24 -6
  330. package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
  331. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  332. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  333. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  334. package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
  335. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  336. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  337. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  338. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  339. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  340. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  341. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  345. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  347. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  351. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  352. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  353. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  354. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  355. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  356. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  357. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  358. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  360. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  361. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  364. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  365. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  366. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  367. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  368. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  369. package/packages/pi-tui/dist/index.d.ts +1 -0
  370. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/index.js +2 -0
  372. package/packages/pi-tui/dist/index.js.map +1 -1
  373. package/packages/pi-tui/dist/style.d.ts +41 -0
  374. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  375. package/packages/pi-tui/dist/style.js +158 -0
  376. package/packages/pi-tui/dist/style.js.map +1 -0
  377. package/packages/pi-tui/dist/tui.d.ts +0 -1
  378. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  379. package/packages/pi-tui/dist/tui.js +21 -16
  380. package/packages/pi-tui/dist/tui.js.map +1 -1
  381. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  382. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  383. package/packages/pi-tui/src/index.ts +9 -0
  384. package/packages/pi-tui/src/style.ts +225 -0
  385. package/packages/pi-tui/src/tui.ts +23 -16
  386. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  387. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  388. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  389. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  390. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  391. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  392. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  393. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  394. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  395. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  396. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  397. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  398. package/src/resources/GSD-WORKFLOW.md +2 -2
  399. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  400. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  401. package/src/resources/extensions/github-sync/templates.ts +38 -8
  402. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  403. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -2
  404. package/src/resources/extensions/gsd/auto/loop.ts +151 -26
  405. package/src/resources/extensions/gsd/auto/phases.ts +289 -196
  406. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  407. package/src/resources/extensions/gsd/auto/run-unit.ts +52 -44
  408. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  409. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  410. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  411. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  412. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  413. package/src/resources/extensions/gsd/auto-dispatch.ts +33 -0
  414. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -14
  415. package/src/resources/extensions/gsd/auto-prompts.ts +228 -16
  416. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  417. package/src/resources/extensions/gsd/auto-start.ts +237 -15
  418. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  419. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  420. package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
  421. package/src/resources/extensions/gsd/auto.ts +110 -22
  422. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +119 -2
  423. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
  424. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
  425. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
  426. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
  427. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
  428. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
  429. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +386 -55
  430. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  431. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  432. package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
  433. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  434. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  435. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  436. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  437. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  438. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  439. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  440. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  441. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  442. package/src/resources/extensions/gsd/detection.ts +128 -0
  443. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  444. package/src/resources/extensions/gsd/git-service.ts +46 -8
  445. package/src/resources/extensions/gsd/graph.ts +12 -5
  446. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  447. package/src/resources/extensions/gsd/guided-flow.ts +150 -51
  448. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  449. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  450. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  451. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  452. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  453. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  454. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  455. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  456. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  457. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  458. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  459. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  460. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  461. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  462. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  463. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  464. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  466. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  467. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  468. package/src/resources/extensions/gsd/quick.ts +37 -2
  469. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  470. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
  471. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  472. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +516 -15
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  476. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
  477. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
  478. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  479. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  480. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  481. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  482. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  484. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  485. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  486. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +117 -7
  487. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  488. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  489. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  490. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  492. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  493. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  494. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  495. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  496. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  497. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  498. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  499. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  500. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  501. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  502. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  503. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  504. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  505. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
  506. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
  507. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  508. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  509. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  510. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  511. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  512. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  513. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  514. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  515. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  516. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  517. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  518. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  519. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  520. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  521. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  522. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  523. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  524. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  525. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  526. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  527. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
  528. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  529. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
  530. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  531. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  533. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  534. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  535. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  536. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  537. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  538. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  539. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  540. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  541. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  542. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  543. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  544. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  545. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  546. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  547. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  548. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
  549. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  550. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  551. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  552. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  553. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  554. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  555. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  556. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  557. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  558. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  559. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  560. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  561. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
  562. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  563. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  564. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  565. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  566. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  567. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  568. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  569. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  570. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  571. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  572. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  573. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  574. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  575. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  576. package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
  577. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  578. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
  579. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * GSD-2 fake model — paired with the fake LLM provider for e2e tests.
3
+ *
4
+ * Only registered when `GSD_FAKE_LLM_TRANSCRIPT` env var is set, via the
5
+ * conditional branch in models/index.ts. The model is invisible to normal
6
+ * users; it shows up in `--list-models` only inside e2e test subprocesses.
7
+ */
8
+ import type { Model } from "../types.js";
9
+ export declare const FAKE_PROVIDER: "gsd-fake";
10
+ export declare const FAKE_MODEL_ID: "gsd-fake-model";
11
+ export declare const FAKE_MODEL: Model<"fake">;
12
+ //# sourceMappingURL=fake-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-model.d.ts","sourceRoot":"","sources":["../../src/models/fake-model.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,eAAO,MAAM,aAAa,EAAG,UAAmB,CAAC;AACjD,eAAO,MAAM,aAAa,EAAG,gBAAyB,CAAC;AAEvD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,MAAM,CAgBpC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * GSD-2 fake model — paired with the fake LLM provider for e2e tests.
3
+ *
4
+ * Only registered when `GSD_FAKE_LLM_TRANSCRIPT` env var is set, via the
5
+ * conditional branch in models/index.ts. The model is invisible to normal
6
+ * users; it shows up in `--list-models` only inside e2e test subprocesses.
7
+ */
8
+ export const FAKE_PROVIDER = "gsd-fake";
9
+ export const FAKE_MODEL_ID = "gsd-fake-model";
10
+ export const FAKE_MODEL = {
11
+ id: FAKE_MODEL_ID,
12
+ name: "GSD Fake (e2e replay)",
13
+ api: "fake",
14
+ provider: FAKE_PROVIDER,
15
+ baseUrl: "https://fake.gsd.local/v1",
16
+ reasoning: false,
17
+ input: ["text"],
18
+ cost: {
19
+ input: 0,
20
+ output: 0,
21
+ cacheRead: 0,
22
+ cacheWrite: 0,
23
+ },
24
+ contextWindow: 200_000,
25
+ maxTokens: 8_192,
26
+ };
27
+ //# sourceMappingURL=fake-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-model.js","sourceRoot":"","sources":["../../src/models/fake-model.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,CAAC,MAAM,aAAa,GAAG,UAAmB,CAAC;AACjD,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAyB,CAAC;AAEvD,MAAM,CAAC,MAAM,UAAU,GAAkB;IACxC,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,uBAAuB;IAC7B,GAAG,EAAE,MAAM;IACX,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,2BAA2B;IACpC,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,CAAC,MAAM,CAAC;IACf,IAAI,EAAE;QACL,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,CAAC;KACb;IACD,aAAa,EAAE,OAAO;IACtB,SAAS,EAAE,KAAK;CAChB,CAAC","sourcesContent":["/**\n * GSD-2 fake model — paired with the fake LLM provider for e2e tests.\n *\n * Only registered when `GSD_FAKE_LLM_TRANSCRIPT` env var is set, via the\n * conditional branch in models/index.ts. The model is invisible to normal\n * users; it shows up in `--list-models` only inside e2e test subprocesses.\n */\n\nimport type { Model } from \"../types.js\";\n\nexport const FAKE_PROVIDER = \"gsd-fake\" as const;\nexport const FAKE_MODEL_ID = \"gsd-fake-model\" as const;\n\nexport const FAKE_MODEL: Model<\"fake\"> = {\n\tid: FAKE_MODEL_ID,\n\tname: \"GSD Fake (e2e replay)\",\n\tapi: \"fake\",\n\tprovider: FAKE_PROVIDER,\n\tbaseUrl: \"https://fake.gsd.local/v1\",\n\treasoning: false,\n\tinput: [\"text\"],\n\tcost: {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t},\n\tcontextWindow: 200_000,\n\tmaxTokens: 8_192,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAsB,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA2CpE,mEAAmE;AACnE,KAAK,iBAAiB,GAAG,MAAM,OAAO,MAAM,GAAG,aAAa,CAAC;AAE7D,KAAK,QAAQ,CACZ,SAAS,SAAS,iBAAiB,EACnC,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,IAC9C,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEjH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,iBAAiB,EAAE,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,EAC9G,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,QAAQ,GACf,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAGtC;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,aAAa,EACxD,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAC,GAAG,CAAC,EAAE,CAGd;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAE3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAC9C,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/B,OAAO,CAGT;AAED,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAsB,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAErF,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAmDpE,mEAAmE;AACnE,KAAK,iBAAiB,GAAG,MAAM,OAAO,MAAM,GAAG,aAAa,CAAC;AAE7D,KAAK,QAAQ,CACZ,SAAS,SAAS,iBAAiB,EACnC,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,IAC9C,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEjH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,iBAAiB,EAAE,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,EAC9G,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,QAAQ,GACf,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAGtC;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,aAAa,EACxD,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAC,GAAG,CAAC,EAAE,CAGd;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAE3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAC9C,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/B,OAAO,CAGT;AAED,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { MODELS } from "./generated/index.js";
2
2
  import { CUSTOM_MODELS } from "./custom.js";
3
3
  import { CAPABILITY_PATCHES, applyCapabilityPatches } from "./capability-patches.js";
4
+ import { FAKE_MODEL, FAKE_MODEL_ID, FAKE_PROVIDER } from "./fake-model.js";
4
5
  const modelRegistry = new Map();
5
6
  // Initialize registry from auto-generated MODELS (models.dev catalog)
6
7
  for (const [provider, models] of Object.entries(MODELS)) {
@@ -24,6 +25,13 @@ for (const [provider, models] of Object.entries(CUSTOM_MODELS)) {
24
25
  }
25
26
  }
26
27
  }
28
+ // E2E-test-only: register the fake model when GSD_FAKE_LLM_TRANSCRIPT is set.
29
+ // Env var must be set BEFORE this module is imported. See providers/fake.ts.
30
+ if (process.env.GSD_FAKE_LLM_TRANSCRIPT) {
31
+ const providerModels = new Map();
32
+ providerModels.set(FAKE_MODEL_ID, FAKE_MODEL);
33
+ modelRegistry.set(FAKE_PROVIDER, providerModels);
34
+ }
27
35
  // Apply patches to the static registry at module load
28
36
  for (const [, providerModels] of modelRegistry) {
29
37
  for (const [id, model] of providerModels) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { MODELS } from \"./generated/index.js\";\nimport { CUSTOM_MODELS } from \"./custom.js\";\nimport { CAPABILITY_PATCHES, applyCapabilityPatches } from \"./capability-patches.js\";\nimport type { Api, KnownProvider, Model, Usage } from \"../types.js\";\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n// Initialize registry from auto-generated MODELS (models.dev catalog)\nfor (const [provider, models] of Object.entries(MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, model as Model<Api>);\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\n// Merge manually-maintained custom providers that are NOT in models.dev.\n// Custom models are additive — they never overwrite generated entries.\n// See: https://github.com/gsd-build/gsd-2/issues/2339\nfor (const [provider, models] of Object.entries(CUSTOM_MODELS)) {\n\tif (!modelRegistry.has(provider)) {\n\t\tmodelRegistry.set(provider, new Map<string, Model<Api>>());\n\t}\n\tconst providerModels = modelRegistry.get(provider)!;\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tif (!providerModels.has(id)) {\n\t\t\tproviderModels.set(id, model as Model<Api>);\n\t\t}\n\t}\n}\n\n// Apply patches to the static registry at module load\nfor (const [, providerModels] of modelRegistry) {\n\tfor (const [id, model] of providerModels) {\n\t\tfor (const patch of CAPABILITY_PATCHES) {\n\t\t\tif (patch.match(model)) {\n\t\t\t\tproviderModels.set(id, {\n\t\t\t\t\t...model,\n\t\t\t\t\tcapabilities: { ...patch.caps, ...model.capabilities },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Providers that have entries in the generated MODELS constant */\ntype GeneratedProvider = keyof typeof MODELS & KnownProvider;\n\ntype ModelApi<\n\tTProvider extends GeneratedProvider,\n\tTModelId extends keyof (typeof MODELS)[TProvider],\n> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends GeneratedProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(\n\tprovider: TProvider,\n\tmodelId: TModelId,\n): Model<ModelApi<TProvider, TModelId>> {\n\tconst providerModels = modelRegistry.get(provider);\n\treturn providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;\n}\n\nexport function getProviders(): KnownProvider[] {\n\treturn Array.from(modelRegistry.keys()) as KnownProvider[];\n}\n\nexport function getModels<TProvider extends KnownProvider>(\n\tprovider: TProvider,\n): Model<Api>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<Api>[]) : [];\n}\n\nexport function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage[\"cost\"] {\n\tusage.cost.input = (model.cost.input / 1000000) * usage.input;\n\tusage.cost.output = (model.cost.output / 1000000) * usage.output;\n\tusage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;\n\tusage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage.cost;\n}\n\n/**\n * Check if a model supports xhigh thinking level.\n *\n * Reads from `model.capabilities.supportsXhigh` — set via CAPABILITY_PATCHES\n * for generated models or declared directly in custom model definitions.\n * Do not add model-ID or provider-name checks here; update CAPABILITY_PATCHES instead.\n */\nexport function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {\n\treturn model.capabilities?.supportsXhigh ?? false;\n}\n\n/**\n * Check if two models are equal by comparing both their id and provider.\n * Returns false if either model is null or undefined.\n */\nexport function modelsAreEqual<TApi extends Api>(\n\ta: Model<TApi> | null | undefined,\n\tb: Model<TApi> | null | undefined,\n): boolean {\n\tif (!a || !b) return false;\n\treturn a.id === b.id && a.provider === b.provider;\n}\n\nexport { MODELS, applyCapabilityPatches };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { MODELS } from \"./generated/index.js\";\nimport { CUSTOM_MODELS } from \"./custom.js\";\nimport { CAPABILITY_PATCHES, applyCapabilityPatches } from \"./capability-patches.js\";\nimport { FAKE_MODEL, FAKE_MODEL_ID, FAKE_PROVIDER } from \"./fake-model.js\";\nimport type { Api, KnownProvider, Model, Usage } from \"../types.js\";\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n// Initialize registry from auto-generated MODELS (models.dev catalog)\nfor (const [provider, models] of Object.entries(MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, model as Model<Api>);\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\n// Merge manually-maintained custom providers that are NOT in models.dev.\n// Custom models are additive — they never overwrite generated entries.\n// See: https://github.com/gsd-build/gsd-2/issues/2339\nfor (const [provider, models] of Object.entries(CUSTOM_MODELS)) {\n\tif (!modelRegistry.has(provider)) {\n\t\tmodelRegistry.set(provider, new Map<string, Model<Api>>());\n\t}\n\tconst providerModels = modelRegistry.get(provider)!;\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tif (!providerModels.has(id)) {\n\t\t\tproviderModels.set(id, model as Model<Api>);\n\t\t}\n\t}\n}\n\n// E2E-test-only: register the fake model when GSD_FAKE_LLM_TRANSCRIPT is set.\n// Env var must be set BEFORE this module is imported. See providers/fake.ts.\nif (process.env.GSD_FAKE_LLM_TRANSCRIPT) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tproviderModels.set(FAKE_MODEL_ID, FAKE_MODEL as Model<Api>);\n\tmodelRegistry.set(FAKE_PROVIDER, providerModels);\n}\n\n// Apply patches to the static registry at module load\nfor (const [, providerModels] of modelRegistry) {\n\tfor (const [id, model] of providerModels) {\n\t\tfor (const patch of CAPABILITY_PATCHES) {\n\t\t\tif (patch.match(model)) {\n\t\t\t\tproviderModels.set(id, {\n\t\t\t\t\t...model,\n\t\t\t\t\tcapabilities: { ...patch.caps, ...model.capabilities },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Providers that have entries in the generated MODELS constant */\ntype GeneratedProvider = keyof typeof MODELS & KnownProvider;\n\ntype ModelApi<\n\tTProvider extends GeneratedProvider,\n\tTModelId extends keyof (typeof MODELS)[TProvider],\n> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends GeneratedProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(\n\tprovider: TProvider,\n\tmodelId: TModelId,\n): Model<ModelApi<TProvider, TModelId>> {\n\tconst providerModels = modelRegistry.get(provider);\n\treturn providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;\n}\n\nexport function getProviders(): KnownProvider[] {\n\treturn Array.from(modelRegistry.keys()) as KnownProvider[];\n}\n\nexport function getModels<TProvider extends KnownProvider>(\n\tprovider: TProvider,\n): Model<Api>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<Api>[]) : [];\n}\n\nexport function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage[\"cost\"] {\n\tusage.cost.input = (model.cost.input / 1000000) * usage.input;\n\tusage.cost.output = (model.cost.output / 1000000) * usage.output;\n\tusage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;\n\tusage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage.cost;\n}\n\n/**\n * Check if a model supports xhigh thinking level.\n *\n * Reads from `model.capabilities.supportsXhigh` — set via CAPABILITY_PATCHES\n * for generated models or declared directly in custom model definitions.\n * Do not add model-ID or provider-name checks here; update CAPABILITY_PATCHES instead.\n */\nexport function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {\n\treturn model.capabilities?.supportsXhigh ?? false;\n}\n\n/**\n * Check if two models are equal by comparing both their id and provider.\n * Returns false if either model is null or undefined.\n */\nexport function modelsAreEqual<TApi extends Api>(\n\ta: Model<TApi> | null | undefined,\n\tb: Model<TApi> | null | undefined,\n): boolean {\n\tif (!a || !b) return false;\n\treturn a.id === b.id && a.provider === b.provider;\n}\n\nexport { MODELS, applyCapabilityPatches };\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * GSD-2 fake LLM provider — deterministic JSONL replay for e2e tests.
3
+ *
4
+ * Activated only when `GSD_FAKE_LLM_TRANSCRIPT` env var is set. Reads a
5
+ * JSONL transcript file (one turn per line) and replays scripted responses
6
+ * sequentially. Each turn carries structural assertions about the incoming
7
+ * request — if the request shape drifts, the provider fails loudly so tests
8
+ * surface it instead of silently consuming wrong inputs.
9
+ *
10
+ * IMPORTANT: env var must be set BEFORE pi-ai is imported. Tests achieve
11
+ * this by setting it on the subprocess they spawn. In-process tests cannot
12
+ * mix fake and real providers in the same Node process.
13
+ *
14
+ * Transcript format (JSONL, one turn per line):
15
+ * {
16
+ * "turn": 1,
17
+ * "expect": {
18
+ * "modelId": "gsd-fake-model",
19
+ * "messageCount": 2, // optional, exact match
20
+ * "lastUserText": "do X", // optional, substring match
21
+ * "systemContains": ["..."], // optional, all must be present
22
+ * "toolNames": ["read_file"], // optional, exact set
23
+ * "hasToolResultFor": "read_file" // optional, last message is a toolResult for this name
24
+ * },
25
+ * "emit": { "kind": "text", "text": "...", "stopReason": "stop" }
26
+ * | { "kind": "tool_use", "calls": [...], "stopReason": "toolUse" }
27
+ * | { "kind": "error_429", "message": "rate limited", "retryAfterMs": 1000 }
28
+ * | { "kind": "malformed" }
29
+ * | { "kind": "timeout", "delayMs": 60000 }
30
+ * }
31
+ */
32
+ import type { ApiProvider } from "../api-registry.js";
33
+ export declare const FAKE_API: "fake";
34
+ /**
35
+ * Create a fake provider bound to a transcript file. Each call to stream()
36
+ * advances the turn cursor by one. Caller is responsible for ensuring the
37
+ * transcript has enough turns.
38
+ */
39
+ export declare function createFakeProvider(opts: {
40
+ transcriptPath: string;
41
+ }): ApiProvider<typeof FAKE_API>;
42
+ //# sourceMappingURL=fake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake.d.ts","sourceRoot":"","sources":["../../src/providers/fake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAYtD,eAAO,MAAM,QAAQ,EAAG,MAAe,CAAC;AAwJxC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAAC,OAAO,QAAQ,CAAC,CA6KjG"}
@@ -0,0 +1,319 @@
1
+ /**
2
+ * GSD-2 fake LLM provider — deterministic JSONL replay for e2e tests.
3
+ *
4
+ * Activated only when `GSD_FAKE_LLM_TRANSCRIPT` env var is set. Reads a
5
+ * JSONL transcript file (one turn per line) and replays scripted responses
6
+ * sequentially. Each turn carries structural assertions about the incoming
7
+ * request — if the request shape drifts, the provider fails loudly so tests
8
+ * surface it instead of silently consuming wrong inputs.
9
+ *
10
+ * IMPORTANT: env var must be set BEFORE pi-ai is imported. Tests achieve
11
+ * this by setting it on the subprocess they spawn. In-process tests cannot
12
+ * mix fake and real providers in the same Node process.
13
+ *
14
+ * Transcript format (JSONL, one turn per line):
15
+ * {
16
+ * "turn": 1,
17
+ * "expect": {
18
+ * "modelId": "gsd-fake-model",
19
+ * "messageCount": 2, // optional, exact match
20
+ * "lastUserText": "do X", // optional, substring match
21
+ * "systemContains": ["..."], // optional, all must be present
22
+ * "toolNames": ["read_file"], // optional, exact set
23
+ * "hasToolResultFor": "read_file" // optional, last message is a toolResult for this name
24
+ * },
25
+ * "emit": { "kind": "text", "text": "...", "stopReason": "stop" }
26
+ * | { "kind": "tool_use", "calls": [...], "stopReason": "toolUse" }
27
+ * | { "kind": "error_429", "message": "rate limited", "retryAfterMs": 1000 }
28
+ * | { "kind": "malformed" }
29
+ * | { "kind": "timeout", "delayMs": 60000 }
30
+ * }
31
+ */
32
+ import { readFileSync } from "node:fs";
33
+ import { AssistantMessageEventStream } from "../utils/event-stream.js";
34
+ export const FAKE_API = "fake";
35
+ function parseTranscript(path) {
36
+ const raw = readFileSync(path, "utf8");
37
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
38
+ const turns = [];
39
+ for (const [i, line] of lines.entries()) {
40
+ try {
41
+ turns.push(JSON.parse(line));
42
+ }
43
+ catch (err) {
44
+ throw new Error(`fake-llm: failed to parse transcript ${path} line ${i + 1}: ${err.message}\n line: ${line}`);
45
+ }
46
+ }
47
+ return turns;
48
+ }
49
+ function lastUserMessage(ctx) {
50
+ for (let i = ctx.messages.length - 1; i >= 0; i--) {
51
+ const m = ctx.messages[i];
52
+ if (m.role === "user")
53
+ return m;
54
+ }
55
+ return undefined;
56
+ }
57
+ function userText(m) {
58
+ if (typeof m.content === "string")
59
+ return m.content;
60
+ return m.content
61
+ .filter((c) => c.type === "text")
62
+ .map((c) => c.text)
63
+ .join("\n");
64
+ }
65
+ function checkExpectations(model, ctx, turn) {
66
+ const e = turn.expect;
67
+ if (!e)
68
+ return;
69
+ const fail = (msg) => {
70
+ // Surface mismatch with enough context to debug, then throw.
71
+ const detail = {
72
+ turn: turn.turn,
73
+ modelId: model.id,
74
+ messageCount: ctx.messages.length,
75
+ lastUserText: lastUserMessage(ctx) ? userText(lastUserMessage(ctx)).slice(0, 200) : null,
76
+ toolNames: ctx.tools?.map((t) => t.name) ?? [],
77
+ };
78
+ throw new Error(`fake-llm: turn ${turn.turn} expectation mismatch: ${msg}\n actual: ${JSON.stringify(detail)}`);
79
+ };
80
+ if (e.modelId !== undefined && model.id !== e.modelId) {
81
+ fail(`expected modelId=${e.modelId}, got ${model.id}`);
82
+ }
83
+ if (e.messageCount !== undefined && ctx.messages.length !== e.messageCount) {
84
+ fail(`expected messageCount=${e.messageCount}, got ${ctx.messages.length}`);
85
+ }
86
+ if (e.lastUserText !== undefined) {
87
+ const last = lastUserMessage(ctx);
88
+ if (!last)
89
+ fail(`expected lastUserText to contain "${e.lastUserText}", but no user messages found`);
90
+ const text = userText(last);
91
+ if (!text.includes(e.lastUserText)) {
92
+ fail(`expected lastUserText to contain "${e.lastUserText}", got "${text.slice(0, 200)}"`);
93
+ }
94
+ }
95
+ if (e.systemContains && e.systemContains.length > 0) {
96
+ const sys = ctx.systemPrompt ?? "";
97
+ for (const needle of e.systemContains) {
98
+ if (!sys.includes(needle))
99
+ fail(`expected systemPrompt to contain "${needle}"`);
100
+ }
101
+ }
102
+ if (e.toolNames) {
103
+ const actual = (ctx.tools ?? []).map((t) => t.name).sort();
104
+ const expected = [...e.toolNames].sort();
105
+ if (actual.length !== expected.length || actual.some((n, i) => n !== expected[i])) {
106
+ fail(`expected toolNames=${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
107
+ }
108
+ }
109
+ if (e.hasToolResultFor !== undefined) {
110
+ const last = ctx.messages[ctx.messages.length - 1];
111
+ if (!last || last.role !== "toolResult" || last.toolName !== e.hasToolResultFor) {
112
+ fail(`expected last message to be a toolResult for "${e.hasToolResultFor}"`);
113
+ }
114
+ }
115
+ }
116
+ function buildAssistantMessage(model, emit) {
117
+ const content = [];
118
+ let stopReason = "stop";
119
+ if (emit.kind === "text") {
120
+ content.push({ type: "text", text: emit.text });
121
+ stopReason = emit.stopReason ?? "stop";
122
+ }
123
+ else if (emit.kind === "tool_use") {
124
+ for (const [i, call] of emit.calls.entries()) {
125
+ const tc = {
126
+ type: "toolCall",
127
+ id: call.id ?? `fake-tool-${Date.now()}-${i}`,
128
+ name: call.name,
129
+ arguments: call.input,
130
+ };
131
+ content.push(tc);
132
+ }
133
+ stopReason = "toolUse";
134
+ }
135
+ return {
136
+ role: "assistant",
137
+ content,
138
+ api: model.api,
139
+ provider: model.provider,
140
+ model: model.id,
141
+ usage: {
142
+ input: 0,
143
+ output: 0,
144
+ cacheRead: 0,
145
+ cacheWrite: 0,
146
+ totalTokens: 0,
147
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
148
+ },
149
+ stopReason,
150
+ timestamp: Date.now(),
151
+ };
152
+ }
153
+ /**
154
+ * Create a fake provider bound to a transcript file. Each call to stream()
155
+ * advances the turn cursor by one. Caller is responsible for ensuring the
156
+ * transcript has enough turns.
157
+ */
158
+ export function createFakeProvider(opts) {
159
+ const transcript = parseTranscript(opts.transcriptPath);
160
+ let cursor = 0;
161
+ function nextTurn() {
162
+ if (cursor >= transcript.length) {
163
+ throw new Error(`fake-llm: provider invoked ${cursor + 1} times but transcript only has ${transcript.length} turns. Add another turn to ${opts.transcriptPath}.`);
164
+ }
165
+ return transcript[cursor++];
166
+ }
167
+ function streamTurn(model, ctx) {
168
+ const stream = new AssistantMessageEventStream();
169
+ const turn = nextTurn();
170
+ // Synchronously validate expectations BEFORE doing any async work — this
171
+ // way drift mismatches are reported with the request that caused them.
172
+ checkExpectations(model, ctx, turn);
173
+ const emit = turn.emit;
174
+ queueMicrotask(async () => {
175
+ try {
176
+ if (emit.kind === "error_429") {
177
+ const errorMsg = {
178
+ role: "assistant",
179
+ content: [],
180
+ api: model.api,
181
+ provider: model.provider,
182
+ model: model.id,
183
+ usage: {
184
+ input: 0,
185
+ output: 0,
186
+ cacheRead: 0,
187
+ cacheWrite: 0,
188
+ totalTokens: 0,
189
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
190
+ },
191
+ stopReason: "error",
192
+ errorMessage: emit.message ?? "rate_limit_exceeded",
193
+ retryAfterMs: emit.retryAfterMs,
194
+ timestamp: Date.now(),
195
+ };
196
+ stream.push({ type: "error", reason: "error", error: errorMsg });
197
+ stream.end(errorMsg);
198
+ return;
199
+ }
200
+ if (emit.kind === "malformed") {
201
+ // Simulate a provider that emits a corrupted/incomplete response.
202
+ // The agent loop converts this to stopReason: "error".
203
+ const errorMsg = {
204
+ role: "assistant",
205
+ content: [],
206
+ api: model.api,
207
+ provider: model.provider,
208
+ model: model.id,
209
+ usage: {
210
+ input: 0,
211
+ output: 0,
212
+ cacheRead: 0,
213
+ cacheWrite: 0,
214
+ totalTokens: 0,
215
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
216
+ },
217
+ stopReason: "error",
218
+ errorMessage: emit.message ?? "malformed_response",
219
+ timestamp: Date.now(),
220
+ };
221
+ stream.push({ type: "error", reason: "error", error: errorMsg });
222
+ stream.end(errorMsg);
223
+ return;
224
+ }
225
+ if (emit.kind === "timeout") {
226
+ const delay = emit.delayMs ?? 60_000;
227
+ await new Promise((r) => setTimeout(r, delay));
228
+ // If the caller hasn't already aborted, emit a synthetic timeout error.
229
+ const errorMsg = {
230
+ role: "assistant",
231
+ content: [],
232
+ api: model.api,
233
+ provider: model.provider,
234
+ model: model.id,
235
+ usage: {
236
+ input: 0,
237
+ output: 0,
238
+ cacheRead: 0,
239
+ cacheWrite: 0,
240
+ totalTokens: 0,
241
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
242
+ },
243
+ stopReason: "error",
244
+ errorMessage: "timeout",
245
+ timestamp: Date.now(),
246
+ };
247
+ stream.push({ type: "error", reason: "error", error: errorMsg });
248
+ stream.end(errorMsg);
249
+ return;
250
+ }
251
+ const message = buildAssistantMessage(model, emit);
252
+ stream.push({ type: "start", partial: { ...message, content: [] } });
253
+ if (emit.kind === "text") {
254
+ stream.push({ type: "text_start", contentIndex: 0, partial: message });
255
+ stream.push({
256
+ type: "text_delta",
257
+ contentIndex: 0,
258
+ delta: emit.text,
259
+ partial: message,
260
+ });
261
+ stream.push({
262
+ type: "text_end",
263
+ contentIndex: 0,
264
+ content: emit.text,
265
+ partial: message,
266
+ });
267
+ }
268
+ else if (emit.kind === "tool_use") {
269
+ for (const [i, c] of message.content.entries()) {
270
+ if (c.type !== "toolCall")
271
+ continue;
272
+ stream.push({ type: "toolcall_start", contentIndex: i, partial: message });
273
+ stream.push({
274
+ type: "toolcall_end",
275
+ contentIndex: i,
276
+ toolCall: c,
277
+ partial: message,
278
+ });
279
+ }
280
+ }
281
+ stream.push({
282
+ type: "done",
283
+ reason: message.stopReason,
284
+ message,
285
+ });
286
+ stream.end(message);
287
+ }
288
+ catch (err) {
289
+ const errorMsg = {
290
+ role: "assistant",
291
+ content: [],
292
+ api: model.api,
293
+ provider: model.provider,
294
+ model: model.id,
295
+ usage: {
296
+ input: 0,
297
+ output: 0,
298
+ cacheRead: 0,
299
+ cacheWrite: 0,
300
+ totalTokens: 0,
301
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
302
+ },
303
+ stopReason: "error",
304
+ errorMessage: err.message,
305
+ timestamp: Date.now(),
306
+ };
307
+ stream.push({ type: "error", reason: "error", error: errorMsg });
308
+ stream.end(errorMsg);
309
+ }
310
+ });
311
+ return stream;
312
+ }
313
+ return {
314
+ api: FAKE_API,
315
+ stream: ((model, ctx, _opts) => streamTurn(model, ctx)),
316
+ streamSimple: ((model, ctx, _opts) => streamTurn(model, ctx)),
317
+ };
318
+ }
319
+ //# sourceMappingURL=fake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake.js","sourceRoot":"","sources":["../../src/providers/fake.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GSD-2 fake LLM provider — deterministic JSONL replay for e2e tests.\n *\n * Activated only when `GSD_FAKE_LLM_TRANSCRIPT` env var is set. Reads a\n * JSONL transcript file (one turn per line) and replays scripted responses\n * sequentially. Each turn carries structural assertions about the incoming\n * request — if the request shape drifts, the provider fails loudly so tests\n * surface it instead of silently consuming wrong inputs.\n *\n * IMPORTANT: env var must be set BEFORE pi-ai is imported. Tests achieve\n * this by setting it on the subprocess they spawn. In-process tests cannot\n * mix fake and real providers in the same Node process.\n *\n * Transcript format (JSONL, one turn per line):\n * {\n * \"turn\": 1,\n * \"expect\": {\n * \"modelId\": \"gsd-fake-model\",\n * \"messageCount\": 2, // optional, exact match\n * \"lastUserText\": \"do X\", // optional, substring match\n * \"systemContains\": [\"...\"], // optional, all must be present\n * \"toolNames\": [\"read_file\"], // optional, exact set\n * \"hasToolResultFor\": \"read_file\" // optional, last message is a toolResult for this name\n * },\n * \"emit\": { \"kind\": \"text\", \"text\": \"...\", \"stopReason\": \"stop\" }\n * | { \"kind\": \"tool_use\", \"calls\": [...], \"stopReason\": \"toolUse\" }\n * | { \"kind\": \"error_429\", \"message\": \"rate limited\", \"retryAfterMs\": 1000 }\n * | { \"kind\": \"malformed\" }\n * | { \"kind\": \"timeout\", \"delayMs\": 60000 }\n * }\n */\n\nimport { readFileSync } from \"node:fs\";\nimport type { ApiProvider } from \"../api-registry.js\";\nimport type {\n\tAssistantMessage,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tToolCall,\n\tUserMessage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\n\nexport const FAKE_API = \"fake\" as const;\n\ninterface ExpectFields {\n\tmodelId?: string;\n\tmessageCount?: number;\n\tlastUserText?: string;\n\tsystemContains?: string[];\n\ttoolNames?: string[];\n\thasToolResultFor?: string;\n}\n\ntype EmitSpec =\n\t| { kind: \"text\"; text: string; stopReason?: \"stop\" | \"length\" }\n\t| {\n\t\t\tkind: \"tool_use\";\n\t\t\tcalls: { id?: string; name: string; input: Record<string, unknown> }[];\n\t\t\tstopReason?: \"toolUse\";\n\t }\n\t| { kind: \"error_429\"; message?: string; retryAfterMs?: number }\n\t| { kind: \"malformed\"; message?: string }\n\t| { kind: \"timeout\"; delayMs?: number };\n\ninterface TranscriptTurn {\n\tturn: number;\n\texpect?: ExpectFields;\n\temit: EmitSpec;\n}\n\nfunction parseTranscript(path: string): TranscriptTurn[] {\n\tconst raw = readFileSync(path, \"utf8\");\n\tconst lines = raw.split(\"\\n\").filter((l) => l.trim().length > 0);\n\tconst turns: TranscriptTurn[] = [];\n\tfor (const [i, line] of lines.entries()) {\n\t\ttry {\n\t\t\tturns.push(JSON.parse(line));\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t`fake-llm: failed to parse transcript ${path} line ${i + 1}: ${(err as Error).message}\\n line: ${line}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn turns;\n}\n\nfunction lastUserMessage(ctx: Context): UserMessage | undefined {\n\tfor (let i = ctx.messages.length - 1; i >= 0; i--) {\n\t\tconst m = ctx.messages[i];\n\t\tif (m.role === \"user\") return m;\n\t}\n\treturn undefined;\n}\n\nfunction userText(m: UserMessage): string {\n\tif (typeof m.content === \"string\") return m.content;\n\treturn m.content\n\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t.map((c) => c.text)\n\t\t.join(\"\\n\");\n}\n\nfunction checkExpectations(model: Model<typeof FAKE_API>, ctx: Context, turn: TranscriptTurn): void {\n\tconst e = turn.expect;\n\tif (!e) return;\n\tconst fail = (msg: string): never => {\n\t\t// Surface mismatch with enough context to debug, then throw.\n\t\tconst detail = {\n\t\t\tturn: turn.turn,\n\t\t\tmodelId: model.id,\n\t\t\tmessageCount: ctx.messages.length,\n\t\t\tlastUserText: lastUserMessage(ctx) ? userText(lastUserMessage(ctx)!).slice(0, 200) : null,\n\t\t\ttoolNames: ctx.tools?.map((t) => t.name) ?? [],\n\t\t};\n\t\tthrow new Error(`fake-llm: turn ${turn.turn} expectation mismatch: ${msg}\\n actual: ${JSON.stringify(detail)}`);\n\t};\n\n\tif (e.modelId !== undefined && model.id !== e.modelId) {\n\t\tfail(`expected modelId=${e.modelId}, got ${model.id}`);\n\t}\n\tif (e.messageCount !== undefined && ctx.messages.length !== e.messageCount) {\n\t\tfail(`expected messageCount=${e.messageCount}, got ${ctx.messages.length}`);\n\t}\n\tif (e.lastUserText !== undefined) {\n\t\tconst last = lastUserMessage(ctx);\n\t\tif (!last) fail(`expected lastUserText to contain \"${e.lastUserText}\", but no user messages found`);\n\t\tconst text = userText(last!);\n\t\tif (!text.includes(e.lastUserText)) {\n\t\t\tfail(`expected lastUserText to contain \"${e.lastUserText}\", got \"${text.slice(0, 200)}\"`);\n\t\t}\n\t}\n\tif (e.systemContains && e.systemContains.length > 0) {\n\t\tconst sys = ctx.systemPrompt ?? \"\";\n\t\tfor (const needle of e.systemContains) {\n\t\t\tif (!sys.includes(needle)) fail(`expected systemPrompt to contain \"${needle}\"`);\n\t\t}\n\t}\n\tif (e.toolNames) {\n\t\tconst actual = (ctx.tools ?? []).map((t) => t.name).sort();\n\t\tconst expected = [...e.toolNames].sort();\n\t\tif (actual.length !== expected.length || actual.some((n, i) => n !== expected[i])) {\n\t\t\tfail(`expected toolNames=${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);\n\t\t}\n\t}\n\tif (e.hasToolResultFor !== undefined) {\n\t\tconst last = ctx.messages[ctx.messages.length - 1];\n\t\tif (!last || last.role !== \"toolResult\" || last.toolName !== e.hasToolResultFor) {\n\t\t\tfail(`expected last message to be a toolResult for \"${e.hasToolResultFor}\"`);\n\t\t}\n\t}\n}\n\nfunction buildAssistantMessage(\n\tmodel: Model<typeof FAKE_API>,\n\temit: EmitSpec,\n): AssistantMessage {\n\tconst content: AssistantMessage[\"content\"] = [];\n\tlet stopReason: AssistantMessage[\"stopReason\"] = \"stop\";\n\n\tif (emit.kind === \"text\") {\n\t\tcontent.push({ type: \"text\", text: emit.text });\n\t\tstopReason = emit.stopReason ?? \"stop\";\n\t} else if (emit.kind === \"tool_use\") {\n\t\tfor (const [i, call] of emit.calls.entries()) {\n\t\t\tconst tc: ToolCall = {\n\t\t\t\ttype: \"toolCall\",\n\t\t\t\tid: call.id ?? `fake-tool-${Date.now()}-${i}`,\n\t\t\t\tname: call.name,\n\t\t\t\targuments: call.input,\n\t\t\t};\n\t\t\tcontent.push(tc);\n\t\t}\n\t\tstopReason = \"toolUse\";\n\t}\n\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent,\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason,\n\t\ttimestamp: Date.now(),\n\t};\n}\n\n/**\n * Create a fake provider bound to a transcript file. Each call to stream()\n * advances the turn cursor by one. Caller is responsible for ensuring the\n * transcript has enough turns.\n */\nexport function createFakeProvider(opts: { transcriptPath: string }): ApiProvider<typeof FAKE_API> {\n\tconst transcript = parseTranscript(opts.transcriptPath);\n\tlet cursor = 0;\n\n\tfunction nextTurn(): TranscriptTurn {\n\t\tif (cursor >= transcript.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`fake-llm: provider invoked ${cursor + 1} times but transcript only has ${transcript.length} turns. Add another turn to ${opts.transcriptPath}.`,\n\t\t\t);\n\t\t}\n\t\treturn transcript[cursor++];\n\t}\n\n\tfunction streamTurn(model: Model<typeof FAKE_API>, ctx: Context): AssistantMessageEventStream {\n\t\tconst stream = new AssistantMessageEventStream();\n\t\tconst turn = nextTurn();\n\n\t\t// Synchronously validate expectations BEFORE doing any async work — this\n\t\t// way drift mismatches are reported with the request that caused them.\n\t\tcheckExpectations(model, ctx, turn);\n\n\t\tconst emit = turn.emit;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tif (emit.kind === \"error_429\") {\n\t\t\t\t\tconst errorMsg: AssistantMessage = {\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [],\n\t\t\t\t\t\tapi: model.api,\n\t\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\t\tmodel: model.id,\n\t\t\t\t\t\tusage: {\n\t\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstopReason: \"error\",\n\t\t\t\t\t\terrorMessage: emit.message ?? \"rate_limit_exceeded\",\n\t\t\t\t\t\tretryAfterMs: emit.retryAfterMs,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t};\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"error\", error: errorMsg });\n\t\t\t\t\tstream.end(errorMsg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (emit.kind === \"malformed\") {\n\t\t\t\t\t// Simulate a provider that emits a corrupted/incomplete response.\n\t\t\t\t\t// The agent loop converts this to stopReason: \"error\".\n\t\t\t\t\tconst errorMsg: AssistantMessage = {\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [],\n\t\t\t\t\t\tapi: model.api,\n\t\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\t\tmodel: model.id,\n\t\t\t\t\t\tusage: {\n\t\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstopReason: \"error\",\n\t\t\t\t\t\terrorMessage: emit.message ?? \"malformed_response\",\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t};\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"error\", error: errorMsg });\n\t\t\t\t\tstream.end(errorMsg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (emit.kind === \"timeout\") {\n\t\t\t\t\tconst delay = emit.delayMs ?? 60_000;\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, delay));\n\t\t\t\t\t// If the caller hasn't already aborted, emit a synthetic timeout error.\n\t\t\t\t\tconst errorMsg: AssistantMessage = {\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [],\n\t\t\t\t\t\tapi: model.api,\n\t\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\t\tmodel: model.id,\n\t\t\t\t\t\tusage: {\n\t\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstopReason: \"error\",\n\t\t\t\t\t\terrorMessage: \"timeout\",\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t};\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"error\", error: errorMsg });\n\t\t\t\t\tstream.end(errorMsg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst message = buildAssistantMessage(model, emit);\n\t\t\t\tstream.push({ type: \"start\", partial: { ...message, content: [] } });\n\n\t\t\t\tif (emit.kind === \"text\") {\n\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: 0, partial: message });\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: 0,\n\t\t\t\t\t\tdelta: emit.text,\n\t\t\t\t\t\tpartial: message,\n\t\t\t\t\t});\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\tcontentIndex: 0,\n\t\t\t\t\t\tcontent: emit.text,\n\t\t\t\t\t\tpartial: message,\n\t\t\t\t\t});\n\t\t\t\t} else if (emit.kind === \"tool_use\") {\n\t\t\t\t\tfor (const [i, c] of message.content.entries()) {\n\t\t\t\t\t\tif (c.type !== \"toolCall\") continue;\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: i, partial: message });\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\tcontentIndex: i,\n\t\t\t\t\t\t\ttoolCall: c,\n\t\t\t\t\t\t\tpartial: message,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tstream.push({\n\t\t\t\t\ttype: \"done\",\n\t\t\t\t\treason: message.stopReason as \"stop\" | \"length\" | \"toolUse\" | \"pauseTurn\",\n\t\t\t\t\tmessage,\n\t\t\t\t});\n\t\t\t\tstream.end(message);\n\t\t\t} catch (err) {\n\t\t\t\tconst errorMsg: AssistantMessage = {\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\tcontent: [],\n\t\t\t\t\tapi: model.api,\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tmodel: model.id,\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t},\n\t\t\t\t\tstopReason: \"error\",\n\t\t\t\t\terrorMessage: (err as Error).message,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t};\n\t\t\t\tstream.push({ type: \"error\", reason: \"error\", error: errorMsg });\n\t\t\t\tstream.end(errorMsg);\n\t\t\t}\n\t\t});\n\n\t\treturn stream;\n\t}\n\n\treturn {\n\t\tapi: FAKE_API,\n\t\tstream: ((model: Model<typeof FAKE_API>, ctx: Context, _opts?: StreamOptions) =>\n\t\t\tstreamTurn(model, ctx)) as ApiProvider<typeof FAKE_API>[\"stream\"],\n\t\tstreamSimple: ((model: Model<typeof FAKE_API>, ctx: Context, _opts?: SimpleStreamOptions) =>\n\t\t\tstreamTurn(model, ctx)) as ApiProvider<typeof FAKE_API>[\"streamSimple\"],\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"register-builtins.d.ts","sourceRoot":"","sources":["../../src/providers/register-builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,qBAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAY1D,UAAU,qBAAqB;IAC9B,aAAa,EAAE,CACd,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,cAAc,KACpB,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC1C,mBAAmB,EAAE,CACpB,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,KACzB,aAAa,CAAC,qBAAqB,CAAC,CAAC;CAC1C;AASD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAE5E;AAsJD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
1
+ {"version":3,"file":"register-builtins.d.ts","sourceRoot":"","sources":["../../src/providers/register-builtins.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,qBAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAY1D,UAAU,qBAAqB;IAC9B,aAAa,EAAE,CACd,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,cAAc,KACpB,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC1C,mBAAmB,EAAE,CACpB,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,KACzB,aAAa,CAAC,qBAAqB,CAAC,CAAC;CAC1C;AASD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAE5E;AAsJD,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC"}
@@ -1,4 +1,5 @@
1
1
  import { clearApiProviders, registerApiProvider } from "../api-registry.js";
2
+ import { createFakeProvider } from "./fake.js";
2
3
  import { AssistantMessageEventStream } from "../utils/event-stream.js";
3
4
  import { streamAnthropic, streamSimpleAnthropic } from "./anthropic.js";
4
5
  import { streamAnthropicVertex, streamSimpleAnthropicVertex } from "./anthropic-vertex.js";
@@ -139,6 +140,29 @@ function registerBuiltInApiProviders() {
139
140
  export function resetApiProviders() {
140
141
  clearApiProviders();
141
142
  registerBuiltInApiProviders();
143
+ registerFakeProviderIfEnabled();
144
+ }
145
+ /**
146
+ * E2E-test-only: when `GSD_FAKE_LLM_TRANSCRIPT` is set, register a
147
+ * deterministic JSONL-replay provider under api "fake". The env var must
148
+ * be set BEFORE this module is imported. Subprocess-spawned e2e tests do
149
+ * this by setting it on the spawn env.
150
+ *
151
+ * Synchronous registration: any failure throws here so the CLI startup
152
+ * fails loudly instead of silently falling through to a real provider.
153
+ */
154
+ function registerFakeProviderIfEnabled() {
155
+ const transcriptPath = process.env.GSD_FAKE_LLM_TRANSCRIPT;
156
+ if (!transcriptPath)
157
+ return;
158
+ try {
159
+ registerApiProvider(createFakeProvider({ transcriptPath }), "fake");
160
+ }
161
+ catch (err) {
162
+ process.stderr.write(`fake-llm: failed to register: ${err.message}\n`);
163
+ throw err;
164
+ }
142
165
  }
143
166
  registerBuiltInApiProviders();
167
+ registerFakeProviderIfEnabled();
144
168
  //# sourceMappingURL=register-builtins.js.map