@clinebot/core 0.0.27 → 0.0.29

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 (339) hide show
  1. package/README.md +7 -0
  2. package/dist/ClineCore.d.ts +28 -2
  3. package/dist/ClineCore.d.ts.map +1 -1
  4. package/dist/account/cline-account-service.d.ts +1 -1
  5. package/dist/account/cline-account-service.d.ts.map +1 -1
  6. package/dist/account/index.d.ts +1 -1
  7. package/dist/account/index.d.ts.map +1 -1
  8. package/dist/account/types.d.ts +5 -0
  9. package/dist/account/types.d.ts.map +1 -1
  10. package/dist/auth/bounded-ttl-cache.d.ts +14 -0
  11. package/dist/auth/bounded-ttl-cache.d.ts.map +1 -0
  12. package/dist/auth/cline.d.ts +27 -2
  13. package/dist/auth/cline.d.ts.map +1 -1
  14. package/dist/auth/oca.d.ts.map +1 -1
  15. package/dist/chat/chat-schema.d.ts +8 -8
  16. package/dist/extensions/config/agent-config-loader.d.ts.map +1 -0
  17. package/dist/{agents → extensions/config}/agent-config-parser.d.ts +2 -2
  18. package/dist/extensions/config/agent-config-parser.d.ts.map +1 -0
  19. package/dist/{agents → extensions/config}/hooks-config-loader.d.ts +1 -1
  20. package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -0
  21. package/dist/{agents → extensions/config}/index.d.ts +2 -4
  22. package/dist/extensions/config/index.d.ts.map +1 -0
  23. package/dist/{runtime/commands.d.ts → extensions/config/runtime-commands.d.ts} +2 -3
  24. package/dist/extensions/config/runtime-commands.d.ts.map +1 -0
  25. package/dist/extensions/config/unified-config-file-watcher.d.ts.map +1 -0
  26. package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -0
  27. package/dist/extensions/context/agentic-compaction.d.ts +13 -0
  28. package/dist/extensions/context/agentic-compaction.d.ts.map +1 -0
  29. package/dist/extensions/context/basic-compaction.d.ts +9 -0
  30. package/dist/extensions/context/basic-compaction.d.ts.map +1 -0
  31. package/dist/extensions/context/compaction-shared.d.ts +60 -0
  32. package/dist/extensions/context/compaction-shared.d.ts.map +1 -0
  33. package/dist/extensions/context/compaction.d.ts +20 -0
  34. package/dist/extensions/context/compaction.d.ts.map +1 -0
  35. package/dist/extensions/index.d.ts +5 -0
  36. package/dist/extensions/index.d.ts.map +1 -0
  37. package/dist/extensions/mcp/client.d.ts +3 -0
  38. package/dist/extensions/mcp/client.d.ts.map +1 -0
  39. package/dist/extensions/mcp/config-loader.d.ts.map +1 -0
  40. package/dist/extensions/mcp/index.d.ts +9 -0
  41. package/dist/extensions/mcp/index.d.ts.map +1 -0
  42. package/dist/{mcp → extensions/mcp}/manager.d.ts +1 -2
  43. package/dist/extensions/mcp/manager.d.ts.map +1 -0
  44. package/dist/extensions/mcp/name-transform.d.ts +3 -0
  45. package/dist/extensions/mcp/name-transform.d.ts.map +1 -0
  46. package/dist/extensions/mcp/policies.d.ts +15 -0
  47. package/dist/extensions/mcp/policies.d.ts.map +1 -0
  48. package/dist/extensions/mcp/tools.d.ts +4 -0
  49. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  50. package/dist/{mcp → extensions/mcp}/types.d.ts +29 -1
  51. package/dist/extensions/mcp/types.d.ts.map +1 -0
  52. package/dist/{agents → extensions/plugin}/plugin-config-loader.d.ts +1 -1
  53. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -0
  54. package/dist/{agents → extensions/plugin}/plugin-loader.d.ts +1 -1
  55. package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -0
  56. package/dist/extensions/plugin/plugin-module-import.d.ts +5 -0
  57. package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -0
  58. package/dist/{agents → extensions/plugin}/plugin-sandbox.d.ts +1 -1
  59. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -0
  60. package/dist/extensions/plugin-sandbox-bootstrap.js +485 -0
  61. package/dist/hooks/index.d.ts +4 -0
  62. package/dist/hooks/index.d.ts.map +1 -0
  63. package/dist/hooks/persistent.d.ts +64 -0
  64. package/dist/hooks/persistent.d.ts.map +1 -0
  65. package/dist/hooks/subprocess-runner.d.ts +22 -0
  66. package/dist/hooks/subprocess-runner.d.ts.map +1 -0
  67. package/dist/hooks/subprocess.d.ts +189 -0
  68. package/dist/hooks/subprocess.d.ts.map +1 -0
  69. package/dist/index.d.ts +22 -25
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +560 -447
  72. package/dist/prompt/default-system.d.ts +2 -0
  73. package/dist/prompt/default-system.d.ts.map +1 -0
  74. package/dist/providers/local-provider-service.d.ts +1 -1
  75. package/dist/providers/local-provider-service.d.ts.map +1 -1
  76. package/dist/runtime/checkpoint-hooks.d.ts +21 -0
  77. package/dist/runtime/checkpoint-hooks.d.ts.map +1 -0
  78. package/dist/runtime/hook-file-hooks.d.ts +1 -1
  79. package/dist/runtime/hook-file-hooks.d.ts.map +1 -1
  80. package/dist/runtime/rules.d.ts +1 -1
  81. package/dist/runtime/rules.d.ts.map +1 -1
  82. package/dist/runtime/runtime-builder.d.ts +1 -1
  83. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  84. package/dist/runtime/session-runtime.d.ts +25 -5
  85. package/dist/runtime/session-runtime.d.ts.map +1 -1
  86. package/dist/runtime/subprocess-sandbox.d.ts.map +1 -0
  87. package/dist/runtime/team-runtime-registry.d.ts +1 -1
  88. package/dist/runtime/team-runtime-registry.d.ts.map +1 -1
  89. package/dist/runtime/tool-approval.d.ts +1 -1
  90. package/dist/session/default-session-manager.d.ts +4 -3
  91. package/dist/session/default-session-manager.d.ts.map +1 -1
  92. package/dist/session/file-session-service.d.ts +1 -1
  93. package/dist/session/file-session-service.d.ts.map +1 -1
  94. package/dist/session/{unified-session-persistence-service.d.ts → persistence-service.d.ts} +11 -42
  95. package/dist/session/persistence-service.d.ts.map +1 -0
  96. package/dist/session/rpc-session-service.d.ts +1 -1
  97. package/dist/session/rpc-session-service.d.ts.map +1 -1
  98. package/dist/session/session-agent-events.d.ts +1 -1
  99. package/dist/session/session-artifacts.d.ts.map +1 -1
  100. package/dist/session/session-config-builder.d.ts.map +1 -1
  101. package/dist/session/session-graph.d.ts +1 -1
  102. package/dist/session/session-graph.d.ts.map +1 -1
  103. package/dist/session/session-host.d.ts.map +1 -1
  104. package/dist/session/session-manager.d.ts +6 -5
  105. package/dist/session/session-manager.d.ts.map +1 -1
  106. package/dist/session/session-manifest.d.ts +1 -1
  107. package/dist/session/session-service.d.ts +3 -2
  108. package/dist/session/session-service.d.ts.map +1 -1
  109. package/dist/session/session-team-coordination.d.ts +2 -1
  110. package/dist/session/session-team-coordination.d.ts.map +1 -1
  111. package/dist/session/utils/helpers.d.ts +51 -3
  112. package/dist/session/utils/helpers.d.ts.map +1 -1
  113. package/dist/session/utils/types.d.ts +41 -7
  114. package/dist/session/utils/types.d.ts.map +1 -1
  115. package/dist/session/workspace-manager.d.ts +1 -2
  116. package/dist/session/workspace-manager.d.ts.map +1 -1
  117. package/dist/session/workspace-manifest.d.ts +1 -22
  118. package/dist/session/workspace-manifest.d.ts.map +1 -1
  119. package/dist/storage/file-team-store.d.ts +2 -1
  120. package/dist/storage/file-team-store.d.ts.map +1 -1
  121. package/dist/storage/sqlite-team-store.d.ts +4 -1
  122. package/dist/storage/sqlite-team-store.d.ts.map +1 -1
  123. package/dist/storage/team-store.d.ts.map +1 -1
  124. package/dist/team/delegated-agent.d.ts +44 -0
  125. package/dist/team/delegated-agent.d.ts.map +1 -0
  126. package/dist/team/index.d.ts +1 -0
  127. package/dist/team/index.d.ts.map +1 -1
  128. package/dist/team/multi-agent.d.ts +229 -0
  129. package/dist/team/multi-agent.d.ts.map +1 -0
  130. package/dist/team/projections.d.ts +2 -2
  131. package/dist/team/projections.d.ts.map +1 -1
  132. package/dist/team/runtime.d.ts +5 -0
  133. package/dist/team/runtime.d.ts.map +1 -0
  134. package/dist/team/spawn-agent-tool.d.ts +85 -0
  135. package/dist/team/spawn-agent-tool.d.ts.map +1 -0
  136. package/dist/team/subagent-prompts.d.ts +4 -0
  137. package/dist/team/subagent-prompts.d.ts.map +1 -0
  138. package/dist/team/team-tools.d.ts +35 -0
  139. package/dist/team/team-tools.d.ts.map +1 -0
  140. package/dist/telemetry/OpenTelemetryProvider.d.ts +11 -1
  141. package/dist/telemetry/OpenTelemetryProvider.d.ts.map +1 -1
  142. package/dist/telemetry/{LoggerTelemetryAdapter.d.ts → TelemetryLoggerSink.d.ts} +10 -4
  143. package/dist/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
  144. package/dist/telemetry/TelemetryService.d.ts.map +1 -1
  145. package/dist/telemetry/index.js +15 -28
  146. package/dist/tools/definitions.d.ts +4 -3
  147. package/dist/tools/definitions.d.ts.map +1 -1
  148. package/dist/tools/index.d.ts +5 -5
  149. package/dist/tools/index.d.ts.map +1 -1
  150. package/dist/tools/model-tool-routing.d.ts.map +1 -1
  151. package/dist/tools/presets.d.ts +26 -0
  152. package/dist/tools/presets.d.ts.map +1 -1
  153. package/dist/tools/schemas.d.ts +8 -0
  154. package/dist/tools/schemas.d.ts.map +1 -1
  155. package/dist/tools/types.d.ts +23 -2
  156. package/dist/tools/types.d.ts.map +1 -1
  157. package/dist/types/config.d.ts +47 -3
  158. package/dist/types/config.d.ts.map +1 -1
  159. package/dist/types/events.d.ts +1 -1
  160. package/dist/types/provider-settings.d.ts +1 -1
  161. package/dist/types/provider-settings.d.ts.map +1 -1
  162. package/dist/types/storage.d.ts +2 -1
  163. package/dist/types/storage.d.ts.map +1 -1
  164. package/dist/types.d.ts +7 -16
  165. package/dist/types.d.ts.map +1 -1
  166. package/package.json +16 -13
  167. package/src/ClineCore.test.ts +150 -0
  168. package/src/ClineCore.ts +114 -8
  169. package/src/account/cline-account-service.test.ts +84 -0
  170. package/src/account/cline-account-service.ts +2 -2
  171. package/src/account/index.ts +1 -0
  172. package/src/account/types.ts +6 -0
  173. package/src/auth/bounded-ttl-cache.test.ts +38 -0
  174. package/src/auth/bounded-ttl-cache.ts +53 -0
  175. package/src/auth/cline.test.ts +173 -36
  176. package/src/auth/cline.ts +395 -93
  177. package/src/auth/oca.test.ts +125 -0
  178. package/src/auth/oca.ts +17 -4
  179. package/src/{agents → extensions/config}/agent-config-loader.test.ts +1 -1
  180. package/src/{agents → extensions/config}/agent-config-parser.ts +2 -2
  181. package/src/{agents → extensions/config}/hooks-config-loader.ts +1 -1
  182. package/src/{agents → extensions/config}/index.ts +7 -11
  183. package/src/{runtime/commands.test.ts → extensions/config/runtime-commands.test.ts} +20 -3
  184. package/src/{runtime/commands.ts → extensions/config/runtime-commands.ts} +1 -8
  185. package/src/{agents → extensions/config}/unified-config-file-watcher.ts +15 -2
  186. package/src/{agents → extensions/config}/user-instruction-config-loader.test.ts +90 -2
  187. package/src/{agents → extensions/config}/user-instruction-config-loader.ts +126 -12
  188. package/src/extensions/context/agentic-compaction.ts +119 -0
  189. package/src/extensions/context/basic-compaction.ts +275 -0
  190. package/src/extensions/context/compaction-shared.ts +458 -0
  191. package/src/extensions/context/compaction.test.ts +477 -0
  192. package/src/extensions/context/compaction.ts +203 -0
  193. package/src/extensions/index.ts +12 -0
  194. package/src/extensions/mcp/client.ts +420 -0
  195. package/src/{mcp → extensions/mcp}/index.ts +16 -0
  196. package/src/{mcp → extensions/mcp}/manager.test.ts +1 -2
  197. package/src/{mcp → extensions/mcp}/manager.ts +3 -5
  198. package/src/extensions/mcp/name-transform.ts +33 -0
  199. package/src/extensions/mcp/policies.ts +47 -0
  200. package/src/extensions/mcp/tools.ts +47 -0
  201. package/src/{mcp → extensions/mcp}/types.ts +35 -7
  202. package/src/{agents → extensions/plugin}/plugin-config-loader.test.ts +18 -13
  203. package/src/{agents → extensions/plugin}/plugin-config-loader.ts +1 -1
  204. package/src/{agents → extensions/plugin}/plugin-loader.test.ts +41 -4
  205. package/src/extensions/plugin/plugin-loader.ts +106 -0
  206. package/src/extensions/plugin/plugin-module-import.ts +278 -0
  207. package/src/{agents → extensions/plugin}/plugin-sandbox-bootstrap.ts +30 -92
  208. package/src/{agents → extensions/plugin}/plugin-sandbox.test.ts +60 -3
  209. package/src/{agents → extensions/plugin}/plugin-sandbox.ts +146 -56
  210. package/src/hooks/index.ts +25 -0
  211. package/src/hooks/persistent.ts +661 -0
  212. package/src/hooks/subprocess-runner.ts +196 -0
  213. package/src/hooks/subprocess.ts +669 -0
  214. package/src/index.ts +200 -118
  215. package/src/prompt/default-system.ts +21 -0
  216. package/src/providers/local-provider-registry.ts +1 -1
  217. package/src/providers/local-provider-service.test.ts +23 -2
  218. package/src/providers/local-provider-service.ts +2 -2
  219. package/src/runtime/checkpoint-hooks.test.ts +167 -0
  220. package/src/runtime/checkpoint-hooks.ts +186 -0
  221. package/src/runtime/hook-file-hooks.test.ts +40 -1
  222. package/src/runtime/hook-file-hooks.ts +35 -16
  223. package/src/runtime/index.ts +4 -19
  224. package/src/runtime/rules.ts +4 -1
  225. package/src/runtime/runtime-builder.team-persistence.test.ts +3 -6
  226. package/src/runtime/runtime-builder.test.ts +266 -160
  227. package/src/runtime/runtime-builder.ts +120 -47
  228. package/src/runtime/runtime-parity.test.ts +22 -22
  229. package/src/runtime/session-runtime.ts +36 -6
  230. package/src/runtime/{sandbox/subprocess-sandbox.ts → subprocess-sandbox.ts} +24 -3
  231. package/src/runtime/team-runtime-registry.ts +1 -4
  232. package/src/runtime/tool-approval.ts +1 -1
  233. package/src/session/default-session-manager.e2e.test.ts +2 -2
  234. package/src/session/default-session-manager.test.ts +553 -9
  235. package/src/session/default-session-manager.ts +140 -46
  236. package/src/session/file-session-service.ts +3 -3
  237. package/src/session/index.ts +6 -6
  238. package/src/session/persistence-service.test.ts +212 -0
  239. package/src/session/{unified-session-persistence-service.ts → persistence-service.ts} +106 -172
  240. package/src/session/rpc-session-service.ts +3 -3
  241. package/src/session/runtime-oauth-token-manager.ts +1 -1
  242. package/src/session/session-agent-events.ts +1 -1
  243. package/src/session/session-artifacts.ts +32 -4
  244. package/src/session/session-config-builder.ts +22 -9
  245. package/src/session/session-graph.ts +1 -1
  246. package/src/session/session-host.ts +19 -11
  247. package/src/session/session-manager.ts +11 -6
  248. package/src/session/session-service.team-persistence.test.ts +1 -1
  249. package/src/session/session-service.ts +6 -9
  250. package/src/session/session-team-coordination.ts +7 -3
  251. package/src/session/session-telemetry.ts +1 -1
  252. package/src/session/utils/helpers.test.ts +160 -0
  253. package/src/session/utils/helpers.ts +289 -42
  254. package/src/session/utils/types.ts +47 -7
  255. package/src/session/workspace-manager.ts +5 -3
  256. package/src/session/workspace-manifest.ts +3 -49
  257. package/src/storage/file-team-store.ts +2 -5
  258. package/src/storage/provider-settings-legacy-migration.ts +2 -2
  259. package/src/storage/provider-settings-manager.test.ts +1 -1
  260. package/src/storage/sqlite-team-store.ts +212 -125
  261. package/src/storage/team-store.ts +1 -5
  262. package/src/team/delegated-agent.ts +131 -0
  263. package/src/team/index.ts +1 -0
  264. package/src/team/multi-agent.lifecycle.test.ts +201 -0
  265. package/src/team/multi-agent.ts +1666 -0
  266. package/src/team/projections.ts +2 -4
  267. package/src/team/runtime.ts +54 -0
  268. package/src/team/spawn-agent-tool.test.ts +387 -0
  269. package/src/team/spawn-agent-tool.ts +207 -0
  270. package/src/team/subagent-prompts.ts +41 -0
  271. package/src/team/team-tools.test.ts +802 -0
  272. package/src/team/team-tools.ts +792 -0
  273. package/src/telemetry/OpenTelemetryProvider.test.ts +25 -3
  274. package/src/telemetry/OpenTelemetryProvider.ts +108 -18
  275. package/src/telemetry/TelemetryLoggerSink.test.ts +42 -0
  276. package/src/telemetry/{LoggerTelemetryAdapter.ts → TelemetryLoggerSink.ts} +21 -14
  277. package/src/telemetry/TelemetryService.test.ts +7 -7
  278. package/src/telemetry/TelemetryService.ts +2 -4
  279. package/src/tools/definitions.test.ts +76 -0
  280. package/src/tools/definitions.ts +41 -2
  281. package/src/tools/executors/apply-patch.ts +1 -1
  282. package/src/tools/executors/editor.ts +1 -1
  283. package/src/tools/executors/file-read.ts +1 -1
  284. package/src/tools/executors/search.ts +1 -1
  285. package/src/tools/executors/web-fetch.ts +1 -1
  286. package/src/tools/index.ts +6 -1
  287. package/src/tools/model-tool-routing.ts +2 -0
  288. package/src/tools/presets.test.ts +8 -0
  289. package/src/tools/presets.ts +40 -2
  290. package/src/tools/schemas.ts +19 -0
  291. package/src/tools/types.ts +31 -2
  292. package/src/types/config.ts +61 -7
  293. package/src/types/events.ts +1 -1
  294. package/src/types/index.ts +0 -1
  295. package/src/types/provider-settings.ts +1 -1
  296. package/src/types/storage.ts +2 -5
  297. package/src/types.ts +32 -44
  298. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  299. package/dist/agents/agent-config-parser.d.ts.map +0 -1
  300. package/dist/agents/hooks-config-loader.d.ts.map +0 -1
  301. package/dist/agents/index.d.ts.map +0 -1
  302. package/dist/agents/plugin-config-loader.d.ts.map +0 -1
  303. package/dist/agents/plugin-loader.d.ts.map +0 -1
  304. package/dist/agents/plugin-sandbox-bootstrap.js +0 -446
  305. package/dist/agents/plugin-sandbox.d.ts.map +0 -1
  306. package/dist/agents/unified-config-file-watcher.d.ts.map +0 -1
  307. package/dist/agents/user-instruction-config-loader.d.ts.map +0 -1
  308. package/dist/mcp/config-loader.d.ts.map +0 -1
  309. package/dist/mcp/index.d.ts +0 -5
  310. package/dist/mcp/index.d.ts.map +0 -1
  311. package/dist/mcp/manager.d.ts.map +0 -1
  312. package/dist/mcp/types.d.ts.map +0 -1
  313. package/dist/runtime/commands.d.ts.map +0 -1
  314. package/dist/runtime/sandbox/subprocess-sandbox.d.ts.map +0 -1
  315. package/dist/runtime/skills.d.ts +0 -14
  316. package/dist/runtime/skills.d.ts.map +0 -1
  317. package/dist/runtime/workflows.d.ts +0 -14
  318. package/dist/runtime/workflows.d.ts.map +0 -1
  319. package/dist/session/unified-session-persistence-service.d.ts.map +0 -1
  320. package/dist/telemetry/LoggerTelemetryAdapter.d.ts.map +0 -1
  321. package/dist/types/workspace.d.ts +0 -8
  322. package/dist/types/workspace.d.ts.map +0 -1
  323. package/src/agents/plugin-loader.ts +0 -175
  324. package/src/runtime/skills.ts +0 -44
  325. package/src/runtime/workflows.test.ts +0 -119
  326. package/src/runtime/workflows.ts +0 -45
  327. package/src/session/unified-session-persistence-service.test.ts +0 -85
  328. package/src/telemetry/LoggerTelemetryAdapter.test.ts +0 -42
  329. package/src/types/workspace.ts +0 -7
  330. /package/dist/{agents → extensions/config}/agent-config-loader.d.ts +0 -0
  331. /package/dist/{agents → extensions/config}/unified-config-file-watcher.d.ts +0 -0
  332. /package/dist/{agents → extensions/config}/user-instruction-config-loader.d.ts +0 -0
  333. /package/dist/{mcp → extensions/mcp}/config-loader.d.ts +0 -0
  334. /package/dist/runtime/{sandbox/subprocess-sandbox.d.ts → subprocess-sandbox.d.ts} +0 -0
  335. /package/src/{agents → extensions/config}/agent-config-loader.ts +0 -0
  336. /package/src/{agents → extensions/config}/hooks-config-loader.test.ts +0 -0
  337. /package/src/{agents → extensions/config}/unified-config-file-watcher.test.ts +0 -0
  338. /package/src/{mcp → extensions/mcp}/config-loader.test.ts +0 -0
  339. /package/src/{mcp → extensions/mcp}/config-loader.ts +0 -0
@@ -0,0 +1,458 @@
1
+ import type * as LlmsProviders from "@clinebot/llms";
2
+ import type { MessageWithMetadata } from "@clinebot/shared";
3
+ import type {
4
+ CoreCompactionContext,
5
+ CoreCompactionSummarizerConfig,
6
+ } from "../../types/config";
7
+
8
+ export const DEFAULT_CONTEXT_WINDOW_TOKENS = 200_000;
9
+ export const DEFAULT_THRESHOLD_RATIO = 0.8;
10
+ export const DEFAULT_RESERVE_TOKENS = 16_384;
11
+ export const DEFAULT_PRESERVE_RECENT_TOKENS = 20_000;
12
+ export const DEFAULT_SUMMARY_MAX_OUTPUT_TOKENS = 1_024;
13
+ export const TOOL_RESULT_CHAR_LIMIT = 2_000;
14
+ export const FILE_CONTENT_CHAR_LIMIT = 2_000;
15
+ export const MIN_TRUNCATED_MESSAGE_TOKENS = 8;
16
+
17
+ export interface FileOperationSummary {
18
+ readFiles: string[];
19
+ modifiedFiles: string[];
20
+ }
21
+
22
+ export interface CompactionSummaryMetadata {
23
+ kind: "compaction_summary";
24
+ summary: string;
25
+ details: FileOperationSummary;
26
+ tokensBefore: number;
27
+ generatedAt: number;
28
+ }
29
+
30
+ export type EstimateMessageTokens = (message: MessageWithMetadata) => number;
31
+
32
+ export function estimateTokens(text: string): number {
33
+ return Math.max(1, Math.ceil(text.length / 4));
34
+ }
35
+
36
+ export function truncateText(text: string, limit: number): string {
37
+ if (text.length <= limit) {
38
+ return text;
39
+ }
40
+ return `${text.slice(0, limit)}\n...[truncated ${text.length - limit} chars]`;
41
+ }
42
+
43
+ export function flattenToolResultContent(
44
+ content: LlmsProviders.ToolResultContent["content"],
45
+ ): string {
46
+ if (typeof content === "string") {
47
+ return truncateText(content, TOOL_RESULT_CHAR_LIMIT);
48
+ }
49
+ return content
50
+ .map((block) => {
51
+ switch (block.type) {
52
+ case "text":
53
+ return block.text;
54
+ case "file":
55
+ return `<file path="${block.path}">\n${truncateText(block.content, FILE_CONTENT_CHAR_LIMIT)}\n</file>`;
56
+ case "image":
57
+ return `[image:${block.mediaType}]`;
58
+ default:
59
+ return "";
60
+ }
61
+ })
62
+ .join("\n");
63
+ }
64
+
65
+ export function formatToolInput(input: Record<string, unknown>): string {
66
+ return Object.entries(input)
67
+ .map(([key, value]) => `${key}=${JSON.stringify(value)}`)
68
+ .join(", ");
69
+ }
70
+
71
+ export function serializeMessage(message: MessageWithMetadata): string {
72
+ if (typeof message.content === "string") {
73
+ return `[${message.role === "user" ? "User" : "Bot"}]: ${message.content}`;
74
+ }
75
+ const lines: string[] = [];
76
+ for (const block of message.content) {
77
+ switch (block.type) {
78
+ case "text":
79
+ lines.push(
80
+ `[${message.role === "user" ? "User" : "Bot"}]: ${block.text}`,
81
+ );
82
+ break;
83
+ case "thinking":
84
+ lines.push(`[Bot thinking]: ${truncateText(block.thinking, 2_000)}`);
85
+ break;
86
+ case "redacted_thinking":
87
+ lines.push("[Bot thinking]: [redacted]");
88
+ break;
89
+ case "tool_use":
90
+ lines.push(
91
+ `[Bot tool calls]: ${block.name}(${formatToolInput(block.input)})`,
92
+ );
93
+ break;
94
+ case "tool_result":
95
+ lines.push(`[Tool result]: ${flattenToolResultContent(block.content)}`);
96
+ break;
97
+ case "file":
98
+ lines.push(
99
+ `[${message.role === "user" ? "User" : "Bot"} file ${block.path}]: ${truncateText(block.content, FILE_CONTENT_CHAR_LIMIT)}`,
100
+ );
101
+ break;
102
+ case "image":
103
+ lines.push(
104
+ `[${message.role === "user" ? "User" : "Bot"} image]: ${block.mediaType}`,
105
+ );
106
+ break;
107
+ }
108
+ }
109
+ return lines.join("\n");
110
+ }
111
+
112
+ export function serializeConversation(messages: MessageWithMetadata[]): string {
113
+ return messages.map(serializeMessage).join("\n\n").trim();
114
+ }
115
+
116
+ export function createTokenEstimator(): EstimateMessageTokens {
117
+ const cache = new WeakMap<object, number>();
118
+ return (message) => {
119
+ const ref = message as unknown as object;
120
+ const cached = cache.get(ref);
121
+ if (typeof cached === "number") {
122
+ return cached;
123
+ }
124
+ const value = estimateTokens(serializeMessage(message));
125
+ cache.set(ref, value);
126
+ return value;
127
+ };
128
+ }
129
+
130
+ export function isCompactionSummaryMessage(
131
+ message: MessageWithMetadata,
132
+ ): boolean {
133
+ return (
134
+ (message.metadata as { kind?: string } | undefined)?.kind ===
135
+ "compaction_summary"
136
+ );
137
+ }
138
+
139
+ export function getCompactionSummaryMetadata(
140
+ message: MessageWithMetadata,
141
+ ): CompactionSummaryMetadata | undefined {
142
+ if (!isCompactionSummaryMessage(message)) {
143
+ return undefined;
144
+ }
145
+ const metadata = message.metadata as Record<string, unknown> | undefined;
146
+ if (!metadata) {
147
+ return undefined;
148
+ }
149
+ const details = metadata.details as Record<string, unknown> | undefined;
150
+ return {
151
+ kind: "compaction_summary",
152
+ summary: String(metadata.summary ?? ""),
153
+ details: {
154
+ readFiles: Array.isArray(details?.readFiles)
155
+ ? details.readFiles
156
+ .filter((value): value is string => typeof value === "string")
157
+ .map((value) => value.trim())
158
+ .filter((value) => value.length > 0)
159
+ : [],
160
+ modifiedFiles: Array.isArray(details?.modifiedFiles)
161
+ ? details.modifiedFiles
162
+ .filter((value): value is string => typeof value === "string")
163
+ .map((value) => value.trim())
164
+ .filter((value) => value.length > 0)
165
+ : [],
166
+ },
167
+ tokensBefore: Number(metadata.tokensBefore ?? 0),
168
+ generatedAt: Number(metadata.generatedAt ?? 0),
169
+ };
170
+ }
171
+
172
+ export function isToolResultOnlyUserMessage(
173
+ message: MessageWithMetadata,
174
+ ): boolean {
175
+ if (message.role !== "user" || !Array.isArray(message.content)) {
176
+ return false;
177
+ }
178
+ return (
179
+ message.content.length > 0 &&
180
+ message.content.every((block) => block.type === "tool_result")
181
+ );
182
+ }
183
+
184
+ export function isTurnStartMessage(message: MessageWithMetadata): boolean {
185
+ return (
186
+ message.role === "user" &&
187
+ !isToolResultOnlyUserMessage(message) &&
188
+ !isCompactionSummaryMessage(message)
189
+ );
190
+ }
191
+
192
+ export function findFirstUserMessageIndex(
193
+ messages: MessageWithMetadata[],
194
+ ): number {
195
+ for (let index = 0; index < messages.length; index += 1) {
196
+ if (isTurnStartMessage(messages[index])) {
197
+ return index;
198
+ }
199
+ }
200
+ return -1;
201
+ }
202
+
203
+ export function findLastTurnStartIndex(
204
+ messages: MessageWithMetadata[],
205
+ ): number {
206
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
207
+ if (isTurnStartMessage(messages[index])) {
208
+ return index;
209
+ }
210
+ }
211
+ return 0;
212
+ }
213
+
214
+ export function findLastAssistantIndex(
215
+ messages: MessageWithMetadata[],
216
+ ): number {
217
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
218
+ if (messages[index].role === "assistant") {
219
+ return index;
220
+ }
221
+ }
222
+ return -1;
223
+ }
224
+
225
+ export function findLatestSummaryIndex(
226
+ messages: MessageWithMetadata[],
227
+ ): number {
228
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
229
+ if (isCompactionSummaryMessage(messages[index])) {
230
+ return index;
231
+ }
232
+ }
233
+ return -1;
234
+ }
235
+
236
+ export function findCutIndex(
237
+ messages: MessageWithMetadata[],
238
+ preserveRecentTokens: number,
239
+ estimateMessageTokens: EstimateMessageTokens,
240
+ ): number {
241
+ const lastTurnStartIndex = findLastTurnStartIndex(messages);
242
+ if (lastTurnStartIndex <= 0) {
243
+ return 0;
244
+ }
245
+
246
+ let total = 0;
247
+ let candidate = messages.length;
248
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
249
+ total += estimateMessageTokens(messages[index]);
250
+ candidate = index;
251
+ if (total >= preserveRecentTokens) {
252
+ break;
253
+ }
254
+ }
255
+
256
+ if (candidate <= 0) {
257
+ return 0;
258
+ }
259
+
260
+ return Math.min(candidate, lastTurnStartIndex);
261
+ }
262
+
263
+ export function collectPaths(value: unknown): string[] {
264
+ if (typeof value === "string" && value.trim().length > 0) {
265
+ return [value];
266
+ }
267
+ if (Array.isArray(value)) {
268
+ return value.flatMap((item) => collectPaths(item));
269
+ }
270
+ if (value && typeof value === "object") {
271
+ const record = value as Record<string, unknown>;
272
+ const paths: string[] = [];
273
+ for (const key of [
274
+ "path",
275
+ "file_path",
276
+ "target_file",
277
+ "new_file_path",
278
+ "old_file_path",
279
+ ]) {
280
+ paths.push(...collectPaths(record[key]));
281
+ }
282
+ if (Array.isArray(record.files)) {
283
+ for (const item of record.files) {
284
+ if (item && typeof item === "object") {
285
+ paths.push(...collectPaths((item as Record<string, unknown>).path));
286
+ }
287
+ }
288
+ }
289
+ if (Array.isArray(record.file_paths)) {
290
+ paths.push(...collectPaths(record.file_paths));
291
+ }
292
+ return paths;
293
+ }
294
+ return [];
295
+ }
296
+
297
+ export function mergeUnique(base: string[], next: Iterable<string>): string[] {
298
+ const seen = new Set(base);
299
+ for (const value of next) {
300
+ const trimmed = value.trim();
301
+ if (!trimmed) {
302
+ continue;
303
+ }
304
+ seen.add(trimmed);
305
+ }
306
+ return [...seen].sort((a, b) => a.localeCompare(b));
307
+ }
308
+
309
+ export function extractFileOps(
310
+ messages: MessageWithMetadata[],
311
+ ): FileOperationSummary {
312
+ let readFiles: string[] = [];
313
+ let modifiedFiles: string[] = [];
314
+ for (const message of messages) {
315
+ const summaryMetadata = getCompactionSummaryMetadata(message);
316
+ if (summaryMetadata) {
317
+ readFiles = mergeUnique(readFiles, summaryMetadata.details.readFiles);
318
+ modifiedFiles = mergeUnique(
319
+ modifiedFiles,
320
+ summaryMetadata.details.modifiedFiles,
321
+ );
322
+ continue;
323
+ }
324
+ if (!Array.isArray(message.content)) {
325
+ continue;
326
+ }
327
+ for (const block of message.content) {
328
+ if (block.type === "file") {
329
+ readFiles = mergeUnique(readFiles, [block.path]);
330
+ continue;
331
+ }
332
+ if (block.type !== "tool_use") {
333
+ continue;
334
+ }
335
+ const paths = collectPaths(block.input);
336
+ if (block.name === "read_files") {
337
+ readFiles = mergeUnique(readFiles, paths);
338
+ continue;
339
+ }
340
+ if (block.name === "editor" || block.name === "apply_patch") {
341
+ modifiedFiles = mergeUnique(modifiedFiles, paths);
342
+ }
343
+ }
344
+ }
345
+ return { readFiles, modifiedFiles };
346
+ }
347
+
348
+ export function renderFilesSection(fileOps: FileOperationSummary): string {
349
+ const readLines =
350
+ fileOps.readFiles.length > 0
351
+ ? fileOps.readFiles.map((path) => `- ${path}`).join("\n")
352
+ : "- none";
353
+ const modifiedLines =
354
+ fileOps.modifiedFiles.length > 0
355
+ ? fileOps.modifiedFiles.map((path) => `- ${path}`).join("\n")
356
+ : "- none";
357
+ return `## Files\nRead:\n${readLines}\nModified:\n${modifiedLines}`;
358
+ }
359
+
360
+ export function ensureFilesSection(
361
+ summary: string,
362
+ fileOps: FileOperationSummary,
363
+ ): string {
364
+ if (/^## Files$/im.test(summary)) {
365
+ return summary.trim();
366
+ }
367
+ return `${summary.trim()}\n\n${renderFilesSection(fileOps)}`.trim();
368
+ }
369
+
370
+ export function buildSummaryRequest(options: {
371
+ previousSummary?: string;
372
+ conversationText: string;
373
+ fileOps: FileOperationSummary;
374
+ }): string {
375
+ const parts: string[] = [
376
+ `Summarize this session for continuation. Be concise and factual.
377
+
378
+ ## Goal
379
+ One sentence: what is being built or fixed.
380
+
381
+ ## State
382
+ - Done: completed steps
383
+ - In Progress: current work
384
+ - Blocked: blockers or open questions
385
+
386
+ ## Highlights
387
+ Key technical choices or notable findings (omit if none).
388
+
389
+ ## Next
390
+ Immediate next steps.
391
+
392
+ ## Files
393
+ Read: ${options.fileOps.readFiles.join(", ") || "none"}
394
+ Edited: ${options.fileOps.modifiedFiles.join(", ") || "none"}`,
395
+ ];
396
+
397
+ if (options.previousSummary?.trim()) {
398
+ parts.push(`Previous summary:\n${options.previousSummary.trim()}`);
399
+ }
400
+
401
+ parts.push(`Conversation:\n${options.conversationText || "(empty)"}`);
402
+
403
+ return parts.join("\n\n");
404
+ }
405
+
406
+ export function resolveSummarizerConfig(options: {
407
+ activeProviderConfig: LlmsProviders.ProviderConfig;
408
+ summarizer?: CoreCompactionSummarizerConfig;
409
+ }): LlmsProviders.ProviderConfig {
410
+ const summarizer = options.summarizer;
411
+ if (!summarizer) {
412
+ return {
413
+ ...options.activeProviderConfig,
414
+ maxOutputTokens: DEFAULT_SUMMARY_MAX_OUTPUT_TOKENS,
415
+ thinking: false,
416
+ };
417
+ }
418
+ const baseProviderConfig =
419
+ summarizer.providerConfig?.providerId === summarizer.providerId
420
+ ? summarizer.providerConfig
421
+ : undefined;
422
+ return {
423
+ ...(baseProviderConfig ?? {}),
424
+ providerId: summarizer.providerId,
425
+ modelId: summarizer.modelId,
426
+ apiKey: summarizer.apiKey ?? baseProviderConfig?.apiKey,
427
+ baseUrl: summarizer.baseUrl ?? baseProviderConfig?.baseUrl,
428
+ headers: summarizer.headers ?? baseProviderConfig?.headers,
429
+ knownModels: summarizer.knownModels ?? baseProviderConfig?.knownModels,
430
+ maxOutputTokens:
431
+ summarizer.maxOutputTokens ?? DEFAULT_SUMMARY_MAX_OUTPUT_TOKENS,
432
+ thinking: false,
433
+ };
434
+ }
435
+
436
+ export function buildSummaryMessage(options: {
437
+ summary: string;
438
+ fileOps: FileOperationSummary;
439
+ tokensBefore: number;
440
+ }): MessageWithMetadata {
441
+ return {
442
+ role: "user",
443
+ content: `Context summary:\n\n${options.summary}`,
444
+ metadata: {
445
+ kind: "compaction_summary",
446
+ summary: options.summary,
447
+ details: options.fileOps,
448
+ tokensBefore: options.tokensBefore,
449
+ generatedAt: Date.now(),
450
+ } satisfies CompactionSummaryMetadata,
451
+ };
452
+ }
453
+
454
+ export function getContextWindowTokens(
455
+ context: Pick<CoreCompactionContext, "contextWindowTokens">,
456
+ ): number {
457
+ return context.contextWindowTokens;
458
+ }