kagent-ts 0.1.3 → 0.1.5

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 (349) hide show
  1. package/LICENSE +68 -21
  2. package/README.md +27 -371
  3. package/dist/compression/progressive-compressor.d.ts +66 -0
  4. package/dist/compression/progressive-compressor.d.ts.map +1 -0
  5. package/dist/compression/progressive-compressor.js +367 -0
  6. package/dist/compression/progressive-compressor.js.map +1 -0
  7. package/dist/compression/types.d.ts +1 -5
  8. package/dist/compression/types.d.ts.map +1 -1
  9. package/dist/context/context-manager.d.ts +34 -15
  10. package/dist/context/context-manager.d.ts.map +1 -1
  11. package/dist/context/context-manager.js +78 -28
  12. package/dist/context/context-manager.js.map +1 -1
  13. package/dist/context/types.d.ts +20 -4
  14. package/dist/context/types.d.ts.map +1 -1
  15. package/dist/core/agent.d.ts +407 -35
  16. package/dist/core/agent.d.ts.map +1 -1
  17. package/dist/core/agent.js +685 -70
  18. package/dist/core/agent.js.map +1 -1
  19. package/dist/core/fusion-agent.d.ts +207 -0
  20. package/dist/core/fusion-agent.d.ts.map +1 -0
  21. package/dist/core/fusion-agent.js +769 -0
  22. package/dist/core/fusion-agent.js.map +1 -0
  23. package/dist/core/hooks.d.ts +19 -7
  24. package/dist/core/hooks.d.ts.map +1 -1
  25. package/dist/core/plan-solve-agent.d.ts +1 -15
  26. package/dist/core/plan-solve-agent.d.ts.map +1 -1
  27. package/dist/core/plan-solve-agent.js +144 -117
  28. package/dist/core/plan-solve-agent.js.map +1 -1
  29. package/dist/core/react-agent.d.ts +0 -13
  30. package/dist/core/react-agent.d.ts.map +1 -1
  31. package/dist/core/react-agent.js +128 -101
  32. package/dist/core/react-agent.js.map +1 -1
  33. package/dist/core/response-schema.d.ts +65 -0
  34. package/dist/core/response-schema.d.ts.map +1 -1
  35. package/dist/core/response-schema.js +174 -1
  36. package/dist/core/response-schema.js.map +1 -1
  37. package/dist/core/system-prompts.d.ts +27 -0
  38. package/dist/core/system-prompts.d.ts.map +1 -0
  39. package/dist/core/system-prompts.js +112 -0
  40. package/dist/core/system-prompts.js.map +1 -0
  41. package/dist/eval/benchmark.d.ts +81 -0
  42. package/dist/eval/benchmark.d.ts.map +1 -0
  43. package/dist/eval/benchmark.js +292 -0
  44. package/dist/eval/benchmark.js.map +1 -0
  45. package/dist/eval/eval-runner.d.ts +79 -0
  46. package/dist/eval/eval-runner.d.ts.map +1 -0
  47. package/dist/eval/eval-runner.js +252 -0
  48. package/dist/eval/eval-runner.js.map +1 -0
  49. package/dist/eval/index.d.ts +7 -0
  50. package/dist/eval/index.d.ts.map +1 -0
  51. package/dist/eval/index.js +13 -0
  52. package/dist/eval/index.js.map +1 -0
  53. package/dist/eval/tool-call-evaluator.d.ts +72 -0
  54. package/dist/eval/tool-call-evaluator.d.ts.map +1 -0
  55. package/dist/eval/tool-call-evaluator.js +265 -0
  56. package/dist/eval/tool-call-evaluator.js.map +1 -0
  57. package/dist/eval/types.d.ts +219 -0
  58. package/dist/eval/types.d.ts.map +1 -0
  59. package/dist/eval/types.js +3 -0
  60. package/dist/eval/types.js.map +1 -0
  61. package/dist/index.d.ts +61 -14
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +121 -8
  64. package/dist/index.js.map +1 -1
  65. package/dist/llm/anthropic-provider.d.ts +141 -0
  66. package/dist/llm/anthropic-provider.d.ts.map +1 -0
  67. package/dist/llm/anthropic-provider.js +486 -0
  68. package/dist/llm/anthropic-provider.js.map +1 -0
  69. package/dist/llm/errors.d.ts +26 -0
  70. package/dist/llm/errors.d.ts.map +1 -0
  71. package/dist/llm/errors.js +19 -0
  72. package/dist/llm/errors.js.map +1 -0
  73. package/dist/llm/factory.d.ts +73 -0
  74. package/dist/llm/factory.d.ts.map +1 -0
  75. package/dist/llm/factory.js +77 -0
  76. package/dist/llm/factory.js.map +1 -0
  77. package/dist/llm/fallback-provider.d.ts +47 -0
  78. package/dist/llm/fallback-provider.d.ts.map +1 -0
  79. package/dist/llm/fallback-provider.js +91 -0
  80. package/dist/llm/fallback-provider.js.map +1 -0
  81. package/dist/llm/interface.d.ts +54 -11
  82. package/dist/llm/interface.d.ts.map +1 -1
  83. package/dist/llm/interface.js +34 -0
  84. package/dist/llm/interface.js.map +1 -1
  85. package/dist/llm/model-router.d.ts +126 -0
  86. package/dist/llm/model-router.d.ts.map +1 -0
  87. package/dist/llm/model-router.js +178 -0
  88. package/dist/llm/model-router.js.map +1 -0
  89. package/dist/llm/openai-provider.d.ts +8 -32
  90. package/dist/llm/openai-provider.d.ts.map +1 -1
  91. package/dist/llm/openai-provider.js +27 -60
  92. package/dist/llm/openai-provider.js.map +1 -1
  93. package/dist/llm/rate-limiter.d.ts +41 -0
  94. package/dist/llm/rate-limiter.d.ts.map +1 -0
  95. package/dist/llm/rate-limiter.js +93 -0
  96. package/dist/llm/rate-limiter.js.map +1 -0
  97. package/dist/llm/retry.d.ts +26 -0
  98. package/dist/llm/retry.d.ts.map +1 -0
  99. package/dist/llm/retry.js +44 -0
  100. package/dist/llm/retry.js.map +1 -0
  101. package/dist/llm/token-budget.d.ts +97 -0
  102. package/dist/llm/token-budget.d.ts.map +1 -0
  103. package/dist/llm/token-budget.js +115 -0
  104. package/dist/llm/token-budget.js.map +1 -0
  105. package/dist/logging/index.d.ts +2 -0
  106. package/dist/logging/index.d.ts.map +1 -0
  107. package/dist/logging/index.js +7 -0
  108. package/dist/logging/index.js.map +1 -0
  109. package/dist/logging/logger.d.ts +38 -0
  110. package/dist/logging/logger.d.ts.map +1 -0
  111. package/dist/logging/logger.js +34 -0
  112. package/dist/logging/logger.js.map +1 -0
  113. package/dist/mcp/index.d.ts +4 -0
  114. package/dist/mcp/index.d.ts.map +1 -0
  115. package/dist/mcp/index.js +8 -0
  116. package/dist/mcp/index.js.map +1 -0
  117. package/dist/mcp/mcp-client-manager.d.ts +72 -0
  118. package/dist/mcp/mcp-client-manager.d.ts.map +1 -0
  119. package/dist/mcp/mcp-client-manager.js +235 -0
  120. package/dist/mcp/mcp-client-manager.js.map +1 -0
  121. package/dist/mcp/mcp-types.d.ts +58 -0
  122. package/dist/mcp/mcp-types.d.ts.map +1 -0
  123. package/dist/mcp/mcp-types.js +20 -0
  124. package/dist/mcp/mcp-types.js.map +1 -0
  125. package/dist/memory/index.d.ts +3 -0
  126. package/dist/memory/index.d.ts.map +1 -0
  127. package/dist/memory/index.js +6 -0
  128. package/dist/memory/index.js.map +1 -0
  129. package/dist/memory/memory-manager.d.ts +119 -0
  130. package/dist/memory/memory-manager.d.ts.map +1 -0
  131. package/dist/memory/memory-manager.js +334 -0
  132. package/dist/memory/memory-manager.js.map +1 -0
  133. package/dist/messages/types.d.ts +2 -0
  134. package/dist/messages/types.d.ts.map +1 -1
  135. package/dist/orchestrator/index.d.ts +5 -0
  136. package/dist/orchestrator/index.d.ts.map +1 -0
  137. package/dist/orchestrator/index.js +13 -0
  138. package/dist/orchestrator/index.js.map +1 -0
  139. package/dist/orchestrator/json-extractor.d.ts +18 -0
  140. package/dist/orchestrator/json-extractor.d.ts.map +1 -0
  141. package/dist/orchestrator/json-extractor.js +111 -0
  142. package/dist/orchestrator/json-extractor.js.map +1 -0
  143. package/dist/orchestrator/orchestrator-agent.d.ts +152 -0
  144. package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -0
  145. package/dist/orchestrator/orchestrator-agent.js +675 -0
  146. package/dist/orchestrator/orchestrator-agent.js.map +1 -0
  147. package/dist/orchestrator/orchestrator-response.d.ts +40 -0
  148. package/dist/orchestrator/orchestrator-response.d.ts.map +1 -0
  149. package/dist/orchestrator/orchestrator-response.js +275 -0
  150. package/dist/orchestrator/orchestrator-response.js.map +1 -0
  151. package/dist/orchestrator/orchestrator-types.d.ts +116 -0
  152. package/dist/orchestrator/orchestrator-types.d.ts.map +1 -0
  153. package/dist/orchestrator/orchestrator-types.js +3 -0
  154. package/dist/orchestrator/orchestrator-types.js.map +1 -0
  155. package/dist/preferences/preference-manager.d.ts +8 -3
  156. package/dist/preferences/preference-manager.d.ts.map +1 -1
  157. package/dist/preferences/preference-manager.js +17 -4
  158. package/dist/preferences/preference-manager.js.map +1 -1
  159. package/dist/rag/chroma-store.d.ts +52 -0
  160. package/dist/rag/chroma-store.d.ts.map +1 -0
  161. package/dist/rag/chroma-store.js +110 -0
  162. package/dist/rag/chroma-store.js.map +1 -0
  163. package/dist/rag/document-loader.d.ts +21 -0
  164. package/dist/rag/document-loader.d.ts.map +1 -0
  165. package/dist/rag/document-loader.js +129 -0
  166. package/dist/rag/document-loader.js.map +1 -0
  167. package/dist/rag/embedding-provider.d.ts +36 -0
  168. package/dist/rag/embedding-provider.d.ts.map +1 -0
  169. package/dist/rag/embedding-provider.js +74 -0
  170. package/dist/rag/embedding-provider.js.map +1 -0
  171. package/dist/rag/index.d.ts +17 -0
  172. package/dist/rag/index.d.ts.map +1 -0
  173. package/dist/rag/index.js +27 -0
  174. package/dist/rag/index.js.map +1 -0
  175. package/dist/rag/keyword-index.d.ts +53 -0
  176. package/dist/rag/keyword-index.d.ts.map +1 -0
  177. package/dist/rag/keyword-index.js +161 -0
  178. package/dist/rag/keyword-index.js.map +1 -0
  179. package/dist/rag/llm-reranker.d.ts +36 -0
  180. package/dist/rag/llm-reranker.d.ts.map +1 -0
  181. package/dist/rag/llm-reranker.js +95 -0
  182. package/dist/rag/llm-reranker.js.map +1 -0
  183. package/dist/rag/rag-manager.d.ts +54 -0
  184. package/dist/rag/rag-manager.d.ts.map +1 -0
  185. package/dist/rag/rag-manager.js +179 -0
  186. package/dist/rag/rag-manager.js.map +1 -0
  187. package/dist/rag/rag-types.d.ts +143 -0
  188. package/dist/rag/rag-types.d.ts.map +1 -0
  189. package/dist/rag/rag-types.js +9 -0
  190. package/dist/rag/rag-types.js.map +1 -0
  191. package/dist/rag/rrf.d.ts +47 -0
  192. package/dist/rag/rrf.d.ts.map +1 -0
  193. package/dist/rag/rrf.js +70 -0
  194. package/dist/rag/rrf.js.map +1 -0
  195. package/dist/rag/search-knowledge.d.ts +24 -0
  196. package/dist/rag/search-knowledge.d.ts.map +1 -0
  197. package/dist/rag/search-knowledge.js +86 -0
  198. package/dist/rag/search-knowledge.js.map +1 -0
  199. package/dist/rag/text-splitter.d.ts +25 -0
  200. package/dist/rag/text-splitter.d.ts.map +1 -0
  201. package/dist/rag/text-splitter.js +136 -0
  202. package/dist/rag/text-splitter.js.map +1 -0
  203. package/dist/rag/vector-store.d.ts +34 -0
  204. package/dist/rag/vector-store.d.ts.map +1 -0
  205. package/dist/rag/vector-store.js +73 -0
  206. package/dist/rag/vector-store.js.map +1 -0
  207. package/dist/reflection/error-notebook.d.ts +125 -0
  208. package/dist/reflection/error-notebook.d.ts.map +1 -0
  209. package/dist/reflection/error-notebook.js +368 -0
  210. package/dist/reflection/error-notebook.js.map +1 -0
  211. package/dist/reflection/index.d.ts +8 -0
  212. package/dist/reflection/index.d.ts.map +1 -0
  213. package/dist/reflection/index.js +12 -0
  214. package/dist/reflection/index.js.map +1 -0
  215. package/dist/reflection/memory-reflector.d.ts +97 -0
  216. package/dist/reflection/memory-reflector.d.ts.map +1 -0
  217. package/dist/reflection/memory-reflector.js +215 -0
  218. package/dist/reflection/memory-reflector.js.map +1 -0
  219. package/dist/reflection/reflection-agent.d.ts +105 -0
  220. package/dist/reflection/reflection-agent.d.ts.map +1 -0
  221. package/dist/reflection/reflection-agent.js +234 -0
  222. package/dist/reflection/reflection-agent.js.map +1 -0
  223. package/dist/reflection/reflection-hook.d.ts +50 -0
  224. package/dist/reflection/reflection-hook.d.ts.map +1 -0
  225. package/dist/reflection/reflection-hook.js +108 -0
  226. package/dist/reflection/reflection-hook.js.map +1 -0
  227. package/dist/rules/project-rules.d.ts +47 -0
  228. package/dist/rules/project-rules.d.ts.map +1 -0
  229. package/dist/rules/project-rules.js +166 -0
  230. package/dist/rules/project-rules.js.map +1 -0
  231. package/dist/security/boundaries.d.ts +81 -0
  232. package/dist/security/boundaries.d.ts.map +1 -0
  233. package/dist/security/boundaries.js +158 -0
  234. package/dist/security/boundaries.js.map +1 -0
  235. package/dist/security/index.d.ts +2 -0
  236. package/dist/security/index.d.ts.map +1 -0
  237. package/dist/security/index.js +11 -0
  238. package/dist/security/index.js.map +1 -0
  239. package/dist/session/session-types.d.ts +25 -4
  240. package/dist/session/session-types.d.ts.map +1 -1
  241. package/dist/skills/file-skill-loader.d.ts +9 -20
  242. package/dist/skills/file-skill-loader.d.ts.map +1 -1
  243. package/dist/skills/file-skill-loader.js +35 -164
  244. package/dist/skills/file-skill-loader.js.map +1 -1
  245. package/dist/skills/index.d.ts +1 -1
  246. package/dist/skills/index.d.ts.map +1 -1
  247. package/dist/skills/index.js +1 -2
  248. package/dist/skills/index.js.map +1 -1
  249. package/dist/skills/skill-manager.d.ts +22 -29
  250. package/dist/skills/skill-manager.d.ts.map +1 -1
  251. package/dist/skills/skill-manager.js +63 -85
  252. package/dist/skills/skill-manager.js.map +1 -1
  253. package/dist/skills/types.d.ts +4 -16
  254. package/dist/skills/types.d.ts.map +1 -1
  255. package/dist/subagent/index.d.ts +4 -0
  256. package/dist/subagent/index.d.ts.map +1 -0
  257. package/dist/subagent/index.js +8 -0
  258. package/dist/subagent/index.js.map +1 -0
  259. package/dist/subagent/subagent-loader.d.ts +53 -0
  260. package/dist/subagent/subagent-loader.d.ts.map +1 -0
  261. package/dist/subagent/subagent-loader.js +155 -0
  262. package/dist/subagent/subagent-loader.js.map +1 -0
  263. package/dist/subagent/subagent-manager.d.ts +161 -0
  264. package/dist/subagent/subagent-manager.d.ts.map +1 -0
  265. package/dist/subagent/subagent-manager.js +468 -0
  266. package/dist/subagent/subagent-manager.js.map +1 -0
  267. package/dist/subagent/subagent-types.d.ts +77 -0
  268. package/dist/subagent/subagent-types.d.ts.map +1 -0
  269. package/dist/subagent/subagent-types.js +3 -0
  270. package/dist/subagent/subagent-types.js.map +1 -0
  271. package/dist/tools/builtin/bash.d.ts +3 -0
  272. package/dist/tools/builtin/bash.d.ts.map +1 -0
  273. package/dist/tools/builtin/bash.js +87 -0
  274. package/dist/tools/builtin/bash.js.map +1 -0
  275. package/dist/tools/builtin/edit-file.d.ts.map +1 -1
  276. package/dist/tools/builtin/edit-file.js +1 -0
  277. package/dist/tools/builtin/edit-file.js.map +1 -1
  278. package/dist/tools/builtin/index.d.ts +14 -0
  279. package/dist/tools/builtin/index.d.ts.map +1 -1
  280. package/dist/tools/builtin/index.js +45 -1
  281. package/dist/tools/builtin/index.js.map +1 -1
  282. package/dist/tools/builtin/list-errors.d.ts +7 -0
  283. package/dist/tools/builtin/list-errors.d.ts.map +1 -0
  284. package/dist/tools/builtin/list-errors.js +64 -0
  285. package/dist/tools/builtin/list-errors.js.map +1 -0
  286. package/dist/tools/builtin/list-subagents.d.ts +7 -0
  287. package/dist/tools/builtin/list-subagents.d.ts.map +1 -0
  288. package/dist/tools/builtin/list-subagents.js +21 -0
  289. package/dist/tools/builtin/list-subagents.js.map +1 -0
  290. package/dist/tools/builtin/recall.d.ts +11 -0
  291. package/dist/tools/builtin/recall.d.ts.map +1 -0
  292. package/dist/tools/builtin/recall.js +60 -0
  293. package/dist/tools/builtin/recall.js.map +1 -0
  294. package/dist/tools/builtin/remember.d.ts +12 -0
  295. package/dist/tools/builtin/remember.d.ts.map +1 -0
  296. package/dist/tools/builtin/remember.js +72 -0
  297. package/dist/tools/builtin/remember.js.map +1 -0
  298. package/dist/tools/builtin/skill.d.ts +14 -0
  299. package/dist/tools/builtin/skill.d.ts.map +1 -0
  300. package/dist/tools/builtin/skill.js +71 -0
  301. package/dist/tools/builtin/skill.js.map +1 -0
  302. package/dist/tools/builtin/spawn-subagent.d.ts +7 -0
  303. package/dist/tools/builtin/spawn-subagent.d.ts.map +1 -0
  304. package/dist/tools/builtin/spawn-subagent.js +43 -0
  305. package/dist/tools/builtin/spawn-subagent.js.map +1 -0
  306. package/dist/tools/builtin/web-fetch.d.ts +3 -0
  307. package/dist/tools/builtin/web-fetch.d.ts.map +1 -0
  308. package/dist/tools/builtin/web-fetch.js +101 -0
  309. package/dist/tools/builtin/web-fetch.js.map +1 -0
  310. package/dist/tools/builtin/write-file.d.ts.map +1 -1
  311. package/dist/tools/builtin/write-file.js +1 -0
  312. package/dist/tools/builtin/write-file.js.map +1 -1
  313. package/dist/tools/circuit-breaker.d.ts +19 -10
  314. package/dist/tools/circuit-breaker.d.ts.map +1 -1
  315. package/dist/tools/circuit-breaker.js +22 -11
  316. package/dist/tools/circuit-breaker.js.map +1 -1
  317. package/dist/tools/error-tracker.d.ts +28 -44
  318. package/dist/tools/error-tracker.d.ts.map +1 -1
  319. package/dist/tools/error-tracker.js +39 -156
  320. package/dist/tools/error-tracker.js.map +1 -1
  321. package/dist/tools/tool-filter.d.ts +70 -0
  322. package/dist/tools/tool-filter.d.ts.map +1 -0
  323. package/dist/tools/tool-filter.js +92 -0
  324. package/dist/tools/tool-filter.js.map +1 -0
  325. package/dist/tools/tool-output-truncator.d.ts +36 -0
  326. package/dist/tools/tool-output-truncator.d.ts.map +1 -0
  327. package/dist/tools/tool-output-truncator.js +117 -0
  328. package/dist/tools/tool-output-truncator.js.map +1 -0
  329. package/dist/tools/tool-registry.d.ts +25 -9
  330. package/dist/tools/tool-registry.d.ts.map +1 -1
  331. package/dist/tools/tool-registry.js +77 -28
  332. package/dist/tools/tool-registry.js.map +1 -1
  333. package/dist/tools/tool-validator.d.ts +13 -0
  334. package/dist/tools/tool-validator.d.ts.map +1 -0
  335. package/dist/tools/tool-validator.js +116 -0
  336. package/dist/tools/tool-validator.js.map +1 -0
  337. package/dist/tools/types.d.ts +86 -3
  338. package/dist/tools/types.d.ts.map +1 -1
  339. package/dist/tools/types.js +51 -2
  340. package/dist/tools/types.js.map +1 -1
  341. package/dist/trace/trace-logger.d.ts +30 -4
  342. package/dist/trace/trace-logger.d.ts.map +1 -1
  343. package/dist/trace/trace-logger.js +83 -7
  344. package/dist/trace/trace-logger.js.map +1 -1
  345. package/package.json +14 -4
  346. package/dist/compression/sliding-window.d.ts +0 -21
  347. package/dist/compression/sliding-window.d.ts.map +0 -1
  348. package/dist/compression/sliding-window.js +0 -44
  349. package/dist/compression/sliding-window.js.map +0 -1
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ProgressiveCompressor = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const types_1 = require("../messages/types");
40
+ const token_counter_1 = require("../utils/token-counter");
41
+ const logger_1 = require("../logging/logger");
42
+ // ─── Configuration ──────────────────────────────────────────────────────────
43
+ const TOOL_TOTAL_BYTE_LIMIT = 200 * 1024; // Step 1: 200 KB
44
+ const KEEP_BYTES = 2048; // Step 1: keep 2 KB
45
+ const TRUNCATED_DIR = ".kagent-context"; // Step 1: save full output here
46
+ /** Tools whose results are "read-type" — can be re-run to get the same data. */
47
+ const READ_TOOLS = new Set([
48
+ "read_file",
49
+ "grep_search",
50
+ "glob_search",
51
+ ]);
52
+ // ─── Main ───────────────────────────────────────────────────────────────────
53
+ /**
54
+ * Progressive 4-step compression.
55
+ *
56
+ * Each step is applied in order. After each step the token count is
57
+ * re-checked; if the context now fits comfortably, later steps are skipped.
58
+ */
59
+ class ProgressiveCompressor {
60
+ config;
61
+ logger;
62
+ constructor(config, logger) {
63
+ this.config = config;
64
+ this.logger = logger ?? new logger_1.ConsoleLogger();
65
+ }
66
+ /**
67
+ * Run progressive compression.
68
+ *
69
+ * @param messages The full message list (without system message).
70
+ * @param systemMessage The system message (preserved).
71
+ * @param llm Optional LLM provider for Step 4 summarization.
72
+ * If omitted, Step 4 is skipped.
73
+ * @returns Compressed message list + removal count.
74
+ */
75
+ async compress(messages, systemMessage, llm, model) {
76
+ const originalCount = messages.length;
77
+ let result = messages;
78
+ let applied = false;
79
+ const t = this.config.compressionThreshold;
80
+ const triggerToken = t < 1
81
+ ? Math.round(this.config.maxTokens * (1 - t))
82
+ : this.config.maxTokens - t;
83
+ // ── Step 1: Truncate large tool results ────────────────────────────
84
+ const after1 = this.step1TruncateToolResults(result);
85
+ if (after1 !== result) {
86
+ applied = true;
87
+ result = after1;
88
+ }
89
+ if (this.tokenCount(result, systemMessage, model) < triggerToken) {
90
+ return this.finalize(result, originalCount, applied);
91
+ }
92
+ // ── Step 2: Drop old turns beyond keepTurns ────────────────────────
93
+ const turnStartsForStep2 = computeTurnStarts(result);
94
+ const after2 = this.step2DropOldTurns(result, turnStartsForStep2);
95
+ if (after2 !== result) {
96
+ applied = true;
97
+ result = after2;
98
+ }
99
+ if (this.tokenCount(result, systemMessage, model) < triggerToken) {
100
+ return this.finalize(result, originalCount, applied);
101
+ }
102
+ // ── Step 3: Drop stale tool results ────────────────────────────────
103
+ const after3 = this.step3DropStaleToolResults(result);
104
+ if (after3 !== result) {
105
+ applied = true;
106
+ result = after3;
107
+ }
108
+ if (this.tokenCount(result, systemMessage, model) < triggerToken) {
109
+ return this.finalize(result, originalCount, applied);
110
+ }
111
+ // ── Step 4: LLM summarization ──────────────────────────────────────
112
+ if (llm) {
113
+ try {
114
+ const turnStartsForStep4 = computeTurnStarts(result);
115
+ const after4 = await this.step4LlmSummarize(result, systemMessage, llm, turnStartsForStep4);
116
+ if (after4 !== result) {
117
+ applied = true;
118
+ result = after4;
119
+ }
120
+ }
121
+ catch (err) {
122
+ this.logger.warn("Compression", `Step 4 (LLM summarization) failed: ` +
123
+ `${err instanceof Error ? err.message : String(err)}. ` +
124
+ `Falling back to truncation.`);
125
+ }
126
+ }
127
+ return this.finalize(result, originalCount, applied);
128
+ }
129
+ finalize(messages, originalCount, applied) {
130
+ return {
131
+ messages,
132
+ removedCount: applied ? Math.max(0, originalCount - messages.length) : 0,
133
+ applied,
134
+ };
135
+ }
136
+ // ─── Token Counting ───────────────────────────────────────────────────────
137
+ tokenCount(messages, sys, model) {
138
+ let total = 0;
139
+ if (sys)
140
+ total += 3 + (0, token_counter_1.countTokens)(sys.content, model);
141
+ for (const m of messages) {
142
+ total += 3 + (0, token_counter_1.countTokens)(m.content, model);
143
+ }
144
+ return total;
145
+ }
146
+ // ─── Step 1: Truncate large tool results ──────────────────────────────────
147
+ /**
148
+ * If total tool-result bytes exceed 200 KB, truncate the largest
149
+ * results (keep 2 KB + save to disk). Returns a new array if modified.
150
+ */
151
+ step1TruncateToolResults(messages) {
152
+ // Collect tool messages with their byte sizes
153
+ const toolIndices = [];
154
+ let totalBytes = 0;
155
+ for (let i = 0; i < messages.length; i++) {
156
+ if (messages[i].role === types_1.Role.Tool) {
157
+ const bytes = Buffer.byteLength(messages[i].content, "utf-8");
158
+ totalBytes += bytes;
159
+ toolIndices.push({ idx: i, bytes });
160
+ }
161
+ }
162
+ if (totalBytes <= TOOL_TOTAL_BYTE_LIMIT)
163
+ return messages;
164
+ // Sort largest first, truncate until under limit
165
+ toolIndices.sort((a, b) => b.bytes - a.bytes);
166
+ const result = [...messages];
167
+ let excess = totalBytes - TOOL_TOTAL_BYTE_LIMIT;
168
+ fs.mkdirSync(TRUNCATED_DIR, { recursive: true });
169
+ for (const { idx, bytes } of toolIndices) {
170
+ if (excess <= 0)
171
+ break;
172
+ // Keep KEEP_BYTES, save rest to file
173
+ const content = result[idx].content;
174
+ const truncatedBytes = bytes - KEEP_BYTES;
175
+ if (truncatedBytes <= 0)
176
+ continue;
177
+ const now = Date.now();
178
+ const hash = simpleHash(content.slice(0, 128) + now);
179
+ const name = result[idx].name ?? "unknown_tool";
180
+ const filename = `ctx_trunc_${sanitize(name)}_${now}_${hash}.txt`;
181
+ const filePath = path.join(TRUNCATED_DIR, filename);
182
+ fs.writeFileSync(filePath, content, "utf-8");
183
+ result[idx] = {
184
+ ...result[idx],
185
+ content: content.slice(0, KEEP_BYTES) +
186
+ `\n\n---\n[Context truncated: ${(bytes / 1024).toFixed(1)} KB → ${(KEEP_BYTES / 1024).toFixed(1)} KB. ` +
187
+ `Full output saved to: ${filePath}]`,
188
+ };
189
+ excess -= truncatedBytes;
190
+ }
191
+ return result;
192
+ }
193
+ // ─── Step 2: Drop old turns ───────────────────────────────────────────────
194
+ /**
195
+ * Remove messages older than `keepTurns` conversation turns.
196
+ * A "turn" is a user message + all subsequent assistant/tool messages
197
+ * until the next user message.
198
+ */
199
+ step2DropOldTurns(messages, turnStarts) {
200
+ if (turnStarts.length <= this.config.keepTurns)
201
+ return messages;
202
+ const cutoffIdx = turnStarts[turnStarts.length - this.config.keepTurns];
203
+ if (cutoffIdx <= 0)
204
+ return messages;
205
+ const dropped = turnStarts.length - this.config.keepTurns;
206
+ const marker = {
207
+ role: types_1.Role.User,
208
+ content: `[Earlier conversation (${dropped} turn(s)) removed to save context space.]`,
209
+ timestamp: Date.now(),
210
+ };
211
+ return [marker, ...messages.slice(cutoffIdx)];
212
+ }
213
+ // ─── Step 3: Drop stale tool results ──────────────────────────────────────
214
+ /**
215
+ * Remove tool results older than `toolResultMaxAgeMs` for read-type
216
+ * tools (results that can be reproduced by re-running the tool).
217
+ * Sub-agent results (`<subagent-result>`) are preserved.
218
+ */
219
+ step3DropStaleToolResults(messages) {
220
+ const now = Date.now();
221
+ const maxAge = this.config.toolResultMaxAgeMs;
222
+ let changed = false;
223
+ const result = messages.map((m) => {
224
+ if (m.role !== types_1.Role.Tool)
225
+ return m;
226
+ if (!m.timestamp)
227
+ return m;
228
+ // Only target read-type tools (results that can be reproduced by re-running)
229
+ if (!READ_TOOLS.has(m.name ?? ""))
230
+ return m;
231
+ // Preserve sub-agent results (injected as user messages, but guard anyway)
232
+ if (m.content.includes("<subagent-result"))
233
+ return m;
234
+ const age = now - m.timestamp;
235
+ if (age < maxAge)
236
+ return m;
237
+ changed = true;
238
+ return {
239
+ ...m,
240
+ content: `[Tool "${m.name ?? "unknown"}" result (${Math.round(age / 60000)} min ago) removed. ` +
241
+ `Re-run the tool if this information is still needed.]`,
242
+ };
243
+ });
244
+ return changed ? result : messages;
245
+ }
246
+ // ─── Step 4: LLM full-conversation summarization ────────────────────────
247
+ /**
248
+ * Generate a structured summary of ALL messages via the LLM.
249
+ *
250
+ * The entire conversation (from the first user message onward) is
251
+ * compressed into a single summary. No recent turns are kept verbatim —
252
+ * the summary is the sole source of history after compression.
253
+ *
254
+ * A continuity hint is appended so the LLM knows it is resuming, not
255
+ * starting from scratch.
256
+ */
257
+ async step4LlmSummarize(messages, _systemMessage, llm, _turnStarts) {
258
+ const prompt = buildSummaryPrompt(messages);
259
+ try {
260
+ const response = await llm.chat([{ role: types_1.Role.User, content: prompt }], []);
261
+ const summary = {
262
+ role: types_1.Role.User,
263
+ content: `[Context Summary — conversation compressed to save space]\n\n` +
264
+ response.content,
265
+ timestamp: Date.now(),
266
+ };
267
+ const hint = {
268
+ role: types_1.Role.User,
269
+ content: "[System] The conversation above has been compressed into a summary. " +
270
+ "You are NOT starting from scratch — continue your work from where you left off. " +
271
+ "Use the summary above to understand what happened before and pick up right where you were.",
272
+ timestamp: Date.now(),
273
+ };
274
+ return [summary, hint];
275
+ }
276
+ catch {
277
+ // If summarization fails, fall back to simple truncation with a marker
278
+ this.logger.warn("Compression", "Step 4 LLM call failed; falling back to simple truncation.");
279
+ const marker = {
280
+ role: types_1.Role.User,
281
+ content: `[Context compressed — LLM summarization was unavailable. ` +
282
+ `Some earlier context may be missing. Continue to the best of your ability.]`,
283
+ timestamp: Date.now(),
284
+ };
285
+ return [marker];
286
+ }
287
+ }
288
+ }
289
+ exports.ProgressiveCompressor = ProgressiveCompressor;
290
+ // ─── Summary Prompt Builder ─────────────────────────────────────────────────
291
+ const MAX_CHARS_PER_MESSAGE = 3000;
292
+ function buildSummaryPrompt(messages) {
293
+ const transcriptLines = messages.map((m) => {
294
+ const roleLabel = m.role.toUpperCase();
295
+ let content = m.content;
296
+ if (content.length > MAX_CHARS_PER_MESSAGE) {
297
+ content = content.slice(0, MAX_CHARS_PER_MESSAGE) + "\n... [truncated for summarization]";
298
+ }
299
+ return `[${roleLabel}]${m.name ? ` (${m.name})` : ""}\n${content}`;
300
+ });
301
+ const transcript = transcriptLines.join("\n\n---\n\n");
302
+ return [
303
+ "You are a context compression assistant. Read the following conversation transcript ",
304
+ "and generate a structured summary document. The summary MUST include ALL of these ",
305
+ "sections (use them as headings, do not skip any):",
306
+ "",
307
+ "## 1. Primary Request and Intent",
308
+ "Every request the user made and their intent/goal.",
309
+ "",
310
+ "## 2. Key Technical Concepts",
311
+ "Technologies, libraries, patterns, and concepts discussed or used.",
312
+ "",
313
+ "## 3. Files and Code Sections",
314
+ "Every file path mentioned or edited, with relevant code snippets where available.",
315
+ "",
316
+ "## 4. Errors and Fixes",
317
+ "Every error encountered and how it was resolved (or if still unresolved).",
318
+ "",
319
+ "## 5. Problem Solving",
320
+ "Chronological walkthrough of how problems were approached and resolved.",
321
+ "",
322
+ "## 6. ALL User Messages",
323
+ "Copy every single user message verbatim. Do NOT summarize, omit, or paraphrase any.",
324
+ "",
325
+ "## 7. Pending Tasks",
326
+ "Tasks that were requested but not yet started or completed.",
327
+ "",
328
+ "## 8. Current Work",
329
+ "What was being worked on right before this compression happened — ",
330
+ "the exact state and context of the ongoing task.",
331
+ "",
332
+ "## 9. Optional Next Step",
333
+ "If you can infer the logical next action, suggest it briefly. " +
334
+ "Otherwise say 'Continue from where you left off.'",
335
+ "",
336
+ "---",
337
+ "",
338
+ "=== CONVERSATION TRANSCRIPT ===",
339
+ "",
340
+ transcript,
341
+ "",
342
+ "=== END ===",
343
+ "",
344
+ "Now generate the structured summary document.",
345
+ ].join("\n");
346
+ }
347
+ // ─── Helpers ────────────────────────────────────────────────────────────────
348
+ function computeTurnStarts(messages) {
349
+ const starts = [];
350
+ for (let i = 0; i < messages.length; i++) {
351
+ if (messages[i].role === types_1.Role.User) {
352
+ starts.push(i);
353
+ }
354
+ }
355
+ return starts;
356
+ }
357
+ function sanitize(name) {
358
+ return name.replace(/[^a-zA-Z0-9_\-.]/g, "_");
359
+ }
360
+ function simpleHash(str) {
361
+ let hash = 5381;
362
+ for (let i = 0; i < str.length; i++) {
363
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) & 0xffffffff;
364
+ }
365
+ return (hash >>> 0).toString(16).padStart(8, "0");
366
+ }
367
+ //# sourceMappingURL=progressive-compressor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressive-compressor.js","sourceRoot":"","sources":["../../src/compression/progressive-compressor.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,6 @@
3
3
  */
4
4
  export interface CompressionConfig {
5
5
  /** The compression strategy to use. */
6
- strategy: "sliding_window";
7
- /** Number of messages to preserve when compression is triggered. */
8
- keepLastN: number;
9
- /** Whether to always keep system messages. */
10
- keepSystemMessages: boolean;
6
+ strategy: "progressive";
11
7
  }
12
8
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compression/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,EAAE,gBAAgB,CAAC;IAE3B,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAElB,8CAA8C;IAC9C,kBAAkB,EAAE,OAAO,CAAC;CAC7B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compression/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,EAAE,aAAa,CAAC;CACzB"}
@@ -1,47 +1,66 @@
1
1
  import { MessageData } from "../messages/types";
2
2
  import { ContextConfig, ContextState } from "./types";
3
+ import { LLMProvider } from "../llm/interface";
4
+ import { Logger } from "../logging/logger";
3
5
  /**
4
6
  * ContextManager maintains the message window that will be sent to the LLM.
5
7
  *
6
8
  * Responsibilities:
7
- * - Accept new messages and update the running token count.
9
+ * - Accept new messages with automatic timestamps.
8
10
  * - Detect when the token threshold is crossed and trigger compression.
11
+ * - Run progressive 4-step compression with optional LLM summarization.
9
12
  * - Provide the current message list to the caller (e.g., Agent).
10
13
  */
11
14
  export declare class ContextManager {
12
15
  private config;
13
16
  private messages;
14
17
  private systemMessage;
15
- private compressionStrategy;
16
18
  private _isCompressed;
17
- constructor(config?: Partial<ContextConfig>);
19
+ private compressor;
20
+ private logger;
21
+ constructor(config?: Partial<ContextConfig>, logger?: Logger);
22
+ /**
23
+ * Compute the trigger token count based on the compressionThreshold mode.
24
+ * Absolute: maxTokens - threshold
25
+ * Ratio: maxTokens * (1 - threshold)
26
+ */
27
+ private triggerTokens;
18
28
  /**
19
29
  * Set or update the system message (always preserved in the window).
20
30
  */
21
31
  setSystemMessage(content: string): void;
22
32
  /**
23
- * Add a message to the context window.
33
+ * Add a message to the context window. Timestamps are auto-set if not
34
+ * already present.
24
35
  */
25
36
  addMessage(message: MessageData): void;
26
37
  /**
27
- * Check whether the context window has exceeded the compression threshold.
38
+ * Check whether compression should trigger.
39
+ * @param model Optional model name for accurate tiktoken encoding.
40
+ * @returns true when remaining free tokens < compressionThreshold.
28
41
  */
29
- shouldCompress(): boolean;
42
+ shouldCompress(model?: string): boolean;
30
43
  /**
31
- * The token count at which compression triggers.
44
+ * Token count of all messages in the window.
45
+ * @param model Optional model name for accurate tiktoken encoding.
32
46
  */
33
- private getCompressionThreshold;
47
+ getCurrentTokens(model?: string): number;
34
48
  /**
35
- * Approximate token count of all messages in the window.
49
+ * Run progressive 4-step compression.
50
+ *
51
+ * @param llm Optional LLM provider for Step 4 (summarization).
52
+ * If omitted, only steps 1-3 are applied.
36
53
  */
37
- getCurrentTokens(): number;
54
+ compress(llm?: LLMProvider): Promise<{
55
+ removedCount: number;
56
+ }>;
38
57
  /**
39
- * Run the compression strategy to reduce the window size.
40
- * Resets the message list to the compressed output.
58
+ * Convenience: check + compress if needed.
59
+ *
60
+ * @param llm LLM provider for Step 4 summarization and accurate token counting.
61
+ * @returns true if compression was applied.
41
62
  */
42
- compress(): {
43
- removedCount: number;
44
- };
63
+ checkAndCompress(llm?: LLMProvider): Promise<boolean>;
45
64
  /**
46
65
  * Get the current context messages (ready to send to the LLM).
47
66
  * Includes the system message as the first element if set.
@@ -1 +1 @@
1
- {"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAQ,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAKtD;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAW3C;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIvC;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAItC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAM/B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAc1B;;;OAGG;IACH,QAAQ,IAAI;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE;IAUpC;;;OAGG;IACH,kBAAkB,IAAI,WAAW,EAAE;IAOnC;;OAEG;IACH,WAAW,IAAI,WAAW,EAAE;IAI5B;;OAEG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;OAEG;IACH,QAAQ,IAAI,YAAY;IASxB;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}
1
+ {"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAQ,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAiB,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM;IAqB5D;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIvC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAOtC;;;;OAIG;IACH,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IASvC;;;OAGG;IACH,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAWxC;;;;;OAKG;IACG,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAepE;;;;;OAKG;IACG,gBAAgB,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB3D;;;OAGG;IACH,kBAAkB,IAAI,WAAW,EAAE;IAOnC;;OAEG;IACH,WAAW,IAAI,WAAW,EAAE;IAI5B;;OAEG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;OAEG;IACH,QAAQ,IAAI,YAAY;IASxB;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}
@@ -2,29 +2,51 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ContextManager = void 0;
4
4
  const types_1 = require("../messages/types");
5
- const sliding_window_1 = require("../compression/sliding-window");
6
5
  const token_counter_1 = require("../utils/token-counter");
6
+ const progressive_compressor_1 = require("../compression/progressive-compressor");
7
+ const logger_1 = require("../logging/logger");
7
8
  /**
8
9
  * ContextManager maintains the message window that will be sent to the LLM.
9
10
  *
10
11
  * Responsibilities:
11
- * - Accept new messages and update the running token count.
12
+ * - Accept new messages with automatic timestamps.
12
13
  * - Detect when the token threshold is crossed and trigger compression.
14
+ * - Run progressive 4-step compression with optional LLM summarization.
13
15
  * - Provide the current message list to the caller (e.g., Agent).
14
16
  */
15
17
  class ContextManager {
16
18
  config;
17
19
  messages = [];
18
20
  systemMessage = null;
19
- compressionStrategy;
20
21
  _isCompressed = false;
21
- constructor(config) {
22
+ compressor;
23
+ logger;
24
+ constructor(config, logger) {
22
25
  this.config = {
23
26
  maxTokens: config?.maxTokens ?? 128000,
24
- compressionThresholdRatio: config?.compressionThresholdRatio ?? 0.75,
27
+ compressionThreshold: config?.compressionThreshold ?? 20000,
28
+ keepTurns: config?.keepTurns ?? 40,
29
+ toolResultMaxAgeMs: config?.toolResultMaxAgeMs ?? 60 * 60 * 1000,
25
30
  compression: config?.compression,
26
31
  };
27
- this.compressionStrategy = new sliding_window_1.SlidingWindowCompression(this.config.compression);
32
+ // Validate ratio mode
33
+ if (this.config.compressionThreshold < 1 && this.config.compressionThreshold > 0.25) {
34
+ throw new Error(`compressionThreshold ratio must be ≤ 0.25 (trigger at ≥ 75% of context). ` +
35
+ `Got ${this.config.compressionThreshold} (trigger at ${Math.round((1 - this.config.compressionThreshold) * 100)}%).`);
36
+ }
37
+ this.logger = logger ?? new logger_1.ConsoleLogger();
38
+ this.compressor = new progressive_compressor_1.ProgressiveCompressor(this.config, this.logger);
39
+ }
40
+ /**
41
+ * Compute the trigger token count based on the compressionThreshold mode.
42
+ * Absolute: maxTokens - threshold
43
+ * Ratio: maxTokens * (1 - threshold)
44
+ */
45
+ triggerTokens() {
46
+ const t = this.config.compressionThreshold;
47
+ return t < 1
48
+ ? Math.round(this.config.maxTokens * (1 - t))
49
+ : this.config.maxTokens - t;
28
50
  }
29
51
  /**
30
52
  * Set or update the system message (always preserved in the window).
@@ -33,49 +55,77 @@ class ContextManager {
33
55
  this.systemMessage = { role: types_1.Role.System, content };
34
56
  }
35
57
  /**
36
- * Add a message to the context window.
58
+ * Add a message to the context window. Timestamps are auto-set if not
59
+ * already present.
37
60
  */
38
61
  addMessage(message) {
62
+ if (!message.timestamp) {
63
+ message.timestamp = Date.now();
64
+ }
39
65
  this.messages.push(message);
40
66
  }
41
67
  /**
42
- * Check whether the context window has exceeded the compression threshold.
43
- */
44
- shouldCompress() {
45
- return this.getCurrentTokens() >= this.getCompressionThreshold();
46
- }
47
- /**
48
- * The token count at which compression triggers.
68
+ * Check whether compression should trigger.
69
+ * @param model Optional model name for accurate tiktoken encoding.
70
+ * @returns true when remaining free tokens < compressionThreshold.
49
71
  */
50
- getCompressionThreshold() {
51
- return Math.floor(this.config.maxTokens * this.config.compressionThresholdRatio);
72
+ shouldCompress(model) {
73
+ // Short-circuit: too few messages to ever hit the compression threshold.
74
+ // The system message + a handful of conversation turns won't breach
75
+ // typical thresholds (64K+). Avoids unnecessary tiktoken calls.
76
+ const totalMsgs = (this.systemMessage ? 1 : 0) + this.messages.length;
77
+ if (totalMsgs < 20)
78
+ return false;
79
+ return this.getCurrentTokens(model) >= this.triggerTokens();
52
80
  }
53
81
  /**
54
- * Approximate token count of all messages in the window.
82
+ * Token count of all messages in the window.
83
+ * @param model Optional model name for accurate tiktoken encoding.
55
84
  */
56
- getCurrentTokens() {
85
+ getCurrentTokens(model) {
57
86
  let total = 0;
58
- // System message overhead
59
87
  if (this.systemMessage) {
60
- total += 3 + (0, token_counter_1.countTokens)(this.systemMessage.content);
88
+ total += 3 + (0, token_counter_1.countTokens)(this.systemMessage.content, model);
61
89
  }
62
- // Per-message overhead + content
63
90
  for (const msg of this.messages) {
64
- total += 3; // role overhead
65
- total += (0, token_counter_1.countTokens)(msg.content);
91
+ total += 3 + (0, token_counter_1.countTokens)(msg.content, model);
66
92
  }
67
93
  return total;
68
94
  }
69
95
  /**
70
- * Run the compression strategy to reduce the window size.
71
- * Resets the message list to the compressed output.
96
+ * Run progressive 4-step compression.
97
+ *
98
+ * @param llm Optional LLM provider for Step 4 (summarization).
99
+ * If omitted, only steps 1-3 are applied.
72
100
  */
73
- compress() {
74
- const result = this.compressionStrategy.compress(this.messages, this.systemMessage ?? undefined);
101
+ async compress(llm) {
102
+ const model = llm?.model;
103
+ const result = await this.compressor.compress(this.messages, this.systemMessage, llm, model);
75
104
  this.messages = result.messages;
76
- this._isCompressed = result.applied;
105
+ if (result.applied) {
106
+ this._isCompressed = true;
107
+ }
77
108
  return { removedCount: result.removedCount };
78
109
  }
110
+ /**
111
+ * Convenience: check + compress if needed.
112
+ *
113
+ * @param llm LLM provider for Step 4 summarization and accurate token counting.
114
+ * @returns true if compression was applied.
115
+ */
116
+ async checkAndCompress(llm) {
117
+ const model = llm?.model;
118
+ if (!this.shouldCompress(model))
119
+ return false;
120
+ const beforeTokens = this.getCurrentTokens(model);
121
+ this.logger.info("Context", `Compression triggered: ${beforeTokens} tokens, ` +
122
+ `threshold at ${this.triggerTokens()}.`);
123
+ const { removedCount } = await this.compress(llm);
124
+ const afterTokens = this.getCurrentTokens(model);
125
+ this.logger.info("Context", `Compression done: ${beforeTokens} → ${afterTokens} tokens ` +
126
+ `(${removedCount > 0 ? `removed ~${removedCount} messages` : "no messages removed"}).`);
127
+ return removedCount > 0;
128
+ }
79
129
  /**
80
130
  * Get the current context messages (ready to send to the LLM).
81
131
  * Includes the system message as the first element if set.