gsd-pi 2.58.0-dev.778d6ac → 2.58.0-dev.d63175c

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 (628) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +35 -49
  3. package/dist/headless-ui.d.ts +0 -17
  4. package/dist/headless-ui.js +3 -97
  5. package/dist/headless.js +6 -67
  6. package/dist/help-text.js +0 -1
  7. package/dist/onboarding.js +0 -44
  8. package/dist/resource-loader.js +1 -16
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +3 -16
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +6 -14
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +36 -59
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +5 -8
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +1 -2
  20. package/dist/resources/extensions/gsd/auto/phases.js +21 -25
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +20 -37
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +2 -17
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +3 -26
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -16
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +5 -13
  28. package/dist/resources/extensions/gsd/auto-start.js +22 -35
  29. package/dist/resources/extensions/gsd/auto-worktree.js +12 -196
  30. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +0 -32
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -80
  32. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -32
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -33
  34. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -44
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +0 -67
  36. package/dist/resources/extensions/gsd/captures.js +4 -56
  37. package/dist/resources/extensions/gsd/db-writer.js +8 -116
  38. package/dist/resources/extensions/gsd/doctor-git-checks.js +0 -28
  39. package/dist/resources/extensions/gsd/doctor-providers.js +1 -2
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +4 -5
  41. package/dist/resources/extensions/gsd/doctor.js +1 -3
  42. package/dist/resources/extensions/gsd/error-classifier.js +10 -13
  43. package/dist/resources/extensions/gsd/extension-manifest.json +1 -16
  44. package/dist/resources/extensions/gsd/forensics.js +20 -123
  45. package/dist/resources/extensions/gsd/git-service.js +1 -23
  46. package/dist/resources/extensions/gsd/gitignore.js +0 -33
  47. package/dist/resources/extensions/gsd/gsd-db.js +9 -36
  48. package/dist/resources/extensions/gsd/guided-flow.js +44 -106
  49. package/dist/resources/extensions/gsd/health-widget-core.js +0 -31
  50. package/dist/resources/extensions/gsd/health-widget.js +0 -17
  51. package/dist/resources/extensions/gsd/index.js +1 -1
  52. package/dist/resources/extensions/gsd/memory-extractor.js +0 -7
  53. package/dist/resources/extensions/gsd/migrate-external.js +1 -8
  54. package/dist/resources/extensions/gsd/model-cost-table.js +0 -18
  55. package/dist/resources/extensions/gsd/model-router.js +1 -35
  56. package/dist/resources/extensions/gsd/native-git-bridge.js +0 -17
  57. package/dist/resources/extensions/gsd/notifications.js +1 -16
  58. package/dist/resources/extensions/gsd/parallel-eligibility.js +2 -13
  59. package/dist/resources/extensions/gsd/parallel-merge.js +5 -78
  60. package/dist/resources/extensions/gsd/parsers-legacy.js +3 -20
  61. package/dist/resources/extensions/gsd/paths.js +0 -43
  62. package/dist/resources/extensions/gsd/preferences-models.js +1 -14
  63. package/dist/resources/extensions/gsd/preferences-types.js +1 -2
  64. package/dist/resources/extensions/gsd/preferences.js +16 -13
  65. package/dist/resources/extensions/gsd/prompt-loader.js +1 -4
  66. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -4
  68. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -3
  71. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  73. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +0 -2
  75. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/triage-captures.md +0 -1
  77. package/dist/resources/extensions/gsd/repo-identity.js +11 -205
  78. package/dist/resources/extensions/gsd/rethink.js +0 -5
  79. package/dist/resources/extensions/gsd/roadmap-slices.js +4 -5
  80. package/dist/resources/extensions/gsd/state.js +27 -85
  81. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +1 -20
  82. package/dist/resources/extensions/gsd/tools/complete-task.js +71 -34
  83. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -12
  84. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +1 -29
  85. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -14
  86. package/dist/resources/extensions/gsd/triage-resolution.js +7 -22
  87. package/dist/resources/extensions/gsd/undo.js +2 -2
  88. package/dist/resources/extensions/gsd/unit-ownership.js +33 -164
  89. package/dist/resources/extensions/gsd/verdict-parser.js +8 -20
  90. package/dist/resources/extensions/gsd/workflow-manifest.js +5 -24
  91. package/dist/resources/extensions/gsd/workflow-projections.js +63 -95
  92. package/dist/resources/extensions/gsd/workflow-reconcile.js +5 -35
  93. package/dist/resources/extensions/gsd/workspace-index.js +0 -24
  94. package/dist/resources/extensions/gsd/worktree-manager.js +1 -105
  95. package/dist/resources/extensions/gsd/worktree-resolver.js +3 -20
  96. package/dist/resources/extensions/mcp-client/index.js +7 -11
  97. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  98. package/dist/resources/extensions/shared/interview-ui.js +1 -11
  99. package/dist/resources/skills/create-gsd-extension/SKILL.md +3 -5
  100. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +4 -5
  101. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  102. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  103. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +3 -5
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/required-server-files.json +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  112. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  128. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/index.html +1 -1
  183. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  184. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  186. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  188. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  189. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  191. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  192. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  195. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  196. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  197. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +9 -0
  198. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-61d3afac6d0f0ce7.js} +1 -1
  199. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +1 -0
  200. package/dist/web/standalone/server.js +1 -1
  201. package/dist/web-mode.js +1 -2
  202. package/package.json +2 -2
  203. package/packages/native/dist/ast/index.js +5 -9
  204. package/packages/native/dist/ast/types.js +1 -2
  205. package/packages/native/dist/clipboard/index.js +7 -12
  206. package/packages/native/dist/clipboard/types.js +1 -2
  207. package/packages/native/dist/diff/index.js +7 -12
  208. package/packages/native/dist/diff/types.js +1 -2
  209. package/packages/native/dist/fd/index.js +3 -6
  210. package/packages/native/dist/fd/types.js +1 -2
  211. package/packages/native/dist/glob/index.js +5 -9
  212. package/packages/native/dist/glob/types.js +1 -2
  213. package/packages/native/dist/grep/index.js +5 -9
  214. package/packages/native/dist/grep/types.js +1 -2
  215. package/packages/native/dist/gsd-parser/index.js +11 -18
  216. package/packages/native/dist/gsd-parser/types.js +1 -2
  217. package/packages/native/dist/highlight/index.js +7 -12
  218. package/packages/native/dist/highlight/types.js +1 -2
  219. package/packages/native/dist/html/index.js +3 -6
  220. package/packages/native/dist/html/types.js +1 -2
  221. package/packages/native/dist/image/index.js +5 -10
  222. package/packages/native/dist/image/types.js +4 -7
  223. package/packages/native/dist/index.js +17 -70
  224. package/packages/native/dist/json-parse/index.js +8 -13
  225. package/packages/native/dist/native.js +10 -47
  226. package/packages/native/dist/ps/index.js +9 -15
  227. package/packages/native/dist/ps/types.js +1 -2
  228. package/packages/native/dist/stream-process/index.js +7 -12
  229. package/packages/native/dist/text/index.js +14 -24
  230. package/packages/native/dist/text/types.js +2 -5
  231. package/packages/native/dist/truncate/index.js +7 -12
  232. package/packages/native/dist/ttsr/index.js +7 -12
  233. package/packages/native/dist/ttsr/types.js +1 -2
  234. package/packages/native/dist/xxhash/index.js +5 -9
  235. package/packages/native/package.json +19 -19
  236. package/packages/native/src/native.ts +8 -9
  237. package/packages/pi-agent-core/dist/agent-loop.js +2 -3
  238. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  239. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  240. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  241. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  242. package/packages/pi-agent-core/src/agent-loop.ts +2 -3
  243. package/packages/pi-agent-core/src/proxy.ts +1 -1
  244. package/packages/pi-ai/dist/env-api-keys.js +0 -1
  245. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  246. package/packages/pi-ai/dist/index.d.ts +0 -1
  247. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  248. package/packages/pi-ai/dist/index.js +0 -1
  249. package/packages/pi-ai/dist/index.js.map +1 -1
  250. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/anthropic-shared.js +2 -19
  252. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/types.d.ts +3 -3
  254. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/types.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/json-parse.d.ts +0 -3
  257. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  258. package/packages/pi-ai/dist/utils/json-parse.js +1 -24
  259. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  260. package/packages/pi-ai/src/env-api-keys.ts +0 -1
  261. package/packages/pi-ai/src/index.ts +0 -1
  262. package/packages/pi-ai/src/providers/anthropic-shared.ts +2 -17
  263. package/packages/pi-ai/src/types.ts +2 -3
  264. package/packages/pi-ai/src/utils/json-parse.ts +1 -28
  265. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +0 -4
  266. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/agent-session.js +0 -31
  268. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +1 -17
  270. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +2 -62
  272. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/exec.js +1 -3
  275. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +0 -4
  277. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/extensions/index.js +0 -2
  279. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +0 -5
  281. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/extensions/loader.js +0 -5
  283. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  285. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  287. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/lsp/index.js +0 -3
  290. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +0 -3
  293. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/messages.js +2 -31
  296. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/model-resolver.js +0 -1
  299. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +0 -10
  301. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -12
  303. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +0 -6
  305. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -48
  307. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -10
  310. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/tools/read.js +4 -13
  313. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  315. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.js +1 -1
  317. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +0 -4
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +0 -1
  322. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +0 -5
  324. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  325. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -38
  326. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +1 -94
  327. package/packages/pi-coding-agent/src/core/exec.ts +1 -3
  328. package/packages/pi-coding-agent/src/core/extensions/index.ts +0 -4
  329. package/packages/pi-coding-agent/src/core/extensions/loader.ts +0 -5
  330. package/packages/pi-coding-agent/src/core/index.ts +0 -6
  331. package/packages/pi-coding-agent/src/core/lsp/index.ts +0 -3
  332. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +0 -3
  333. package/packages/pi-coding-agent/src/core/messages.ts +2 -29
  334. package/packages/pi-coding-agent/src/core/model-resolver.ts +0 -1
  335. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -20
  336. package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -52
  337. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +3 -11
  338. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -14
  339. package/packages/pi-coding-agent/src/index.ts +0 -6
  340. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +0 -7
  341. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +0 -6
  342. package/packages/pi-tui/dist/terminal.d.ts +0 -2
  343. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  344. package/packages/pi-tui/dist/terminal.js +0 -9
  345. package/packages/pi-tui/dist/terminal.js.map +1 -1
  346. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  347. package/packages/pi-tui/dist/tui.js +0 -9
  348. package/packages/pi-tui/dist/tui.js.map +1 -1
  349. package/packages/pi-tui/src/terminal.ts +0 -14
  350. package/packages/pi-tui/src/tui.ts +0 -8
  351. package/scripts/ensure-workspace-builds.cjs +14 -45
  352. package/src/resources/agents/researcher.md +1 -1
  353. package/src/resources/extensions/ask-user-questions.ts +3 -21
  354. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  355. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  356. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  357. package/src/resources/extensions/claude-code-cli/partial-builder.ts +6 -13
  358. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +35 -63
  359. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +0 -28
  360. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +1 -108
  361. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  362. package/src/resources/extensions/get-secrets-from-user.ts +5 -8
  363. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  364. package/src/resources/extensions/google-search/index.ts +1 -2
  365. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -1
  366. package/src/resources/extensions/gsd/auto/phases.ts +34 -43
  367. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  368. package/src/resources/extensions/gsd/auto-dashboard.ts +19 -37
  369. package/src/resources/extensions/gsd/auto-dispatch.ts +2 -18
  370. package/src/resources/extensions/gsd/auto-model-selection.ts +5 -26
  371. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -18
  372. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  373. package/src/resources/extensions/gsd/auto-recovery.ts +5 -12
  374. package/src/resources/extensions/gsd/auto-start.ts +26 -35
  375. package/src/resources/extensions/gsd/auto-worktree.ts +9 -190
  376. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +0 -31
  377. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -85
  378. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -38
  379. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +19 -31
  380. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -50
  381. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +0 -75
  382. package/src/resources/extensions/gsd/captures.ts +3 -63
  383. package/src/resources/extensions/gsd/db-writer.ts +7 -140
  384. package/src/resources/extensions/gsd/doctor-git-checks.ts +0 -26
  385. package/src/resources/extensions/gsd/doctor-providers.ts +1 -2
  386. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +4 -5
  387. package/src/resources/extensions/gsd/doctor.ts +1 -3
  388. package/src/resources/extensions/gsd/error-classifier.ts +11 -14
  389. package/src/resources/extensions/gsd/extension-manifest.json +1 -16
  390. package/src/resources/extensions/gsd/forensics.ts +20 -144
  391. package/src/resources/extensions/gsd/git-service.ts +3 -26
  392. package/src/resources/extensions/gsd/gitignore.ts +0 -33
  393. package/src/resources/extensions/gsd/gsd-db.ts +7 -43
  394. package/src/resources/extensions/gsd/guided-flow.ts +45 -114
  395. package/src/resources/extensions/gsd/health-widget-core.ts +0 -34
  396. package/src/resources/extensions/gsd/health-widget.ts +0 -17
  397. package/src/resources/extensions/gsd/index.ts +0 -1
  398. package/src/resources/extensions/gsd/memory-extractor.ts +0 -8
  399. package/src/resources/extensions/gsd/migrate-external.ts +1 -9
  400. package/src/resources/extensions/gsd/model-cost-table.ts +0 -19
  401. package/src/resources/extensions/gsd/model-router.ts +1 -35
  402. package/src/resources/extensions/gsd/native-git-bridge.ts +0 -17
  403. package/src/resources/extensions/gsd/notifications.ts +0 -16
  404. package/src/resources/extensions/gsd/parallel-eligibility.ts +2 -15
  405. package/src/resources/extensions/gsd/parallel-merge.ts +4 -87
  406. package/src/resources/extensions/gsd/parsers-legacy.ts +3 -22
  407. package/src/resources/extensions/gsd/paths.ts +0 -42
  408. package/src/resources/extensions/gsd/preferences-models.ts +1 -14
  409. package/src/resources/extensions/gsd/preferences-types.ts +1 -2
  410. package/src/resources/extensions/gsd/preferences.ts +15 -13
  411. package/src/resources/extensions/gsd/prompt-loader.ts +1 -4
  412. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  413. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -4
  414. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  415. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  416. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -3
  417. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  418. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  419. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +0 -2
  421. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  422. package/src/resources/extensions/gsd/prompts/triage-captures.md +0 -1
  423. package/src/resources/extensions/gsd/repo-identity.ts +11 -186
  424. package/src/resources/extensions/gsd/rethink.ts +0 -6
  425. package/src/resources/extensions/gsd/roadmap-slices.ts +4 -5
  426. package/src/resources/extensions/gsd/state.ts +32 -84
  427. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +0 -29
  428. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +1 -71
  429. package/src/resources/extensions/gsd/tests/captures.test.ts +0 -103
  430. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +0 -27
  431. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +0 -21
  432. package/src/resources/extensions/gsd/tests/db-writer.test.ts +12 -7
  433. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +5 -78
  434. package/src/resources/extensions/gsd/tests/derive-state.test.ts +0 -29
  435. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +0 -40
  436. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +1 -20
  437. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +0 -117
  438. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +79 -0
  439. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -31
  440. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +12 -125
  441. package/src/resources/extensions/gsd/tests/health-widget.test.ts +0 -67
  442. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +1 -111
  443. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +0 -101
  444. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -59
  445. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +0 -110
  446. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  447. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +2 -85
  448. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +0 -34
  449. package/src/resources/extensions/gsd/tests/model-router.test.ts +3 -68
  450. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +0 -28
  451. package/src/resources/extensions/gsd/tests/notifications.test.ts +0 -45
  452. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +1 -33
  453. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +0 -29
  454. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -38
  455. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +0 -117
  456. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +0 -97
  457. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +0 -134
  458. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -2
  459. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +0 -8
  460. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +17 -100
  461. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +1 -4
  462. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +0 -48
  463. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +0 -92
  464. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +2 -4
  465. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +1 -48
  466. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -29
  467. package/src/resources/extensions/gsd/tools/complete-task.ts +74 -36
  468. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -13
  469. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +0 -36
  470. package/src/resources/extensions/gsd/tools/validate-milestone.ts +2 -20
  471. package/src/resources/extensions/gsd/triage-resolution.ts +6 -23
  472. package/src/resources/extensions/gsd/types.ts +2 -4
  473. package/src/resources/extensions/gsd/undo.ts +2 -2
  474. package/src/resources/extensions/gsd/unit-ownership.ts +35 -206
  475. package/src/resources/extensions/gsd/verdict-parser.ts +6 -21
  476. package/src/resources/extensions/gsd/workflow-logger.ts +1 -3
  477. package/src/resources/extensions/gsd/workflow-manifest.ts +5 -22
  478. package/src/resources/extensions/gsd/workflow-projections.ts +64 -97
  479. package/src/resources/extensions/gsd/workflow-reconcile.ts +10 -39
  480. package/src/resources/extensions/gsd/workspace-index.ts +0 -30
  481. package/src/resources/extensions/gsd/worktree-manager.ts +1 -120
  482. package/src/resources/extensions/gsd/worktree-resolver.ts +3 -22
  483. package/src/resources/extensions/mcp-client/index.ts +7 -13
  484. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  485. package/src/resources/extensions/shared/interview-ui.ts +1 -12
  486. package/src/resources/skills/create-gsd-extension/SKILL.md +3 -5
  487. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +4 -5
  488. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  489. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  490. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +3 -5
  491. package/dist/resources/extensions/gsd/milestone-validation-gates.js +0 -45
  492. package/dist/resources/extensions/ollama/index.js +0 -112
  493. package/dist/resources/extensions/ollama/model-capabilities.js +0 -115
  494. package/dist/resources/extensions/ollama/ollama-client.js +0 -168
  495. package/dist/resources/extensions/ollama/ollama-commands.js +0 -194
  496. package/dist/resources/extensions/ollama/ollama-discovery.js +0 -69
  497. package/dist/resources/extensions/ollama/ollama-tool.js +0 -184
  498. package/dist/resources/extensions/ollama/types.js +0 -2
  499. package/dist/startup-model-validation.d.ts +0 -39
  500. package/dist/startup-model-validation.js +0 -50
  501. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  502. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +0 -1
  503. package/packages/native/src/__tests__/module-compat.test.mjs +0 -91
  504. package/packages/pi-agent-core/src/agent-loop.test.ts +0 -45
  505. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +0 -2
  506. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +0 -1
  507. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +0 -25
  508. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +0 -1
  509. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +0 -37
  510. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +0 -1
  511. package/packages/pi-ai/dist/utils/repair-tool-json.js +0 -75
  512. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +0 -1
  513. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +0 -2
  514. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +0 -1
  515. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -73
  516. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +0 -1
  517. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +0 -29
  518. package/packages/pi-ai/src/utils/repair-tool-json.ts +0 -88
  519. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -102
  520. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +0 -6
  521. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +0 -1
  522. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +0 -176
  523. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +0 -1
  524. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +0 -28
  525. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +0 -1
  526. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +0 -37
  527. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +0 -1
  528. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +0 -2
  529. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +0 -1
  530. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +0 -63
  531. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +0 -1
  532. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +0 -19
  533. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +0 -1
  534. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +0 -115
  535. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +0 -1
  536. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +0 -2
  537. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +0 -1
  538. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +0 -109
  539. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +0 -1
  540. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +0 -44
  541. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +0 -1
  542. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +0 -97
  543. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +0 -1
  544. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +0 -2
  545. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +0 -1
  546. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +0 -181
  547. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +0 -1
  548. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +0 -9
  549. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +0 -1
  550. package/packages/pi-coding-agent/dist/core/messages.test.js +0 -86
  551. package/packages/pi-coding-agent/dist/core/messages.test.js.map +0 -1
  552. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +0 -9
  553. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +0 -1
  554. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +0 -193
  555. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +0 -1
  556. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +0 -16
  557. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +0 -1
  558. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +0 -80
  559. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +0 -1
  560. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +0 -236
  561. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +0 -77
  562. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +0 -62
  563. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +0 -134
  564. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +0 -137
  565. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +0 -228
  566. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +0 -118
  567. package/packages/pi-coding-agent/src/core/messages.test.ts +0 -114
  568. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +0 -255
  569. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +0 -92
  570. package/src/resources/extensions/gsd/milestone-validation-gates.ts +0 -56
  571. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +0 -71
  572. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +0 -47
  573. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +0 -192
  574. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +0 -131
  575. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +0 -47
  576. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +0 -127
  577. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +0 -20
  578. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -74
  579. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +0 -140
  580. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -129
  581. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  582. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +0 -164
  583. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +0 -135
  584. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +0 -97
  585. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +0 -107
  586. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +0 -243
  587. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +0 -150
  588. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +0 -959
  589. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +0 -105
  590. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +0 -116
  591. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +0 -159
  592. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +0 -150
  593. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +0 -70
  594. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +0 -297
  595. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +0 -178
  596. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +0 -69
  597. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +0 -157
  598. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +0 -90
  599. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +0 -162
  600. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +0 -233
  601. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +0 -305
  602. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +0 -405
  603. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +0 -257
  604. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +0 -1628
  605. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +0 -106
  606. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +0 -174
  607. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +0 -221
  608. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +0 -289
  609. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +0 -154
  610. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +0 -156
  611. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +0 -82
  612. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +0 -140
  613. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +0 -101
  614. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +0 -95
  615. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +0 -55
  616. package/src/resources/extensions/ollama/index.ts +0 -130
  617. package/src/resources/extensions/ollama/model-capabilities.ts +0 -145
  618. package/src/resources/extensions/ollama/ollama-client.ts +0 -196
  619. package/src/resources/extensions/ollama/ollama-commands.ts +0 -248
  620. package/src/resources/extensions/ollama/ollama-discovery.ts +0 -106
  621. package/src/resources/extensions/ollama/ollama-tool.ts +0 -218
  622. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +0 -162
  623. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +0 -38
  624. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -28
  625. package/src/resources/extensions/ollama/types.ts +0 -130
  626. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +0 -156
  627. /package/dist/web/standalone/.next/static/{R0D4xaIPl5kg93edN7Oo0 → 5DLsjFHdSB6_a1EDQVjr7}/_buildManifest.js +0 -0
  628. /package/dist/web/standalone/.next/static/{R0D4xaIPl5kg93edN7Oo0 → 5DLsjFHdSB6_a1EDQVjr7}/_ssgManifest.js +0 -0
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=image-overflow-recovery.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-overflow-recovery.test.d.ts","sourceRoot":"","sources":["../../src/core/image-overflow-recovery.test.ts"],"names":[],"mappings":""}
@@ -1,181 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { isImageDimensionError, MANY_IMAGE_MAX_DIMENSION, downsizeConversationImages, } from "./image-overflow-recovery.js";
4
- // ─── isImageDimensionError ────────────────────────────────────────────────────
5
- describe("isImageDimensionError", () => {
6
- it("returns true for Anthropic many-image dimension error", () => {
7
- const errorMessage = 'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.125.content.38.image.source.base64.data: At least one of the image dimensions exceed max allowed size for many-image requests: 2000 pixels"}}';
8
- assert.equal(isImageDimensionError(errorMessage), true);
9
- });
10
- it("returns true for bare dimension exceed message", () => {
11
- const errorMessage = "image dimensions exceed max allowed size for many-image requests: 2000 pixels";
12
- assert.equal(isImageDimensionError(errorMessage), true);
13
- });
14
- it("returns false for unrelated 400 error", () => {
15
- const errorMessage = 'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"max_tokens: 4096 > 2048"}}';
16
- assert.equal(isImageDimensionError(errorMessage), false);
17
- });
18
- it("returns false for rate limit error", () => {
19
- assert.equal(isImageDimensionError("429 rate limit exceeded"), false);
20
- });
21
- it("returns false for empty string", () => {
22
- assert.equal(isImageDimensionError(""), false);
23
- });
24
- it("returns false for undefined", () => {
25
- assert.equal(isImageDimensionError(undefined), false);
26
- });
27
- });
28
- // ─── MANY_IMAGE_MAX_DIMENSION ─────────────────────────────────────────────────
29
- describe("MANY_IMAGE_MAX_DIMENSION", () => {
30
- it("is less than 2000 (the API-enforced limit)", () => {
31
- assert.ok(MANY_IMAGE_MAX_DIMENSION < 2000);
32
- });
33
- it("is a positive integer", () => {
34
- assert.ok(MANY_IMAGE_MAX_DIMENSION > 0);
35
- assert.equal(MANY_IMAGE_MAX_DIMENSION, Math.floor(MANY_IMAGE_MAX_DIMENSION));
36
- });
37
- });
38
- // ─── helpers ──────────────────────────────────────────────────────────────────
39
- function makeUserMsg(content) {
40
- return { role: "user", content, timestamp: Date.now() };
41
- }
42
- function makeAssistantMsg(text) {
43
- return {
44
- role: "assistant",
45
- content: [{ type: "text", text }],
46
- api: "anthropic-messages",
47
- provider: "anthropic",
48
- model: "claude-opus-4-6",
49
- usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
50
- stopReason: "stop",
51
- timestamp: Date.now(),
52
- };
53
- }
54
- function makeToolResultMsg(images) {
55
- const content = [];
56
- for (let i = 0; i < images; i++) {
57
- content.push({ type: "image", data: `img${i}`, mimeType: "image/png" });
58
- }
59
- return {
60
- role: "toolResult",
61
- toolCallId: `tc${Math.random()}`,
62
- toolName: "screenshot",
63
- content,
64
- isError: false,
65
- timestamp: Date.now(),
66
- };
67
- }
68
- // ─── downsizeConversationImages ───────────────────────────────────────────────
69
- describe("downsizeConversationImages", () => {
70
- it("counts images in user and toolResult messages", () => {
71
- const messages = [
72
- makeUserMsg([
73
- { type: "image", data: "img1", mimeType: "image/png" },
74
- { type: "image", data: "img2", mimeType: "image/png" },
75
- ]),
76
- makeAssistantMsg("I see them"),
77
- makeToolResultMsg(1),
78
- ];
79
- const result = downsizeConversationImages(messages);
80
- assert.equal(result.imageCount, 3);
81
- });
82
- it("returns processed=false when no images present", () => {
83
- const messages = [
84
- makeUserMsg("just text"),
85
- makeAssistantMsg("reply"),
86
- ];
87
- const result = downsizeConversationImages(messages);
88
- assert.equal(result.imageCount, 0);
89
- assert.equal(result.processed, false);
90
- });
91
- it("returns processed=false when image count <= RECENT_IMAGES_TO_KEEP", () => {
92
- const messages = [
93
- makeUserMsg([
94
- { type: "image", data: "img1", mimeType: "image/png" },
95
- ]),
96
- makeAssistantMsg("got it"),
97
- ];
98
- const result = downsizeConversationImages(messages);
99
- assert.equal(result.imageCount, 1);
100
- assert.equal(result.processed, false);
101
- });
102
- it("strips older images when many images present, preserves recent ones", () => {
103
- const messages = [];
104
- for (let i = 0; i < 25; i++) {
105
- messages.push(makeUserMsg([
106
- { type: "text", text: `message ${i}` },
107
- { type: "image", data: `img${i}`, mimeType: "image/png" },
108
- ]));
109
- messages.push(makeAssistantMsg(`reply ${i}`));
110
- }
111
- const result = downsizeConversationImages(messages);
112
- assert.ok(result.processed);
113
- assert.equal(result.imageCount, 25);
114
- assert.equal(result.strippedCount, 20); // 25 - 5 recent
115
- // Count remaining images
116
- let remainingImages = 0;
117
- for (const msg of messages) {
118
- if (msg.role === "assistant")
119
- continue;
120
- if (typeof msg.content === "string")
121
- continue;
122
- const arr = msg.content;
123
- for (const block of arr) {
124
- if (block.type === "image")
125
- remainingImages++;
126
- }
127
- }
128
- assert.equal(remainingImages, 5, "Should keep exactly 5 most recent images");
129
- // The 5 most recent user messages (indices 40,42,44,46,48) should have images
130
- for (let i = 20; i < 25; i++) {
131
- const userMsg = messages[i * 2]; // user messages at even indices
132
- const arr = userMsg.content;
133
- const hasImage = arr.some((c) => c.type === "image");
134
- assert.ok(hasImage, `Recent message ${i} should retain its image`);
135
- }
136
- });
137
- it("adds text placeholder when stripping an image", () => {
138
- const messages = [];
139
- for (let i = 0; i < 10; i++) {
140
- messages.push(makeUserMsg([
141
- { type: "image", data: `img${i}`, mimeType: "image/jpeg" },
142
- ]));
143
- messages.push(makeAssistantMsg(`reply ${i}`));
144
- }
145
- downsizeConversationImages(messages);
146
- // First message's image should have been replaced with text
147
- const firstMsg = messages[0];
148
- const arr = firstMsg.content;
149
- const placeholder = arr.find((c) => c.type === "text" && c.text.includes("[image removed"));
150
- assert.ok(placeholder, "Stripped image should be replaced with text placeholder");
151
- assert.ok(placeholder.text.includes("image/jpeg"), "Placeholder should mention original mime type");
152
- });
153
- it("handles toolResult messages with images", () => {
154
- const messages = [];
155
- for (let i = 0; i < 10; i++) {
156
- messages.push(makeToolResultMsg(1));
157
- messages.push(makeAssistantMsg(`reply ${i}`));
158
- }
159
- const result = downsizeConversationImages(messages);
160
- assert.equal(result.imageCount, 10);
161
- assert.equal(result.strippedCount, 5);
162
- assert.ok(result.processed);
163
- });
164
- it("handles mixed user and toolResult images", () => {
165
- const messages = [];
166
- for (let i = 0; i < 8; i++) {
167
- messages.push(makeUserMsg([
168
- { type: "text", text: `check ${i}` },
169
- { type: "image", data: `uimg${i}`, mimeType: "image/png" },
170
- ]));
171
- messages.push(makeAssistantMsg(`processing ${i}`));
172
- messages.push(makeToolResultMsg(1));
173
- messages.push(makeAssistantMsg(`done ${i}`));
174
- }
175
- const result = downsizeConversationImages(messages);
176
- // 8 user images + 8 tool result images = 16 total
177
- assert.equal(result.imageCount, 16);
178
- assert.equal(result.strippedCount, 11); // 16 - 5 recent
179
- });
180
- });
181
- //# sourceMappingURL=image-overflow-recovery.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-overflow-recovery.test.js","sourceRoot":"","sources":["../../src/core/image-overflow-recovery.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\nimport {\n\tisImageDimensionError,\n\tMANY_IMAGE_MAX_DIMENSION,\n\tdownsizeConversationImages,\n} from \"./image-overflow-recovery.js\";\nimport type { Message } from \"@gsd/pi-ai\";\n\n// ─── isImageDimensionError ────────────────────────────────────────────────────\n\ndescribe(\"isImageDimensionError\", () => {\n\tit(\"returns true for Anthropic many-image dimension error\", () => {\n\t\tconst errorMessage =\n\t\t\t'Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.125.content.38.image.source.base64.data: At least one of the image dimensions exceed max allowed size for many-image requests: 2000 pixels\"}}';\n\t\tassert.equal(isImageDimensionError(errorMessage), true);\n\t});\n\n\tit(\"returns true for bare dimension exceed message\", () => {\n\t\tconst errorMessage =\n\t\t\t\"image dimensions exceed max allowed size for many-image requests: 2000 pixels\";\n\t\tassert.equal(isImageDimensionError(errorMessage), true);\n\t});\n\n\tit(\"returns false for unrelated 400 error\", () => {\n\t\tconst errorMessage =\n\t\t\t'Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens: 4096 > 2048\"}}';\n\t\tassert.equal(isImageDimensionError(errorMessage), false);\n\t});\n\n\tit(\"returns false for rate limit error\", () => {\n\t\tassert.equal(isImageDimensionError(\"429 rate limit exceeded\"), false);\n\t});\n\n\tit(\"returns false for empty string\", () => {\n\t\tassert.equal(isImageDimensionError(\"\"), false);\n\t});\n\n\tit(\"returns false for undefined\", () => {\n\t\tassert.equal(isImageDimensionError(undefined), false);\n\t});\n});\n\n// ─── MANY_IMAGE_MAX_DIMENSION ─────────────────────────────────────────────────\n\ndescribe(\"MANY_IMAGE_MAX_DIMENSION\", () => {\n\tit(\"is less than 2000 (the API-enforced limit)\", () => {\n\t\tassert.ok(MANY_IMAGE_MAX_DIMENSION < 2000);\n\t});\n\n\tit(\"is a positive integer\", () => {\n\t\tassert.ok(MANY_IMAGE_MAX_DIMENSION > 0);\n\t\tassert.equal(MANY_IMAGE_MAX_DIMENSION, Math.floor(MANY_IMAGE_MAX_DIMENSION));\n\t});\n});\n\n// ─── helpers ──────────────────────────────────────────────────────────────────\n\nfunction makeUserMsg(content: Message[\"content\"] & any): Message {\n\treturn { role: \"user\", content, timestamp: Date.now() } as Message;\n}\n\nfunction makeAssistantMsg(text: string): Message {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [{ type: \"text\", text }],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t} as Message;\n}\n\nfunction makeToolResultMsg(images: number): Message {\n\tconst content: any[] = [];\n\tfor (let i = 0; i < images; i++) {\n\t\tcontent.push({ type: \"image\", data: `img${i}`, mimeType: \"image/png\" });\n\t}\n\treturn {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: `tc${Math.random()}`,\n\t\ttoolName: \"screenshot\",\n\t\tcontent,\n\t\tisError: false,\n\t\ttimestamp: Date.now(),\n\t} as Message;\n}\n\n// ─── downsizeConversationImages ───────────────────────────────────────────────\n\ndescribe(\"downsizeConversationImages\", () => {\n\tit(\"counts images in user and toolResult messages\", () => {\n\t\tconst messages: Message[] = [\n\t\t\tmakeUserMsg([\n\t\t\t\t{ type: \"image\", data: \"img1\", mimeType: \"image/png\" },\n\t\t\t\t{ type: \"image\", data: \"img2\", mimeType: \"image/png\" },\n\t\t\t]),\n\t\t\tmakeAssistantMsg(\"I see them\"),\n\t\t\tmakeToolResultMsg(1),\n\t\t];\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\tassert.equal(result.imageCount, 3);\n\t});\n\n\tit(\"returns processed=false when no images present\", () => {\n\t\tconst messages: Message[] = [\n\t\t\tmakeUserMsg(\"just text\"),\n\t\t\tmakeAssistantMsg(\"reply\"),\n\t\t];\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\tassert.equal(result.imageCount, 0);\n\t\tassert.equal(result.processed, false);\n\t});\n\n\tit(\"returns processed=false when image count <= RECENT_IMAGES_TO_KEEP\", () => {\n\t\tconst messages: Message[] = [\n\t\t\tmakeUserMsg([\n\t\t\t\t{ type: \"image\", data: \"img1\", mimeType: \"image/png\" },\n\t\t\t]),\n\t\t\tmakeAssistantMsg(\"got it\"),\n\t\t];\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\tassert.equal(result.imageCount, 1);\n\t\tassert.equal(result.processed, false);\n\t});\n\n\tit(\"strips older images when many images present, preserves recent ones\", () => {\n\t\tconst messages: Message[] = [];\n\t\tfor (let i = 0; i < 25; i++) {\n\t\t\tmessages.push(\n\t\t\t\tmakeUserMsg([\n\t\t\t\t\t{ type: \"text\", text: `message ${i}` },\n\t\t\t\t\t{ type: \"image\", data: `img${i}`, mimeType: \"image/png\" },\n\t\t\t\t]),\n\t\t\t);\n\t\t\tmessages.push(makeAssistantMsg(`reply ${i}`));\n\t\t}\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\tassert.ok(result.processed);\n\t\tassert.equal(result.imageCount, 25);\n\t\tassert.equal(result.strippedCount, 20); // 25 - 5 recent\n\n\t\t// Count remaining images\n\t\tlet remainingImages = 0;\n\t\tfor (const msg of messages) {\n\t\t\tif (msg.role === \"assistant\") continue;\n\t\t\tif (typeof msg.content === \"string\") continue;\n\t\t\tconst arr = msg.content as any[];\n\t\t\tfor (const block of arr) {\n\t\t\t\tif (block.type === \"image\") remainingImages++;\n\t\t\t}\n\t\t}\n\t\tassert.equal(remainingImages, 5, \"Should keep exactly 5 most recent images\");\n\n\t\t// The 5 most recent user messages (indices 40,42,44,46,48) should have images\n\t\tfor (let i = 20; i < 25; i++) {\n\t\t\tconst userMsg = messages[i * 2]; // user messages at even indices\n\t\t\tconst arr = userMsg.content as any[];\n\t\t\tconst hasImage = arr.some((c: any) => c.type === \"image\");\n\t\t\tassert.ok(hasImage, `Recent message ${i} should retain its image`);\n\t\t}\n\t});\n\n\tit(\"adds text placeholder when stripping an image\", () => {\n\t\tconst messages: Message[] = [];\n\t\tfor (let i = 0; i < 10; i++) {\n\t\t\tmessages.push(\n\t\t\t\tmakeUserMsg([\n\t\t\t\t\t{ type: \"image\", data: `img${i}`, mimeType: \"image/jpeg\" },\n\t\t\t\t]),\n\t\t\t);\n\t\t\tmessages.push(makeAssistantMsg(`reply ${i}`));\n\t\t}\n\n\t\tdownsizeConversationImages(messages);\n\n\t\t// First message's image should have been replaced with text\n\t\tconst firstMsg = messages[0];\n\t\tconst arr = firstMsg.content as any[];\n\t\tconst placeholder = arr.find(\n\t\t\t(c: any) => c.type === \"text\" && c.text.includes(\"[image removed\"),\n\t\t);\n\t\tassert.ok(placeholder, \"Stripped image should be replaced with text placeholder\");\n\t\tassert.ok(\n\t\t\tplaceholder.text.includes(\"image/jpeg\"),\n\t\t\t\"Placeholder should mention original mime type\",\n\t\t);\n\t});\n\n\tit(\"handles toolResult messages with images\", () => {\n\t\tconst messages: Message[] = [];\n\t\tfor (let i = 0; i < 10; i++) {\n\t\t\tmessages.push(makeToolResultMsg(1));\n\t\t\tmessages.push(makeAssistantMsg(`reply ${i}`));\n\t\t}\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\tassert.equal(result.imageCount, 10);\n\t\tassert.equal(result.strippedCount, 5);\n\t\tassert.ok(result.processed);\n\t});\n\n\tit(\"handles mixed user and toolResult images\", () => {\n\t\tconst messages: Message[] = [];\n\t\tfor (let i = 0; i < 8; i++) {\n\t\t\tmessages.push(\n\t\t\t\tmakeUserMsg([\n\t\t\t\t\t{ type: \"text\", text: `check ${i}` },\n\t\t\t\t\t{ type: \"image\", data: `uimg${i}`, mimeType: \"image/png\" },\n\t\t\t\t]),\n\t\t\t);\n\t\t\tmessages.push(makeAssistantMsg(`processing ${i}`));\n\t\t\tmessages.push(makeToolResultMsg(1));\n\t\t\tmessages.push(makeAssistantMsg(`done ${i}`));\n\t\t}\n\n\t\tconst result = downsizeConversationImages(messages);\n\t\t// 8 user images + 8 tool result images = 16 total\n\t\tassert.equal(result.imageCount, 16);\n\t\tassert.equal(result.strippedCount, 11); // 16 - 5 recent\n\t});\n});\n"]}
@@ -1,9 +0,0 @@
1
- /**
2
- * messages.test.ts — Tests for convertToLlm custom message handling.
3
- *
4
- * Reproduction test for #3026: background job completion notifications
5
- * delivered as custom messages must be clearly distinguishable from
6
- * user-typed input when converted to LLM messages.
7
- */
8
- export {};
9
- //# sourceMappingURL=messages.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"messages.test.d.ts","sourceRoot":"","sources":["../../src/core/messages.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,86 +0,0 @@
1
- /**
2
- * messages.test.ts — Tests for convertToLlm custom message handling.
3
- *
4
- * Reproduction test for #3026: background job completion notifications
5
- * delivered as custom messages must be clearly distinguishable from
6
- * user-typed input when converted to LLM messages.
7
- */
8
- import test from "node:test";
9
- import assert from "node:assert/strict";
10
- import { convertToLlm } from "./messages.js";
11
- /** Extract the first content block from a message, asserting array content. */
12
- function firstTextBlock(msg) {
13
- const { content } = msg;
14
- assert.ok(Array.isArray(content), "Expected content to be an array");
15
- const block = content[0];
16
- assert.ok(typeof block === "object" && block !== null, "Expected first block to be an object");
17
- return block;
18
- }
19
- test("convertToLlm wraps custom messages with system notification prefix", () => {
20
- const customMsg = {
21
- role: "custom",
22
- customType: "async_job_result",
23
- content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
24
- display: true,
25
- timestamp: Date.now(),
26
- };
27
- const result = convertToLlm([customMsg]);
28
- assert.equal(result.length, 1);
29
- assert.equal(result[0].role, "user");
30
- // The content must include a system notification wrapper so the LLM
31
- // does not confuse it with user input (#3026).
32
- const text = firstTextBlock(result[0]);
33
- assert.equal(text.type, "text");
34
- assert.ok("text" in text && text.text.includes("[system notification"), "Custom message should be wrapped with system notification marker");
35
- });
36
- test("convertToLlm wraps custom messages with array content", () => {
37
- const customMsg = {
38
- role: "custom",
39
- customType: "bg-shell-status",
40
- content: [{ type: "text", text: "Background processes:\n ✓ bg1 dev-server :3000" }],
41
- display: false,
42
- timestamp: Date.now(),
43
- };
44
- const result = convertToLlm([customMsg]);
45
- assert.equal(result.length, 1);
46
- assert.equal(result[0].role, "user");
47
- const text = firstTextBlock(result[0]);
48
- assert.equal(text.type, "text");
49
- assert.ok("text" in text && text.text.includes("[system notification"), "Custom message with array content should be wrapped with system notification marker");
50
- });
51
- test("convertToLlm includes customType in notification wrapper", () => {
52
- const customMsg = {
53
- role: "custom",
54
- customType: "async_job_result",
55
- content: "job output here",
56
- display: true,
57
- timestamp: Date.now(),
58
- };
59
- const result = convertToLlm([customMsg]);
60
- const text = firstTextBlock(result[0]);
61
- assert.ok("text" in text && text.text.includes("async_job_result"), "Notification wrapper should include the customType for context");
62
- });
63
- test("convertToLlm notification wrapper instructs LLM not to treat as user input", () => {
64
- const customMsg = {
65
- role: "custom",
66
- customType: "async_job_result",
67
- content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
68
- display: true,
69
- timestamp: Date.now(),
70
- };
71
- const result = convertToLlm([customMsg]);
72
- const text = firstTextBlock(result[0]);
73
- assert.ok("text" in text && text.text.includes("not user input"), "Notification should explicitly state this is not user input");
74
- });
75
- test("convertToLlm preserves user messages without wrapper", () => {
76
- const userMsg = {
77
- role: "user",
78
- content: [{ type: "text", text: "Hello world" }],
79
- timestamp: Date.now(),
80
- };
81
- const result = convertToLlm([userMsg]);
82
- assert.equal(result.length, 1);
83
- const text = firstTextBlock(result[0]);
84
- assert.ok("text" in text && text.text === "Hello world", "User messages should pass through unchanged");
85
- });
86
- //# sourceMappingURL=messages.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"messages.test.js","sourceRoot":"","sources":["../../src/core/messages.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC;AAEjE,+EAA+E;AAC/E,SAAS,cAAc,CAAC,GAA4C;IACnE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,iCAAiC,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,sCAAsC,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC;AACd,CAAC;AAED,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;IAC/E,MAAM,SAAS,GAAkB;QAChC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,kBAAkB;QAC9B,OAAO,EAAE,4DAA4D;QACrE,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAErC,oEAAoE;IACpE,+CAA+C;IAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,CACR,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC5D,kEAAkE,CAClE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;IAClE,MAAM,SAAS,GAAkB;QAChC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,iBAAiB;QAC7B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iDAAiD,EAAE,CAAC;QACpF,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAErC,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,CACR,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC5D,qFAAqF,CACrF,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACrE,MAAM,SAAS,GAAkB;QAChC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,kBAAkB;QAC9B,OAAO,EAAE,iBAAiB;QAC1B,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,CACR,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EACxD,gEAAgE,CAChE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4EAA4E,EAAE,GAAG,EAAE;IACvF,MAAM,SAAS,GAAkB;QAChC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,kBAAkB;QAC9B,OAAO,EAAE,4DAA4D;QACrE,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,CACR,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EACtD,6DAA6D,CAC7D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACjE,MAAM,OAAO,GAAG;QACf,IAAI,EAAE,MAAe;QACrB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QACzD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,CACR,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAC7C,6CAA6C,CAC7C,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["/**\n * messages.test.ts — Tests for convertToLlm custom message handling.\n *\n * Reproduction test for #3026: background job completion notifications\n * delivered as custom messages must be clearly distinguishable from\n * user-typed input when converted to LLM messages.\n */\n\nimport test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { convertToLlm, type CustomMessage } from \"./messages.js\";\n\n/** Extract the first content block from a message, asserting array content. */\nfunction firstTextBlock(msg: ReturnType<typeof convertToLlm>[number]) {\n\tconst { content } = msg;\n\tassert.ok(Array.isArray(content), \"Expected content to be an array\");\n\tconst block = content[0];\n\tassert.ok(typeof block === \"object\" && block !== null, \"Expected first block to be an object\");\n\treturn block;\n}\n\ntest(\"convertToLlm wraps custom messages with system notification prefix\", () => {\n\tconst customMsg: CustomMessage = {\n\t\trole: \"custom\",\n\t\tcustomType: \"async_job_result\",\n\t\tcontent: \"**Background job done: bg_abc123** (sleep 2, 2.1s)\\n\\ndone\",\n\t\tdisplay: true,\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst result = convertToLlm([customMsg]);\n\tassert.equal(result.length, 1);\n\tassert.equal(result[0].role, \"user\");\n\n\t// The content must include a system notification wrapper so the LLM\n\t// does not confuse it with user input (#3026).\n\tconst text = firstTextBlock(result[0]);\n\tassert.equal(text.type, \"text\");\n\tassert.ok(\n\t\t\"text\" in text && text.text.includes(\"[system notification\"),\n\t\t\"Custom message should be wrapped with system notification marker\",\n\t);\n});\n\ntest(\"convertToLlm wraps custom messages with array content\", () => {\n\tconst customMsg: CustomMessage = {\n\t\trole: \"custom\",\n\t\tcustomType: \"bg-shell-status\",\n\t\tcontent: [{ type: \"text\", text: \"Background processes:\\n ✓ bg1 dev-server :3000\" }],\n\t\tdisplay: false,\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst result = convertToLlm([customMsg]);\n\tassert.equal(result.length, 1);\n\tassert.equal(result[0].role, \"user\");\n\n\tconst text = firstTextBlock(result[0]);\n\tassert.equal(text.type, \"text\");\n\tassert.ok(\n\t\t\"text\" in text && text.text.includes(\"[system notification\"),\n\t\t\"Custom message with array content should be wrapped with system notification marker\",\n\t);\n});\n\ntest(\"convertToLlm includes customType in notification wrapper\", () => {\n\tconst customMsg: CustomMessage = {\n\t\trole: \"custom\",\n\t\tcustomType: \"async_job_result\",\n\t\tcontent: \"job output here\",\n\t\tdisplay: true,\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst result = convertToLlm([customMsg]);\n\tconst text = firstTextBlock(result[0]);\n\tassert.ok(\n\t\t\"text\" in text && text.text.includes(\"async_job_result\"),\n\t\t\"Notification wrapper should include the customType for context\",\n\t);\n});\n\ntest(\"convertToLlm notification wrapper instructs LLM not to treat as user input\", () => {\n\tconst customMsg: CustomMessage = {\n\t\trole: \"custom\",\n\t\tcustomType: \"async_job_result\",\n\t\tcontent: \"**Background job done: bg_abc123** (sleep 2, 2.1s)\\n\\ndone\",\n\t\tdisplay: true,\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst result = convertToLlm([customMsg]);\n\tconst text = firstTextBlock(result[0]);\n\tassert.ok(\n\t\t\"text\" in text && text.text.includes(\"not user input\"),\n\t\t\"Notification should explicitly state this is not user input\",\n\t);\n});\n\ntest(\"convertToLlm preserves user messages without wrapper\", () => {\n\tconst userMsg = {\n\t\trole: \"user\" as const,\n\t\tcontent: [{ type: \"text\" as const, text: \"Hello world\" }],\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst result = convertToLlm([userMsg]);\n\tassert.equal(result.length, 1);\n\tconst text = firstTextBlock(result[0]);\n\tassert.ok(\n\t\t\"text\" in text && text.text === \"Hello world\",\n\t\t\"User messages should pass through unchanged\",\n\t);\n});\n"]}
@@ -1,9 +0,0 @@
1
- /**
2
- * RetryHandler tests — long-context entitlement 429 error handling (#2803)
3
- *
4
- * Verifies that "Extra usage is required for long context requests" errors
5
- * are classified as quota_exhausted (not rate_limit) and trigger a model
6
- * downgrade from [1m] to base when no cross-provider fallback exists.
7
- */
8
- export {};
9
- //# sourceMappingURL=retry-handler.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retry-handler.test.d.ts","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,193 +0,0 @@
1
- /**
2
- * RetryHandler tests — long-context entitlement 429 error handling (#2803)
3
- *
4
- * Verifies that "Extra usage is required for long context requests" errors
5
- * are classified as quota_exhausted (not rate_limit) and trigger a model
6
- * downgrade from [1m] to base when no cross-provider fallback exists.
7
- */
8
- import { describe, it, mock } from "node:test";
9
- import assert from "node:assert/strict";
10
- import { RetryHandler } from "./retry-handler.js";
11
- // ─── Helpers ────────────────────────────────────────────────────────────────
12
- function createMockModel(provider, id) {
13
- return {
14
- id,
15
- name: id,
16
- api: "anthropic",
17
- provider,
18
- baseUrl: "https://api.anthropic.com",
19
- reasoning: false,
20
- input: ["text"],
21
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
22
- contextWindow: 1_000_000,
23
- maxTokens: 16384,
24
- };
25
- }
26
- function errorMessage(msg) {
27
- return {
28
- role: "assistant",
29
- content: [],
30
- api: "anthropic-messages",
31
- provider: "anthropic",
32
- model: "claude-opus-4-6[1m]",
33
- usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
34
- stopReason: "error",
35
- errorMessage: msg,
36
- timestamp: Date.now(),
37
- };
38
- }
39
- function createMockDeps(overrides) {
40
- const model = overrides?.model ?? createMockModel("anthropic", "claude-opus-4-6[1m]");
41
- const emittedEvents = [];
42
- const continueFn = mock.fn(async () => { });
43
- const onModelChangeFn = mock.fn((_model) => { });
44
- const markUsageLimitReached = mock.fn(() => overrides?.markUsageLimitReachedResult ?? false);
45
- const findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);
46
- const findModel = mock.fn(overrides?.findModelResult ?? ((_provider, _modelId) => undefined));
47
- const messages = [];
48
- const deps = {
49
- agent: {
50
- continue: continueFn,
51
- state: { messages },
52
- setModel: mock.fn(),
53
- replaceMessages: mock.fn((newMessages) => {
54
- messages.length = 0;
55
- messages.push(...newMessages);
56
- }),
57
- },
58
- settingsManager: {
59
- getRetryEnabled: () => overrides?.retryEnabled ?? true,
60
- getRetrySettings: () => ({
61
- enabled: overrides?.retryEnabled ?? true,
62
- maxRetries: 5,
63
- baseDelayMs: 1000,
64
- maxDelayMs: 30000,
65
- }),
66
- },
67
- modelRegistry: {
68
- authStorage: {
69
- markUsageLimitReached,
70
- },
71
- find: findModel,
72
- },
73
- fallbackResolver: {
74
- findFallback,
75
- },
76
- getModel: () => model,
77
- getSessionId: () => "test-session",
78
- emit: (event) => emittedEvents.push(event),
79
- onModelChange: onModelChangeFn,
80
- };
81
- return { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };
82
- }
83
- // ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────
84
- describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
85
- describe("error classification", () => {
86
- it("classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit", async () => {
87
- // When the error is classified as quota_exhausted AND no alternate credentials
88
- // AND no fallback, the handler should emit fallback_chain_exhausted and stop.
89
- // If misclassified as rate_limit, it would enter the backoff loop instead.
90
- const { deps, emittedEvents, findModel } = createMockDeps({
91
- model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
92
- markUsageLimitReachedResult: false, // no alternate credentials
93
- fallbackResult: null, // no cross-provider fallback
94
- findModelResult: () => undefined, // no base model either
95
- });
96
- const handler = new RetryHandler(deps);
97
- const msg = errorMessage('429 {"type":"error","error":{"type":"rate_limit_error","message":"Extra usage is required for long context requests."}}');
98
- const result = await handler.handleRetryableError(msg);
99
- // Should NOT retry (would be true if misclassified as rate_limit entering backoff)
100
- assert.equal(result, false);
101
- // Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)
102
- const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
103
- assert.ok(chainExhausted, "Expected fallback_chain_exhausted event for entitlement error");
104
- const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
105
- assert.equal(retryStart, undefined, "Should NOT emit auto_retry_start for entitlement error");
106
- });
107
- it("still classifies regular 429 rate limits as rate_limit", async () => {
108
- // A normal "rate limit" 429 should still be classified as rate_limit
109
- const { deps, emittedEvents } = createMockDeps({
110
- model: createMockModel("anthropic", "claude-opus-4-6"),
111
- markUsageLimitReachedResult: false,
112
- fallbackResult: null,
113
- });
114
- const handler = new RetryHandler(deps);
115
- const msg = errorMessage("429 Too Many Requests");
116
- const result = await handler.handleRetryableError(msg);
117
- // Should enter the backoff loop (rate_limit path, not quota_exhausted)
118
- assert.equal(result, true);
119
- const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
120
- assert.ok(retryStart, "Regular 429 should enter backoff retry");
121
- });
122
- });
123
- describe("long-context model downgrade", () => {
124
- it("downgrades from [1m] to base model when entitlement error and no fallback", async () => {
125
- const baseModel = createMockModel("anthropic", "claude-opus-4-6");
126
- const { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({
127
- model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
128
- markUsageLimitReachedResult: false,
129
- fallbackResult: null,
130
- findModelResult: (provider, modelId) => {
131
- if (provider === "anthropic" && modelId === "claude-opus-4-6")
132
- return baseModel;
133
- return undefined;
134
- },
135
- });
136
- const handler = new RetryHandler(deps);
137
- const msg = errorMessage("Extra usage is required for long context requests.");
138
- const result = await handler.handleRetryableError(msg);
139
- assert.equal(result, true, "Should retry after downgrade");
140
- // Should have called setModel with the base model
141
- const setModelCalls = deps.agent.setModel.mock.calls;
142
- assert.equal(setModelCalls.length, 1);
143
- assert.equal(setModelCalls[0].arguments[0].id, "claude-opus-4-6");
144
- // Should have notified about model change
145
- assert.equal(onModelChangeFn.mock.calls.length, 1);
146
- // Should emit a fallback_provider_switch event indicating downgrade
147
- const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
148
- assert.ok(switchEvent, "Expected fallback_provider_switch event for downgrade");
149
- assert.ok(switchEvent.reason.includes("long context downgrade"), `reason should mention downgrade: ${switchEvent.reason}`);
150
- });
151
- it("emits fallback_chain_exhausted when base model is also unavailable", async () => {
152
- const { deps, emittedEvents } = createMockDeps({
153
- model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
154
- markUsageLimitReachedResult: false,
155
- fallbackResult: null,
156
- findModelResult: () => undefined, // base model not found
157
- });
158
- const handler = new RetryHandler(deps);
159
- const msg = errorMessage("Extra usage is required for long context requests.");
160
- const result = await handler.handleRetryableError(msg);
161
- assert.equal(result, false);
162
- const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
163
- assert.ok(chainExhausted, "Expected fallback_chain_exhausted when base model unavailable");
164
- });
165
- it("does not attempt downgrade for non-[1m] models", async () => {
166
- // When a regular model (no [1m] suffix) gets a quota_exhausted error
167
- // with no fallback, it should just stop — no downgrade attempt.
168
- const { deps, emittedEvents } = createMockDeps({
169
- model: createMockModel("anthropic", "claude-opus-4-6"),
170
- markUsageLimitReachedResult: false,
171
- fallbackResult: null,
172
- });
173
- const handler = new RetryHandler(deps);
174
- const msg = errorMessage("Extra usage is required for long context requests.");
175
- const result = await handler.handleRetryableError(msg);
176
- assert.equal(result, false);
177
- const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
178
- assert.ok(chainExhausted);
179
- // No downgrade switch should occur
180
- const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
181
- assert.equal(switchEvent, undefined, "Should not switch for non-[1m] models");
182
- });
183
- });
184
- describe("isRetryableError", () => {
185
- it("considers long-context entitlement error as retryable", () => {
186
- const { deps } = createMockDeps();
187
- const handler = new RetryHandler(deps);
188
- const msg = errorMessage("Extra usage is required for long context requests.");
189
- assert.equal(handler.isRetryableError(msg), true);
190
- });
191
- });
192
- });
193
- //# sourceMappingURL=retry-handler.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retry-handler.test.js","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RetryHandler tests — long-context entitlement 429 error handling (#2803)\n *\n * Verifies that \"Extra usage is required for long context requests\" errors\n * are classified as quota_exhausted (not rate_limit) and trigger a model\n * downgrade from [1m] to base when no cross-provider fallback exists.\n */\n\nimport { describe, it, beforeEach, mock, type Mock } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { RetryHandler, type RetryHandlerDeps } from \"./retry-handler.js\";\nimport type { Api, AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction createMockModel(provider: string, id: string): Model<Api> {\n\treturn {\n\t\tid,\n\t\tname: id,\n\t\tapi: \"anthropic\" as Api,\n\t\tprovider,\n\t\tbaseUrl: \"https://api.anthropic.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 1_000_000,\n\t\tmaxTokens: 16384,\n\t} as Model<Api>;\n}\n\nfunction errorMessage(msg: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6[1m]\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"error\",\n\t\terrorMessage: msg,\n\t\ttimestamp: Date.now(),\n\t} as AssistantMessage;\n}\n\ninterface MockDeps {\n\tdeps: RetryHandlerDeps;\n\temittedEvents: Array<Record<string, any>>;\n\tcontinueFn: Mock<() => Promise<void>>;\n\tonModelChangeFn: Mock<(model: Model<any>) => void>;\n\tmarkUsageLimitReached: Mock<(...args: any[]) => boolean>;\n\tfindFallback: Mock<(...args: any[]) => Promise<any>>;\n\tfindModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;\n}\n\nfunction createMockDeps(overrides?: {\n\tmodel?: Model<Api>;\n\tretryEnabled?: boolean;\n\tmarkUsageLimitReachedResult?: boolean;\n\tfallbackResult?: any;\n\tfindModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;\n}): MockDeps {\n\tconst model = overrides?.model ?? createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\");\n\tconst emittedEvents: Array<Record<string, any>> = [];\n\tconst continueFn = mock.fn(async () => {});\n\tconst onModelChangeFn = mock.fn((_model: Model<any>) => {});\n\tconst markUsageLimitReached = mock.fn(\n\t\t() => overrides?.markUsageLimitReachedResult ?? false,\n\t);\n\tconst findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);\n\tconst findModel = mock.fn(\n\t\toverrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),\n\t);\n\n\tconst messages: Array<{ role: string } & Record<string, any>> = [];\n\n\tconst deps: RetryHandlerDeps = {\n\t\tagent: {\n\t\t\tcontinue: continueFn,\n\t\t\tstate: { messages },\n\t\t\tsetModel: mock.fn(),\n\t\t\treplaceMessages: mock.fn((newMessages: any[]) => {\n\t\t\t\tmessages.length = 0;\n\t\t\t\tmessages.push(...newMessages);\n\t\t\t}),\n\t\t} as any,\n\t\tsettingsManager: {\n\t\t\tgetRetryEnabled: () => overrides?.retryEnabled ?? true,\n\t\t\tgetRetrySettings: () => ({\n\t\t\t\tenabled: overrides?.retryEnabled ?? true,\n\t\t\t\tmaxRetries: 5,\n\t\t\t\tbaseDelayMs: 1000,\n\t\t\t\tmaxDelayMs: 30000,\n\t\t\t}),\n\t\t} as unknown as SettingsManager,\n\t\tmodelRegistry: {\n\t\t\tauthStorage: {\n\t\t\t\tmarkUsageLimitReached,\n\t\t\t},\n\t\t\tfind: findModel,\n\t\t} as unknown as ModelRegistry,\n\t\tfallbackResolver: {\n\t\t\tfindFallback,\n\t\t} as unknown as FallbackResolver,\n\t\tgetModel: () => model,\n\t\tgetSessionId: () => \"test-session\",\n\t\temit: (event: any) => emittedEvents.push(event),\n\t\tonModelChange: onModelChangeFn,\n\t};\n\n\treturn { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };\n}\n\n// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────\n\ndescribe(\"RetryHandler — long-context entitlement 429 (#2803)\", () => {\n\n\tdescribe(\"error classification\", () => {\n\t\tit(\"classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit\", async () => {\n\t\t\t// When the error is classified as quota_exhausted AND no alternate credentials\n\t\t\t// AND no fallback, the handler should emit fallback_chain_exhausted and stop.\n\t\t\t// If misclassified as rate_limit, it would enter the backoff loop instead.\n\t\t\tconst { deps, emittedEvents, findModel } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false, // no alternate credentials\n\t\t\t\tfallbackResult: null, // no cross-provider fallback\n\t\t\t\tfindModelResult: () => undefined, // no base model either\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}'\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT retry (would be true if misclassified as rate_limit entering backoff)\n\t\t\tassert.equal(result, false);\n\n\t\t\t// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted event for entitlement error\");\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.equal(retryStart, undefined, \"Should NOT emit auto_retry_start for entitlement error\");\n\t\t});\n\n\t\tit(\"still classifies regular 429 rate limits as rate_limit\", async () => {\n\t\t\t// A normal \"rate limit\" 429 should still be classified as rate_limit\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should enter the backoff loop (rate_limit path, not quota_exhausted)\n\t\t\tassert.equal(result, true);\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Regular 429 should enter backoff retry\");\n\t\t});\n\t});\n\n\tdescribe(\"long-context model downgrade\", () => {\n\t\tit(\"downgrades from [1m] to base model when entitlement error and no fallback\", async () => {\n\t\t\tconst baseModel = createMockModel(\"anthropic\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"anthropic\" && modelId === \"claude-opus-4-6\") return baseModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"Should retry after downgrade\");\n\n\t\t\t// Should have called setModel with the base model\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1);\n\t\t\tassert.equal(setModelCalls[0].arguments[0].id, \"claude-opus-4-6\");\n\n\t\t\t// Should have notified about model change\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1);\n\n\t\t\t// Should emit a fallback_provider_switch event indicating downgrade\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event for downgrade\");\n\t\t\tassert.ok(switchEvent!.reason.includes(\"long context downgrade\"), `reason should mention downgrade: ${switchEvent!.reason}`);\n\t\t});\n\n\t\tit(\"emits fallback_chain_exhausted when base model is also unavailable\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined, // base model not found\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted when base model unavailable\");\n\t\t});\n\n\t\tit(\"does not attempt downgrade for non-[1m] models\", async () => {\n\t\t\t// When a regular model (no [1m] suffix) gets a quota_exhausted error\n\t\t\t// with no fallback, it should just stop — no downgrade attempt.\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted);\n\n\t\t\t// No downgrade switch should occur\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.equal(switchEvent, undefined, \"Should not switch for non-[1m] models\");\n\t\t});\n\t});\n\n\tdescribe(\"isRetryableError\", () => {\n\t\tit(\"considers long-context entitlement error as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\t});\n});\n"]}
@@ -1,16 +0,0 @@
1
- /**
2
- * spawn-shell-windows.test.ts — Regression test for Windows spawn ENOENT/EINVAL.
3
- *
4
- * On Windows, npm/npx/tsc and other tools are installed as .cmd batch scripts.
5
- * Node's `spawn()` without `shell: true` cannot execute .cmd files, resulting
6
- * in ENOENT or EINVAL errors. Every spawn site that may invoke a user-installed
7
- * binary (not `node` or a shell like `sh`/`bash`/`cmd`) must include
8
- * `shell: process.platform === "win32"` so the call is resolved through cmd.exe
9
- * on Windows while remaining a direct exec on POSIX.
10
- *
11
- * This test structurally scans all spawn sites and verifies the guard is present.
12
- *
13
- * Fixes: gsd-build/gsd-2#2854
14
- */
15
- export {};
16
- //# sourceMappingURL=spawn-shell-windows.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spawn-shell-windows.test.d.ts","sourceRoot":"","sources":["../../../src/core/tools/spawn-shell-windows.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}