gsd-pi 2.78.0 → 2.78.1-dev.8a893322c

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 (559) hide show
  1. package/README.md +60 -23
  2. package/dist/bundled-resource-path.d.ts +7 -0
  3. package/dist/bundled-resource-path.js +34 -2
  4. package/dist/claude-cli-check.js +104 -33
  5. package/dist/cli-policy.d.ts +13 -0
  6. package/dist/cli-policy.js +17 -0
  7. package/dist/cli.js +95 -55
  8. package/dist/headless-query.d.ts +22 -0
  9. package/dist/headless-query.js +43 -8
  10. package/dist/headless.d.ts +10 -0
  11. package/dist/headless.js +16 -1
  12. package/dist/loader.js +9 -13
  13. package/dist/onboarding.d.ts +10 -0
  14. package/dist/onboarding.js +2 -2
  15. package/dist/provider-migrations.d.ts +2 -2
  16. package/dist/provider-migrations.js +5 -2
  17. package/dist/resource-loader.d.ts +5 -2
  18. package/dist/resource-loader.js +30 -13
  19. package/dist/resources/.managed-resources-content-hash +1 -0
  20. package/dist/resources/extensions/claude-code-cli/readiness.js +128 -32
  21. package/dist/resources/extensions/google-search/index.js +2 -6
  22. package/dist/resources/extensions/gsd/auto/loop.js +23 -0
  23. package/dist/resources/extensions/gsd/auto/phases.js +5 -13
  24. package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
  25. package/dist/resources/extensions/gsd/auto/session.js +5 -6
  26. package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
  27. package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
  28. package/dist/resources/extensions/gsd/auto-prompts.js +63 -2
  29. package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
  30. package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
  31. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  33. package/dist/resources/extensions/gsd/auto-worktree.js +60 -13
  34. package/dist/resources/extensions/gsd/auto.js +14 -5
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
  36. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
  37. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  38. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
  39. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +112 -31
  40. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
  41. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
  42. package/dist/resources/extensions/gsd/bootstrap/system-context.js +45 -8
  43. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
  44. package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
  45. package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
  46. package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
  47. package/dist/resources/extensions/gsd/commands-config.js +3 -2
  48. package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
  49. package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
  50. package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
  52. package/dist/resources/extensions/gsd/commands-worktree.js +309 -0
  53. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  54. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  55. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  56. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
  57. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  58. package/dist/resources/extensions/gsd/forensics.js +10 -8
  59. package/dist/resources/extensions/gsd/git-service.js +12 -5
  60. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  61. package/dist/resources/extensions/gsd/guided-flow.js +25 -24
  62. package/dist/resources/extensions/gsd/home-dir.js +16 -0
  63. package/dist/resources/extensions/gsd/key-manager.js +2 -1
  64. package/dist/resources/extensions/gsd/memory-store.js +66 -31
  65. package/dist/resources/extensions/gsd/migrate/command.js +3 -2
  66. package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
  67. package/dist/resources/extensions/gsd/model-router.js +114 -9
  68. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
  69. package/dist/resources/extensions/gsd/preferences-models.js +91 -15
  70. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  71. package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
  72. package/dist/resources/extensions/gsd/preferences.js +5 -3
  73. package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
  74. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  75. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  77. package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  78. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
  79. package/dist/resources/extensions/gsd/state.js +42 -0
  80. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  81. package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
  82. package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
  83. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  84. package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
  85. package/dist/resources/extensions/gsd/worktree-command.js +26 -46
  86. package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
  87. package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
  88. package/dist/resources/extensions/gsd/worktree-root.js +124 -0
  89. package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
  90. package/dist/resources/extensions/gsd/worktree.js +4 -115
  91. package/dist/resources/extensions/mcp-client/index.js +6 -9
  92. package/dist/resources/extensions/ollama/index.js +15 -2
  93. package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
  94. package/dist/resources/extensions/ollama/ollama-client.js +40 -4
  95. package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
  96. package/dist/resources/extensions/subagent/index.js +324 -178
  97. package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
  98. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  99. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  100. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  101. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  102. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  103. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  104. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  105. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  106. package/dist/rtk-shared.d.ts +3 -0
  107. package/dist/rtk-shared.js +17 -0
  108. package/dist/rtk.d.ts +2 -5
  109. package/dist/rtk.js +3 -20
  110. package/dist/runtime-checks.d.ts +27 -0
  111. package/dist/runtime-checks.js +38 -0
  112. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  113. package/dist/web/standalone/.next/BUILD_ID +1 -1
  114. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  115. package/dist/web/standalone/.next/build-manifest.json +4 -4
  116. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  117. package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
  118. package/dist/web/standalone/.next/required-server-files.json +3 -3
  119. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
  194. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  208. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  210. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  212. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  214. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/app/index.html +1 -1
  224. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  225. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  226. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  227. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  228. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  229. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  230. package/dist/web/standalone/.next/server/app/page.js +2 -2
  231. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  233. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  234. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  235. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  237. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/middleware.js +2 -2
  239. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  240. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  241. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  242. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  243. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  244. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  245. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
  249. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
  250. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
  252. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
  253. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
  254. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  256. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  257. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
  258. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  259. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  260. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
  261. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  262. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  263. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  264. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  265. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  266. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  267. package/dist/web/standalone/package.json +2 -1
  268. package/dist/web/standalone/server.js +1 -1
  269. package/dist/welcome-screen.js +27 -1
  270. package/dist/worktree-cli.d.ts +1 -0
  271. package/dist/worktree-cli.js +9 -3
  272. package/dist/worktree-status-banner.d.ts +1 -0
  273. package/dist/worktree-status-banner.js +132 -0
  274. package/package.json +1 -3
  275. package/packages/daemon/package.json +2 -2
  276. package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
  277. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
  278. package/packages/mcp-server/dist/alias-telemetry.js +30 -0
  279. package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
  280. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  281. package/packages/mcp-server/dist/workflow-tools.js +74 -46
  282. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  283. package/packages/mcp-server/package.json +2 -2
  284. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  285. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  286. package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
  287. package/packages/mcp-server/src/workflow-tools.ts +93 -58
  288. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  289. package/packages/native/package.json +1 -1
  290. package/packages/native/tsconfig.tsbuildinfo +1 -1
  291. package/packages/pi-agent-core/package.json +1 -1
  292. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  293. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
  294. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
  295. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
  296. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
  297. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  298. package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
  299. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  300. package/packages/pi-ai/dist/types.d.ts +13 -0
  301. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/types.js.map +1 -1
  303. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  304. package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
  305. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  306. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
  307. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  308. package/packages/pi-ai/package.json +1 -1
  309. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  310. package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
  311. package/packages/pi-ai/src/types.ts +13 -0
  312. package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
  313. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
  314. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  315. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
  317. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/messages.js +4 -0
  320. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
  322. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
  324. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
  326. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
  328. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
  330. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
  332. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
  334. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
  336. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
  337. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
  338. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
  339. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  340. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
  342. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
  344. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
  346. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
  351. package/packages/pi-coding-agent/package.json +1 -1
  352. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
  353. package/packages/pi-coding-agent/src/core/messages.ts +4 -0
  354. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
  355. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
  356. package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
  357. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  358. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
  360. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  361. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  362. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  363. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  364. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
  365. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  366. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  367. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  368. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  369. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  370. package/packages/pi-tui/package.json +1 -1
  371. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
  372. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  373. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  374. package/packages/rpc-client/package.json +1 -1
  375. package/pkg/package.json +1 -1
  376. package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
  377. package/src/resources/extensions/google-search/index.ts +2 -9
  378. package/src/resources/extensions/gsd/auto/loop.ts +24 -2
  379. package/src/resources/extensions/gsd/auto/phases.ts +6 -14
  380. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
  381. package/src/resources/extensions/gsd/auto/session.ts +5 -6
  382. package/src/resources/extensions/gsd/auto/types.ts +1 -0
  383. package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
  384. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
  385. package/src/resources/extensions/gsd/auto-prompts.ts +60 -2
  386. package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
  387. package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
  388. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  389. package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
  390. package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
  391. package/src/resources/extensions/gsd/auto.ts +14 -4
  392. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
  393. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
  394. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  395. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
  396. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +121 -31
  397. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
  398. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
  399. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -8
  400. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
  401. package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
  402. package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
  403. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  404. package/src/resources/extensions/gsd/commands-config.ts +3 -2
  405. package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
  406. package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
  407. package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
  408. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
  409. package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
  410. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  411. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  412. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  413. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
  414. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  415. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  416. package/src/resources/extensions/gsd/forensics.ts +12 -7
  417. package/src/resources/extensions/gsd/git-service.ts +13 -5
  418. package/src/resources/extensions/gsd/gsd-db.ts +12 -2
  419. package/src/resources/extensions/gsd/guided-flow.ts +27 -26
  420. package/src/resources/extensions/gsd/home-dir.ts +19 -0
  421. package/src/resources/extensions/gsd/journal.ts +4 -1
  422. package/src/resources/extensions/gsd/key-manager.ts +2 -1
  423. package/src/resources/extensions/gsd/memory-store.ts +81 -28
  424. package/src/resources/extensions/gsd/migrate/command.ts +3 -2
  425. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  426. package/src/resources/extensions/gsd/model-router.ts +172 -9
  427. package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
  428. package/src/resources/extensions/gsd/preferences-models.ts +101 -15
  429. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  430. package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
  431. package/src/resources/extensions/gsd/preferences.ts +16 -2
  432. package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
  433. package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
  434. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
  435. package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
  436. package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
  437. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
  438. package/src/resources/extensions/gsd/state.ts +42 -0
  439. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  440. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
  441. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
  442. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
  443. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
  444. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  445. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
  446. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +50 -27
  447. package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
  448. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
  449. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
  450. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
  451. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
  452. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
  453. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
  454. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
  455. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
  456. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
  457. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
  458. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
  459. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  460. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
  461. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  462. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
  463. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
  464. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  465. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
  466. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
  467. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +25 -65
  468. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
  469. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
  470. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
  471. package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
  472. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  473. package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
  474. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  475. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
  476. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
  477. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
  478. package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
  479. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
  480. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
  481. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  482. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
  483. package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
  484. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  485. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
  486. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
  487. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
  488. package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
  489. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
  490. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  491. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  492. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
  493. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +34 -0
  494. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
  495. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
  496. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
  497. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
  498. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
  499. package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
  500. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
  501. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
  502. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
  503. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
  504. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  505. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
  506. package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
  507. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
  508. package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
  509. package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
  510. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  511. package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
  512. package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
  513. package/src/resources/extensions/gsd/worktree-command.ts +31 -44
  514. package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
  516. package/src/resources/extensions/gsd/worktree-root.ts +144 -0
  517. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  518. package/src/resources/extensions/gsd/worktree.ts +8 -119
  519. package/src/resources/extensions/mcp-client/index.ts +6 -10
  520. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  521. package/src/resources/extensions/ollama/index.ts +16 -2
  522. package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
  523. package/src/resources/extensions/ollama/ollama-client.ts +41 -4
  524. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
  525. package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
  526. package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
  527. package/src/resources/extensions/subagent/index.ts +165 -7
  528. package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
  529. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  530. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  531. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  532. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  533. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  534. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  535. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  536. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  537. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  538. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
  539. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  540. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
  541. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
  542. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
  543. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
  544. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
  545. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
  546. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
  547. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  548. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
  549. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
  550. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
  551. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
  552. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  553. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  554. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
  555. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
  556. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
  557. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
  558. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → QK8fABiGPmonfTgboN0Y9}/_buildManifest.js +0 -0
  559. /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → QK8fABiGPmonfTgboN0Y9}/_ssgManifest.js +0 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=anthropic-shared.cache-breakpoint.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-shared.cache-breakpoint.test.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic-shared.cache-breakpoint.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,231 @@
1
+ // @gsd/pi-ai + anthropic-shared.cache-breakpoint.test — coverage for #5027.
2
+ // `convertMessages` must apply Anthropic `cache_control` to:
3
+ // - the last message (existing volatile-suffix anchor — preserved)
4
+ // - the most recent message flagged with `cacheBreakpoint: true`
5
+ // (new compaction-boundary anchor)
6
+ // And it must NOT exceed the 4-breakpoint limit by treating multiple
7
+ // breakpoints as one — only the most recent earns the marker.
8
+ import { describe, test } from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { buildParams, convertMessages } from "./anthropic-shared.js";
11
+ // Minimal model stub — convertMessages only reads `input` to decide whether to
12
+ // drop image blocks. Returning ["image"] keeps the conversion paths exercised.
13
+ const model = { input: ["text", "image"] };
14
+ const cacheControl = { type: "ephemeral" };
15
+ function userMsg(text, opts = {}) {
16
+ return {
17
+ role: "user",
18
+ content: text,
19
+ timestamp: 0,
20
+ ...(opts.cacheBreakpoint ? { cacheBreakpoint: true } : {}),
21
+ };
22
+ }
23
+ /** Produces a UserMessage whose content is an array of text blocks —
24
+ * the production shape emitted by `convertToLlm()` for compaction summaries. */
25
+ function userMsgArray(text, opts = {}) {
26
+ return {
27
+ role: "user",
28
+ content: [{ type: "text", text }],
29
+ timestamp: 0,
30
+ ...(opts.cacheBreakpoint ? { cacheBreakpoint: true } : {}),
31
+ };
32
+ }
33
+ function assistantMsg(text) {
34
+ return {
35
+ role: "assistant",
36
+ content: [{ type: "text", text }],
37
+ api: "anthropic-messages",
38
+ provider: "anthropic",
39
+ model: "claude-sonnet-4-6",
40
+ usage: {
41
+ input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0,
42
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
43
+ },
44
+ stopReason: "stop",
45
+ timestamp: 0,
46
+ };
47
+ }
48
+ /** Returns whether the message at the given index has cache_control on its last block. */
49
+ function hasCacheControl(params, index) {
50
+ const param = params[index];
51
+ if (!param || param.role !== "user")
52
+ return false;
53
+ if (!Array.isArray(param.content))
54
+ return false;
55
+ const lastBlock = param.content[param.content.length - 1];
56
+ return Boolean(lastBlock && lastBlock.cache_control);
57
+ }
58
+ describe("convertMessages — cache breakpoints (#5027)", () => {
59
+ test("with no cacheControl option: no breakpoints are placed", () => {
60
+ const result = convertMessages([userMsg("hello"), assistantMsg("hi"), userMsg("again")], model, false);
61
+ for (let i = 0; i < result.length; i++) {
62
+ assert.equal(hasCacheControl(result, i), false, `index ${i} should have no cache_control`);
63
+ }
64
+ });
65
+ test("no cacheBreakpoint anywhere: only the last message gets cache_control (existing behavior preserved)", () => {
66
+ const result = convertMessages([userMsg("first"), assistantMsg("response"), userMsg("second")], model, false, cacheControl);
67
+ assert.equal(hasCacheControl(result, 0), false, "first user msg has no breakpoint");
68
+ assert.equal(hasCacheControl(result, result.length - 1), true, "last msg gets the volatile-suffix anchor");
69
+ });
70
+ test("one cacheBreakpoint message: both that message AND the last message get breakpoints", () => {
71
+ const result = convertMessages([
72
+ userMsg("ancient"),
73
+ assistantMsg("ancient response"),
74
+ userMsg("[COMPACTION SUMMARY]", { cacheBreakpoint: true }),
75
+ assistantMsg("post-compaction response"),
76
+ userMsg("new turn"),
77
+ ], model, false, cacheControl);
78
+ // Find the compaction-summary index (it's the third user-shaped param)
79
+ const compactionIdx = result.findIndex((p) => p.role === "user" && Array.isArray(p.content) && p.content[0]?.text?.includes("COMPACTION SUMMARY"));
80
+ assert.ok(compactionIdx >= 0, "compaction summary should be in the params");
81
+ assert.equal(hasCacheControl(result, compactionIdx), true, "compaction boundary gets a breakpoint");
82
+ assert.equal(hasCacheControl(result, result.length - 1), true, "last msg still gets the volatile-suffix anchor");
83
+ });
84
+ test("array-content cacheBreakpoint message: breakpoint is applied (production shape for compaction summary)", () => {
85
+ // convertToLlm() emits compaction summaries as content:[{type:"text",...}];
86
+ // this exercises the array-backed branch in anthropic-shared.ts.
87
+ const result = convertMessages([
88
+ userMsgArray("[COMPACTION SUMMARY]", { cacheBreakpoint: true }),
89
+ assistantMsg("post-compaction response"),
90
+ userMsg("post-compaction turn"),
91
+ ], model, false, cacheControl);
92
+ const compactionIdx = result.findIndex((p) => p.role === "user" &&
93
+ Array.isArray(p.content) &&
94
+ p.content[0]?.text?.includes("COMPACTION SUMMARY"));
95
+ assert.ok(compactionIdx >= 0, "compaction summary param should be present");
96
+ assert.equal(hasCacheControl(result, compactionIdx), true, "array-content boundary gets cache_control");
97
+ assert.equal(hasCacheControl(result, result.length - 1), true, "last msg still gets the volatile-suffix anchor");
98
+ });
99
+ test("multiple cacheBreakpoint messages: only the most recent one earns a breakpoint (4-limit safety)", () => {
100
+ const result = convertMessages([
101
+ userMsg("[OLD COMPACTION]", { cacheBreakpoint: true }),
102
+ assistantMsg("post-old response"),
103
+ userMsg("[NEW COMPACTION]", { cacheBreakpoint: true }),
104
+ assistantMsg("post-new response"),
105
+ userMsg("latest turn"),
106
+ ], model, false, cacheControl);
107
+ const oldIdx = result.findIndex((p) => p.role === "user" && Array.isArray(p.content) && p.content[0]?.text?.includes("OLD COMPACTION"));
108
+ const newIdx = result.findIndex((p) => p.role === "user" && Array.isArray(p.content) && p.content[0]?.text?.includes("NEW COMPACTION"));
109
+ assert.equal(hasCacheControl(result, oldIdx), false, "older boundary should not earn a breakpoint");
110
+ assert.equal(hasCacheControl(result, newIdx), true, "most recent boundary earns the breakpoint");
111
+ assert.equal(hasCacheControl(result, result.length - 1), true, "last msg still gets the volatile-suffix anchor");
112
+ });
113
+ test("cacheBreakpoint on the LAST message: only one breakpoint applied (deduplication)", () => {
114
+ // When the boundary message IS the last message, applying twice would be
115
+ // a no-op overwrite but the deduplication guard avoids the double-call.
116
+ const result = convertMessages([userMsg("hello"), userMsg("[BOUNDARY AS LAST]", { cacheBreakpoint: true })], model, false, cacheControl);
117
+ assert.equal(hasCacheControl(result, result.length - 1), true);
118
+ // Only one user message besides the last, with no breakpoint
119
+ assert.equal(hasCacheControl(result, 0), false);
120
+ });
121
+ test("cacheBreakpoint flag is ignored when no cacheControl option is provided", () => {
122
+ const result = convertMessages([userMsg("[COMPACTION]", { cacheBreakpoint: true }), userMsg("turn")], model, false);
123
+ for (let i = 0; i < result.length; i++) {
124
+ assert.equal(hasCacheControl(result, i), false, `index ${i} should have no cache_control`);
125
+ }
126
+ });
127
+ test("array-content cacheBreakpoint on last message: deduplication guard prevents double application", () => {
128
+ // The boundary IS the last message — both anchors target the same param,
129
+ // so cache_control should appear exactly once.
130
+ const result = convertMessages([userMsg("prior turn"), userMsgArray("[BOUNDARY AS LAST]", { cacheBreakpoint: true })], model, false, cacheControl);
131
+ const lastParam = result[result.length - 1];
132
+ assert.ok(lastParam && Array.isArray(lastParam.content), "last param has array content");
133
+ const cacheBlocks = lastParam.content.filter((b) => b.cache_control);
134
+ assert.equal(cacheBlocks.length, 1, "cache_control applied exactly once");
135
+ assert.equal(hasCacheControl(result, 0), false, "prior turn has no cache_control");
136
+ });
137
+ });
138
+ // ─── 4-breakpoint-limit safety at buildParams level (OAuth path) ──────────
139
+ /** Count cache_control occurrences across system + tools + messages params. */
140
+ function countBreakpoints(params) {
141
+ let n = 0;
142
+ if (Array.isArray(params.system)) {
143
+ for (const block of params.system)
144
+ if (block.cache_control)
145
+ n++;
146
+ }
147
+ if (Array.isArray(params.tools)) {
148
+ for (const tool of params.tools)
149
+ if (tool.cache_control)
150
+ n++;
151
+ }
152
+ for (const m of params.messages) {
153
+ if (m.role === "user" && Array.isArray(m.content)) {
154
+ for (const block of m.content)
155
+ if (block.cache_control)
156
+ n++;
157
+ }
158
+ }
159
+ return n;
160
+ }
161
+ const buildParamsModel = {
162
+ id: "claude-sonnet-4-6",
163
+ baseUrl: "https://api.anthropic.com",
164
+ api: "anthropic-messages",
165
+ input: ["text", "image"],
166
+ maxTokens: 64000,
167
+ };
168
+ describe("buildParams — 4-breakpoint limit safety in OAuth + boundary scenario (#5027)", () => {
169
+ test("OAuth + system prompt + last user: ≤2 breakpoints (no boundary, no tools)", () => {
170
+ const ctx = {
171
+ messages: [userMsg("hello")],
172
+ systemPrompt: "You are a helpful coding assistant.",
173
+ };
174
+ const params = buildParams(buildParamsModel, ctx, true);
175
+ assert.ok(countBreakpoints(params) <= 4, `expected ≤4 breakpoints, got ${countBreakpoints(params)}`);
176
+ // One on user system block, one on last user msg.
177
+ assert.equal(countBreakpoints(params), 2);
178
+ });
179
+ test("OAuth + system prompt + boundary + last user: ≤3 breakpoints (system de-duplicated)", () => {
180
+ const ctx = {
181
+ messages: [
182
+ userMsg("[COMPACTION SUMMARY]", { cacheBreakpoint: true }),
183
+ userMsg("post-compaction turn"),
184
+ ],
185
+ systemPrompt: "You are a helpful coding assistant.",
186
+ };
187
+ const params = buildParams(buildParamsModel, ctx, true);
188
+ const count = countBreakpoints(params);
189
+ assert.ok(count <= 4, `must stay under Anthropic's 4-breakpoint limit, got ${count}`);
190
+ // system(1, the user's prompt — Claude Code header skipped) + boundary(1) + last(1) = 3.
191
+ assert.equal(count, 3);
192
+ });
193
+ test("OAuth + system prompt + tools + boundary + last user: exactly 4 breakpoints (ceiling)", () => {
194
+ // Worst-case breakpoint budget:
195
+ // system(user prompt, 1) + last tool(1) + boundary(1) + last user(1) = 4.
196
+ // The "You are Claude Code" header intentionally carries NO cache_control
197
+ // when a user systemPrompt is present (#5027), which keeps us at 4 rather than 5.
198
+ const tool = {
199
+ name: "Read",
200
+ description: "Read a file from disk.",
201
+ parameters: {
202
+ type: "object",
203
+ properties: {
204
+ path: { type: "string" },
205
+ },
206
+ required: ["path"],
207
+ },
208
+ };
209
+ const ctx = {
210
+ messages: [
211
+ userMsg("[COMPACTION SUMMARY]", { cacheBreakpoint: true }),
212
+ userMsg("post-compaction turn"),
213
+ ],
214
+ systemPrompt: "You are a helpful coding assistant.",
215
+ tools: [tool],
216
+ };
217
+ const params = buildParams(buildParamsModel, ctx, true);
218
+ const count = countBreakpoints(params);
219
+ assert.ok(count <= 4, `must stay under Anthropic's 4-breakpoint limit, got ${count}`);
220
+ // system(1) + tool(1) + boundary(1) + last-user(1) = 4 exactly.
221
+ assert.equal(count, 4);
222
+ });
223
+ test("OAuth header WITHOUT user systemPrompt still cache-marks the header", () => {
224
+ // When there's no user systemPrompt, the Claude Code header IS the
225
+ // last system block, so it correctly carries cache_control.
226
+ const ctx = { messages: [userMsg("hello")] };
227
+ const params = buildParams(buildParamsModel, ctx, true);
228
+ assert.equal(countBreakpoints(params), 2, "header(1) + last user(1) = 2");
229
+ });
230
+ });
231
+ //# sourceMappingURL=anthropic-shared.cache-breakpoint.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-shared.cache-breakpoint.test.js","sourceRoot":"","sources":["../../src/providers/anthropic-shared.cache-breakpoint.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @gsd/pi-ai + anthropic-shared.cache-breakpoint.test — coverage for #5027.\n// `convertMessages` must apply Anthropic `cache_control` to:\n// - the last message (existing volatile-suffix anchor — preserved)\n// - the most recent message flagged with `cacheBreakpoint: true`\n// (new compaction-boundary anchor)\n// And it must NOT exceed the 4-breakpoint limit by treating multiple\n// breakpoints as one — only the most recent earns the marker.\n\nimport { describe, test } from \"node:test\";\nimport assert from \"node:assert/strict\";\n\nimport { buildParams, convertMessages } from \"./anthropic-shared.js\";\nimport type { Context, Message, Model, Tool } from \"../types.js\";\nimport type { AnthropicApi } from \"./anthropic-shared.js\";\n\n// Minimal model stub — convertMessages only reads `input` to decide whether to\n// drop image blocks. Returning [\"image\"] keeps the conversion paths exercised.\nconst model = { input: [\"text\", \"image\"] } as unknown as Model<AnthropicApi>;\nconst cacheControl = { type: \"ephemeral\" as const };\n\nfunction userMsg(text: string, opts: { cacheBreakpoint?: boolean } = {}): Message {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: text,\n\t\ttimestamp: 0,\n\t\t...(opts.cacheBreakpoint ? { cacheBreakpoint: true } : {}),\n\t} as Message;\n}\n\n/** Produces a UserMessage whose content is an array of text blocks —\n * the production shape emitted by `convertToLlm()` for compaction summaries. */\nfunction userMsgArray(text: string, opts: { cacheBreakpoint?: boolean } = {}): Message {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: [{ type: \"text\", text }],\n\t\ttimestamp: 0,\n\t\t...(opts.cacheBreakpoint ? { cacheBreakpoint: true } : {}),\n\t} as Message;\n}\n\nfunction assistantMsg(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-sonnet-4-6\",\n\t\tusage: {\n\t\t\tinput: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\ttimestamp: 0,\n\t} as Message;\n}\n\n/** Returns whether the message at the given index has cache_control on its last block. */\nfunction hasCacheControl(params: ReturnType<typeof convertMessages>, index: number): boolean {\n\tconst param = params[index];\n\tif (!param || param.role !== \"user\") return false;\n\tif (!Array.isArray(param.content)) return false;\n\tconst lastBlock = param.content[param.content.length - 1];\n\treturn Boolean(lastBlock && (lastBlock as any).cache_control);\n}\n\ndescribe(\"convertMessages — cache breakpoints (#5027)\", () => {\n\ttest(\"with no cacheControl option: no breakpoints are placed\", () => {\n\t\tconst result = convertMessages([userMsg(\"hello\"), assistantMsg(\"hi\"), userMsg(\"again\")], model, false);\n\t\tfor (let i = 0; i < result.length; i++) {\n\t\t\tassert.equal(hasCacheControl(result, i), false, `index ${i} should have no cache_control`);\n\t\t}\n\t});\n\n\ttest(\"no cacheBreakpoint anywhere: only the last message gets cache_control (existing behavior preserved)\", () => {\n\t\tconst result = convertMessages(\n\t\t\t[userMsg(\"first\"), assistantMsg(\"response\"), userMsg(\"second\")],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\tassert.equal(hasCacheControl(result, 0), false, \"first user msg has no breakpoint\");\n\t\tassert.equal(hasCacheControl(result, result.length - 1), true, \"last msg gets the volatile-suffix anchor\");\n\t});\n\n\ttest(\"one cacheBreakpoint message: both that message AND the last message get breakpoints\", () => {\n\t\tconst result = convertMessages(\n\t\t\t[\n\t\t\t\tuserMsg(\"ancient\"),\n\t\t\t\tassistantMsg(\"ancient response\"),\n\t\t\t\tuserMsg(\"[COMPACTION SUMMARY]\", { cacheBreakpoint: true }),\n\t\t\t\tassistantMsg(\"post-compaction response\"),\n\t\t\t\tuserMsg(\"new turn\"),\n\t\t\t],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\t// Find the compaction-summary index (it's the third user-shaped param)\n\t\tconst compactionIdx = result.findIndex(\n\t\t\t(p) => p.role === \"user\" && Array.isArray(p.content) && (p.content as any)[0]?.text?.includes(\"COMPACTION SUMMARY\"),\n\t\t);\n\t\tassert.ok(compactionIdx >= 0, \"compaction summary should be in the params\");\n\t\tassert.equal(hasCacheControl(result, compactionIdx), true, \"compaction boundary gets a breakpoint\");\n\t\tassert.equal(hasCacheControl(result, result.length - 1), true, \"last msg still gets the volatile-suffix anchor\");\n\t});\n\n\ttest(\"array-content cacheBreakpoint message: breakpoint is applied (production shape for compaction summary)\", () => {\n\t\t// convertToLlm() emits compaction summaries as content:[{type:\"text\",...}];\n\t\t// this exercises the array-backed branch in anthropic-shared.ts.\n\t\tconst result = convertMessages(\n\t\t\t[\n\t\t\t\tuserMsgArray(\"[COMPACTION SUMMARY]\", { cacheBreakpoint: true }),\n\t\t\t\tassistantMsg(\"post-compaction response\"),\n\t\t\t\tuserMsg(\"post-compaction turn\"),\n\t\t\t],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\tconst compactionIdx = result.findIndex(\n\t\t\t(p) =>\n\t\t\t\tp.role === \"user\" &&\n\t\t\t\tArray.isArray(p.content) &&\n\t\t\t\t(p.content as any)[0]?.text?.includes(\"COMPACTION SUMMARY\"),\n\t\t);\n\t\tassert.ok(compactionIdx >= 0, \"compaction summary param should be present\");\n\t\tassert.equal(hasCacheControl(result, compactionIdx), true, \"array-content boundary gets cache_control\");\n\t\tassert.equal(hasCacheControl(result, result.length - 1), true, \"last msg still gets the volatile-suffix anchor\");\n\t});\n\n\ttest(\"multiple cacheBreakpoint messages: only the most recent one earns a breakpoint (4-limit safety)\", () => {\n\t\tconst result = convertMessages(\n\t\t\t[\n\t\t\t\tuserMsg(\"[OLD COMPACTION]\", { cacheBreakpoint: true }),\n\t\t\t\tassistantMsg(\"post-old response\"),\n\t\t\t\tuserMsg(\"[NEW COMPACTION]\", { cacheBreakpoint: true }),\n\t\t\t\tassistantMsg(\"post-new response\"),\n\t\t\t\tuserMsg(\"latest turn\"),\n\t\t\t],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\tconst oldIdx = result.findIndex(\n\t\t\t(p) => p.role === \"user\" && Array.isArray(p.content) && (p.content as any)[0]?.text?.includes(\"OLD COMPACTION\"),\n\t\t);\n\t\tconst newIdx = result.findIndex(\n\t\t\t(p) => p.role === \"user\" && Array.isArray(p.content) && (p.content as any)[0]?.text?.includes(\"NEW COMPACTION\"),\n\t\t);\n\t\tassert.equal(hasCacheControl(result, oldIdx), false, \"older boundary should not earn a breakpoint\");\n\t\tassert.equal(hasCacheControl(result, newIdx), true, \"most recent boundary earns the breakpoint\");\n\t\tassert.equal(hasCacheControl(result, result.length - 1), true, \"last msg still gets the volatile-suffix anchor\");\n\t});\n\n\ttest(\"cacheBreakpoint on the LAST message: only one breakpoint applied (deduplication)\", () => {\n\t\t// When the boundary message IS the last message, applying twice would be\n\t\t// a no-op overwrite but the deduplication guard avoids the double-call.\n\t\tconst result = convertMessages(\n\t\t\t[userMsg(\"hello\"), userMsg(\"[BOUNDARY AS LAST]\", { cacheBreakpoint: true })],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\tassert.equal(hasCacheControl(result, result.length - 1), true);\n\t\t// Only one user message besides the last, with no breakpoint\n\t\tassert.equal(hasCacheControl(result, 0), false);\n\t});\n\n\ttest(\"cacheBreakpoint flag is ignored when no cacheControl option is provided\", () => {\n\t\tconst result = convertMessages(\n\t\t\t[userMsg(\"[COMPACTION]\", { cacheBreakpoint: true }), userMsg(\"turn\")],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t);\n\t\tfor (let i = 0; i < result.length; i++) {\n\t\t\tassert.equal(hasCacheControl(result, i), false, `index ${i} should have no cache_control`);\n\t\t}\n\t});\n\n\ttest(\"array-content cacheBreakpoint on last message: deduplication guard prevents double application\", () => {\n\t\t// The boundary IS the last message — both anchors target the same param,\n\t\t// so cache_control should appear exactly once.\n\t\tconst result = convertMessages(\n\t\t\t[userMsg(\"prior turn\"), userMsgArray(\"[BOUNDARY AS LAST]\", { cacheBreakpoint: true })],\n\t\t\tmodel,\n\t\t\tfalse,\n\t\t\tcacheControl,\n\t\t);\n\t\tconst lastParam = result[result.length - 1];\n\t\tassert.ok(lastParam && Array.isArray(lastParam.content), \"last param has array content\");\n\t\tconst cacheBlocks = (lastParam!.content as any[]).filter((b) => b.cache_control);\n\t\tassert.equal(cacheBlocks.length, 1, \"cache_control applied exactly once\");\n\t\tassert.equal(hasCacheControl(result, 0), false, \"prior turn has no cache_control\");\n\t});\n});\n\n// ─── 4-breakpoint-limit safety at buildParams level (OAuth path) ──────────\n\n/** Count cache_control occurrences across system + tools + messages params. */\nfunction countBreakpoints(params: { system?: any; tools?: any[]; messages: any[] }): number {\n\tlet n = 0;\n\tif (Array.isArray(params.system)) {\n\t\tfor (const block of params.system) if (block.cache_control) n++;\n\t}\n\tif (Array.isArray(params.tools)) {\n\t\tfor (const tool of params.tools) if ((tool as any).cache_control) n++;\n\t}\n\tfor (const m of params.messages) {\n\t\tif (m.role === \"user\" && Array.isArray(m.content)) {\n\t\t\tfor (const block of m.content) if (block.cache_control) n++;\n\t\t}\n\t}\n\treturn n;\n}\n\nconst buildParamsModel = {\n\tid: \"claude-sonnet-4-6\",\n\tbaseUrl: \"https://api.anthropic.com\",\n\tapi: \"anthropic-messages\",\n\tinput: [\"text\", \"image\"],\n\tmaxTokens: 64000,\n} as unknown as Model<AnthropicApi>;\n\ndescribe(\"buildParams — 4-breakpoint limit safety in OAuth + boundary scenario (#5027)\", () => {\n\ttest(\"OAuth + system prompt + last user: ≤2 breakpoints (no boundary, no tools)\", () => {\n\t\tconst ctx: Context = {\n\t\t\tmessages: [userMsg(\"hello\")],\n\t\t\tsystemPrompt: \"You are a helpful coding assistant.\",\n\t\t} as Context;\n\t\tconst params = buildParams(buildParamsModel, ctx, true) as any;\n\t\tassert.ok(countBreakpoints(params) <= 4, `expected ≤4 breakpoints, got ${countBreakpoints(params)}`);\n\t\t// One on user system block, one on last user msg.\n\t\tassert.equal(countBreakpoints(params), 2);\n\t});\n\n\ttest(\"OAuth + system prompt + boundary + last user: ≤3 breakpoints (system de-duplicated)\", () => {\n\t\tconst ctx: Context = {\n\t\t\tmessages: [\n\t\t\t\tuserMsg(\"[COMPACTION SUMMARY]\", { cacheBreakpoint: true }),\n\t\t\t\tuserMsg(\"post-compaction turn\"),\n\t\t\t],\n\t\t\tsystemPrompt: \"You are a helpful coding assistant.\",\n\t\t} as Context;\n\t\tconst params = buildParams(buildParamsModel, ctx, true) as any;\n\t\tconst count = countBreakpoints(params);\n\t\tassert.ok(count <= 4, `must stay under Anthropic's 4-breakpoint limit, got ${count}`);\n\t\t// system(1, the user's prompt — Claude Code header skipped) + boundary(1) + last(1) = 3.\n\t\tassert.equal(count, 3);\n\t});\n\n\ttest(\"OAuth + system prompt + tools + boundary + last user: exactly 4 breakpoints (ceiling)\", () => {\n\t\t// Worst-case breakpoint budget:\n\t\t// system(user prompt, 1) + last tool(1) + boundary(1) + last user(1) = 4.\n\t\t// The \"You are Claude Code\" header intentionally carries NO cache_control\n\t\t// when a user systemPrompt is present (#5027), which keeps us at 4 rather than 5.\n\t\tconst tool: Tool = {\n\t\t\tname: \"Read\",\n\t\t\tdescription: \"Read a file from disk.\",\n\t\t\tparameters: {\n\t\t\t\ttype: \"object\" as const,\n\t\t\t\tproperties: {\n\t\t\t\t\tpath: { type: \"string\" },\n\t\t\t\t},\n\t\t\t\trequired: [\"path\"],\n\t\t\t} as any,\n\t\t};\n\t\tconst ctx: Context = {\n\t\t\tmessages: [\n\t\t\t\tuserMsg(\"[COMPACTION SUMMARY]\", { cacheBreakpoint: true }),\n\t\t\t\tuserMsg(\"post-compaction turn\"),\n\t\t\t],\n\t\t\tsystemPrompt: \"You are a helpful coding assistant.\",\n\t\t\ttools: [tool],\n\t\t} as Context;\n\t\tconst params = buildParams(buildParamsModel, ctx, true) as any;\n\t\tconst count = countBreakpoints(params);\n\t\tassert.ok(count <= 4, `must stay under Anthropic's 4-breakpoint limit, got ${count}`);\n\t\t// system(1) + tool(1) + boundary(1) + last-user(1) = 4 exactly.\n\t\tassert.equal(count, 4);\n\t});\n\n\ttest(\"OAuth header WITHOUT user systemPrompt still cache-marks the header\", () => {\n\t\t// When there's no user systemPrompt, the Claude Code header IS the\n\t\t// last system block, so it correctly carries cache_control.\n\t\tconst ctx: Context = { messages: [userMsg(\"hello\")] } as Context;\n\t\tconst params = buildParams(buildParamsModel, ctx, true) as any;\n\t\tassert.equal(countBreakpoints(params), 2, \"header(1) + last user(1) = 2\");\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-shared.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic-shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"anthropic-shared.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic-shared.ts"],"names":[],"mappings":"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"}
@@ -182,6 +182,11 @@ export function normalizeToolCallId(id) {
182
182
  /** Convert GSD messages to Anthropic SDK `MessageParam` format, applying cache control to the last user turn. */
183
183
  export function convertMessages(messages, model, isOAuthToken, cacheControl) {
184
184
  const params = [];
185
+ // Indices into `params` for messages flagged with `cacheBreakpoint: true` —
186
+ // e.g. compaction summaries. We apply cache_control to the most recent one
187
+ // (in addition to the last message) so the stable summary + kept-history
188
+ // block can earn cache reads on every post-compaction turn. (#5027)
189
+ const breakpointIndices = [];
185
190
  const transformedMessages = transformMessagesWithReport(messages, model, normalizeToolCallId, "anthropic-messages");
186
191
  for (let i = 0; i < transformedMessages.length; i++) {
187
192
  const msg = transformedMessages[i];
@@ -192,6 +197,8 @@ export function convertMessages(messages, model, isOAuthToken, cacheControl) {
192
197
  role: "user",
193
198
  content: sanitizeSurrogates(msg.content),
194
199
  });
200
+ if (msg.cacheBreakpoint)
201
+ breakpointIndices.push(params.length - 1);
195
202
  }
196
203
  }
197
204
  else {
@@ -226,6 +233,8 @@ export function convertMessages(messages, model, isOAuthToken, cacheControl) {
226
233
  role: "user",
227
234
  content: filteredBlocks,
228
235
  });
236
+ if (msg.cacheBreakpoint)
237
+ breakpointIndices.push(params.length - 1);
229
238
  }
230
239
  }
231
240
  else if (msg.role === "assistant") {
@@ -328,28 +337,42 @@ export function convertMessages(messages, model, isOAuthToken, cacheControl) {
328
337
  }
329
338
  }
330
339
  if (cacheControl && params.length > 0) {
331
- const lastMessage = params[params.length - 1];
332
- if (lastMessage.role === "user") {
333
- if (Array.isArray(lastMessage.content)) {
334
- const lastBlock = lastMessage.content[lastMessage.content.length - 1];
335
- if (lastBlock &&
336
- (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
337
- lastBlock.cache_control = cacheControl;
338
- }
339
- }
340
- else if (typeof lastMessage.content === "string") {
341
- lastMessage.content = [
342
- {
343
- type: "text",
344
- text: lastMessage.content,
345
- cache_control: cacheControl,
346
- },
347
- ];
348
- }
340
+ // Apply to the volatile suffix anchor (last user message) — existing behavior.
341
+ applyCacheControlToParam(params, params.length - 1, cacheControl);
342
+ // Apply to the most recent compaction-boundary message, if any. Capping at
343
+ // one boundary keeps us safely under Anthropic's 4-breakpoint limit
344
+ // (system + tools + boundary + last user = 4). If multiple
345
+ // cacheBreakpoint messages are present, only the most recent one the
346
+ // freshest stable boundary — earns the breakpoint. (#5027)
347
+ const mostRecentBreakpoint = breakpointIndices[breakpointIndices.length - 1];
348
+ if (mostRecentBreakpoint !== undefined && mostRecentBreakpoint !== params.length - 1) {
349
+ applyCacheControlToParam(params, mostRecentBreakpoint, cacheControl);
349
350
  }
350
351
  }
351
352
  return params;
352
353
  }
354
+ /** Apply `cache_control` to the last cacheable block of the user-role param at `index`. No-op for non-user roles. */
355
+ function applyCacheControlToParam(params, index, cacheControl) {
356
+ const param = params[index];
357
+ if (!param || param.role !== "user")
358
+ return;
359
+ if (Array.isArray(param.content)) {
360
+ const lastBlock = param.content[param.content.length - 1];
361
+ if (lastBlock &&
362
+ (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
363
+ lastBlock.cache_control = cacheControl;
364
+ }
365
+ }
366
+ else if (typeof param.content === "string") {
367
+ param.content = [
368
+ {
369
+ type: "text",
370
+ text: param.content,
371
+ cache_control: cacheControl,
372
+ },
373
+ ];
374
+ }
375
+ }
353
376
  /** Convert GSD tools to Anthropic SDK tool definitions, applying cache control to the last entry. */
354
377
  export function convertTools(tools, isOAuthToken, cacheControl) {
355
378
  if (!tools)
@@ -383,11 +406,17 @@ export function buildParams(model, context, isOAuthToken, options) {
383
406
  stream: true,
384
407
  };
385
408
  if (isOAuthToken) {
409
+ // Only the LAST system block carries `cache_control` — the boundary
410
+ // covers the entire system prefix up to that point. Putting cache_control
411
+ // on the short "You are Claude Code" header AND the user systemPrompt
412
+ // would consume two of Anthropic's 4 breakpoint slots for redundant
413
+ // coverage, leaving no room for a compaction-summary breakpoint. (#5027)
414
+ const hasUserSystemPrompt = Boolean(context.systemPrompt);
386
415
  params.system = [
387
416
  {
388
417
  type: "text",
389
418
  text: "You are Claude Code, Anthropic's official CLI for Claude.",
390
- ...(cacheControl ? { cache_control: cacheControl } : {}),
419
+ ...(cacheControl && !hasUserSystemPrompt ? { cache_control: cacheControl } : {}),
391
420
  },
392
421
  ];
393
422
  if (context.systemPrompt) {