@dexto/core 1.2.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/README.md +55 -13
  2. package/dist/agent/DextoAgent.cjs +627 -228
  3. package/dist/agent/DextoAgent.d.ts +157 -34
  4. package/dist/agent/DextoAgent.d.ts.map +1 -1
  5. package/dist/agent/DextoAgent.js +625 -227
  6. package/dist/agent/agentCard.js +1 -1
  7. package/dist/agent/error-codes.cjs +1 -0
  8. package/dist/agent/error-codes.d.ts +2 -1
  9. package/dist/agent/error-codes.d.ts.map +1 -1
  10. package/dist/agent/error-codes.js +2 -1
  11. package/dist/agent/errors.cjs +13 -0
  12. package/dist/agent/errors.d.ts +4 -0
  13. package/dist/agent/errors.d.ts.map +1 -1
  14. package/dist/agent/errors.js +14 -1
  15. package/dist/agent/index.d.ts +1 -1
  16. package/dist/agent/index.d.ts.map +1 -1
  17. package/dist/agent/index.js +1 -1
  18. package/dist/agent/schemas.cjs +4 -1
  19. package/dist/agent/schemas.d.ts +92 -55
  20. package/dist/agent/schemas.d.ts.map +1 -1
  21. package/dist/agent/schemas.js +7 -3
  22. package/dist/agent/state-manager.cjs +5 -5
  23. package/dist/agent/state-manager.d.ts +4 -4
  24. package/dist/agent/state-manager.js +6 -6
  25. package/dist/agent/types.d.ts +24 -11
  26. package/dist/agent/types.d.ts.map +1 -1
  27. package/dist/approval/error-codes.js +1 -1
  28. package/dist/approval/errors.js +1 -1
  29. package/dist/approval/factory.js +1 -1
  30. package/dist/approval/index.js +1 -1
  31. package/dist/approval/manager.cjs +69 -3
  32. package/dist/approval/manager.d.ts +41 -3
  33. package/dist/approval/manager.d.ts.map +1 -1
  34. package/dist/approval/manager.js +70 -4
  35. package/dist/approval/schemas.cjs +20 -5
  36. package/dist/approval/schemas.d.ts +127 -52
  37. package/dist/approval/schemas.d.ts.map +1 -1
  38. package/dist/approval/schemas.js +21 -6
  39. package/dist/approval/types.d.ts +6 -0
  40. package/dist/approval/types.d.ts.map +1 -1
  41. package/dist/approval/types.js +1 -1
  42. package/dist/{chunk-C6A6W6XS.js → chunk-PTJYTZNU.js} +44 -1
  43. package/dist/{llm/tokenizer/factory.cjs → context/compression/overflow.cjs} +20 -21
  44. package/dist/context/compression/overflow.d.ts +33 -0
  45. package/dist/context/compression/overflow.d.ts.map +1 -0
  46. package/dist/context/compression/overflow.js +19 -0
  47. package/dist/context/compression/reactive-overflow.cjs +201 -0
  48. package/dist/context/compression/reactive-overflow.d.ts +81 -0
  49. package/dist/context/compression/reactive-overflow.d.ts.map +1 -0
  50. package/dist/context/compression/reactive-overflow.js +178 -0
  51. package/dist/context/compression/types.d.ts +9 -7
  52. package/dist/context/compression/types.d.ts.map +1 -1
  53. package/dist/context/error-codes.cjs +3 -0
  54. package/dist/context/error-codes.d.ts +4 -1
  55. package/dist/context/error-codes.d.ts.map +1 -1
  56. package/dist/context/error-codes.js +4 -1
  57. package/dist/context/errors.cjs +28 -0
  58. package/dist/context/errors.d.ts +7 -0
  59. package/dist/context/errors.d.ts.map +1 -1
  60. package/dist/context/errors.js +29 -1
  61. package/dist/context/index.js +1 -1
  62. package/dist/context/manager.cjs +287 -323
  63. package/dist/context/manager.d.ts +65 -111
  64. package/dist/context/manager.d.ts.map +1 -1
  65. package/dist/context/manager.js +287 -328
  66. package/dist/context/media-helpers.js +1 -1
  67. package/dist/context/types.cjs +49 -0
  68. package/dist/context/types.d.ts +185 -72
  69. package/dist/context/types.d.ts.map +1 -1
  70. package/dist/context/types.js +35 -0
  71. package/dist/context/utils.cjs +266 -283
  72. package/dist/context/utils.d.ts +32 -18
  73. package/dist/context/utils.d.ts.map +1 -1
  74. package/dist/context/utils.js +266 -283
  75. package/dist/errors/DextoBaseError.js +1 -1
  76. package/dist/errors/DextoRuntimeError.js +1 -1
  77. package/dist/errors/DextoValidationError.js +1 -1
  78. package/dist/errors/index.js +1 -1
  79. package/dist/errors/result-bridge.js +1 -1
  80. package/dist/errors/types.cjs +1 -0
  81. package/dist/errors/types.d.ts +4 -2
  82. package/dist/errors/types.d.ts.map +1 -1
  83. package/dist/errors/types.js +2 -1
  84. package/dist/events/index.cjs +22 -2
  85. package/dist/events/index.d.ts +170 -62
  86. package/dist/events/index.d.ts.map +1 -1
  87. package/dist/events/index.js +23 -3
  88. package/dist/filesystem/error-codes.js +1 -1
  89. package/dist/filesystem/errors.js +1 -1
  90. package/dist/filesystem/filesystem-service.js +1 -1
  91. package/dist/filesystem/index.js +1 -1
  92. package/dist/filesystem/path-validator.js +1 -1
  93. package/dist/index.browser.cjs +23 -8
  94. package/dist/index.browser.d.ts +4 -3
  95. package/dist/index.browser.d.ts.map +1 -1
  96. package/dist/index.browser.js +20 -3
  97. package/dist/index.js +1 -1
  98. package/dist/llm/error-codes.cjs +0 -1
  99. package/dist/llm/error-codes.d.ts +0 -1
  100. package/dist/llm/error-codes.d.ts.map +1 -1
  101. package/dist/llm/error-codes.js +1 -2
  102. package/dist/llm/errors.cjs +10 -10
  103. package/dist/llm/errors.d.ts +5 -6
  104. package/dist/llm/errors.d.ts.map +1 -1
  105. package/dist/llm/errors.js +12 -12
  106. package/dist/llm/executor/stream-processor.cjs +367 -0
  107. package/dist/llm/executor/stream-processor.d.ts +55 -0
  108. package/dist/llm/executor/stream-processor.d.ts.map +1 -0
  109. package/dist/llm/executor/stream-processor.js +344 -0
  110. package/dist/llm/executor/tool-output-truncator.cjs +75 -0
  111. package/dist/llm/executor/tool-output-truncator.d.ts +27 -0
  112. package/dist/llm/executor/tool-output-truncator.d.ts.map +1 -0
  113. package/dist/llm/executor/tool-output-truncator.js +48 -0
  114. package/dist/llm/executor/turn-executor.cjs +753 -0
  115. package/dist/llm/executor/turn-executor.d.ts +166 -0
  116. package/dist/llm/executor/turn-executor.d.ts.map +1 -0
  117. package/dist/llm/executor/turn-executor.js +684 -0
  118. package/dist/llm/executor/types.d.ts +27 -0
  119. package/dist/llm/executor/types.d.ts.map +1 -0
  120. package/dist/llm/formatters/vercel.cjs +20 -186
  121. package/dist/llm/formatters/vercel.d.ts +2 -14
  122. package/dist/llm/formatters/vercel.d.ts.map +1 -1
  123. package/dist/llm/formatters/vercel.js +19 -185
  124. package/dist/llm/registry.cjs +36 -45
  125. package/dist/llm/registry.d.ts +53 -39
  126. package/dist/llm/registry.d.ts.map +1 -1
  127. package/dist/llm/registry.js +34 -42
  128. package/dist/llm/resolver.cjs +1 -31
  129. package/dist/llm/resolver.d.ts.map +1 -1
  130. package/dist/llm/resolver.js +2 -34
  131. package/dist/llm/schemas.cjs +2 -17
  132. package/dist/llm/schemas.d.ts +10 -23
  133. package/dist/llm/schemas.d.ts.map +1 -1
  134. package/dist/llm/schemas.js +5 -22
  135. package/dist/llm/services/factory.cjs +3 -92
  136. package/dist/llm/services/factory.d.ts +14 -4
  137. package/dist/llm/services/factory.d.ts.map +1 -1
  138. package/dist/llm/services/factory.js +4 -83
  139. package/dist/llm/services/test-utils.integration.cjs +6 -8
  140. package/dist/llm/services/test-utils.integration.d.ts.map +1 -1
  141. package/dist/llm/services/test-utils.integration.js +7 -9
  142. package/dist/llm/services/types.d.ts +1 -28
  143. package/dist/llm/services/types.d.ts.map +1 -1
  144. package/dist/llm/services/vercel.cjs +54 -468
  145. package/dist/llm/services/vercel.d.ts +38 -21
  146. package/dist/llm/services/vercel.d.ts.map +1 -1
  147. package/dist/llm/services/vercel.js +56 -475
  148. package/dist/llm/types.cjs +0 -3
  149. package/dist/llm/types.d.ts +8 -8
  150. package/dist/llm/types.d.ts.map +1 -1
  151. package/dist/llm/types.js +1 -3
  152. package/dist/llm/validation.js +1 -1
  153. package/dist/logger/browser.js +1 -1
  154. package/dist/logger/factory.js +1 -1
  155. package/dist/logger/index.js +1 -1
  156. package/dist/logger/logger.js +1 -1
  157. package/dist/logger/v2/dexto-logger.cjs +34 -6
  158. package/dist/logger/v2/dexto-logger.d.ts +20 -2
  159. package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
  160. package/dist/logger/v2/dexto-logger.js +35 -7
  161. package/dist/logger/v2/error-codes.js +1 -1
  162. package/dist/logger/v2/errors.js +1 -1
  163. package/dist/logger/v2/schemas.cjs +1 -1
  164. package/dist/logger/v2/schemas.js +2 -2
  165. package/dist/logger/v2/test-utils.cjs +70 -0
  166. package/dist/logger/v2/test-utils.d.ts +17 -0
  167. package/dist/logger/v2/test-utils.d.ts.map +1 -0
  168. package/dist/logger/v2/test-utils.js +46 -0
  169. package/dist/logger/v2/transport-factory.js +1 -1
  170. package/dist/logger/v2/transports/console-transport.js +1 -1
  171. package/dist/logger/v2/transports/file-transport.cjs +6 -0
  172. package/dist/logger/v2/transports/file-transport.d.ts +4 -0
  173. package/dist/logger/v2/transports/file-transport.d.ts.map +1 -1
  174. package/dist/logger/v2/transports/file-transport.js +7 -1
  175. package/dist/logger/v2/types.cjs +1 -0
  176. package/dist/logger/v2/types.d.ts +18 -2
  177. package/dist/logger/v2/types.d.ts.map +1 -1
  178. package/dist/logger/v2/types.js +2 -1
  179. package/dist/mcp/error-codes.cjs +1 -0
  180. package/dist/mcp/error-codes.d.ts +1 -0
  181. package/dist/mcp/error-codes.d.ts.map +1 -1
  182. package/dist/mcp/error-codes.js +2 -1
  183. package/dist/mcp/errors.cjs +13 -0
  184. package/dist/mcp/errors.d.ts +7 -0
  185. package/dist/mcp/errors.d.ts.map +1 -1
  186. package/dist/mcp/errors.js +14 -1
  187. package/dist/mcp/manager.cjs +4 -0
  188. package/dist/mcp/manager.d.ts.map +1 -1
  189. package/dist/mcp/manager.js +5 -1
  190. package/dist/mcp/mcp-client.js +1 -1
  191. package/dist/mcp/resolver.js +1 -1
  192. package/dist/mcp/schemas.cjs +6 -0
  193. package/dist/mcp/schemas.d.ts +52 -0
  194. package/dist/mcp/schemas.d.ts.map +1 -1
  195. package/dist/mcp/schemas.js +6 -1
  196. package/dist/memory/error-codes.js +1 -1
  197. package/dist/memory/errors.js +1 -1
  198. package/dist/memory/index.js +1 -1
  199. package/dist/memory/manager.js +1 -1
  200. package/dist/memory/schemas.d.ts +2 -2
  201. package/dist/memory/schemas.js +1 -1
  202. package/dist/plugins/builtins/content-policy.js +1 -1
  203. package/dist/plugins/builtins/response-sanitizer.js +1 -1
  204. package/dist/plugins/error-codes.cjs +1 -0
  205. package/dist/plugins/error-codes.d.ts +3 -1
  206. package/dist/plugins/error-codes.d.ts.map +1 -1
  207. package/dist/plugins/error-codes.js +2 -1
  208. package/dist/plugins/index.js +1 -1
  209. package/dist/plugins/loader.cjs +25 -5
  210. package/dist/plugins/loader.d.ts.map +1 -1
  211. package/dist/plugins/loader.js +26 -6
  212. package/dist/plugins/manager.js +1 -1
  213. package/dist/plugins/registrations/builtins.js +1 -1
  214. package/dist/plugins/schemas.d.ts +3 -3
  215. package/dist/plugins/schemas.js +1 -1
  216. package/dist/plugins/types.d.ts +0 -1
  217. package/dist/plugins/types.d.ts.map +1 -1
  218. package/dist/process/command-validator.js +1 -1
  219. package/dist/process/error-codes.js +1 -1
  220. package/dist/process/errors.js +1 -1
  221. package/dist/process/index.js +1 -1
  222. package/dist/process/process-service.cjs +78 -26
  223. package/dist/process/process-service.d.ts +6 -1
  224. package/dist/process/process-service.d.ts.map +1 -1
  225. package/dist/process/process-service.js +79 -27
  226. package/dist/process/types.d.ts +2 -2
  227. package/dist/process/types.d.ts.map +1 -1
  228. package/dist/prompts/error-codes.cjs +1 -0
  229. package/dist/prompts/error-codes.d.ts +2 -1
  230. package/dist/prompts/error-codes.d.ts.map +1 -1
  231. package/dist/prompts/error-codes.js +2 -1
  232. package/dist/prompts/errors.cjs +15 -0
  233. package/dist/prompts/errors.d.ts +4 -0
  234. package/dist/prompts/errors.d.ts.map +1 -1
  235. package/dist/prompts/errors.js +16 -1
  236. package/dist/prompts/index.js +1 -1
  237. package/dist/prompts/name-validation.js +1 -1
  238. package/dist/prompts/prompt-manager.cjs +13 -2
  239. package/dist/prompts/prompt-manager.d.ts +7 -0
  240. package/dist/prompts/prompt-manager.d.ts.map +1 -1
  241. package/dist/prompts/prompt-manager.js +14 -3
  242. package/dist/prompts/providers/config-prompt-provider.cjs +12 -3
  243. package/dist/prompts/providers/config-prompt-provider.d.ts +2 -1
  244. package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
  245. package/dist/prompts/providers/config-prompt-provider.js +13 -4
  246. package/dist/prompts/providers/custom-prompt-provider.cjs +2 -2
  247. package/dist/prompts/providers/custom-prompt-provider.d.ts +1 -1
  248. package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
  249. package/dist/prompts/providers/custom-prompt-provider.js +3 -3
  250. package/dist/prompts/providers/mcp-prompt-provider.js +1 -1
  251. package/dist/prompts/schemas.d.ts +12 -0
  252. package/dist/prompts/schemas.d.ts.map +1 -1
  253. package/dist/prompts/schemas.js +1 -1
  254. package/dist/prompts/types.d.ts +2 -0
  255. package/dist/prompts/types.d.ts.map +1 -1
  256. package/dist/prompts/utils.js +1 -1
  257. package/dist/resources/error-codes.js +1 -1
  258. package/dist/resources/errors.js +1 -1
  259. package/dist/resources/handlers/blob-handler.js +1 -1
  260. package/dist/resources/handlers/factory.js +1 -1
  261. package/dist/resources/handlers/filesystem-handler.js +1 -1
  262. package/dist/resources/index.js +1 -1
  263. package/dist/resources/internal-provider.js +1 -1
  264. package/dist/resources/manager.js +1 -1
  265. package/dist/resources/reference-parser.js +1 -1
  266. package/dist/resources/schemas.js +1 -1
  267. package/dist/search/index.js +1 -1
  268. package/dist/search/search-service.js +1 -1
  269. package/dist/session/chat-session.cjs +149 -51
  270. package/dist/session/chat-session.d.ts +69 -29
  271. package/dist/session/chat-session.d.ts.map +1 -1
  272. package/dist/session/chat-session.js +150 -52
  273. package/dist/session/error-codes.js +1 -1
  274. package/dist/session/errors.js +1 -1
  275. package/dist/session/history/database.cjs +134 -21
  276. package/dist/session/history/database.d.ts +37 -8
  277. package/dist/session/history/database.d.ts.map +1 -1
  278. package/dist/session/history/database.js +135 -22
  279. package/dist/session/history/factory.js +1 -1
  280. package/dist/session/history/memory.cjs +18 -0
  281. package/dist/session/history/memory.d.ts +8 -0
  282. package/dist/session/history/memory.d.ts.map +1 -1
  283. package/dist/session/history/memory.js +19 -1
  284. package/dist/session/history/types.d.ts +13 -1
  285. package/dist/session/history/types.d.ts.map +1 -1
  286. package/dist/session/index.cjs +3 -0
  287. package/dist/session/index.d.ts +3 -0
  288. package/dist/session/index.d.ts.map +1 -1
  289. package/dist/session/index.js +3 -1
  290. package/dist/session/message-queue.cjs +201 -0
  291. package/dist/session/message-queue.d.ts +114 -0
  292. package/dist/session/message-queue.d.ts.map +1 -0
  293. package/dist/session/message-queue.js +178 -0
  294. package/dist/session/schemas.js +1 -1
  295. package/dist/session/session-manager.cjs +57 -7
  296. package/dist/session/session-manager.d.ts +18 -0
  297. package/dist/session/session-manager.d.ts.map +1 -1
  298. package/dist/session/session-manager.js +58 -8
  299. package/dist/session/title-generator.cjs +4 -8
  300. package/dist/session/title-generator.d.ts +1 -2
  301. package/dist/session/title-generator.d.ts.map +1 -1
  302. package/dist/session/title-generator.js +5 -9
  303. package/dist/session/types.cjs +16 -0
  304. package/dist/session/types.d.ts +14 -0
  305. package/dist/session/types.d.ts.map +1 -0
  306. package/dist/session/types.js +0 -0
  307. package/dist/storage/blob/factory.js +1 -1
  308. package/dist/storage/blob/local-blob-store.js +1 -1
  309. package/dist/storage/blob/memory-blob-store.js +1 -1
  310. package/dist/storage/blob/schemas.js +1 -1
  311. package/dist/storage/cache/factory.cjs +6 -2
  312. package/dist/storage/cache/factory.d.ts +2 -1
  313. package/dist/storage/cache/factory.d.ts.map +1 -1
  314. package/dist/storage/cache/factory.js +7 -3
  315. package/dist/storage/cache/memory-cache-store.js +1 -1
  316. package/dist/storage/cache/redis-store.js +1 -1
  317. package/dist/storage/cache/schemas.js +1 -1
  318. package/dist/storage/database/factory.cjs +11 -17
  319. package/dist/storage/database/factory.d.ts +2 -1
  320. package/dist/storage/database/factory.d.ts.map +1 -1
  321. package/dist/storage/database/factory.js +12 -18
  322. package/dist/storage/database/memory-database-store.js +1 -1
  323. package/dist/storage/database/postgres-store.cjs +12 -0
  324. package/dist/storage/database/postgres-store.d.ts.map +1 -1
  325. package/dist/storage/database/postgres-store.js +13 -1
  326. package/dist/storage/database/schemas.js +1 -1
  327. package/dist/storage/database/sqlite-store.cjs +8 -0
  328. package/dist/storage/database/sqlite-store.d.ts.map +1 -1
  329. package/dist/storage/database/sqlite-store.js +9 -1
  330. package/dist/storage/error-codes.cjs +1 -0
  331. package/dist/storage/error-codes.d.ts +1 -0
  332. package/dist/storage/error-codes.d.ts.map +1 -1
  333. package/dist/storage/error-codes.js +2 -1
  334. package/dist/storage/errors.cjs +17 -0
  335. package/dist/storage/errors.d.ts +9 -0
  336. package/dist/storage/errors.d.ts.map +1 -1
  337. package/dist/storage/errors.js +18 -1
  338. package/dist/storage/index.js +1 -1
  339. package/dist/storage/schemas.js +1 -1
  340. package/dist/storage/storage-manager.js +1 -1
  341. package/dist/systemPrompt/contributors.js +1 -1
  342. package/dist/systemPrompt/error-codes.js +1 -1
  343. package/dist/systemPrompt/errors.js +1 -1
  344. package/dist/systemPrompt/in-built-prompts.js +1 -1
  345. package/dist/systemPrompt/index.js +1 -1
  346. package/dist/systemPrompt/manager.js +1 -1
  347. package/dist/systemPrompt/registry.js +1 -1
  348. package/dist/systemPrompt/schemas.d.ts +5 -5
  349. package/dist/systemPrompt/schemas.js +1 -1
  350. package/dist/telemetry/decorators.js +1 -1
  351. package/dist/{llm/tokenizer/default.cjs → telemetry/error-codes.cjs} +14 -19
  352. package/dist/telemetry/error-codes.d.ts +13 -0
  353. package/dist/telemetry/error-codes.d.ts.map +1 -0
  354. package/dist/telemetry/error-codes.js +13 -0
  355. package/dist/telemetry/errors.cjs +105 -0
  356. package/dist/telemetry/errors.d.ts +28 -0
  357. package/dist/telemetry/errors.d.ts.map +1 -0
  358. package/dist/telemetry/errors.js +82 -0
  359. package/dist/telemetry/exporters.js +1 -1
  360. package/dist/telemetry/index.js +1 -1
  361. package/dist/telemetry/schemas.js +1 -1
  362. package/dist/telemetry/telemetry.cjs +92 -26
  363. package/dist/telemetry/telemetry.d.ts +1 -1
  364. package/dist/telemetry/telemetry.d.ts.map +1 -1
  365. package/dist/telemetry/telemetry.js +75 -19
  366. package/dist/telemetry/utils.js +1 -1
  367. package/dist/tools/bash-pattern-utils.cjs +91 -0
  368. package/dist/tools/bash-pattern-utils.d.ts +58 -0
  369. package/dist/tools/bash-pattern-utils.d.ts.map +1 -0
  370. package/dist/tools/bash-pattern-utils.js +64 -0
  371. package/dist/tools/confirmation/allowed-tools-provider/factory.js +1 -1
  372. package/dist/tools/confirmation/allowed-tools-provider/in-memory.js +1 -1
  373. package/dist/tools/confirmation/allowed-tools-provider/storage.js +1 -1
  374. package/dist/tools/display-types.cjs +60 -0
  375. package/dist/tools/display-types.d.ts +133 -0
  376. package/dist/tools/display-types.d.ts.map +1 -0
  377. package/dist/tools/display-types.js +32 -0
  378. package/dist/tools/error-codes.cjs +2 -0
  379. package/dist/tools/error-codes.d.ts +3 -1
  380. package/dist/tools/error-codes.d.ts.map +1 -1
  381. package/dist/tools/error-codes.js +3 -1
  382. package/dist/tools/errors.cjs +30 -0
  383. package/dist/tools/errors.d.ts +16 -0
  384. package/dist/tools/errors.d.ts.map +1 -1
  385. package/dist/tools/errors.js +31 -1
  386. package/dist/tools/index.cjs +2 -0
  387. package/dist/tools/index.d.ts +1 -0
  388. package/dist/tools/index.d.ts.map +1 -1
  389. package/dist/tools/index.js +2 -1
  390. package/dist/tools/internal-tools/constants.js +1 -1
  391. package/dist/tools/internal-tools/implementations/ask-user-tool.cjs +1 -1
  392. package/dist/tools/internal-tools/implementations/ask-user-tool.js +2 -2
  393. package/dist/tools/internal-tools/implementations/bash-exec-tool.cjs +42 -18
  394. package/dist/tools/internal-tools/implementations/bash-exec-tool.d.ts +3 -3
  395. package/dist/tools/internal-tools/implementations/bash-exec-tool.d.ts.map +1 -1
  396. package/dist/tools/internal-tools/implementations/bash-exec-tool.js +43 -19
  397. package/dist/tools/internal-tools/implementations/bash-output-tool.js +1 -1
  398. package/dist/tools/internal-tools/implementations/delegate-to-url-tool.js +1 -1
  399. package/dist/tools/internal-tools/implementations/edit-file-tool.cjs +66 -1
  400. package/dist/tools/internal-tools/implementations/edit-file-tool.d.ts.map +1 -1
  401. package/dist/tools/internal-tools/implementations/edit-file-tool.js +67 -2
  402. package/dist/tools/internal-tools/implementations/glob-files-tool.cjs +14 -1
  403. package/dist/tools/internal-tools/implementations/glob-files-tool.d.ts.map +1 -1
  404. package/dist/tools/internal-tools/implementations/glob-files-tool.js +15 -2
  405. package/dist/tools/internal-tools/implementations/grep-content-tool.cjs +16 -1
  406. package/dist/tools/internal-tools/implementations/grep-content-tool.d.ts.map +1 -1
  407. package/dist/tools/internal-tools/implementations/grep-content-tool.js +17 -2
  408. package/dist/tools/internal-tools/implementations/kill-process-tool.js +1 -1
  409. package/dist/tools/internal-tools/implementations/read-file-tool.cjs +9 -1
  410. package/dist/tools/internal-tools/implementations/read-file-tool.d.ts.map +1 -1
  411. package/dist/tools/internal-tools/implementations/read-file-tool.js +10 -2
  412. package/dist/tools/internal-tools/implementations/search-history-tool.js +1 -1
  413. package/dist/tools/internal-tools/implementations/write-file-tool.cjs +69 -1
  414. package/dist/tools/internal-tools/implementations/write-file-tool.d.ts.map +1 -1
  415. package/dist/tools/internal-tools/implementations/write-file-tool.js +72 -2
  416. package/dist/tools/internal-tools/provider.cjs +27 -10
  417. package/dist/tools/internal-tools/provider.d.ts +8 -5
  418. package/dist/tools/internal-tools/provider.d.ts.map +1 -1
  419. package/dist/tools/internal-tools/provider.js +28 -11
  420. package/dist/tools/internal-tools/registry.cjs +4 -3
  421. package/dist/tools/internal-tools/registry.d.ts +28 -7
  422. package/dist/tools/internal-tools/registry.d.ts.map +1 -1
  423. package/dist/tools/internal-tools/registry.js +5 -4
  424. package/dist/tools/schemas.cjs +17 -7
  425. package/dist/tools/schemas.d.ts +31 -4
  426. package/dist/tools/schemas.d.ts.map +1 -1
  427. package/dist/tools/schemas.js +15 -7
  428. package/dist/tools/tool-manager.cjs +140 -18
  429. package/dist/tools/tool-manager.d.ts +23 -1
  430. package/dist/tools/tool-manager.d.ts.map +1 -1
  431. package/dist/tools/tool-manager.js +145 -19
  432. package/dist/tools/types.d.ts +20 -11
  433. package/dist/tools/types.d.ts.map +1 -1
  434. package/dist/utils/api-key-resolver.js +1 -1
  435. package/dist/utils/async-context.js +1 -1
  436. package/dist/utils/debug.js +1 -1
  437. package/dist/{llm/tokenizer/types.cjs → utils/defer.cjs} +19 -10
  438. package/dist/utils/defer.d.ts +63 -0
  439. package/dist/utils/defer.d.ts.map +1 -0
  440. package/dist/utils/defer.js +19 -0
  441. package/dist/utils/env-file.js +1 -1
  442. package/dist/utils/error-conversion.js +1 -1
  443. package/dist/utils/execution-context.js +1 -1
  444. package/dist/utils/fs-walk.js +1 -1
  445. package/dist/utils/index.cjs +3 -1
  446. package/dist/utils/index.d.ts +1 -0
  447. package/dist/utils/index.d.ts.map +1 -1
  448. package/dist/utils/index.js +1 -0
  449. package/dist/utils/path.js +1 -1
  450. package/dist/utils/redactor.js +1 -1
  451. package/dist/utils/result.js +1 -1
  452. package/dist/utils/safe-stringify.js +1 -1
  453. package/dist/utils/schema-metadata.js +1 -1
  454. package/dist/utils/schema.d.ts +6 -0
  455. package/dist/utils/schema.d.ts.map +1 -1
  456. package/dist/utils/schema.js +1 -1
  457. package/dist/utils/service-initializer.cjs +6 -2
  458. package/dist/utils/service-initializer.d.ts.map +1 -1
  459. package/dist/utils/service-initializer.js +7 -3
  460. package/dist/utils/user-info.js +1 -1
  461. package/dist/utils/zod-schema-converter.js +1 -1
  462. package/package.json +54 -17
  463. package/dist/context/compression/middle-removal.cjs +0 -95
  464. package/dist/context/compression/middle-removal.d.ts +0 -47
  465. package/dist/context/compression/middle-removal.d.ts.map +0 -1
  466. package/dist/context/compression/middle-removal.js +0 -72
  467. package/dist/context/compression/oldest-removal.cjs +0 -83
  468. package/dist/context/compression/oldest-removal.d.ts +0 -42
  469. package/dist/context/compression/oldest-removal.d.ts.map +0 -1
  470. package/dist/context/compression/oldest-removal.js +0 -60
  471. package/dist/llm/formatters/anthropic.cjs +0 -257
  472. package/dist/llm/formatters/anthropic.d.ts +0 -46
  473. package/dist/llm/formatters/anthropic.d.ts.map +0 -1
  474. package/dist/llm/formatters/anthropic.js +0 -239
  475. package/dist/llm/formatters/factory.cjs +0 -50
  476. package/dist/llm/formatters/factory.d.ts +0 -10
  477. package/dist/llm/formatters/factory.d.ts.map +0 -1
  478. package/dist/llm/formatters/factory.js +0 -27
  479. package/dist/llm/formatters/openai.cjs +0 -196
  480. package/dist/llm/formatters/openai.d.ts +0 -39
  481. package/dist/llm/formatters/openai.d.ts.map +0 -1
  482. package/dist/llm/formatters/openai.js +0 -177
  483. package/dist/llm/formatters/types.d.ts +0 -41
  484. package/dist/llm/formatters/types.d.ts.map +0 -1
  485. package/dist/llm/services/anthropic.cjs +0 -511
  486. package/dist/llm/services/anthropic.d.ts +0 -48
  487. package/dist/llm/services/anthropic.d.ts.map +0 -1
  488. package/dist/llm/services/anthropic.js +0 -447
  489. package/dist/llm/services/openai.cjs +0 -611
  490. package/dist/llm/services/openai.d.ts +0 -48
  491. package/dist/llm/services/openai.d.ts.map +0 -1
  492. package/dist/llm/services/openai.js +0 -547
  493. package/dist/llm/tokenizer/anthropic.cjs +0 -43
  494. package/dist/llm/tokenizer/anthropic.d.ts +0 -19
  495. package/dist/llm/tokenizer/anthropic.d.ts.map +0 -1
  496. package/dist/llm/tokenizer/anthropic.js +0 -20
  497. package/dist/llm/tokenizer/default.d.ts +0 -14
  498. package/dist/llm/tokenizer/default.d.ts.map +0 -1
  499. package/dist/llm/tokenizer/default.js +0 -18
  500. package/dist/llm/tokenizer/factory.d.ts +0 -12
  501. package/dist/llm/tokenizer/factory.d.ts.map +0 -1
  502. package/dist/llm/tokenizer/factory.js +0 -21
  503. package/dist/llm/tokenizer/google.cjs +0 -52
  504. package/dist/llm/tokenizer/google.d.ts +0 -29
  505. package/dist/llm/tokenizer/google.d.ts.map +0 -1
  506. package/dist/llm/tokenizer/google.js +0 -29
  507. package/dist/llm/tokenizer/openai.cjs +0 -115
  508. package/dist/llm/tokenizer/openai.d.ts +0 -33
  509. package/dist/llm/tokenizer/openai.d.ts.map +0 -1
  510. package/dist/llm/tokenizer/openai.js +0 -91
  511. package/dist/llm/tokenizer/types.d.ts +0 -18
  512. package/dist/llm/tokenizer/types.d.ts.map +0 -1
  513. package/dist/llm/tokenizer/types.js +0 -10
  514. /package/dist/llm/{formatters → executor}/types.cjs +0 -0
  515. /package/dist/llm/{formatters → executor}/types.js +0 -0
@@ -1,14 +1,9 @@
1
- import "../chunk-C6A6W6XS.js";
2
- import { MiddleRemovalStrategy } from "./compression/middle-removal.js";
3
- import { OldestRemovalStrategy } from "./compression/oldest-removal.js";
1
+ import "../chunk-PTJYTZNU.js";
2
+ import { randomUUID } from "crypto";
3
+ import { isSystemMessage, isUserMessage, isAssistantMessage, isToolMessage } from "./types.js";
4
4
  import { DextoLogComponent } from "../logger/v2/types.js";
5
5
  import { eventBus } from "../events/index.js";
6
- import {
7
- countMessagesTokens,
8
- sanitizeToolResult,
9
- expandBlobReferences,
10
- isLikelyBase64String
11
- } from "./utils.js";
6
+ import { expandBlobReferences, isLikelyBase64String, filterCompacted } from "./utils.js";
12
7
  import { ContextError } from "./errors.js";
13
8
  class ContextManager {
14
9
  /**
@@ -27,27 +22,6 @@ class ContextManager {
27
22
  * Maximum number of tokens allowed in the conversation (if specified)
28
23
  */
29
24
  maxInputTokens;
30
- /**
31
- * Actual token count from the last LLM response.
32
- * Used for more accurate token estimation in hybrid approach.
33
- */
34
- lastActualTokenCount = 0;
35
- /**
36
- * Compression threshold as a percentage of maxInputTokens.
37
- * When estimated tokens exceed (maxInputTokens * threshold), compression is triggered.
38
- */
39
- compressionThreshold = 0.8;
40
- // 80% threshold
41
- /**
42
- * Tokenizer used for counting tokens and enabling compression (if specified)
43
- */
44
- tokenizer;
45
- /**
46
- * The sequence of compression strategies to apply when maxInputTokens is exceeded.
47
- * The order in this array matters, as strategies are applied sequentially until
48
- * the token count is within the limit.
49
- */
50
- compressionStrategies;
51
25
  historyProvider;
52
26
  sessionId;
53
27
  /**
@@ -62,26 +36,19 @@ class ContextManager {
62
36
  * @param llmConfig The validated LLM configuration.
63
37
  * @param formatter Formatter implementation for the target LLM provider
64
38
  * @param systemPromptManager SystemPromptManager instance for the conversation
65
- * @param maxInputTokens Maximum token limit for the conversation history. Triggers compression if exceeded and a tokenizer is provided.
66
- * @param tokenizer Tokenizer implementation used for counting tokens and enabling compression.
39
+ * @param maxInputTokens Maximum token limit for the conversation history.
67
40
  * @param historyProvider Session-scoped ConversationHistoryProvider instance for managing conversation history
68
41
  * @param sessionId Unique identifier for the conversation session (readonly, for debugging)
69
- * @param compressionStrategies Optional array of compression strategies to apply when token limits are exceeded
70
- * @param resourceManager Optional ResourceManager for resolving blob references in messages
42
+ * @param resourceManager ResourceManager for resolving blob references in messages
71
43
  * @param logger Logger instance for logging
72
44
  */
73
- constructor(llmConfig, formatter, systemPromptManager, maxInputTokens, tokenizer, historyProvider, sessionId, resourceManager, logger, compressionStrategies = [
74
- new MiddleRemovalStrategy({}, logger),
75
- new OldestRemovalStrategy({}, logger)
76
- ]) {
45
+ constructor(llmConfig, formatter, systemPromptManager, maxInputTokens, historyProvider, sessionId, resourceManager, logger) {
77
46
  this.llmConfig = llmConfig;
78
47
  this.formatter = formatter;
79
48
  this.systemPromptManager = systemPromptManager;
80
49
  this.maxInputTokens = maxInputTokens;
81
- this.tokenizer = tokenizer;
82
50
  this.historyProvider = historyProvider;
83
51
  this.sessionId = sessionId;
84
- this.compressionStrategies = compressionStrategies;
85
52
  this.resourceManager = resourceManager;
86
53
  this.logger = logger.createChild(DextoLogComponent.CONTEXT);
87
54
  this.logger.debug(
@@ -148,117 +115,177 @@ class ContextManager {
148
115
  return data;
149
116
  }
150
117
  /**
151
- * Returns the current token count of the conversation history.
152
- * @returns Promise that resolves to the number of tokens in the current history
118
+ * Returns the configured maximum number of input tokens for the conversation.
153
119
  */
154
- async getTokenCount() {
155
- const history = await this.historyProvider.getHistory();
156
- return countMessagesTokens(history, this.tokenizer, void 0, this.logger);
120
+ getMaxInputTokens() {
121
+ return this.maxInputTokens;
157
122
  }
158
123
  /**
159
- * Returns the total token count that will be sent to the LLM provider,
160
- * including system prompt, formatted messages, and provider-specific overhead.
161
- * This provides a more accurate estimate than getTokenCount() alone.
124
+ * Assembles and returns the current system prompt by invoking the SystemPromptManager.
125
+ */
126
+ async getSystemPrompt(context) {
127
+ const prompt = await this.systemPromptManager.build(context);
128
+ this.logger.debug(`[SystemPrompt] Built system prompt:
129
+ ${prompt}`);
130
+ return prompt;
131
+ }
132
+ /**
133
+ * Gets the raw conversation history
134
+ * Returns a defensive copy to prevent modification
162
135
  *
163
- * @param context The DynamicContributorContext for system prompt contributors
164
- * @returns Promise that resolves to the total number of tokens that will be sent to the provider
136
+ * @returns Promise that resolves to a read-only copy of the conversation history
165
137
  */
166
- async getTotalTokenCount(context) {
167
- try {
168
- const systemPrompt = await this.getSystemPrompt(context);
169
- let history = await this.historyProvider.getHistory();
170
- const systemPromptTokens = this.tokenizer.countTokens(systemPrompt);
171
- history = await this.compressHistoryIfNeeded(history, systemPromptTokens);
172
- const historyTokens = countMessagesTokens(
173
- history,
174
- this.tokenizer,
175
- void 0,
176
- this.logger
177
- );
178
- const formattingOverhead = Math.ceil((systemPromptTokens + historyTokens) * 0.05);
179
- const totalTokens = systemPromptTokens + historyTokens + formattingOverhead;
180
- this.logger.debug(
181
- `Token breakdown - System: ${systemPromptTokens}, History: ${historyTokens}, Overhead: ${formattingOverhead}, Total: ${totalTokens}`
182
- );
183
- return totalTokens;
184
- } catch (error) {
185
- this.logger.error(
186
- `Error calculating total token count: ${error instanceof Error ? error.message : String(error)}`,
187
- { error }
188
- );
189
- return this.getTokenCount();
190
- }
138
+ async getHistory() {
139
+ const history = await this.historyProvider.getHistory();
140
+ return [...history];
191
141
  }
192
142
  /**
193
- * Returns the configured maximum number of input tokens for the conversation.
143
+ * Flush any pending history updates to durable storage.
144
+ * Should be called at turn boundaries (after streaming completes, on cancel, on error).
145
+ * This ensures all message updates are persisted before returning control to the caller.
194
146
  */
195
- getMaxInputTokens() {
196
- return this.maxInputTokens;
147
+ async flush() {
148
+ await this.historyProvider.flush();
197
149
  }
198
150
  /**
199
- * Updates the ContextManager configuration when LLM config changes.
200
- * This is called when DextoAgent.switchLLM() updates the LLM configuration.
151
+ * Clears the context window without deleting history.
152
+ *
153
+ * This adds a "context clear" marker to the conversation history. When the
154
+ * context is loaded for LLM via getFormattedMessagesWithCompression(),
155
+ * filterCompacted() excludes all messages before this marker.
201
156
  *
202
- * @param newMaxInputTokens New maximum token limit
203
- * @param newTokenizer Optional new tokenizer if provider changed
204
- * @param newFormatter Optional new formatter if provider/router changed
157
+ * The full history remains in the database for review via /resume or session history.
205
158
  */
206
- updateConfig(newMaxInputTokens, newTokenizer, newFormatter) {
207
- const oldMaxInputTokens = this.maxInputTokens;
208
- this.maxInputTokens = newMaxInputTokens;
209
- if (newTokenizer) {
210
- this.tokenizer = newTokenizer;
211
- }
212
- if (newFormatter) {
213
- this.formatter = newFormatter;
214
- }
215
- this.logger.debug(
216
- `ContextManager config updated: maxInputTokens ${oldMaxInputTokens} -> ${newMaxInputTokens}`
217
- );
159
+ async clearContext() {
160
+ const clearMarker = {
161
+ id: `clear-${Date.now()}`,
162
+ role: "assistant",
163
+ content: [{ type: "text", text: "[Context cleared]" }],
164
+ timestamp: Date.now(),
165
+ metadata: {
166
+ isSummary: true,
167
+ clearedAt: Date.now()
168
+ }
169
+ };
170
+ await this.addMessage(clearMarker);
171
+ this.logger.debug(`Context cleared for session: ${this.sessionId}`);
218
172
  }
219
173
  /**
220
- * Updates the actual token count from the last LLM response.
221
- * This enables hybrid token counting for more accurate estimates.
222
- *
223
- * @param actualTokens The actual token count reported by the LLM provider
174
+ * Appends text to an existing assistant message.
175
+ * Used for streaming responses.
224
176
  */
225
- updateActualTokenCount(actualTokens) {
226
- this.lastActualTokenCount = actualTokens;
227
- this.logger.debug(`Updated actual token count to: ${actualTokens}`);
177
+ async appendAssistantText(messageId, text) {
178
+ const history = await this.historyProvider.getHistory();
179
+ const messageIndex = history.findIndex((m) => m.id === messageId);
180
+ if (messageIndex === -1) {
181
+ throw ContextError.messageNotFound(messageId);
182
+ }
183
+ const message = history[messageIndex];
184
+ if (!message) {
185
+ throw ContextError.messageNotFound(messageId);
186
+ }
187
+ if (message.role !== "assistant") {
188
+ throw ContextError.messageNotAssistant(messageId);
189
+ }
190
+ if (message.content === null) {
191
+ message.content = [{ type: "text", text }];
192
+ } else if (Array.isArray(message.content)) {
193
+ const lastPart = message.content[message.content.length - 1];
194
+ if (lastPart && lastPart.type === "text") {
195
+ lastPart.text += text;
196
+ } else {
197
+ message.content.push({ type: "text", text });
198
+ }
199
+ }
200
+ await this.historyProvider.updateMessage(message);
228
201
  }
229
202
  /**
230
- * Estimates if new input would trigger compression using hybrid approach.
231
- * Combines actual tokens from last response with estimated tokens for new input.
232
- *
233
- * @param newInputTokens Estimated tokens for the new user input
234
- * @returns True if compression should be triggered
203
+ * Adds a tool call to an existing assistant message.
204
+ * Used for streaming responses.
235
205
  */
236
- shouldCompress(newInputTokens) {
237
- const estimatedTotal = this.lastActualTokenCount + newInputTokens;
238
- const compressionTrigger = this.maxInputTokens * this.compressionThreshold;
239
- this.logger.debug(
240
- `Compression check: actual=${this.lastActualTokenCount}, newInput=${newInputTokens}, total=${estimatedTotal}, trigger=${compressionTrigger}`
241
- );
242
- return estimatedTotal > compressionTrigger;
206
+ async addToolCall(messageId, toolCall) {
207
+ const history = await this.historyProvider.getHistory();
208
+ const messageIndex = history.findIndex((m) => m.id === messageId);
209
+ if (messageIndex === -1) {
210
+ throw ContextError.messageNotFound(messageId);
211
+ }
212
+ const message = history[messageIndex];
213
+ if (!message) {
214
+ throw ContextError.messageNotFound(messageId);
215
+ }
216
+ if (message.role !== "assistant") {
217
+ throw ContextError.messageNotAssistant(messageId);
218
+ }
219
+ if (!message.toolCalls) {
220
+ message.toolCalls = [];
221
+ }
222
+ message.toolCalls.push(toolCall);
223
+ await this.historyProvider.updateMessage(message);
243
224
  }
244
225
  /**
245
- * Assembles and returns the current system prompt by invoking the SystemPromptManager.
226
+ * Updates an existing assistant message with new properties.
227
+ * Used for finalizing streaming responses (e.g. adding token usage).
246
228
  */
247
- async getSystemPrompt(context) {
248
- const prompt = await this.systemPromptManager.build(context);
249
- this.logger.debug(`[SystemPrompt] Built system prompt:
250
- ${prompt}`);
251
- return prompt;
229
+ async updateAssistantMessage(messageId, updates) {
230
+ const history = await this.historyProvider.getHistory();
231
+ const messageIndex = history.findIndex((m) => m.id === messageId);
232
+ if (messageIndex === -1) {
233
+ throw ContextError.messageNotFound(messageId);
234
+ }
235
+ const message = history[messageIndex];
236
+ if (!message) {
237
+ throw ContextError.messageNotFound(messageId);
238
+ }
239
+ if (message.role !== "assistant") {
240
+ throw ContextError.messageNotAssistant(messageId);
241
+ }
242
+ Object.assign(message, updates);
243
+ await this.historyProvider.updateMessage(message);
252
244
  }
253
245
  /**
254
- * Gets the raw conversation history
255
- * Returns a defensive copy to prevent modification
246
+ * Marks tool messages as compacted (pruned).
247
+ * Sets the compactedAt timestamp - content transformation happens at format time
248
+ * in getFormattedMessagesWithCompression(). Original content is preserved in
249
+ * storage for debugging/audit.
256
250
  *
257
- * @returns Promise that resolves to a read-only copy of the conversation history
251
+ * Used by TurnExecutor's pruneOldToolOutputs() to reclaim token space
252
+ * by marking old tool outputs that are no longer needed for context.
253
+ *
254
+ * @param messageIds Array of message IDs to mark as compacted
255
+ * @returns Number of messages successfully marked
258
256
  */
259
- async getHistory() {
257
+ async markMessagesAsCompacted(messageIds) {
258
+ if (messageIds.length === 0) {
259
+ return 0;
260
+ }
260
261
  const history = await this.historyProvider.getHistory();
261
- return [...history];
262
+ const timestamp = Date.now();
263
+ let markedCount = 0;
264
+ for (const messageId of messageIds) {
265
+ const message = history.find((m) => m.id === messageId);
266
+ if (!message) {
267
+ this.logger.warn(`markMessagesAsCompacted: Message ${messageId} not found`);
268
+ continue;
269
+ }
270
+ if (message.role !== "tool") {
271
+ this.logger.warn(
272
+ `markMessagesAsCompacted: Message ${messageId} is not a tool message (role=${message.role})`
273
+ );
274
+ continue;
275
+ }
276
+ if (message.compactedAt) {
277
+ continue;
278
+ }
279
+ message.compactedAt = timestamp;
280
+ await this.historyProvider.updateMessage(message);
281
+ markedCount++;
282
+ }
283
+ if (markedCount > 0) {
284
+ this.logger.debug(
285
+ `markMessagesAsCompacted: Marked ${markedCount} messages as compacted`
286
+ );
287
+ }
288
+ return markedCount;
262
289
  }
263
290
  /**
264
291
  * Adds a message to the conversation history.
@@ -271,10 +298,7 @@ ${prompt}`);
271
298
  async addMessage(message) {
272
299
  switch (message.role) {
273
300
  case "user":
274
- if (
275
- // Allow array content for user messages
276
- !(Array.isArray(message.content) && message.content.length > 0) && (typeof message.content !== "string" || message.content.trim() === "")
277
- ) {
301
+ if (!Array.isArray(message.content) || message.content.length === 0) {
278
302
  throw ContextError.userMessageContentInvalid();
279
303
  }
280
304
  break;
@@ -290,7 +314,6 @@ ${prompt}`);
290
314
  }
291
315
  }
292
316
  message.provider = this.llmConfig.provider;
293
- message.router = this.llmConfig.router;
294
317
  message.model = this.llmConfig.model;
295
318
  break;
296
319
  case "tool":
@@ -298,14 +321,22 @@ ${prompt}`);
298
321
  throw ContextError.toolMessageFieldsMissing();
299
322
  }
300
323
  break;
301
- case "system":
324
+ case "system": {
302
325
  this.logger.warn(
303
- "ContextManager: Adding system message directly to history. Use setSystemPrompt instead."
326
+ "ContextManager: Adding system message directly to history. Use SystemPromptManager instead."
304
327
  );
305
- if (typeof message.content !== "string" || message.content.trim() === "") {
328
+ const textContent = message.content?.filter((p) => p.type === "text").map((p) => p.text).join("");
329
+ if (!textContent || textContent.trim() === "") {
306
330
  throw ContextError.systemMessageContentInvalid();
307
331
  }
308
332
  break;
333
+ }
334
+ }
335
+ if (!message.id) {
336
+ message.id = randomUUID();
337
+ }
338
+ if (!message.timestamp) {
339
+ message.timestamp = Date.now();
309
340
  }
310
341
  this.logger.debug(
311
342
  `ContextManager: Adding message to history provider: ${JSON.stringify(message, null, 2)}`
@@ -315,57 +346,64 @@ ${prompt}`);
315
346
  this.logger.debug(`ContextManager: History now contains ${history.length} messages`);
316
347
  }
317
348
  /**
318
- * Adds a user message to the conversation
319
- * Can include image data for multimodal input
349
+ * Adds a user message to the conversation.
350
+ * Supports multiple images and files via ContentPart[].
320
351
  *
321
- * @param textContent The user message content
322
- * @param imageData Optional image data for multimodal input
323
- * @param fileData Optional file data for file input
324
- * @throws Error if content is empty or not a string
352
+ * @param content Array of content parts (text, images, files)
353
+ * @throws Error if content is empty or invalid
325
354
  */
326
- async addUserMessage(textContent, imageData, fileData) {
327
- if (typeof textContent !== "string" || textContent.trim() === "" && !imageData && !fileData) {
355
+ async addUserMessage(content) {
356
+ if (!Array.isArray(content) || content.length === 0) {
328
357
  throw ContextError.userMessageContentEmpty();
329
358
  }
330
- const finalTextContent = textContent.trim() || (imageData || fileData ? "" : textContent);
331
- const messageParts = [];
332
- if (finalTextContent) {
333
- messageParts.push({ type: "text", text: finalTextContent });
334
- }
335
- if (imageData) {
336
- const processedImage = await this.processUserInput(imageData.image, {
337
- mimeType: imageData.mimeType || "image/jpeg",
338
- source: "user"
339
- });
340
- messageParts.push({
341
- type: "image",
342
- image: processedImage,
343
- mimeType: imageData.mimeType || "image/jpeg"
344
- });
359
+ const hasText = content.some((p) => p.type === "text" && p.text.trim() !== "");
360
+ const hasAttachment = content.some((p) => p.type === "image" || p.type === "file");
361
+ if (!hasText && !hasAttachment) {
362
+ throw ContextError.userMessageContentEmpty();
345
363
  }
346
- if (fileData) {
347
- const metadata = {
348
- mimeType: fileData.mimeType,
349
- source: "user"
350
- };
351
- if (fileData.filename) {
352
- metadata.originalName = fileData.filename;
364
+ const processedParts = [];
365
+ for (const part of content) {
366
+ if (part.type === "text") {
367
+ if (part.text.trim()) {
368
+ processedParts.push({ type: "text", text: part.text });
369
+ }
370
+ } else if (part.type === "image") {
371
+ const processedImage = await this.processUserInput(part.image, {
372
+ mimeType: part.mimeType || "image/jpeg",
373
+ source: "user"
374
+ });
375
+ processedParts.push({
376
+ type: "image",
377
+ image: processedImage,
378
+ mimeType: part.mimeType || "image/jpeg"
379
+ });
380
+ } else if (part.type === "file") {
381
+ const metadata = {
382
+ mimeType: part.mimeType,
383
+ source: "user"
384
+ };
385
+ if (part.filename) {
386
+ metadata.originalName = part.filename;
387
+ }
388
+ const processedData = await this.processUserInput(part.data, metadata);
389
+ processedParts.push({
390
+ type: "file",
391
+ data: processedData,
392
+ mimeType: part.mimeType,
393
+ ...part.filename && { filename: part.filename }
394
+ });
353
395
  }
354
- const processedData = await this.processUserInput(fileData.data, metadata);
355
- messageParts.push({
356
- type: "file",
357
- data: processedData,
358
- mimeType: fileData.mimeType,
359
- ...fileData.filename && { filename: fileData.filename }
360
- });
361
- }
362
- if (messageParts.length === 0) {
363
- messageParts.push({ type: "text", text: finalTextContent });
364
396
  }
365
- this.logger.debug(
366
- `ContextManager: Adding user message: ${JSON.stringify(messageParts, null, 2)}`
367
- );
368
- await this.addMessage({ role: "user", content: messageParts });
397
+ const textParts = processedParts.filter((p) => p.type === "text");
398
+ const imageParts = processedParts.filter((p) => p.type === "image");
399
+ const fileParts = processedParts.filter((p) => p.type === "file");
400
+ this.logger.info("User message received", {
401
+ textParts: textParts.length,
402
+ imageParts: imageParts.length,
403
+ fileParts: fileParts.length,
404
+ totalParts: processedParts.length
405
+ });
406
+ await this.addMessage({ role: "user", content: processedParts });
369
407
  }
370
408
  /**
371
409
  * Adds an assistant message to the conversation
@@ -380,54 +418,50 @@ ${prompt}`);
380
418
  if (content === null && (!toolCalls || toolCalls.length === 0)) {
381
419
  throw ContextError.assistantMessageContentOrToolsRequired();
382
420
  }
421
+ const contentArray = content !== null ? [{ type: "text", text: content }] : null;
383
422
  await this.addMessage({
384
423
  role: "assistant",
385
- content,
424
+ content: contentArray,
386
425
  ...toolCalls && toolCalls.length > 0 && { toolCalls },
387
426
  ...metadata?.tokenUsage && { tokenUsage: metadata.tokenUsage },
388
427
  ...metadata?.reasoning && { reasoning: metadata.reasoning }
389
428
  });
390
429
  }
391
430
  /**
392
- * Adds a tool result message to the conversation
431
+ * Adds a tool result message to the conversation.
432
+ * The result must already be sanitized - this method only persists it.
433
+ *
434
+ * Success status is read from sanitizedResult.meta.success (single source of truth).
393
435
  *
394
436
  * @param toolCallId ID of the tool call this result is responding to
395
437
  * @param name Name of the tool that executed
396
- * @param result The result returned by the tool
438
+ * @param sanitizedResult The already-sanitized result to store (includes success in meta)
439
+ * @param metadata Optional approval-related metadata
397
440
  * @throws Error if required parameters are missing
398
441
  */
399
- async addToolResult(toolCallId, name, result, options) {
442
+ async addToolResult(toolCallId, name, sanitizedResult, metadata) {
400
443
  if (!toolCallId || !name) {
401
444
  throw ContextError.toolCallIdNameRequired();
402
445
  }
403
- const blobService = this.resourceManager.getBlobStore();
404
- const sanitizeOptions = {
405
- blobStore: blobService,
406
- toolName: name,
407
- toolCallId
408
- };
409
- if (options?.success !== void 0) {
410
- sanitizeOptions.success = options.success;
411
- }
412
- const sanitized = await sanitizeToolResult(result, sanitizeOptions, this.logger);
413
- const summary = sanitized.content.map(
414
- (p) => p.type === "text" ? `text(${p.text.length})` : p.type === "image" ? `image(${p.mimeType || "image"})` : `file(${p.mimeType || "file"})`
446
+ const summary = sanitizedResult.content.map(
447
+ (p) => p.type === "text" ? `text(${p.text.length})` : p.type === "image" ? `image(${p.mimeType || "image"})` : p.type === "ui-resource" ? `ui-resource(${p.uri})` : `file(${p.mimeType || "file"})`
415
448
  ).join(", ");
416
449
  this.logger.debug(`ContextManager: Storing tool result (parts) for ${name}: [${summary}]`);
417
450
  await this.addMessage({
418
451
  role: "tool",
419
- content: sanitized.content,
452
+ content: sanitizedResult.content,
420
453
  toolCallId,
421
- name
454
+ name,
455
+ // Success status comes from sanitizedResult.meta (single source of truth)
456
+ success: sanitizedResult.meta.success,
457
+ // Persist approval metadata for frontend display after reload
458
+ ...metadata?.requireApproval !== void 0 && {
459
+ requireApproval: metadata.requireApproval
460
+ },
461
+ ...metadata?.approvalStatus !== void 0 && {
462
+ approvalStatus: metadata.approvalStatus
463
+ }
422
464
  });
423
- return sanitized;
424
- }
425
- /**
426
- * Sets the system prompt for the conversation
427
- *
428
- * @param prompt The system prompt text
429
- */
430
- setSystemPrompt(_prompt) {
431
465
  }
432
466
  /**
433
467
  * Gets the conversation history formatted for the target LLM provider.
@@ -471,13 +505,28 @@ ${prompt}`);
471
505
  this.logger.debug("Resolving blob references in message history before formatting");
472
506
  messageHistory = await Promise.all(
473
507
  messageHistory.map(async (message) => {
474
- const expandedContent = await expandBlobReferences(
475
- message.content,
476
- this.resourceManager,
477
- this.logger,
478
- allowedMediaTypes
479
- );
480
- return { ...message, content: expandedContent };
508
+ if (isSystemMessage(message) || isAssistantMessage(message)) {
509
+ return message;
510
+ }
511
+ if (isUserMessage(message)) {
512
+ const expandedContent = await expandBlobReferences(
513
+ message.content,
514
+ this.resourceManager,
515
+ this.logger,
516
+ allowedMediaTypes
517
+ );
518
+ return { ...message, content: expandedContent };
519
+ }
520
+ if (isToolMessage(message)) {
521
+ const expandedContent = await expandBlobReferences(
522
+ message.content,
523
+ this.resourceManager,
524
+ this.logger,
525
+ allowedMediaTypes
526
+ );
527
+ return { ...message, content: expandedContent };
528
+ }
529
+ return message;
481
530
  })
482
531
  );
483
532
  const prompt = systemPrompt ?? await this.getSystemPrompt(contributorContext);
@@ -486,7 +535,7 @@ ${prompt}`);
486
535
  /**
487
536
  * Gets the conversation ready for LLM consumption with proper flow:
488
537
  * 1. Get system prompt
489
- * 2. Get history and compress if needed
538
+ * 2. Get history and filter (exclude pre-summary messages)
490
539
  * 3. Format messages
491
540
  * This method implements the correct ordering to avoid circular dependencies.
492
541
  *
@@ -496,25 +545,39 @@ ${prompt}`);
496
545
  */
497
546
  async getFormattedMessagesWithCompression(contributorContext, llmContext) {
498
547
  const systemPrompt = await this.getSystemPrompt(contributorContext);
499
- const systemPromptTokens = this.tokenizer.countTokens(systemPrompt);
500
- let history = await this.historyProvider.getHistory();
501
- history = await this.compressHistoryIfNeeded(history, systemPromptTokens);
548
+ const fullHistory = await this.historyProvider.getHistory();
549
+ let history = filterCompacted(fullHistory);
550
+ if (history.length < fullHistory.length) {
551
+ this.logger.debug(
552
+ `filterCompacted: Reduced history from ${fullHistory.length} to ${history.length} messages (summary present)`
553
+ );
554
+ }
555
+ const compactedCount = history.filter((m) => m.role === "tool" && m.compactedAt).length;
556
+ if (compactedCount > 0) {
557
+ history = history.map((msg) => {
558
+ if (msg.role === "tool" && msg.compactedAt) {
559
+ return {
560
+ ...msg,
561
+ content: [
562
+ { type: "text", text: "[Old tool result content cleared]" }
563
+ ]
564
+ };
565
+ }
566
+ return msg;
567
+ });
568
+ this.logger.debug(
569
+ `Transformed ${compactedCount} compacted tool messages to placeholders`
570
+ );
571
+ }
502
572
  const formattedMessages = await this.getFormattedMessages(
503
573
  contributorContext,
504
574
  llmContext,
505
575
  systemPrompt,
506
576
  history
507
577
  );
508
- const historyTokens = countMessagesTokens(history, this.tokenizer, void 0, this.logger);
509
- const formattingOverhead = Math.ceil((systemPromptTokens + historyTokens) * 0.05);
510
- const tokensUsed = systemPromptTokens + historyTokens + formattingOverhead;
511
- this.logger.debug(
512
- `Final token breakdown - System: ${systemPromptTokens}, History: ${historyTokens}, Overhead: ${formattingOverhead}, Total: ${tokensUsed}`
513
- );
514
578
  return {
515
579
  formattedMessages,
516
- systemPrompt,
517
- tokensUsed
580
+ systemPrompt
518
581
  };
519
582
  }
520
583
  /**
@@ -524,9 +587,8 @@ ${prompt}`);
524
587
  * @returns Formatted system prompt or null/undefined based on formatter implementation
525
588
  * @throws Error if formatting fails
526
589
  */
527
- async getFormattedSystemPrompt(context) {
528
- const systemPrompt = await this.getSystemPrompt(context);
529
- return this.formatter.formatSystemPrompt?.(systemPrompt);
590
+ async getFormattedSystemPrompt(_context) {
591
+ return this.formatter.formatSystemPrompt?.();
530
592
  }
531
593
  /**
532
594
  * Resets the conversation history
@@ -538,109 +600,6 @@ ${prompt}`);
538
600
  `ContextManager: Conversation history cleared for session ${this.sessionId}`
539
601
  );
540
602
  }
541
- /**
542
- * Checks if history compression is needed based on token count and applies strategies.
543
- *
544
- * @param history The conversation history to potentially compress
545
- * @param systemPromptTokens The actual token count of the system prompt
546
- * @returns The potentially compressed history
547
- */
548
- async compressHistoryIfNeeded(history, systemPromptTokens) {
549
- let currentTotalTokens = countMessagesTokens(
550
- history,
551
- this.tokenizer,
552
- void 0,
553
- this.logger
554
- );
555
- currentTotalTokens += systemPromptTokens;
556
- this.logger.debug(`ContextManager: Checking if history compression is needed.`);
557
- this.logger.debug(
558
- `History tokens: ${countMessagesTokens(history, this.tokenizer, void 0, this.logger)}, System prompt tokens: ${systemPromptTokens}, Total: ${currentTotalTokens}`
559
- );
560
- if (currentTotalTokens <= this.maxInputTokens) {
561
- this.logger.debug(
562
- `ContextManager: History compression not needed. Total token count: ${currentTotalTokens}, Max tokens: ${this.maxInputTokens}`
563
- );
564
- return history;
565
- }
566
- this.logger.info(
567
- `ContextManager: History exceeds token limit (${currentTotalTokens} > ${this.maxInputTokens}). Applying compression strategies sequentially.`
568
- );
569
- const initialLength = history.length;
570
- let workingHistory = [...history];
571
- const targetHistoryTokens = this.maxInputTokens - systemPromptTokens;
572
- for (const strategy of this.compressionStrategies) {
573
- const strategyName = strategy.constructor.name;
574
- this.logger.debug(`ContextManager: Applying ${strategyName}...`);
575
- try {
576
- workingHistory = strategy.compress(
577
- [...workingHistory],
578
- this.tokenizer,
579
- targetHistoryTokens
580
- // Use target tokens that account for system prompt
581
- );
582
- } catch (error) {
583
- this.logger.error(
584
- `ContextManager: Error applying ${strategyName}: ${error instanceof Error ? error.message : String(error)}`,
585
- { error }
586
- );
587
- break;
588
- }
589
- const historyTokens = countMessagesTokens(
590
- workingHistory,
591
- this.tokenizer,
592
- void 0,
593
- this.logger
594
- );
595
- currentTotalTokens = historyTokens + systemPromptTokens;
596
- const messagesRemoved = initialLength - workingHistory.length;
597
- if (currentTotalTokens <= this.maxInputTokens) {
598
- this.logger.debug(
599
- `ContextManager: Compression successful after ${strategyName}. New total count: ${currentTotalTokens}, messages removed: ${messagesRemoved}`
600
- );
601
- break;
602
- }
603
- }
604
- return workingHistory;
605
- }
606
- /**
607
- * Parses a raw LLM stream response, converts it into internal messages and adds them to the history.
608
- *
609
- * @param response The stream response from the LLM provider
610
- */
611
- async processLLMStreamResponse(response) {
612
- if (this.formatter.parseStreamResponse) {
613
- const msgs = await this.formatter.parseStreamResponse(response) ?? [];
614
- for (const msg of msgs) {
615
- try {
616
- await this.addMessage(msg);
617
- } catch (error) {
618
- this.logger.error(
619
- `ContextManager: Failed to process LLM stream response message for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
620
- );
621
- }
622
- }
623
- } else {
624
- await this.processLLMResponse(response);
625
- }
626
- }
627
- /**
628
- * Parses a raw LLM response, converts it into internal messages and adds them to the history.
629
- *
630
- * @param response The response from the LLM provider
631
- */
632
- async processLLMResponse(response) {
633
- const msgs = this.formatter.parseResponse(response) ?? [];
634
- for (const msg of msgs) {
635
- try {
636
- await this.addMessage(msg);
637
- } catch (error) {
638
- this.logger.error(
639
- `ContextManager: Failed to process LLM response message for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
640
- );
641
- }
642
- }
643
- }
644
603
  }
645
604
  export {
646
605
  ContextManager