@superblocksteam/vite-plugin-file-sync 2.0.123-next.0 → 2.0.124-next.0

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 (271) hide show
  1. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts +16 -1
  2. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
  3. package/dist/ai-service/agent/prompts/build-base-system-prompt.js +27 -1
  4. package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
  5. package/dist/ai-service/agent/prompts/build-security-scan-prompt.d.ts.map +1 -1
  6. package/dist/ai-service/agent/prompts/build-security-scan-prompt.js +3 -1
  7. package/dist/ai-service/agent/prompts/build-security-scan-prompt.js.map +1 -1
  8. package/dist/ai-service/agent/tools/apis/api-comparator.d.ts.map +1 -1
  9. package/dist/ai-service/agent/tools/apis/api-comparator.js +1 -4
  10. package/dist/ai-service/agent/tools/apis/api-comparator.js.map +1 -1
  11. package/dist/ai-service/agent/tools/apis/api-testing-state.js +7 -0
  12. package/dist/ai-service/agent/tools/apis/api-testing-state.js.map +1 -1
  13. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +1 -1
  14. package/dist/ai-service/agent/tools/apis/write-api.d.ts +2 -2
  15. package/dist/ai-service/agent/tools/build-capture-screenshot.d.ts.map +1 -1
  16. package/dist/ai-service/agent/tools/build-capture-screenshot.js +11 -33
  17. package/dist/ai-service/agent/tools/build-capture-screenshot.js.map +1 -1
  18. package/dist/ai-service/agent/tools/build-copy-directory.d.ts +1 -1
  19. package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
  20. package/dist/ai-service/agent/tools/build-finalize.js +11 -2
  21. package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
  22. package/dist/ai-service/agent/tools/build-install-packages.d.ts +41 -1
  23. package/dist/ai-service/agent/tools/build-install-packages.d.ts.map +1 -1
  24. package/dist/ai-service/agent/tools/build-install-packages.js +208 -0
  25. package/dist/ai-service/agent/tools/build-install-packages.js.map +1 -1
  26. package/dist/ai-service/agent/tools/build-lookup-npm-package.d.ts +28 -0
  27. package/dist/ai-service/agent/tools/build-lookup-npm-package.d.ts.map +1 -0
  28. package/dist/ai-service/agent/tools/build-lookup-npm-package.js +78 -0
  29. package/dist/ai-service/agent/tools/build-lookup-npm-package.js.map +1 -0
  30. package/dist/ai-service/agent/tools/build-manage-checklist.d.ts +4 -4
  31. package/dist/ai-service/agent/tools/build-navigate-preview.d.ts +16 -0
  32. package/dist/ai-service/agent/tools/build-navigate-preview.d.ts.map +1 -0
  33. package/dist/ai-service/agent/tools/build-navigate-preview.js +68 -0
  34. package/dist/ai-service/agent/tools/build-navigate-preview.js.map +1 -0
  35. package/dist/ai-service/agent/tools/build-write-file.d.ts +1 -1
  36. package/dist/ai-service/agent/tools/databases/dev-database.d.ts +9 -9
  37. package/dist/ai-service/agent/tools/index.d.ts +2 -0
  38. package/dist/ai-service/agent/tools/index.d.ts.map +1 -1
  39. package/dist/ai-service/agent/tools/index.js +2 -0
  40. package/dist/ai-service/agent/tools/index.js.map +1 -1
  41. package/dist/ai-service/agent/tools/integrations/execute-request.d.ts +3 -3
  42. package/dist/ai-service/agent/tools/report-security-findings.d.ts +11 -5
  43. package/dist/ai-service/agent/tools/report-security-findings.d.ts.map +1 -1
  44. package/dist/ai-service/agent/tools/report-security-findings.js +1 -0
  45. package/dist/ai-service/agent/tools/report-security-findings.js.map +1 -1
  46. package/dist/ai-service/agent/tools.d.ts.map +1 -1
  47. package/dist/ai-service/agent/tools.js +3 -1
  48. package/dist/ai-service/agent/tools.js.map +1 -1
  49. package/dist/ai-service/agent/tools2/tools/git.d.ts +2 -2
  50. package/dist/ai-service/agent/tools2/tools/grep.d.ts +2 -2
  51. package/dist/ai-service/agent/tools2/tools/update-test-case-status.d.ts +2 -2
  52. package/dist/ai-service/app-interface/npm-error-parser.d.ts +161 -0
  53. package/dist/ai-service/app-interface/npm-error-parser.d.ts.map +1 -0
  54. package/dist/ai-service/app-interface/npm-error-parser.js +510 -0
  55. package/dist/ai-service/app-interface/npm-error-parser.js.map +1 -0
  56. package/dist/ai-service/app-interface/npm-package-lookup.d.ts +286 -0
  57. package/dist/ai-service/app-interface/npm-package-lookup.d.ts.map +1 -0
  58. package/dist/ai-service/app-interface/npm-package-lookup.js +793 -0
  59. package/dist/ai-service/app-interface/npm-package-lookup.js.map +1 -0
  60. package/dist/ai-service/app-interface/npm-registry.d.ts +735 -47
  61. package/dist/ai-service/app-interface/npm-registry.d.ts.map +1 -1
  62. package/dist/ai-service/app-interface/npm-registry.js +1882 -153
  63. package/dist/ai-service/app-interface/npm-registry.js.map +1 -1
  64. package/dist/ai-service/app-interface/shell.d.ts +118 -1
  65. package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
  66. package/dist/ai-service/app-interface/shell.js +579 -157
  67. package/dist/ai-service/app-interface/shell.js.map +1 -1
  68. package/dist/ai-service/app-skills/manager.d.ts +1 -1
  69. package/dist/ai-service/app-skills/manager.d.ts.map +1 -1
  70. package/dist/ai-service/app-skills/manager.js +39 -7
  71. package/dist/ai-service/app-skills/manager.js.map +1 -1
  72. package/dist/ai-service/checklist/api-migration-checklist-gate.d.ts +9 -0
  73. package/dist/ai-service/checklist/api-migration-checklist-gate.d.ts.map +1 -0
  74. package/dist/ai-service/checklist/api-migration-checklist-gate.js +30 -0
  75. package/dist/ai-service/checklist/api-migration-checklist-gate.js.map +1 -0
  76. package/dist/ai-service/checklist/api-migration-origins.d.ts +4 -0
  77. package/dist/ai-service/checklist/api-migration-origins.d.ts.map +1 -0
  78. package/dist/ai-service/checklist/api-migration-origins.js +8 -0
  79. package/dist/ai-service/checklist/api-migration-origins.js.map +1 -0
  80. package/dist/ai-service/checklist/persisted-checklist-store.d.ts +2 -3
  81. package/dist/ai-service/checklist/persisted-checklist-store.d.ts.map +1 -1
  82. package/dist/ai-service/checklist/persisted-checklist-store.js +6 -7
  83. package/dist/ai-service/checklist/persisted-checklist-store.js.map +1 -1
  84. package/dist/ai-service/context-archive-paths.d.ts +4 -0
  85. package/dist/ai-service/context-archive-paths.d.ts.map +1 -0
  86. package/dist/ai-service/context-archive-paths.js +28 -0
  87. package/dist/ai-service/context-archive-paths.js.map +1 -0
  88. package/dist/ai-service/context-download.d.ts +3 -1
  89. package/dist/ai-service/context-download.d.ts.map +1 -1
  90. package/dist/ai-service/context-download.js +48 -9
  91. package/dist/ai-service/context-download.js.map +1 -1
  92. package/dist/ai-service/context-upload.d.ts +3 -2
  93. package/dist/ai-service/context-upload.d.ts.map +1 -1
  94. package/dist/ai-service/context-upload.js +44 -26
  95. package/dist/ai-service/context-upload.js.map +1 -1
  96. package/dist/ai-service/dev-database-client.d.ts +3 -11
  97. package/dist/ai-service/dev-database-client.d.ts.map +1 -1
  98. package/dist/ai-service/dev-database-client.js.map +1 -1
  99. package/dist/ai-service/features.d.ts +4 -0
  100. package/dist/ai-service/features.d.ts.map +1 -1
  101. package/dist/ai-service/features.js +8 -0
  102. package/dist/ai-service/features.js.map +1 -1
  103. package/dist/ai-service/filter-disabled-tools-for-migration.d.ts.map +1 -1
  104. package/dist/ai-service/filter-disabled-tools-for-migration.js +4 -0
  105. package/dist/ai-service/filter-disabled-tools-for-migration.js.map +1 -1
  106. package/dist/ai-service/index.d.ts +94 -0
  107. package/dist/ai-service/index.d.ts.map +1 -1
  108. package/dist/ai-service/index.js +564 -17
  109. package/dist/ai-service/index.js.map +1 -1
  110. package/dist/ai-service/llm/client.d.ts +38 -3
  111. package/dist/ai-service/llm/client.d.ts.map +1 -1
  112. package/dist/ai-service/llm/client.js +73 -22
  113. package/dist/ai-service/llm/client.js.map +1 -1
  114. package/dist/ai-service/llm/context-v2/adapter.d.ts +3 -1
  115. package/dist/ai-service/llm/context-v2/adapter.d.ts.map +1 -1
  116. package/dist/ai-service/llm/context-v2/adapter.js +11 -11
  117. package/dist/ai-service/llm/context-v2/adapter.js.map +1 -1
  118. package/dist/ai-service/llm/context-v2/compaction/client-side.d.ts +44 -0
  119. package/dist/ai-service/llm/context-v2/compaction/client-side.d.ts.map +1 -0
  120. package/dist/ai-service/llm/context-v2/compaction/client-side.js +170 -0
  121. package/dist/ai-service/llm/context-v2/compaction/client-side.js.map +1 -0
  122. package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.d.ts +56 -0
  123. package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.d.ts.map +1 -0
  124. package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.js +9 -0
  125. package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.js.map +1 -0
  126. package/dist/ai-service/llm/context-v2/compaction/index.d.ts +5 -0
  127. package/dist/ai-service/llm/context-v2/compaction/index.d.ts.map +1 -0
  128. package/dist/ai-service/llm/context-v2/compaction/index.js +3 -0
  129. package/dist/ai-service/llm/context-v2/compaction/index.js.map +1 -0
  130. package/dist/ai-service/llm/context-v2/compaction/server-side.d.ts +30 -0
  131. package/dist/ai-service/llm/context-v2/compaction/server-side.d.ts.map +1 -0
  132. package/dist/ai-service/llm/context-v2/compaction/server-side.js +130 -0
  133. package/dist/ai-service/llm/context-v2/compaction/server-side.js.map +1 -0
  134. package/dist/ai-service/llm/context-v2/context-management.d.ts +203 -0
  135. package/dist/ai-service/llm/context-v2/context-management.d.ts.map +1 -0
  136. package/dist/ai-service/llm/context-v2/context-management.js +183 -0
  137. package/dist/ai-service/llm/context-v2/context-management.js.map +1 -0
  138. package/dist/ai-service/llm/context-v2/context.d.ts +64 -22
  139. package/dist/ai-service/llm/context-v2/context.d.ts.map +1 -1
  140. package/dist/ai-service/llm/context-v2/context.js +233 -157
  141. package/dist/ai-service/llm/context-v2/context.js.map +1 -1
  142. package/dist/ai-service/llm/context-v2/conversation-context.d.ts +24 -7
  143. package/dist/ai-service/llm/context-v2/conversation-context.d.ts.map +1 -1
  144. package/dist/ai-service/llm/context-v2/conversation-context.js +1 -1
  145. package/dist/ai-service/llm/context-v2/index.d.ts +0 -4
  146. package/dist/ai-service/llm/context-v2/index.d.ts.map +1 -1
  147. package/dist/ai-service/llm/context-v2/index.js +0 -4
  148. package/dist/ai-service/llm/context-v2/index.js.map +1 -1
  149. package/dist/ai-service/llm/context-v2/manager.d.ts +24 -3
  150. package/dist/ai-service/llm/context-v2/manager.d.ts.map +1 -1
  151. package/dist/ai-service/llm/context-v2/manager.js +146 -4
  152. package/dist/ai-service/llm/context-v2/manager.js.map +1 -1
  153. package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.d.ts +2 -7
  154. package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.d.ts.map +1 -1
  155. package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.js +5 -73
  156. package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.js.map +1 -1
  157. package/dist/ai-service/llm/context-v2/storage/event-store.d.ts +57 -0
  158. package/dist/ai-service/llm/context-v2/storage/event-store.d.ts.map +1 -0
  159. package/dist/ai-service/llm/context-v2/storage/event-store.js +10 -0
  160. package/dist/ai-service/llm/context-v2/storage/event-store.js.map +1 -0
  161. package/dist/ai-service/llm/context-v2/storage/event-types.d.ts +50 -0
  162. package/dist/ai-service/llm/context-v2/storage/event-types.d.ts.map +1 -0
  163. package/dist/ai-service/llm/context-v2/storage/event-types.js +10 -0
  164. package/dist/ai-service/llm/context-v2/storage/event-types.js.map +1 -0
  165. package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.d.ts +87 -0
  166. package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.d.ts.map +1 -0
  167. package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.js +184 -0
  168. package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.js.map +1 -0
  169. package/dist/ai-service/llm/context-v2/storage/migration.d.ts +49 -0
  170. package/dist/ai-service/llm/context-v2/storage/migration.d.ts.map +1 -0
  171. package/dist/ai-service/llm/context-v2/storage/migration.js +126 -0
  172. package/dist/ai-service/llm/context-v2/storage/migration.js.map +1 -0
  173. package/dist/ai-service/llm/context-v2/types.d.ts +16 -11
  174. package/dist/ai-service/llm/context-v2/types.d.ts.map +1 -1
  175. package/dist/ai-service/llm/context-v2/types.js +2 -2
  176. package/dist/ai-service/llm/context-v2/types.js.map +1 -1
  177. package/dist/ai-service/llm/impl/clark.d.ts +8 -0
  178. package/dist/ai-service/llm/impl/clark.d.ts.map +1 -1
  179. package/dist/ai-service/llm/impl/clark.js +8 -0
  180. package/dist/ai-service/llm/impl/clark.js.map +1 -1
  181. package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -1
  182. package/dist/ai-service/llm/interaction/adapters/vercel.js +17 -1
  183. package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -1
  184. package/dist/ai-service/llm/provider.d.ts.map +1 -1
  185. package/dist/ai-service/llm/provider.js +1 -3
  186. package/dist/ai-service/llm/provider.js.map +1 -1
  187. package/dist/ai-service/llm/stream/observers/context.d.ts +23 -0
  188. package/dist/ai-service/llm/stream/observers/context.d.ts.map +1 -1
  189. package/dist/ai-service/llm/stream/observers/context.js +62 -0
  190. package/dist/ai-service/llm/stream/observers/context.js.map +1 -1
  191. package/dist/ai-service/llm/tool-context-integrity.d.ts +25 -0
  192. package/dist/ai-service/llm/tool-context-integrity.d.ts.map +1 -0
  193. package/dist/ai-service/llm/tool-context-integrity.js +141 -0
  194. package/dist/ai-service/llm/tool-context-integrity.js.map +1 -0
  195. package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts +1 -1
  196. package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts.map +1 -1
  197. package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js +6 -1
  198. package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js.map +1 -1
  199. package/dist/ai-service/skills/system/third-party-migration/skill.generated.d.ts +1 -1
  200. package/dist/ai-service/skills/system/third-party-migration/skill.generated.d.ts.map +1 -1
  201. package/dist/ai-service/skills/system/third-party-migration/skill.generated.js +3 -2
  202. package/dist/ai-service/skills/system/third-party-migration/skill.generated.js.map +1 -1
  203. package/dist/ai-service/state-machine/clark-fsm.d.ts +23 -2
  204. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  205. package/dist/ai-service/state-machine/clark-fsm.js +37 -2
  206. package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
  207. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  208. package/dist/ai-service/state-machine/handlers/agent-planning.js +29 -2
  209. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  210. package/dist/ai-service/state-machine/handlers/awaiting-user.d.ts.map +1 -1
  211. package/dist/ai-service/state-machine/handlers/awaiting-user.js +9 -0
  212. package/dist/ai-service/state-machine/handlers/awaiting-user.js.map +1 -1
  213. package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
  214. package/dist/ai-service/state-machine/handlers/llm-generating.js +25 -2
  215. package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
  216. package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.d.ts +6 -0
  217. package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.d.ts.map +1 -0
  218. package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.js +36 -0
  219. package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.js.map +1 -0
  220. package/dist/ai-service/state-machine/helpers/stable-peer.d.ts +30 -1
  221. package/dist/ai-service/state-machine/helpers/stable-peer.d.ts.map +1 -1
  222. package/dist/ai-service/state-machine/helpers/stable-peer.js +85 -2
  223. package/dist/ai-service/state-machine/helpers/stable-peer.js.map +1 -1
  224. package/dist/ai-service/state-machine/helpers/user-preferences.d.ts +8 -0
  225. package/dist/ai-service/state-machine/helpers/user-preferences.d.ts.map +1 -0
  226. package/dist/ai-service/state-machine/helpers/user-preferences.js +11 -0
  227. package/dist/ai-service/state-machine/helpers/user-preferences.js.map +1 -0
  228. package/dist/ai-service/template-renderer.d.ts +18 -1
  229. package/dist/ai-service/template-renderer.d.ts.map +1 -1
  230. package/dist/ai-service/template-renderer.js +73 -12
  231. package/dist/ai-service/template-renderer.js.map +1 -1
  232. package/dist/ai-service/types.d.ts +157 -0
  233. package/dist/ai-service/types.d.ts.map +1 -1
  234. package/dist/ai-service/types.js +137 -0
  235. package/dist/ai-service/types.js.map +1 -1
  236. package/dist/ai-service/util/llm-config-utils.d.ts +21 -22
  237. package/dist/ai-service/util/llm-config-utils.d.ts.map +1 -1
  238. package/dist/ai-service/util/llm-config-utils.js +40 -67
  239. package/dist/ai-service/util/llm-config-utils.js.map +1 -1
  240. package/dist/file-sync-vite-plugin.d.ts.map +1 -1
  241. package/dist/file-sync-vite-plugin.js +5 -0
  242. package/dist/file-sync-vite-plugin.js.map +1 -1
  243. package/dist/file-system-helpers.d.ts +17 -0
  244. package/dist/file-system-helpers.d.ts.map +1 -1
  245. package/dist/file-system-helpers.js +22 -0
  246. package/dist/file-system-helpers.js.map +1 -1
  247. package/dist/git-service/index.d.ts.map +1 -1
  248. package/dist/git-service/index.js +15 -1
  249. package/dist/git-service/index.js.map +1 -1
  250. package/dist/migration/migration-routes.d.ts.map +1 -1
  251. package/dist/migration/migration-routes.js +26 -3
  252. package/dist/migration/migration-routes.js.map +1 -1
  253. package/dist/migration/translation-prompt.d.ts.map +1 -1
  254. package/dist/migration/translation-prompt.js +5 -0
  255. package/dist/migration/translation-prompt.js.map +1 -1
  256. package/dist/migration-templates/app-fullstack/package.json +2 -2
  257. package/dist/policy-gate-callback-mapper.d.ts +24 -0
  258. package/dist/policy-gate-callback-mapper.d.ts.map +1 -0
  259. package/dist/policy-gate-callback-mapper.js +61 -0
  260. package/dist/policy-gate-callback-mapper.js.map +1 -0
  261. package/dist/policy-gate-runner.d.ts +32 -0
  262. package/dist/policy-gate-runner.d.ts.map +1 -0
  263. package/dist/policy-gate-runner.js +191 -0
  264. package/dist/policy-gate-runner.js.map +1 -0
  265. package/dist/router-parser.d.ts.map +1 -1
  266. package/dist/router-parser.js +107 -11
  267. package/dist/router-parser.js.map +1 -1
  268. package/dist/sync-service/list-dir.d.ts.map +1 -1
  269. package/dist/sync-service/list-dir.js +13 -3
  270. package/dist/sync-service/list-dir.js.map +1 -1
  271. package/package.json +28 -10
@@ -1,7 +1,9 @@
1
- import type { LanguageModel, ModelMessage, UserModelMessage, SystemModelMessage, LanguageModelUsage } from "ai";
1
+ import type { ModelMessage, UserModelMessage, SystemModelMessage, LanguageModelUsage } from "ai";
2
2
  import type { LLMObsTracer } from "../../llmobs/tracer.js";
3
+ import type { CompactionStrategy } from "./compaction/compaction-strategy.js";
3
4
  import type { ContextOptionsV2, CachingConfig } from "./config.js";
4
- import type { ContextRecordV2, CompactionCallbacks, CompactionPhase, ModeState, AttachmentsRecord, CompactionSummary } from "./types.js";
5
+ import type { EventStore } from "./storage/event-store.js";
6
+ import type { ContextRecordV2, ContextId, ModeState, AttachmentsRecord, CompactionSummary, CompactionCallbacks } from "./types.js";
5
7
  /** Strip base64 media from screenshot tool results, replacing with a text placeholder. */
6
8
  export declare function stripScreenshotMediaFromToolMessage(msg: ModelMessage): ModelMessage;
7
9
  export interface Context {
@@ -10,16 +12,29 @@ export interface Context {
10
12
  addResponse(response: ModelMessage, usage: LanguageModelUsage): Promise<void>;
11
13
  getMessages(): Promise<ModelMessage[]>;
12
14
  }
13
- export type { CompactionCallbacks, CompactionPhase, ModeState };
15
+ export type { ModeState };
14
16
  export interface ContextV2Options {
15
17
  rootDir: string;
16
- summarizationModel: LanguageModel;
17
18
  config?: Partial<ContextOptionsV2>;
18
19
  caching?: Partial<CachingConfig>;
19
20
  onPersist?: (record: ContextRecordV2) => Promise<void>;
20
- compactionCallbacks?: CompactionCallbacks;
21
21
  tracer?: LLMObsTracer;
22
22
  getModeState?: () => ModeState | undefined;
23
+ /** Event store for appending live conversation events (prompt_sent, response_received). */
24
+ eventStore?: EventStore;
25
+ /**
26
+ * Full context identifier (appId + userId + name) used to partition event
27
+ * log writes. Keying on `appId` alone would let two users sharing the same
28
+ * application surface each other's conversation history.
29
+ */
30
+ contextId?: ContextId;
31
+ /**
32
+ * Compaction strategy. Defaults to {@link ServerSideCompactionStrategy} when
33
+ * not provided so tests and ad-hoc callers can construct a ContextV2 without
34
+ * picking one. Production code paths (via ContextManagerV2) always supply a
35
+ * strategy derived from runtime config.
36
+ */
37
+ compaction?: CompactionStrategy;
23
38
  }
24
39
  export declare class ContextV2 implements Context {
25
40
  private systemPrompt?;
@@ -27,23 +42,32 @@ export declare class ContextV2 implements Context {
27
42
  private attachments?;
28
43
  private config;
29
44
  private caching;
30
- private summarizationModel;
31
45
  private queue;
32
46
  private onPersist?;
33
- private compactionCallbacks?;
34
47
  private tracer?;
35
48
  private rootDir;
36
- private pendingInputSummaries;
37
- private pendingOutputSummaries;
38
- private pendingProtection;
39
49
  private skillsNeedReload;
40
50
  private getModeState?;
51
+ private readonly eventStore?;
52
+ private readonly contextId?;
53
+ private compaction;
54
+ private compactionCallbacks?;
41
55
  private isDisposed;
42
56
  constructor(options: ContextV2Options);
43
- setCompactionCallbacks(callbacks: CompactionCallbacks | undefined): void;
44
57
  updateConfig(config: Partial<ContextOptionsV2>): void;
58
+ /**
59
+ * Swap the active compaction strategy on a live context. Called from
60
+ * `ContextManagerV2.getOrCreateContext` on a cache hit when the
61
+ * incoming `contextManagement` selection (derived from the per-request
62
+ * LD flag) differs from whatever the cached context was first
63
+ * constructed with. Without this, the first caller's strategy locks
64
+ * in for the lifetime of the cache entry and the kill-switch flag
65
+ * silently no-ops.
66
+ */
67
+ setCompactionStrategy(strategy: CompactionStrategy): void;
45
68
  dispose(): void;
46
69
  storeSummary(toolCallId: string, summary: CompactionSummary): void;
70
+ setCompactionCallbacks(callbacks: CompactionCallbacks | undefined): void;
47
71
  markSkillsNeedReload(): void;
48
72
  checkAndClearSkillsNeedReload(): boolean;
49
73
  setAttachments(attachments: AttachmentsRecord): void;
@@ -52,25 +76,43 @@ export declare class ContextV2 implements Context {
52
76
  static fromRecord(record: ContextRecordV2, options: ContextV2Options): ContextV2;
53
77
  toRecord(): ContextRecordV2;
54
78
  setSystemPrompt(prompt: SystemModelMessage): void;
55
- private collectPendingInputSummaries;
56
- private collectPendingOutputSummaries;
79
+ addUserMessage(message: UserModelMessage): Promise<void>;
80
+ addResponse(response: ModelMessage, usage: LanguageModelUsage): Promise<void>;
57
81
  /**
58
- * Collect protection flags for tool results in this message.
59
- * Returns a record mapping toolCallId to protection status, or undefined if none are protected.
60
- * Clears the pending protection flags as they are consumed.
82
+ * Runs the configured compaction strategy after the most recent response
83
+ * has been stored. For the server-side strategy this is a no-op; for the
84
+ * client-side strategy it may replace `this.messages` with a compacted set
85
+ * and flip `skillsNeedReload`.
86
+ *
87
+ * Defers when `this.messages` ends in an assistant turn whose `tool_use`
88
+ * blocks haven't been matched by a `tool_result` message yet. Running
89
+ * compaction at that point would summarize the assistant message away;
90
+ * when the matching tool result arrives in the next step it would
91
+ * reference a `toolCallId` that no longer exists, and
92
+ * `repairOrphanedToolResults` would strip it on the next `getMessages`.
93
+ * Waiting for the tool result to arrive first means both halves of the
94
+ * pair are summarized together — no orphan.
95
+ *
96
+ * Triggered from both assistant and tool responses (drop the original
97
+ * assistant-only gate) so the deferred run can fire on the tool_result
98
+ * that closes out a step's pending tool calls.
61
99
  */
62
- private collectPendingProtection;
63
- addUserMessage(message: UserModelMessage): Promise<void>;
64
- addResponse(response: ModelMessage, usage: LanguageModelUsage, options?: {
65
- skipCompaction?: boolean;
66
- }): Promise<void>;
100
+ private runCompactionIfNeeded;
67
101
  getMessages(): Promise<ModelMessage[]>;
102
+ onCompactionDetected(): Promise<void>;
103
+ /**
104
+ * Returns deduplicated tool names from messages marked as protected.
105
+ * Delegates to the active compaction strategy.
106
+ */
107
+ getProtectedToolNames(): string[];
108
+ private appendEvent;
109
+ private appendCompactionWindow;
110
+ private toEventLogEntry;
68
111
  /**
69
112
  * Returns the last known input token count from the most recent assistant message.
70
113
  * This represents the cumulative context size at the time of that turn.
71
114
  */
72
115
  private getLastKnownInputTokens;
73
116
  private persist;
74
- private compactIfNeeded;
75
117
  }
76
118
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/llm/context-v2/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/llm/context-v2/context.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,28 @@
1
1
  import { getPrefixedLogger } from "../../../util/logger.js";
2
- import { buildModeMessage } from "../../util/mode-message.js";
3
2
  import { findBreakpoints } from "./caching.js";
4
- import { compact } from "./compactor.js";
3
+ import { ServerSideCompactionStrategy } from "./compaction/server-side.js";
5
4
  import { DEFAULT_OPTIONS, DEFAULT_CACHING } from "./config.js";
6
5
  import { OperationQueue } from "./operation-queue.js";
7
- import { getTotalInputTokens, getTotalTokens } from "./token-tracker.js";
8
- import { toStoredMessage, toSdkMessages, CACHE_BREAKPOINT_PROVIDER_OPTIONS, normalizeToolMessage, stripUndefinedFromToolOutputs, repairBrokenToolCalls, repairOrphanedToolResults, normalizeReasoningProviderOptions, stripUnsignedReasoning, stripTrailingAssistantPrefill, } from "./types.js";
6
+ import { getTotalInputTokens } from "./token-tracker.js";
7
+ import { toStoredMessage, toSdkMessages, CACHE_BREAKPOINT_PROVIDER_OPTIONS, normalizeToolMessage, stripUndefinedFromToolOutputs, repairBrokenToolCalls, repairOrphanedToolResults, normalizeReasoningProviderOptions, stripUnsignedReasoning, stripTrailingAssistantPrefill, extractTokenUsage, } from "./types.js";
9
8
  import { uniquifyFilePartFilenames } from "./uniquify-filenames.js";
10
9
  const logger = getPrefixedLogger("[context-v2]");
10
+ /**
11
+ * Whether an assistant message contains `tool-call` content parts whose
12
+ * matching `tool-result` messages have not been stored yet. Used by
13
+ * `runCompactionIfNeeded` to defer compaction past the assistant turn that
14
+ * produced the call until the tool result arrives (otherwise the assistant
15
+ * tool_use gets summarized away and the upcoming tool_result is orphaned).
16
+ */
17
+ function hasPendingToolCalls(msg) {
18
+ if (msg.role !== "assistant" || !Array.isArray(msg.content)) {
19
+ return false;
20
+ }
21
+ return msg.content.some((part) => typeof part === "object" &&
22
+ part !== null &&
23
+ "type" in part &&
24
+ part.type === "tool-call");
25
+ }
11
26
  /** Check if a tool message contains an unstripped screenshot media result. */
12
27
  function hasScreenshotMedia(msg) {
13
28
  if (msg.role !== "tool" || !Array.isArray(msg.content)) {
@@ -65,51 +80,60 @@ export class ContextV2 {
65
80
  attachments;
66
81
  config;
67
82
  caching;
68
- summarizationModel;
69
83
  queue = new OperationQueue();
70
84
  onPersist;
71
- compactionCallbacks;
72
85
  tracer;
73
86
  rootDir;
74
- // Pending summaries waiting to be attached to messages
75
- pendingInputSummaries = new Map();
76
- pendingOutputSummaries = new Map();
77
- // Pending protection flags for tool calls (e.g., system skill reads)
78
- pendingProtection = new Set();
79
87
  skillsNeedReload = false;
80
88
  getModeState;
89
+ eventStore;
90
+ contextId;
91
+ compaction;
92
+ compactionCallbacks;
81
93
  // When disposed, this context may still be referenced by in-flight streams.
82
94
  // Keep it inert so stale generations cannot persist cleared history.
83
95
  isDisposed = false;
84
96
  constructor(options) {
85
97
  this.rootDir = options.rootDir;
86
- this.summarizationModel = options.summarizationModel;
87
98
  this.config = { ...DEFAULT_OPTIONS, ...options.config };
88
99
  this.caching = { ...DEFAULT_CACHING, ...options.caching };
89
100
  this.onPersist = options.onPersist;
90
- this.compactionCallbacks = options.compactionCallbacks;
91
101
  this.tracer = options.tracer;
92
102
  this.getModeState = options.getModeState;
93
- }
94
- setCompactionCallbacks(callbacks) {
95
- this.compactionCallbacks = callbacks;
103
+ this.eventStore = options.eventStore;
104
+ this.contextId = options.contextId;
105
+ this.compaction = options.compaction ?? new ServerSideCompactionStrategy();
96
106
  }
97
107
  updateConfig(config) {
98
108
  this.config = { ...this.config, ...config };
109
+ this.compaction.updateConfig(config);
110
+ }
111
+ /**
112
+ * Swap the active compaction strategy on a live context. Called from
113
+ * `ContextManagerV2.getOrCreateContext` on a cache hit when the
114
+ * incoming `contextManagement` selection (derived from the per-request
115
+ * LD flag) differs from whatever the cached context was first
116
+ * constructed with. Without this, the first caller's strategy locks
117
+ * in for the lifetime of the cache entry and the kill-switch flag
118
+ * silently no-ops.
119
+ */
120
+ setCompactionStrategy(strategy) {
121
+ if (this.compaction === strategy)
122
+ return;
123
+ this.compaction = strategy;
124
+ this.compaction.updateConfig(this.config);
125
+ this.compaction.setCallbacks(this.compactionCallbacks);
99
126
  }
100
127
  dispose() {
101
128
  this.isDisposed = true;
102
129
  this.onPersist = undefined;
103
130
  }
104
131
  storeSummary(toolCallId, summary) {
105
- if (summary.input) {
106
- this.pendingInputSummaries.set(toolCallId, summary.input);
107
- }
108
- this.pendingOutputSummaries.set(toolCallId, summary.output);
109
- // If the summary indicates protection, store that too
110
- if (summary.protected) {
111
- this.pendingProtection.add(toolCallId);
112
- }
132
+ this.compaction.storeSummary(toolCallId, summary);
133
+ }
134
+ setCompactionCallbacks(callbacks) {
135
+ this.compactionCallbacks = callbacks;
136
+ this.compaction.setCallbacks(callbacks);
113
137
  }
114
138
  markSkillsNeedReload() {
115
139
  this.skillsNeedReload = true;
@@ -154,70 +178,16 @@ export class ContextV2 {
154
178
  setSystemPrompt(prompt) {
155
179
  this.systemPrompt = toStoredMessage(prompt);
156
180
  }
157
- collectPendingInputSummaries(message) {
158
- if (message.role !== "assistant" || typeof message.content === "string") {
159
- return undefined;
160
- }
161
- const toolCallIds = message.content
162
- .filter((p) => p.type === "tool-call" && p.toolCallId)
163
- .map((p) => p.toolCallId);
164
- const summaries = {};
165
- for (const id of toolCallIds) {
166
- const summary = this.pendingInputSummaries.get(id);
167
- if (summary) {
168
- summaries[id] = summary;
169
- this.pendingInputSummaries.delete(id);
170
- }
171
- }
172
- return Object.keys(summaries).length > 0 ? summaries : undefined;
173
- }
174
- collectPendingOutputSummaries(message) {
175
- if (message.role !== "tool" || !Array.isArray(message.content)) {
176
- return undefined;
177
- }
178
- const toolCallIds = message.content
179
- .filter((p) => p.type === "tool-result" && p.toolCallId)
180
- .map((p) => p.toolCallId);
181
- const summaries = {};
182
- for (const id of toolCallIds) {
183
- const summary = this.pendingOutputSummaries.get(id);
184
- if (summary) {
185
- summaries[id] = summary;
186
- this.pendingOutputSummaries.delete(id);
187
- }
188
- }
189
- return Object.keys(summaries).length > 0 ? summaries : undefined;
190
- }
191
- /**
192
- * Collect protection flags for tool results in this message.
193
- * Returns a record mapping toolCallId to protection status, or undefined if none are protected.
194
- * Clears the pending protection flags as they are consumed.
195
- */
196
- collectPendingProtection(message) {
197
- if (message.role !== "tool" || !Array.isArray(message.content)) {
198
- return undefined;
199
- }
200
- const toolCallIds = message.content
201
- .filter((p) => p.type === "tool-result" && p.toolCallId)
202
- .map((p) => p.toolCallId);
203
- const protectedResults = {};
204
- for (const id of toolCallIds) {
205
- if (this.pendingProtection.has(id)) {
206
- protectedResults[id] = true;
207
- this.pendingProtection.delete(id);
208
- }
209
- }
210
- return Object.keys(protectedResults).length > 0
211
- ? protectedResults
212
- : undefined;
213
- }
214
181
  async addUserMessage(message) {
215
182
  return this.queue.enqueue(async () => {
216
- this.messages.push(toStoredMessage(message));
183
+ const storedMessage = toStoredMessage(message);
184
+ this.messages.push(storedMessage);
185
+ await this.appendEvent("prompt_sent", storedMessage);
217
186
  });
218
187
  }
219
- async addResponse(response, usage, options) {
220
- return this.queue.enqueue(async () => {
188
+ async addResponse(response, usage) {
189
+ await this.queue.enqueue(async () => {
190
+ let storedResponse;
221
191
  switch (response.role) {
222
192
  case "assistant": {
223
193
  // Total input tokens = non-cached + cached (prompt caching splits these)
@@ -227,14 +197,14 @@ export class ContextV2 {
227
197
  // Use the higher of reported tokens or last known to maintain monotonicity.
228
198
  const lastKnownTokens = this.getLastKnownInputTokens();
229
199
  const cumulativeInputTokens = Math.max(reportedInputTokens, lastKnownTokens);
230
- // Collect pending input summaries for tool-calls in this message
231
- const toolSummaries = this.collectPendingInputSummaries(response);
232
200
  normalizeReasoningProviderOptions(response);
233
- this.messages.push(toStoredMessage(response, {
201
+ const extraMeta = this.compaction.collectAssistantMetadata(response) ?? {};
202
+ storedResponse = toStoredMessage(response, {
234
203
  cumulativeInputTokens,
235
204
  tokenCount: usage.outputTokens,
236
- ...(toolSummaries && { toolSummaries }),
237
- }));
205
+ ...extraMeta,
206
+ });
207
+ this.messages.push(storedResponse);
238
208
  break;
239
209
  }
240
210
  case "tool": {
@@ -253,31 +223,97 @@ export class ContextV2 {
253
223
  logger.info(`Stripped media from ${strippedCount} older screenshot(s)`);
254
224
  }
255
225
  }
256
- // Collect pending output summaries for tool-results in this message
257
- const toolSummaries = this.collectPendingOutputSummaries(normalized);
258
- // Collect protection flags for individual tool results
259
- const protectedResults = this.collectPendingProtection(normalized);
260
- this.messages.push(toStoredMessage(normalized, {
261
- ...(toolSummaries && { toolSummaries }),
262
- ...(protectedResults && { protected: protectedResults }),
263
- }));
226
+ const extraMeta = this.compaction.collectToolMetadata(normalized) ?? {};
227
+ storedResponse = toStoredMessage(normalized, extraMeta);
228
+ this.messages.push(storedResponse);
264
229
  break;
265
230
  }
266
231
  default:
267
- this.messages.push(toStoredMessage(response));
232
+ storedResponse = toStoredMessage(response);
233
+ this.messages.push(storedResponse);
268
234
  break;
269
235
  }
270
- if (!options?.skipCompaction) {
271
- await this.compactIfNeeded(usage);
236
+ if (response.role === "assistant" || response.role === "tool") {
237
+ const eventUsage = response.role === "assistant" ? extractTokenUsage(usage) : undefined;
238
+ await this.appendEvent("response_received", storedResponse, eventUsage);
272
239
  }
273
240
  await this.persist();
274
241
  });
242
+ // After the queued write completes, give the compaction strategy a chance
243
+ // to react. Server-side is a no-op; client-side may compact this.messages
244
+ // and flip skillsNeedReload. Must be `await` (not `return`) because the
245
+ // earlier `await ... .enqueue(...)` already settles before we reach here
246
+ // — a `return` over the previous line would have made this unreachable.
247
+ await this.runCompactionIfNeeded(response, usage);
248
+ }
249
+ /**
250
+ * Runs the configured compaction strategy after the most recent response
251
+ * has been stored. For the server-side strategy this is a no-op; for the
252
+ * client-side strategy it may replace `this.messages` with a compacted set
253
+ * and flip `skillsNeedReload`.
254
+ *
255
+ * Defers when `this.messages` ends in an assistant turn whose `tool_use`
256
+ * blocks haven't been matched by a `tool_result` message yet. Running
257
+ * compaction at that point would summarize the assistant message away;
258
+ * when the matching tool result arrives in the next step it would
259
+ * reference a `toolCallId` that no longer exists, and
260
+ * `repairOrphanedToolResults` would strip it on the next `getMessages`.
261
+ * Waiting for the tool result to arrive first means both halves of the
262
+ * pair are summarized together — no orphan.
263
+ *
264
+ * Triggered from both assistant and tool responses (drop the original
265
+ * assistant-only gate) so the deferred run can fire on the tool_result
266
+ * that closes out a step's pending tool calls.
267
+ */
268
+ async runCompactionIfNeeded(response, usage) {
269
+ if (this.isDisposed)
270
+ return;
271
+ if (response.role !== "assistant" && response.role !== "tool")
272
+ return;
273
+ return this.queue.enqueue(async () => {
274
+ const last = this.messages[this.messages.length - 1];
275
+ if (!last)
276
+ return;
277
+ if (last.role === "assistant" && hasPendingToolCalls(last)) {
278
+ return;
279
+ }
280
+ const result = await this.compaction.afterResponse({
281
+ messages: this.messages,
282
+ usage,
283
+ });
284
+ if (result.messages) {
285
+ this.messages = result.messages;
286
+ }
287
+ if (result.skillsNeedReload) {
288
+ this.skillsNeedReload = true;
289
+ }
290
+ if (result.eventLogAnchor && result.messages) {
291
+ await this.appendCompactionWindow(result.messages);
292
+ }
293
+ if (result.messages) {
294
+ await this.persist();
295
+ }
296
+ });
275
297
  }
276
298
  async getMessages() {
277
299
  return this.queue.enqueue(async () => {
300
+ // Strip system-role messages from the conversation array before
301
+ // building the wire payload. The `compaction_received` marker
302
+ // (written by `onCompactionDetected`, surfaced by
303
+ // `JsonlEventStore.loadMessages` as the anchor StoredMessage, and
304
+ // inserted in memory by `ServerSideCompactionStrategy`) carries
305
+ // `role: "system"` and is useful as an in-memory / on-disk
306
+ // breadcrumb but is not a valid conversation turn — Anthropic
307
+ // (and most other providers) only accept system messages at the
308
+ // start of the request, routed through the dedicated `system`
309
+ // parameter we set from `this.systemPrompt` below. Letting the
310
+ // marker through would put a second system-role message in the
311
+ // middle of the `messages` array and 400 the request on the
312
+ // first post-compaction turn.
313
+ const conversationMessages = this.messages.filter((msg) => msg.role !== "system");
278
314
  const allMessages = this.systemPrompt
279
- ? [this.systemPrompt, ...this.messages]
280
- : [...this.messages];
315
+ ? [this.systemPrompt, ...conversationMessages]
316
+ : [...conversationMessages];
281
317
  // Convert to SDK format (removes _superblocks metadata)
282
318
  const sanitized = toSdkMessages(allMessages);
283
319
  // Normalize malformed tool outputs and repair broken tool calls.
@@ -332,6 +368,101 @@ export class ContextV2 {
332
368
  return deduped;
333
369
  });
334
370
  }
371
+ async onCompactionDetected() {
372
+ // Serialize with `addUserMessage` / `addResponse` / `getMessages`: this
373
+ // method is driven by the stream observer and can otherwise interleave
374
+ // with a queued write, leading to lost mutations or torn state.
375
+ await this.queue.enqueue(async () => {
376
+ const result = this.compaction.onCompactionDetected(this.messages);
377
+ if (result.messages) {
378
+ this.messages = result.messages;
379
+ }
380
+ if (result.skillsNeedReload) {
381
+ this.skillsNeedReload = true;
382
+ }
383
+ if (!this.eventStore || !this.contextId) {
384
+ logger.info("Server-side compaction detected (no event store configured)");
385
+ return;
386
+ }
387
+ const marker = result.messages?.[0];
388
+ const entry = {
389
+ type: "compaction_received",
390
+ timestamp: marker?._superblocks?.timestamp ?? Date.now(),
391
+ role: "system",
392
+ content: marker?.content ?? "Server-side compaction applied",
393
+ };
394
+ const retainedMessages = result.messages?.slice(1) ?? [];
395
+ try {
396
+ await this.eventStore.appendEvent(this.contextId, entry);
397
+ for (const message of retainedMessages) {
398
+ await this.eventStore.appendEvent(this.contextId, this.toEventLogEntry(message));
399
+ }
400
+ }
401
+ catch (err) {
402
+ logger.error(`Failed to append compaction_received event: ${err}`);
403
+ }
404
+ logger.info(`Server-side compaction detected, wrote compaction_received event and replayed ${retainedMessages.length} retained message(s)`);
405
+ });
406
+ }
407
+ /**
408
+ * Returns deduplicated tool names from messages marked as protected.
409
+ * Delegates to the active compaction strategy.
410
+ */
411
+ getProtectedToolNames() {
412
+ return this.compaction.getProtectedToolNames(this.messages);
413
+ }
414
+ async appendEvent(type, message, usage) {
415
+ if (!this.eventStore || !this.contextId) {
416
+ return;
417
+ }
418
+ const raw = message;
419
+ const providerMetadata = raw.providerMetadata;
420
+ const entry = {
421
+ type,
422
+ timestamp: message._superblocks?.timestamp ?? Date.now(),
423
+ role: message.role,
424
+ content: message.content,
425
+ ...(message._superblocks != null
426
+ ? { _superblocks: message._superblocks }
427
+ : {}),
428
+ ...(providerMetadata != null ? { providerMetadata } : {}),
429
+ ...(usage && { usage }),
430
+ };
431
+ try {
432
+ await this.eventStore.appendEvent(this.contextId, entry);
433
+ }
434
+ catch (err) {
435
+ logger.error(`Failed to append ${type} event: ${err}`);
436
+ }
437
+ }
438
+ async appendCompactionWindow(messages) {
439
+ if (!this.eventStore || !this.contextId) {
440
+ return;
441
+ }
442
+ try {
443
+ for (const message of messages) {
444
+ await this.eventStore.appendEvent(this.contextId, this.toEventLogEntry(message));
445
+ }
446
+ logger.info(`Wrote ${messages.length} client-side compaction message(s) to event log`);
447
+ }
448
+ catch (err) {
449
+ logger.error(`Failed to append client-side compaction window: ${err}`);
450
+ }
451
+ }
452
+ toEventLogEntry(message) {
453
+ const raw = message;
454
+ const providerMetadata = raw.providerMetadata;
455
+ return {
456
+ type: message.role === "user" ? "prompt_sent" : "response_received",
457
+ timestamp: message._superblocks?.timestamp ?? Date.now(),
458
+ role: message.role,
459
+ content: message.content,
460
+ ...(message._superblocks != null
461
+ ? { _superblocks: message._superblocks }
462
+ : {}),
463
+ ...(providerMetadata != null ? { providerMetadata } : {}),
464
+ };
465
+ }
335
466
  /**
336
467
  * Returns the last known input token count from the most recent assistant message.
337
468
  * This represents the cumulative context size at the time of that turn.
@@ -358,60 +489,5 @@ export class ContextV2 {
358
489
  }
359
490
  }
360
491
  }
361
- async compactIfNeeded(usage) {
362
- const llmReportedTokens = getTotalTokens(usage);
363
- const threshold = this.config.contextLimit -
364
- this.config.maxOutputTokens -
365
- this.config.contextBufferTokens;
366
- if (llmReportedTokens <= threshold) {
367
- return;
368
- }
369
- logger.info(`Compaction triggered: ${llmReportedTokens} tokens > ${threshold} threshold ` +
370
- `(${this.messages.length} messages)`);
371
- const result = await compact({
372
- messages: this.messages,
373
- usage,
374
- model: this.summarizationModel,
375
- config: this.config,
376
- callbacks: this.compactionCallbacks,
377
- tracer: this.tracer,
378
- rootDir: this.rootDir,
379
- });
380
- let phase = "none";
381
- if (result.phase2Applied) {
382
- phase = "phase1+phase2";
383
- }
384
- else if (result.phase1Applied) {
385
- phase = "phase1";
386
- }
387
- logger.info(`Compaction complete (${phase}): saved ${result.tokensSaved} tokens, ${this.messages.length}→${result.messages.length} messages`);
388
- this.messages = result.messages.map((msg) => ({
389
- ...msg,
390
- _superblocks: {
391
- ...msg._superblocks,
392
- timestamp: msg._superblocks?.timestamp ?? Date.now(),
393
- },
394
- }));
395
- if (result.phase2Applied) {
396
- // Re-inject mode context that was lost when messages were replaced by the summary.
397
- try {
398
- const modeState = this.getModeState?.();
399
- if (modeState) {
400
- this.messages.push(toStoredMessage({
401
- role: "user",
402
- content: buildModeMessage(modeState.mode, modeState.planApproved),
403
- }));
404
- logger.info(`Re-injected mode context after phase 2 compaction (mode=${modeState.mode})`);
405
- }
406
- else if (this.getModeState) {
407
- logger.warn("Phase 2 compaction completed but getModeState() returned undefined; " +
408
- "mode context will NOT be re-injected");
409
- }
410
- }
411
- catch (err) {
412
- logger.error(`Failed to re-inject mode state after phase 2 compaction: ${err}`);
413
- }
414
- }
415
- }
416
492
  }
417
493
  //# sourceMappingURL=context.js.map