@clinebot/core 0.0.28 → 0.0.30

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 (340) 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 +11 -11
  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 +9 -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 +15 -12
  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 +168 -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 +162 -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/OpenTelemetryAdapter.ts +1 -1
  274. package/src/telemetry/OpenTelemetryProvider.test.ts +216 -3
  275. package/src/telemetry/OpenTelemetryProvider.ts +110 -20
  276. package/src/telemetry/TelemetryLoggerSink.test.ts +42 -0
  277. package/src/telemetry/{LoggerTelemetryAdapter.ts → TelemetryLoggerSink.ts} +21 -14
  278. package/src/telemetry/TelemetryService.test.ts +7 -7
  279. package/src/telemetry/TelemetryService.ts +2 -4
  280. package/src/tools/definitions.test.ts +76 -0
  281. package/src/tools/definitions.ts +41 -2
  282. package/src/tools/executors/apply-patch.ts +1 -1
  283. package/src/tools/executors/editor.ts +1 -1
  284. package/src/tools/executors/file-read.ts +1 -1
  285. package/src/tools/executors/search.ts +1 -1
  286. package/src/tools/executors/web-fetch.ts +1 -1
  287. package/src/tools/index.ts +6 -1
  288. package/src/tools/model-tool-routing.ts +2 -0
  289. package/src/tools/presets.test.ts +8 -0
  290. package/src/tools/presets.ts +40 -2
  291. package/src/tools/schemas.ts +19 -0
  292. package/src/tools/types.ts +31 -2
  293. package/src/types/config.ts +61 -7
  294. package/src/types/events.ts +1 -1
  295. package/src/types/index.ts +0 -1
  296. package/src/types/provider-settings.ts +1 -1
  297. package/src/types/storage.ts +2 -5
  298. package/src/types.ts +32 -44
  299. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  300. package/dist/agents/agent-config-parser.d.ts.map +0 -1
  301. package/dist/agents/hooks-config-loader.d.ts.map +0 -1
  302. package/dist/agents/index.d.ts.map +0 -1
  303. package/dist/agents/plugin-config-loader.d.ts.map +0 -1
  304. package/dist/agents/plugin-loader.d.ts.map +0 -1
  305. package/dist/agents/plugin-sandbox-bootstrap.js +0 -446
  306. package/dist/agents/plugin-sandbox.d.ts.map +0 -1
  307. package/dist/agents/unified-config-file-watcher.d.ts.map +0 -1
  308. package/dist/agents/user-instruction-config-loader.d.ts.map +0 -1
  309. package/dist/mcp/config-loader.d.ts.map +0 -1
  310. package/dist/mcp/index.d.ts +0 -5
  311. package/dist/mcp/index.d.ts.map +0 -1
  312. package/dist/mcp/manager.d.ts.map +0 -1
  313. package/dist/mcp/types.d.ts.map +0 -1
  314. package/dist/runtime/commands.d.ts.map +0 -1
  315. package/dist/runtime/sandbox/subprocess-sandbox.d.ts.map +0 -1
  316. package/dist/runtime/skills.d.ts +0 -14
  317. package/dist/runtime/skills.d.ts.map +0 -1
  318. package/dist/runtime/workflows.d.ts +0 -14
  319. package/dist/runtime/workflows.d.ts.map +0 -1
  320. package/dist/session/unified-session-persistence-service.d.ts.map +0 -1
  321. package/dist/telemetry/LoggerTelemetryAdapter.d.ts.map +0 -1
  322. package/dist/types/workspace.d.ts +0 -8
  323. package/dist/types/workspace.d.ts.map +0 -1
  324. package/src/agents/plugin-loader.ts +0 -175
  325. package/src/runtime/skills.ts +0 -44
  326. package/src/runtime/workflows.test.ts +0 -119
  327. package/src/runtime/workflows.ts +0 -45
  328. package/src/session/unified-session-persistence-service.test.ts +0 -85
  329. package/src/telemetry/LoggerTelemetryAdapter.test.ts +0 -42
  330. package/src/types/workspace.ts +0 -7
  331. /package/dist/{agents → extensions/config}/agent-config-loader.d.ts +0 -0
  332. /package/dist/{agents → extensions/config}/unified-config-file-watcher.d.ts +0 -0
  333. /package/dist/{agents → extensions/config}/user-instruction-config-loader.d.ts +0 -0
  334. /package/dist/{mcp → extensions/mcp}/config-loader.d.ts +0 -0
  335. /package/dist/runtime/{sandbox/subprocess-sandbox.d.ts → subprocess-sandbox.d.ts} +0 -0
  336. /package/src/{agents → extensions/config}/agent-config-loader.ts +0 -0
  337. /package/src/{agents → extensions/config}/hooks-config-loader.test.ts +0 -0
  338. /package/src/{agents → extensions/config}/unified-config-file-watcher.test.ts +0 -0
  339. /package/src/{mcp → extensions/mcp}/config-loader.test.ts +0 -0
  340. /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
+ }