@hashgraphonline/conversational-agent 0.2.216 → 0.2.218

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 (312) hide show
  1. package/cli/readme.md +181 -0
  2. package/dist/cjs/index.cjs +1 -1
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs/index.d.ts +1 -0
  5. package/dist/cjs/plugins/community/swarm/SwarmPlugin.d.ts +17 -0
  6. package/dist/cjs/plugins/community/swarm/__tests__/SwarmPlugin.mocks.d.ts +1 -0
  7. package/dist/cjs/plugins/community/swarm/__tests__/SwarmPlugin.test.d.ts +1 -0
  8. package/dist/cjs/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.d.ts +1 -0
  9. package/dist/cjs/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.d.ts +1 -0
  10. package/dist/cjs/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.d.ts +1 -0
  11. package/dist/cjs/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.d.ts +1 -0
  12. package/dist/cjs/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.d.ts +1 -0
  13. package/dist/cjs/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.d.ts +1 -0
  14. package/dist/cjs/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.d.ts +1 -0
  15. package/dist/cjs/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.d.ts +1 -0
  16. package/dist/cjs/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.d.ts +14 -0
  17. package/dist/cjs/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.d.ts +1 -0
  18. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadDataTool.test.d.ts +1 -0
  19. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadFileTool.test.d.ts +1 -0
  20. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.d.ts +1 -0
  21. package/dist/cjs/plugins/community/swarm/config.d.ts +6 -0
  22. package/dist/cjs/plugins/community/swarm/constants.d.ts +8 -0
  23. package/dist/cjs/plugins/community/swarm/index.d.ts +2 -0
  24. package/dist/cjs/plugins/community/swarm/model.d.ts +23 -0
  25. package/dist/cjs/plugins/community/swarm/tools/CreatePostageStampTool.d.ts +47 -0
  26. package/dist/cjs/plugins/community/swarm/tools/DownloadDataTool.d.ts +35 -0
  27. package/dist/cjs/plugins/community/swarm/tools/DownloadFilesTool.d.ts +41 -0
  28. package/dist/cjs/plugins/community/swarm/tools/ExtendPostageStampTool.d.ts +47 -0
  29. package/dist/cjs/plugins/community/swarm/tools/GetPostageStampTool.d.ts +35 -0
  30. package/dist/cjs/plugins/community/swarm/tools/ListPostageStampsTool.d.ts +53 -0
  31. package/dist/cjs/plugins/community/swarm/tools/QueryUploadProgressTool.d.ts +35 -0
  32. package/dist/cjs/plugins/community/swarm/tools/ReadFeedTool.d.ts +41 -0
  33. package/dist/cjs/plugins/community/swarm/tools/UpdateFeedTool.d.ts +47 -0
  34. package/dist/cjs/plugins/community/swarm/tools/UploadDataTool.d.ts +47 -0
  35. package/dist/cjs/plugins/community/swarm/tools/UploadFileTool.d.ts +53 -0
  36. package/dist/cjs/plugins/community/swarm/tools/UploadFolderTool.d.ts +47 -0
  37. package/dist/cjs/plugins/community/swarm/utils.d.ts +22 -0
  38. package/dist/cjs/plugins/index.d.ts +1 -0
  39. package/dist/esm/index.js +33 -31
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/index10.js +13 -677
  42. package/dist/esm/index10.js.map +1 -1
  43. package/dist/esm/index11.js +601 -234
  44. package/dist/esm/index11.js.map +1 -1
  45. package/dist/esm/index12.js +296 -136
  46. package/dist/esm/index12.js.map +1 -1
  47. package/dist/esm/index13.js +127 -235
  48. package/dist/esm/index13.js.map +1 -1
  49. package/dist/esm/index14.js +247 -84
  50. package/dist/esm/index14.js.map +1 -1
  51. package/dist/esm/index15.js +81 -159
  52. package/dist/esm/index15.js.map +1 -1
  53. package/dist/esm/index16.js +155 -229
  54. package/dist/esm/index16.js.map +1 -1
  55. package/dist/esm/index17.js +238 -140
  56. package/dist/esm/index17.js.map +1 -1
  57. package/dist/esm/index18.js +139 -493
  58. package/dist/esm/index18.js.map +1 -1
  59. package/dist/esm/index19.js +479 -91
  60. package/dist/esm/index19.js.map +1 -1
  61. package/dist/esm/index20.js +88 -147
  62. package/dist/esm/index20.js.map +1 -1
  63. package/dist/esm/index21.js +127 -666
  64. package/dist/esm/index21.js.map +1 -1
  65. package/dist/esm/index22.js +698 -44
  66. package/dist/esm/index22.js.map +1 -1
  67. package/dist/esm/index23.js +45 -304
  68. package/dist/esm/index23.js.map +1 -1
  69. package/dist/esm/index24.js +303 -153
  70. package/dist/esm/index24.js.map +1 -1
  71. package/dist/esm/index25.js +150 -117
  72. package/dist/esm/index25.js.map +1 -1
  73. package/dist/esm/index26.js +154 -18
  74. package/dist/esm/index26.js.map +1 -1
  75. package/dist/esm/index27.js +18 -22
  76. package/dist/esm/index27.js.map +1 -1
  77. package/dist/esm/index28.js +15 -74
  78. package/dist/esm/index28.js.map +1 -1
  79. package/dist/esm/index29.js +70 -295
  80. package/dist/esm/index29.js.map +1 -1
  81. package/dist/esm/index30.js +279 -100
  82. package/dist/esm/index30.js.map +1 -1
  83. package/dist/esm/index31.js +86 -922
  84. package/dist/esm/index31.js.map +1 -1
  85. package/dist/esm/index32.js +904 -189
  86. package/dist/esm/index32.js.map +1 -1
  87. package/dist/esm/index33.js +185 -1169
  88. package/dist/esm/index33.js.map +1 -1
  89. package/dist/esm/index34.js +1218 -112
  90. package/dist/esm/index34.js.map +1 -1
  91. package/dist/esm/index35.js +111 -99
  92. package/dist/esm/index35.js.map +1 -1
  93. package/dist/esm/index36.js +113 -8
  94. package/dist/esm/index36.js.map +1 -1
  95. package/dist/esm/index37.js +8 -45
  96. package/dist/esm/index37.js.map +1 -1
  97. package/dist/esm/index38.js +41 -102
  98. package/dist/esm/index38.js.map +1 -1
  99. package/dist/esm/index39.js +96 -55
  100. package/dist/esm/index39.js.map +1 -1
  101. package/dist/esm/index4.js +1 -1
  102. package/dist/esm/index40.js +58 -71
  103. package/dist/esm/index40.js.map +1 -1
  104. package/dist/esm/index41.js +79 -21
  105. package/dist/esm/index41.js.map +1 -1
  106. package/dist/esm/index42.js +21 -5
  107. package/dist/esm/index42.js.map +1 -1
  108. package/dist/esm/index43.js +26 -11
  109. package/dist/esm/index43.js.map +1 -1
  110. package/dist/esm/index44.js +12 -322
  111. package/dist/esm/index44.js.map +1 -1
  112. package/dist/esm/index45.js +66 -173
  113. package/dist/esm/index45.js.map +1 -1
  114. package/dist/esm/index46.js +69 -24
  115. package/dist/esm/index46.js.map +1 -1
  116. package/dist/esm/index47.js +47 -88
  117. package/dist/esm/index47.js.map +1 -1
  118. package/dist/esm/index48.js +100 -7
  119. package/dist/esm/index48.js.map +1 -1
  120. package/dist/esm/index49.js +79 -0
  121. package/dist/esm/index49.js.map +1 -0
  122. package/dist/esm/index5.js +2 -2
  123. package/dist/esm/index50.js +75 -0
  124. package/dist/esm/index50.js.map +1 -0
  125. package/dist/esm/index51.js +124 -0
  126. package/dist/esm/index51.js.map +1 -0
  127. package/dist/esm/index52.js +58 -0
  128. package/dist/esm/index52.js.map +1 -0
  129. package/dist/esm/index53.js +83 -0
  130. package/dist/esm/index53.js.map +1 -0
  131. package/dist/esm/index54.js +100 -0
  132. package/dist/esm/index54.js.map +1 -0
  133. package/dist/esm/index55.js +118 -0
  134. package/dist/esm/index55.js.map +1 -0
  135. package/dist/esm/index56.js +108 -0
  136. package/dist/esm/index56.js.map +1 -0
  137. package/dist/esm/index57.js +8 -0
  138. package/dist/esm/index57.js.map +1 -0
  139. package/dist/esm/index58.js +325 -0
  140. package/dist/esm/index58.js.map +1 -0
  141. package/dist/esm/index59.js +187 -0
  142. package/dist/esm/index59.js.map +1 -0
  143. package/dist/esm/index6.js +132 -833
  144. package/dist/esm/index6.js.map +1 -1
  145. package/dist/esm/index60.js +10 -0
  146. package/dist/esm/index60.js.map +1 -0
  147. package/dist/esm/index61.js +98 -0
  148. package/dist/esm/index61.js.map +1 -0
  149. package/dist/esm/index62.js +131 -0
  150. package/dist/esm/index62.js.map +1 -0
  151. package/dist/esm/index63.js +19 -0
  152. package/dist/esm/index63.js.map +1 -0
  153. package/dist/esm/index7.js +826 -75
  154. package/dist/esm/index7.js.map +1 -1
  155. package/dist/esm/index8.js +91 -13
  156. package/dist/esm/index8.js.map +1 -1
  157. package/dist/esm/index9.js +13 -17
  158. package/dist/esm/index9.js.map +1 -1
  159. package/dist/types/index.d.ts +1 -0
  160. package/dist/types/plugins/community/swarm/SwarmPlugin.d.ts +17 -0
  161. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.mocks.d.ts +1 -0
  162. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.test.d.ts +1 -0
  163. package/dist/types/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.d.ts +1 -0
  164. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.d.ts +1 -0
  165. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.d.ts +1 -0
  166. package/dist/types/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.d.ts +1 -0
  167. package/dist/types/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.d.ts +1 -0
  168. package/dist/types/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.d.ts +1 -0
  169. package/dist/types/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.d.ts +1 -0
  170. package/dist/types/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.d.ts +1 -0
  171. package/dist/types/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.d.ts +14 -0
  172. package/dist/types/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.d.ts +1 -0
  173. package/dist/types/plugins/community/swarm/__tests__/tools/UploadDataTool.test.d.ts +1 -0
  174. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFileTool.test.d.ts +1 -0
  175. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.d.ts +1 -0
  176. package/dist/types/plugins/community/swarm/config.d.ts +6 -0
  177. package/dist/types/plugins/community/swarm/constants.d.ts +8 -0
  178. package/dist/types/plugins/community/swarm/index.d.ts +2 -0
  179. package/dist/types/plugins/community/swarm/model.d.ts +23 -0
  180. package/dist/types/plugins/community/swarm/tools/CreatePostageStampTool.d.ts +47 -0
  181. package/dist/types/plugins/community/swarm/tools/DownloadDataTool.d.ts +35 -0
  182. package/dist/types/plugins/community/swarm/tools/DownloadFilesTool.d.ts +41 -0
  183. package/dist/types/plugins/community/swarm/tools/ExtendPostageStampTool.d.ts +47 -0
  184. package/dist/types/plugins/community/swarm/tools/GetPostageStampTool.d.ts +35 -0
  185. package/dist/types/plugins/community/swarm/tools/ListPostageStampsTool.d.ts +53 -0
  186. package/dist/types/plugins/community/swarm/tools/QueryUploadProgressTool.d.ts +35 -0
  187. package/dist/types/plugins/community/swarm/tools/ReadFeedTool.d.ts +41 -0
  188. package/dist/types/plugins/community/swarm/tools/UpdateFeedTool.d.ts +47 -0
  189. package/dist/types/plugins/community/swarm/tools/UploadDataTool.d.ts +47 -0
  190. package/dist/types/plugins/community/swarm/tools/UploadFileTool.d.ts +53 -0
  191. package/dist/types/plugins/community/swarm/tools/UploadFolderTool.d.ts +47 -0
  192. package/dist/types/plugins/community/swarm/utils.d.ts +22 -0
  193. package/dist/types/plugins/index.d.ts +1 -0
  194. package/package.json +37 -27
  195. package/src/index.ts +1 -0
  196. package/src/plugins/community/swarm/README.md +279 -0
  197. package/src/plugins/community/swarm/SwarmPlugin.ts +178 -0
  198. package/src/plugins/community/swarm/__tests__/SwarmPlugin.mocks.ts +105 -0
  199. package/src/plugins/community/swarm/__tests__/SwarmPlugin.test.ts +93 -0
  200. package/src/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.ts +152 -0
  201. package/src/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.ts +93 -0
  202. package/src/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.ts +163 -0
  203. package/src/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.ts +132 -0
  204. package/src/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.ts +83 -0
  205. package/src/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.ts +219 -0
  206. package/src/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.ts +169 -0
  207. package/src/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.ts +133 -0
  208. package/src/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.ts +67 -0
  209. package/src/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.ts +148 -0
  210. package/src/plugins/community/swarm/__tests__/tools/UploadDataTool.test.ts +125 -0
  211. package/src/plugins/community/swarm/__tests__/tools/UploadFileTool.test.ts +194 -0
  212. package/src/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.ts +118 -0
  213. package/src/plugins/community/swarm/config.ts +6 -0
  214. package/src/plugins/community/swarm/constants.ts +12 -0
  215. package/src/plugins/community/swarm/index.ts +2 -0
  216. package/src/plugins/community/swarm/model.ts +23 -0
  217. package/src/plugins/community/swarm/tools/CreatePostageStampTool.ts +137 -0
  218. package/src/plugins/community/swarm/tools/DownloadDataTool.ts +79 -0
  219. package/src/plugins/community/swarm/tools/DownloadFilesTool.ts +155 -0
  220. package/src/plugins/community/swarm/tools/ExtendPostageStampTool.ts +112 -0
  221. package/src/plugins/community/swarm/tools/GetPostageStampTool.ts +92 -0
  222. package/src/plugins/community/swarm/tools/ListPostageStampsTool.ts +124 -0
  223. package/src/plugins/community/swarm/tools/QueryUploadProgressTool.ts +109 -0
  224. package/src/plugins/community/swarm/tools/ReadFeedTool.ts +110 -0
  225. package/src/plugins/community/swarm/tools/UpdateFeedTool.ts +149 -0
  226. package/src/plugins/community/swarm/tools/UploadDataTool.ts +109 -0
  227. package/src/plugins/community/swarm/tools/UploadFileTool.ts +163 -0
  228. package/src/plugins/community/swarm/tools/UploadFolderTool.ts +150 -0
  229. package/src/plugins/community/swarm/utils.ts +172 -0
  230. package/src/plugins/index.ts +1 -0
  231. package/cli/dist/CLIApp.d.ts +0 -11
  232. package/cli/dist/CLIApp.d.ts.map +0 -1
  233. package/cli/dist/CLIApp.js +0 -128
  234. package/cli/dist/CLIApp.js.map +0 -1
  235. package/cli/dist/LocalConversationalAgent.d.ts +0 -37
  236. package/cli/dist/LocalConversationalAgent.js +0 -58
  237. package/cli/dist/app.d.ts +0 -18
  238. package/cli/dist/app.d.ts.map +0 -1
  239. package/cli/dist/app.js +0 -14
  240. package/cli/dist/app.js.map +0 -1
  241. package/cli/dist/cli.d.ts +0 -3
  242. package/cli/dist/cli.d.ts.map +0 -1
  243. package/cli/dist/cli.js +0 -87
  244. package/cli/dist/cli.js.map +0 -1
  245. package/cli/dist/components/AppContainer.d.ts +0 -16
  246. package/cli/dist/components/AppContainer.js +0 -24
  247. package/cli/dist/components/AppScreens.d.ts +0 -2
  248. package/cli/dist/components/AppScreens.js +0 -259
  249. package/cli/dist/components/ChatScreen.d.ts +0 -21
  250. package/cli/dist/components/ChatScreen.d.ts.map +0 -1
  251. package/cli/dist/components/ChatScreen.js +0 -40
  252. package/cli/dist/components/ChatScreen.js.map +0 -1
  253. package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
  254. package/cli/dist/components/DebugLoadingScreen.js +0 -31
  255. package/cli/dist/components/LoadingScreen.d.ts +0 -3
  256. package/cli/dist/components/LoadingScreen.d.ts.map +0 -1
  257. package/cli/dist/components/LoadingScreen.js +0 -17
  258. package/cli/dist/components/LoadingScreen.js.map +0 -1
  259. package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
  260. package/cli/dist/components/LoadingScreenDebug.js +0 -27
  261. package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
  262. package/cli/dist/components/MCPConfigScreen.d.ts.map +0 -1
  263. package/cli/dist/components/MCPConfigScreen.js +0 -186
  264. package/cli/dist/components/MCPConfigScreen.js.map +0 -1
  265. package/cli/dist/components/ScreenRouter.d.ts +0 -13
  266. package/cli/dist/components/ScreenRouter.d.ts.map +0 -1
  267. package/cli/dist/components/ScreenRouter.js +0 -23
  268. package/cli/dist/components/ScreenRouter.js.map +0 -1
  269. package/cli/dist/components/SetupScreen.d.ts +0 -16
  270. package/cli/dist/components/SetupScreen.d.ts.map +0 -1
  271. package/cli/dist/components/SetupScreen.js +0 -67
  272. package/cli/dist/components/SetupScreen.js.map +0 -1
  273. package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
  274. package/cli/dist/components/SingleLoadingScreen.js +0 -27
  275. package/cli/dist/components/StatusBadge.d.ts +0 -10
  276. package/cli/dist/components/StatusBadge.d.ts.map +0 -1
  277. package/cli/dist/components/StatusBadge.js +0 -24
  278. package/cli/dist/components/StatusBadge.js.map +0 -1
  279. package/cli/dist/components/TerminalWindow.d.ts +0 -9
  280. package/cli/dist/components/TerminalWindow.d.ts.map +0 -1
  281. package/cli/dist/components/TerminalWindow.js +0 -19
  282. package/cli/dist/components/TerminalWindow.js.map +0 -1
  283. package/cli/dist/components/WelcomeScreen.d.ts +0 -12
  284. package/cli/dist/components/WelcomeScreen.d.ts.map +0 -1
  285. package/cli/dist/components/WelcomeScreen.js +0 -47
  286. package/cli/dist/components/WelcomeScreen.js.map +0 -1
  287. package/cli/dist/context/AppContext.d.ts +0 -68
  288. package/cli/dist/context/AppContext.js +0 -363
  289. package/cli/dist/headless-runner.d.ts +0 -17
  290. package/cli/dist/headless-runner.d.ts.map +0 -1
  291. package/cli/dist/headless-runner.js +0 -128
  292. package/cli/dist/headless-runner.js.map +0 -1
  293. package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
  294. package/cli/dist/hooks/useInitializeAgent.d.ts.map +0 -1
  295. package/cli/dist/hooks/useInitializeAgent.js +0 -29
  296. package/cli/dist/hooks/useInitializeAgent.js.map +0 -1
  297. package/cli/dist/hooks/useStableState.d.ts +0 -38
  298. package/cli/dist/hooks/useStableState.d.ts.map +0 -1
  299. package/cli/dist/hooks/useStableState.js +0 -69
  300. package/cli/dist/hooks/useStableState.js.map +0 -1
  301. package/cli/dist/managers/AgentManager.d.ts +0 -58
  302. package/cli/dist/managers/AgentManager.d.ts.map +0 -1
  303. package/cli/dist/managers/AgentManager.js +0 -121
  304. package/cli/dist/managers/AgentManager.js.map +0 -1
  305. package/cli/dist/managers/ConfigManager.d.ts +0 -54
  306. package/cli/dist/managers/ConfigManager.d.ts.map +0 -1
  307. package/cli/dist/managers/ConfigManager.js +0 -188
  308. package/cli/dist/managers/ConfigManager.js.map +0 -1
  309. package/cli/dist/types.d.ts +0 -52
  310. package/cli/dist/types.d.ts.map +0 -1
  311. package/cli/dist/types.js +0 -34
  312. package/cli/dist/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index19.js","sources":["../../src/memory/token-counter.ts"],"sourcesContent":["import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}"],"names":[],"mappings":";AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAOxB,YAAY,YAAoC,UAAU;AACxD,SAAK,YAAY,OAAO,SAAS;AACjC,QAAI;AACF,WAAK,WAAW,mBAAmB,SAA0B;AAAA,IAC/D,QAAQ;AACN,WAAK,WAAW,mBAAmB,QAAQ;AAC3C,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAsB;AAChC,QAAI,CAAC,QAAQ,KAAK,KAAA,MAAW,IAAI;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,SAAS,OAAO,IAAI;AACxC,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,aAAO,KAAK,KAAK,KAAK,MAAM,KAAK,EAAE,SAAS,GAAG;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAA8B;AAC/C,UAAM,gBAAgB,KAAK,YAAY,OAAO,QAAQ,WAAW,EAAE,CAAC;AACpE,UAAM,aAAa,KAAK,YAAY,KAAK,eAAe,OAAO,CAAC;AAEhE,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,UAAiC;AACnD,QAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ;AACZ,eAAW,WAAW,UAAU;AAC9B,eAAS,KAAK,mBAAmB,OAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAA2B,cAA8B;AACvD,QAAI,CAAC,gBAAgB,aAAa,KAAA,MAAW,IAAI;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,KAAK,YAAY,YAAY;AACnD,UAAM,aAAa,KAAK,YAAY,QAAQ;AAE5C,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,cAAsB,UAAiC;AACzE,UAAM,eAAe,KAAK,2BAA2B,YAAY;AACjE,UAAM,gBAAgB,KAAK,oBAAoB,QAAQ;AAEvD,UAAM,qBAAqB;AAE3B,WAAO,eAAe,gBAAgB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,SAA8B;AACnD,UAAM,cAAc,QAAQ,SAAA;AAC5B,YAAQ,aAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI;AACF,WAAK,SAAS,KAAA;AAAA,IAChB,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AApIE,cAAwB,mBAAmB;AAC3C,cAAwB,gBAAgB;AALnC,IAAM,eAAN;"}
1
+ {"version":3,"file":"index19.js","sources":["../../src/memory/smart-memory-manager.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\nimport { SystemMessage } from '@langchain/core/messages';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { MemoryWindow } from './memory-window';\nimport { ContentStorage } from './content-storage';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Entity association for storing blockchain entity contexts\n */\nexport interface EntityAssociation {\n /** The blockchain entity ID (e.g., tokenId, accountId, topicId) */\n entityId: string;\n /** User-provided or derived friendly name */\n entityName: string;\n /** Type of entity (token, account, topic, schedule, etc.) */\n entityType: string;\n /** When the entity was created/associated */\n createdAt: Date;\n /** Transaction ID that created this entity */\n transactionId?: string;\n /** Optional session identifier to scope associations */\n sessionId?: string;\n}\n\n/**\n * Options for resolving entity references\n */\nexport interface EntityResolutionOptions {\n /** Filter by specific entity type */\n entityType?: string;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use fuzzy matching for natural language queries */\n fuzzyMatch?: boolean;\n}\n\n/**\n * Configuration for SmartMemoryManager\n */\nexport interface SmartMemoryConfig {\n /** Maximum tokens for active memory window */\n maxTokens?: number;\n /** Reserve tokens for response generation */\n reserveTokens?: number;\n /** Model name for token counting */\n modelName?: string;\n /** Maximum messages to store in content storage */\n storageLimit?: number;\n}\n\n/**\n * Search options for history search\n */\nexport interface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Memory statistics for active memory window\n */\nexport interface MemoryStats {\n /** Total active messages in memory window */\n totalActiveMessages: number;\n /** Current token count including system prompt */\n currentTokenCount: number;\n /** Maximum token capacity */\n maxTokens: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n /** System prompt token count */\n systemPromptTokens: number;\n /** Memory usage percentage */\n usagePercentage: number;\n}\n\nconst IS_ENTITY_ASSOCIATION_FLAG = '\"isEntityAssociation\":true';\n\n/**\n * TODO: investigate using chroma / rag for long term memory\n * Smart memory manager that combines active memory window with long-term storage\n * Provides context-aware memory management with automatic pruning and searchable history\n */\nexport class SmartMemoryManager {\n private memoryWindow: MemoryWindow;\n private _contentStorage: ContentStorage;\n private tokenCounter: TokenCounter;\n private config: Required<SmartMemoryConfig>;\n private logger: Logger;\n\n private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {\n maxTokens: 8000,\n reserveTokens: 1000,\n modelName: 'gpt-4o',\n storageLimit: 1000,\n };\n\n constructor(config: SmartMemoryConfig = {}) {\n this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };\n this.logger = new Logger({ module: 'SmartMemoryManager' });\n\n this.tokenCounter = new TokenCounter(this.config.modelName);\n this._contentStorage = new ContentStorage(this.config.storageLimit);\n this.memoryWindow = new MemoryWindow(\n this.config.maxTokens,\n this.config.reserveTokens,\n this.tokenCounter\n );\n }\n\n /**\n * Get the content storage instance for file/content reference operations\n * @returns ContentStorage instance\n */\n get contentStorage(): ContentStorage {\n return this._contentStorage;\n }\n\n /**\n * Add a message to the active memory window\n * Automatically handles pruning and storage of displaced messages\n * @param message - Message to add\n */\n addMessage(message: BaseMessage): void {\n const result = this.memoryWindow.addMessage(message);\n\n if (result.prunedMessages.length > 0) {\n this._contentStorage.storeMessages(result.prunedMessages);\n }\n }\n\n /**\n * Get all active messages from the memory window\n * @returns Array of active messages in chronological order\n */\n getMessages(): BaseMessage[] {\n return this.memoryWindow.getMessages();\n }\n\n /**\n * Clear active memory window\n * @param clearStorage - Whether to also clear the content storage (default: false)\n */\n clear(clearStorage: boolean = false): void {\n this.memoryWindow.clear();\n\n if (clearStorage) {\n this._contentStorage.clear();\n }\n }\n\n /**\n * Set the system prompt for the memory window\n * @param systemPrompt - System prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.memoryWindow.setSystemPrompt(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt text\n */\n getSystemPrompt(): string {\n return this.memoryWindow.getSystemPrompt();\n }\n\n /**\n * Search through stored message history\n * @param query - Search term or pattern\n * @param options - Search configuration\n * @returns Array of matching messages from history\n */\n searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {\n return this._contentStorage.searchMessages(query, options);\n }\n\n /**\n * Get recent messages from storage history\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages from storage\n */\n getRecentHistory(count: number): BaseMessage[] {\n return this._contentStorage.getRecentMessages(count);\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - Message to test\n * @returns True if message can be added\n */\n canAddMessage(message: BaseMessage): boolean {\n return this.memoryWindow.canAddMessage(message);\n }\n\n /**\n * Get statistics about the active memory window\n * @returns Memory usage statistics\n */\n getMemoryStats(): MemoryStats {\n const windowStats = this.memoryWindow.getStats();\n\n return {\n totalActiveMessages: windowStats.totalMessages,\n currentTokenCount: windowStats.currentTokens,\n maxTokens: windowStats.maxTokens,\n remainingCapacity: windowStats.remainingCapacity,\n systemPromptTokens: windowStats.systemPromptTokens,\n usagePercentage: windowStats.usagePercentage,\n };\n }\n\n /**\n * Get statistics about the content storage\n * @returns Storage usage statistics\n */\n getStorageStats(): ReturnType<ContentStorage['getStorageStats']> {\n return this._contentStorage.getStorageStats();\n }\n\n /**\n * Get combined statistics for both active memory and storage\n * @returns Combined memory and storage statistics\n */\n getOverallStats(): {\n activeMemory: MemoryStats;\n storage: ReturnType<ContentStorage['getStorageStats']>;\n totalMessagesManaged: number;\n activeMemoryUtilization: number;\n storageUtilization: number;\n } {\n const memoryStats = this.getMemoryStats();\n const storageStats = this.getStorageStats();\n\n return {\n activeMemory: memoryStats,\n storage: storageStats,\n totalMessagesManaged:\n memoryStats.totalActiveMessages + storageStats.totalMessages,\n activeMemoryUtilization: memoryStats.usagePercentage,\n storageUtilization: storageStats.usagePercentage,\n };\n }\n\n /**\n * Update the configuration and apply changes\n * @param newConfig - New configuration options\n */\n updateConfig(newConfig: Partial<SmartMemoryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (\n newConfig.maxTokens !== undefined ||\n newConfig.reserveTokens !== undefined\n ) {\n this.memoryWindow.updateLimits(\n this.config.maxTokens,\n this.config.reserveTokens\n );\n }\n\n if (newConfig.storageLimit !== undefined) {\n this._contentStorage.updateStorageLimit(this.config.storageLimit);\n }\n }\n\n /**\n * Get current configuration\n * @returns Current configuration settings\n */\n getConfig(): Required<SmartMemoryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get messages from storage within a time range\n * @param startTime - Start of time range\n * @param endTime - End of time range\n * @returns Messages within the specified time range\n */\n getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n return this._contentStorage.getMessagesFromTimeRange(startTime, endTime);\n }\n\n /**\n * Get messages from storage by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Messages of the specified type\n */\n getHistoryByType(messageType: string, limit?: number): BaseMessage[] {\n return this._contentStorage.getMessagesByType(messageType, limit);\n }\n\n /**\n * Get recent messages from storage within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Messages from the last N minutes\n */\n getRecentHistoryByTime(minutes: number): BaseMessage[] {\n return this._contentStorage.getRecentMessagesByTime(minutes);\n }\n\n /**\n * Export the current state for persistence or analysis\n * @returns Serializable representation of memory state\n */\n exportState(): {\n config: Required<SmartMemoryConfig>;\n activeMessages: Array<{ content: unknown; type: string }>;\n systemPrompt: string;\n memoryStats: MemoryStats;\n storageStats: ReturnType<ContentStorage['getStorageStats']>;\n storedMessages: ReturnType<ContentStorage['exportMessages']>;\n } {\n return {\n config: this.config,\n activeMessages: this.memoryWindow.getMessages().map((msg) => ({\n content: msg.content,\n type: msg._getType(),\n })),\n systemPrompt: this.memoryWindow.getSystemPrompt(),\n memoryStats: this.getMemoryStats(),\n storageStats: this.getStorageStats(),\n storedMessages: this._contentStorage.exportMessages(),\n };\n }\n\n /**\n * Get a summary of conversation context for external use\n * Useful for providing context to other systems or for logging\n * @param includeStoredContext - Whether to include recent stored messages\n * @returns Context summary object\n */\n getContextSummary(includeStoredContext: boolean = false): {\n activeMessageCount: number;\n systemPrompt: string;\n recentMessages: BaseMessage[];\n memoryUtilization: number;\n hasStoredHistory: boolean;\n recentStoredMessages?: BaseMessage[];\n storageStats?: ReturnType<ContentStorage['getStorageStats']>;\n } {\n const activeMessages = this.getMessages();\n const summary = {\n activeMessageCount: activeMessages.length,\n systemPrompt: this.getSystemPrompt(),\n recentMessages: activeMessages.slice(-5),\n memoryUtilization: this.getMemoryStats().usagePercentage,\n hasStoredHistory: this.getStorageStats().totalMessages > 0,\n };\n\n if (includeStoredContext) {\n return {\n ...summary,\n recentStoredMessages: this.getRecentHistory(10),\n storageStats: this.getStorageStats(),\n };\n }\n\n return summary;\n }\n\n /**\n * Perform maintenance operations\n * Optimizes storage and cleans up resources\n */\n performMaintenance(): void {}\n\n /**\n * Store an entity association for later resolution\n * @param entityId - The blockchain entity ID\n * @param entityName - User-provided or derived friendly name\n * @param entityType - Type of entity (token, account, topic, etc.)\n * @param transactionId - Optional transaction ID that created this entity\n */\n storeEntityAssociation(\n entityId: string,\n entityName: string,\n entityType: string,\n transactionId?: string,\n sessionId?: string\n ): void {\n try {\n if (\n !entityId ||\n typeof entityId !== 'string' ||\n entityId.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityName ||\n typeof entityName !== 'string' ||\n entityName.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityType ||\n typeof entityType !== 'string' ||\n entityType.trim().length === 0\n ) {\n return;\n }\n\n const sanitizedEntityId = entityId.trim();\n const sanitizedEntityName = entityName.trim().substring(0, 100);\n const sanitizedEntityType = this.normalizeEntityType(entityType);\n\n let usageHint = '';\n if (sanitizedEntityType === 'tokenid') {\n usageHint = 'Use this as tokenId for HTS operations';\n } else if (sanitizedEntityType === 'topicid') {\n usageHint =\n 'Can be used for HCS operations, HRLs for minting with the format hcs://1/<topicId>, etc.';\n } else if (sanitizedEntityType === 'accountid') {\n usageHint = 'Can be used for account based operations';\n }\n\n const association: EntityAssociation & {\n isEntityAssociation: boolean;\n usage?: string;\n hrl?: string;\n } = {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n createdAt: new Date(),\n isEntityAssociation: true,\n ...(usageHint ? { usage: usageHint } : {}),\n ...(sanitizedEntityType === 'topicId'\n ? { hrl: `hcs://1/${sanitizedEntityId}` }\n : {}),\n ...(transactionId !== undefined &&\n transactionId !== null &&\n transactionId.trim() !== ''\n ? { transactionId: transactionId.trim() }\n : {}),\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n };\n\n const content = JSON.stringify(association);\n type LangChainLikeMessage = {\n _getType: () => string;\n content: unknown;\n id: string;\n name?: string;\n additional_kwargs?: Record<string, unknown>;\n };\n\n const entityMessage: LangChainLikeMessage = {\n _getType: () => 'system',\n content: content,\n id: `entity_${sanitizedEntityId}_${Date.now()}`,\n name: 'entity_association',\n additional_kwargs: {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n isEntityAssociation: true,\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n },\n };\n\n try {\n this.memoryWindow.addMessage(new SystemMessage(content));\n } catch {}\n\n this._contentStorage.storeMessages([entityMessage as BaseMessage]);\n } catch (error) {\n this.logger.error('Failed to store entity association', {\n entityId,\n entityName,\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Normalize various type aliases to canonical EntityFormat strings using a registry.\n */\n private normalizeEntityType(input: string): string {\n const raw = (input || '').trim();\n if (raw.length === 0) {\n return '';\n }\n\n const key = raw.replace(/[^a-z]/gi, '').toLowerCase();\n\n const REGISTRY: Record<string, string> = {\n topic: 'topicId',\n topicid: 'topicId',\n token: 'tokenId',\n tokenid: 'tokenId',\n account: 'accountId',\n accountid: 'accountId',\n contract: 'contractId',\n contractid: 'contractId',\n file: 'fileId',\n fileid: 'fileId',\n schedule: 'scheduleId',\n scheduleid: 'scheduleId',\n };\n\n if (Object.prototype.hasOwnProperty.call(REGISTRY, key)) {\n return REGISTRY[key];\n }\n\n if (/^[a-z]+Id$/.test(raw)) {\n return raw;\n }\n\n return raw;\n }\n\n /**\n * Resolve entity references from natural language queries\n * @param query - Search query (entity name or natural language reference)\n * @param options - Resolution options for filtering and fuzzy matching\n * @returns Array of matching entity associations\n */\n resolveEntityReference(\n query: string,\n options: EntityResolutionOptions = {}\n ): EntityAssociation[] {\n try {\n if (!query || typeof query !== 'string') {\n return [];\n }\n\n const sanitizedQuery = query.trim();\n if (sanitizedQuery.length === 0) {\n return [];\n }\n\n if (sanitizedQuery.length > 200) {\n }\n\n const { entityType, limit = 10, fuzzyMatch = true } = options;\n\n const safeLimit = Math.max(1, Math.min(limit || 10, 100));\n\n const isEntityIdQuery = /^0\\.0\\.\\d+$/.test(sanitizedQuery);\n\n const searchResults = this._contentStorage.searchMessages(\n sanitizedQuery.substring(0, 200),\n {\n caseSensitive: false,\n limit: safeLimit * 2,\n }\n );\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (\n content.includes(IS_ENTITY_ASSOCIATION_FLAG) ||\n content.includes('entityId')\n ) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n\n if (isEntityIdQuery) {\n if (parsed.entityId !== sanitizedQuery) {\n continue;\n }\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n\n if (fuzzyMatch && associations.length === 0 && !isEntityIdQuery) {\n const fuzzyQueries = [\n query.toLowerCase(),\n `token`,\n `account`,\n entityType || '',\n ].filter(Boolean);\n\n for (const fuzzyQuery of fuzzyQueries) {\n if (fuzzyQuery === query.toLowerCase()) continue;\n\n const fuzzyResults = this._contentStorage.searchMessages(fuzzyQuery, {\n caseSensitive: false,\n limit: limit,\n });\n\n for (const message of fuzzyResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n }\n }\n\n const uniqueAssociations = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n const results = uniqueAssociations.slice(0, safeLimit);\n\n return results;\n } catch (error) {\n this.logger.error('Failed to resolve entity reference', {\n query,\n options,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Get all entity associations, optionally filtered by type\n * @param entityType - Optional filter by entity type\n * @returns Array of entity associations\n */\n getEntityAssociations(entityType?: string): EntityAssociation[] {\n try {\n const rawFilter = entityType ? entityType.trim() : undefined;\n const filterCanonical = rawFilter ? this.normalizeEntityType(rawFilter) : undefined;\n\n if (entityType && (!rawFilter || rawFilter.length === 0)) {\n return [];\n }\n\n const SEARCH_ANY_ENTITY = 'entityId';\n const searchQuery = filterCanonical || SEARCH_ANY_ENTITY;\n const searchResults = this._contentStorage.searchMessages(searchQuery, {\n caseSensitive: false,\n limit: 100,\n });\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (filterCanonical && parsed.entityType !== filterCanonical) {\n continue;\n }\n\n if (parsed.createdAt && typeof parsed.createdAt === 'string') {\n parsed.createdAt = new Date(parsed.createdAt);\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch (parseError) {\n this.logger.warn('Failed to parse entity association from message', {\n messageContent:\n typeof message.content === 'string'\n ? message.content.substring(0, 100)\n : 'non-string',\n error:\n parseError instanceof Error\n ? parseError.message\n : String(parseError),\n });\n continue;\n }\n }\n\n const mergedById = new Map<string, EntityAssociation>();\n const getTime = (d: Date | string): number =>\n d instanceof Date ? d.getTime() : new Date(d).getTime();\n\n for (const assoc of associations) {\n const existing = mergedById.get(assoc.entityId);\n if (!existing) {\n mergedById.set(assoc.entityId, assoc);\n continue;\n }\n\n const existingTime = getTime(existing.createdAt);\n const currentTime = getTime(assoc.createdAt);\n\n const preferCurrent =\n currentTime > existingTime ||\n (!!assoc.transactionId && !existing.transactionId);\n\n if (preferCurrent) {\n mergedById.set(assoc.entityId, {\n ...existing,\n ...assoc,\n });\n }\n }\n\n const results = Array.from(mergedById.values()).sort((a, b) =>\n getTime(b.createdAt) - getTime(a.createdAt)\n );\n\n return results;\n } catch (error) {\n this.logger.error('Failed to get entity associations', {\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Clean up resources and dispose of components\n */\n dispose(): void {\n this.memoryWindow.dispose();\n this._contentStorage.dispose();\n this.tokenCounter.dispose();\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,183 +1,124 @@
1
- import { TokenCounter } from "./index19.js";
2
- const _MemoryWindow = class _MemoryWindow {
3
- constructor(maxTokens = _MemoryWindow.DEFAULT_MAX_TOKENS, reserveTokens = _MemoryWindow.DEFAULT_RESERVE_TOKENS, tokenCounter) {
4
- this.messages = [];
5
- this.systemPrompt = "";
6
- this.systemPromptTokens = 0;
7
- if (reserveTokens >= maxTokens) {
8
- throw new Error("Reserve tokens must be less than max tokens");
1
+ import { encoding_for_model } from "tiktoken";
2
+ const _TokenCounter = class _TokenCounter {
3
+ constructor(modelName = "gpt-4o") {
4
+ this.modelName = String(modelName);
5
+ try {
6
+ this.encoding = encoding_for_model(modelName);
7
+ } catch {
8
+ this.encoding = encoding_for_model("gpt-4o");
9
+ this.modelName = "gpt-4o";
9
10
  }
10
- this.maxTokens = maxTokens;
11
- this.reserveTokens = reserveTokens;
12
- this.tokenCounter = tokenCounter || new TokenCounter();
13
11
  }
14
12
  /**
15
- * Add a message to the memory window, pruning old messages if necessary
16
- * @param message - The message to add
17
- * @returns Result of the add operation including any pruned messages
13
+ * Count tokens in raw text content
14
+ * @param text - The text to count tokens for
15
+ * @returns Number of tokens
18
16
  */
19
- addMessage(message) {
20
- this.tokenCounter.countMessageTokens(message);
21
- this.messages.push(message);
22
- const currentTokens = this.getCurrentTokenCount();
23
- const availableTokens = this.maxTokens - this.reserveTokens;
24
- let prunedMessages = [];
25
- if (currentTokens > availableTokens) {
26
- this.messages.pop();
27
- prunedMessages = this.pruneToFit();
28
- this.messages.push(message);
17
+ countTokens(text) {
18
+ if (!text || text.trim() === "") {
19
+ return 0;
29
20
  }
30
- return {
31
- added: true,
32
- prunedMessages,
33
- currentTokenCount: this.getCurrentTokenCount(),
34
- remainingCapacity: this.getRemainingTokenCapacity()
35
- };
36
- }
37
- /**
38
- * Prune old messages to fit within token limits
39
- * Removes messages in pairs to maintain conversational flow
40
- * @returns Array of pruned messages
41
- */
42
- pruneToFit() {
43
- const prunedMessages = [];
44
- const targetTokens = this.maxTokens - this.reserveTokens;
45
- while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {
46
- const batchSize = Math.min(
47
- _MemoryWindow.PRUNING_BATCH_SIZE,
48
- this.messages.length
49
- );
50
- for (let i = 0; i < batchSize; i++) {
51
- const prunedMessage = this.messages.shift();
52
- if (prunedMessage) {
53
- prunedMessages.push(prunedMessage);
54
- }
55
- }
56
- if (prunedMessages.length > 1e3) {
57
- break;
58
- }
21
+ try {
22
+ const tokens = this.encoding.encode(text);
23
+ return tokens.length;
24
+ } catch {
25
+ return Math.ceil(text.split(/\s+/).length * 1.3);
59
26
  }
60
- return prunedMessages;
61
- }
62
- /**
63
- * Get current token count including system prompt and messages
64
- * @returns Current token count
65
- */
66
- getCurrentTokenCount() {
67
- const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);
68
- return this.systemPromptTokens + messageTokens;
69
27
  }
70
28
  /**
71
- * Get remaining token capacity before hitting the reserve limit
72
- * @returns Remaining tokens that can be used
29
+ * Count tokens for a single chat message including role overhead
30
+ * @param message - The message to count tokens for
31
+ * @returns Number of tokens including message formatting overhead
73
32
  */
74
- getRemainingTokenCapacity() {
75
- return Math.max(0, this.maxTokens - this.getCurrentTokenCount());
33
+ countMessageTokens(message) {
34
+ const contentTokens = this.countTokens(String(message.content ?? ""));
35
+ const roleTokens = this.countTokens(this.getMessageRole(message));
36
+ return contentTokens + roleTokens + _TokenCounter.MESSAGE_OVERHEAD + _TokenCounter.ROLE_OVERHEAD;
76
37
  }
77
38
  /**
78
- * Check if a message can be added without exceeding limits
79
- * @param message - The message to check
80
- * @returns True if message can be added within reserve limits
39
+ * Count tokens for multiple messages
40
+ * @param messages - Array of messages to count
41
+ * @returns Total token count for all messages
81
42
  */
82
- canAddMessage(message) {
83
- const messageTokens = this.tokenCounter.countMessageTokens(message);
84
- const currentTokens = this.getCurrentTokenCount();
85
- const wouldExceedReserve = currentTokens + messageTokens > this.maxTokens - this.reserveTokens;
86
- if (messageTokens > this.maxTokens) {
87
- return false;
43
+ countMessagesTokens(messages) {
44
+ if (!messages || messages.length === 0) {
45
+ return 0;
88
46
  }
89
- return !wouldExceedReserve || this.messages.length > 0;
90
- }
91
- /**
92
- * Get all messages in the memory window
93
- * @returns Copy of current messages array
94
- */
95
- getMessages() {
96
- return [...this.messages];
97
- }
98
- /**
99
- * Clear all messages from the memory window
100
- */
101
- clear() {
102
- this.messages = [];
47
+ let total = 0;
48
+ for (const message of messages) {
49
+ total += this.countMessageTokens(message);
50
+ }
51
+ return total;
103
52
  }
104
53
  /**
105
- * Set the system prompt and update token calculations
54
+ * Estimate tokens for system prompt
55
+ * System prompts have slightly different overhead in chat completions
106
56
  * @param systemPrompt - The system prompt text
57
+ * @returns Estimated token count
107
58
  */
108
- setSystemPrompt(systemPrompt) {
109
- this.systemPrompt = systemPrompt;
110
- this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);
111
- }
112
- /**
113
- * Get the current system prompt
114
- * @returns Current system prompt
115
- */
116
- getSystemPrompt() {
117
- return this.systemPrompt;
59
+ estimateSystemPromptTokens(systemPrompt) {
60
+ if (!systemPrompt || systemPrompt.trim() === "") {
61
+ return 0;
62
+ }
63
+ const contentTokens = this.countTokens(systemPrompt);
64
+ const roleTokens = this.countTokens("system");
65
+ return contentTokens + roleTokens + _TokenCounter.MESSAGE_OVERHEAD + _TokenCounter.ROLE_OVERHEAD;
118
66
  }
119
67
  /**
120
- * Get current configuration
121
- * @returns Memory window configuration
68
+ * Get total context size estimate including system prompt and messages
69
+ * @param systemPrompt - System prompt text
70
+ * @param messages - Conversation messages
71
+ * @returns Total estimated token count
122
72
  */
123
- getConfig() {
124
- return {
125
- maxTokens: this.maxTokens,
126
- reserveTokens: this.reserveTokens,
127
- currentTokens: this.getCurrentTokenCount(),
128
- messageCount: this.messages.length,
129
- systemPromptTokens: this.systemPromptTokens
130
- };
73
+ estimateContextSize(systemPrompt, messages) {
74
+ const systemTokens = this.estimateSystemPromptTokens(systemPrompt);
75
+ const messageTokens = this.countMessagesTokens(messages);
76
+ const completionOverhead = 10;
77
+ return systemTokens + messageTokens + completionOverhead;
131
78
  }
132
79
  /**
133
- * Update token limits
134
- * @param maxTokens - New maximum token limit
135
- * @param reserveTokens - New reserve token amount
80
+ * Get the role string for a message
81
+ * @param message - The message to get the role for
82
+ * @returns Role string ('user', 'assistant', 'system', etc.)
136
83
  */
137
- updateLimits(maxTokens, reserveTokens) {
138
- if (reserveTokens !== void 0 && reserveTokens >= maxTokens) {
139
- throw new Error("Reserve tokens must be less than max tokens");
140
- }
141
- this.maxTokens = maxTokens;
142
- if (reserveTokens !== void 0) {
143
- this.reserveTokens = reserveTokens;
144
- }
145
- if (this.getCurrentTokenCount() > this.maxTokens - this.reserveTokens) {
146
- this.pruneToFit();
84
+ getMessageRole(message) {
85
+ const messageType = message._getType();
86
+ switch (messageType) {
87
+ case "human":
88
+ return "user";
89
+ case "ai":
90
+ return "assistant";
91
+ case "system":
92
+ return "system";
93
+ case "function":
94
+ return "function";
95
+ case "tool":
96
+ return "tool";
97
+ default:
98
+ return "user";
147
99
  }
148
100
  }
149
101
  /**
150
- * Get statistics about the memory window
151
- * @returns Memory usage statistics
102
+ * Get the model name being used for token counting
103
+ * @returns The tiktoken model name
152
104
  */
153
- getStats() {
154
- const currentTokens = this.getCurrentTokenCount();
155
- const capacity = this.maxTokens;
156
- const usagePercentage = currentTokens / capacity * 100;
157
- return {
158
- totalMessages: this.messages.length,
159
- currentTokens,
160
- maxTokens: capacity,
161
- reserveTokens: this.reserveTokens,
162
- systemPromptTokens: this.systemPromptTokens,
163
- usagePercentage: Math.round(usagePercentage * 100) / 100,
164
- remainingCapacity: this.getRemainingTokenCapacity(),
165
- canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens
166
- };
105
+ getModelName() {
106
+ return this.modelName;
167
107
  }
168
108
  /**
169
- * Clean up resources
109
+ * Clean up encoding resources
170
110
  */
171
111
  dispose() {
172
- this.clear();
173
- this.tokenCounter.dispose();
112
+ try {
113
+ this.encoding.free();
114
+ } catch {
115
+ }
174
116
  }
175
117
  };
176
- _MemoryWindow.DEFAULT_MAX_TOKENS = 8e3;
177
- _MemoryWindow.DEFAULT_RESERVE_TOKENS = 1e3;
178
- _MemoryWindow.PRUNING_BATCH_SIZE = 2;
179
- let MemoryWindow = _MemoryWindow;
118
+ _TokenCounter.MESSAGE_OVERHEAD = 3;
119
+ _TokenCounter.ROLE_OVERHEAD = 1;
120
+ let TokenCounter = _TokenCounter;
180
121
  export {
181
- MemoryWindow
122
+ TokenCounter
182
123
  };
183
124
  //# sourceMappingURL=index20.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index20.js","sources":["../../src/memory/memory-window.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n\n this.messages.push(message);\n\n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n\n let prunedMessages: BaseMessage[] = [];\n\n if (currentTokens > availableTokens) {\n this.messages.pop();\n\n prunedMessages = this.pruneToFit();\n\n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity(),\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n\n while (\n this.getCurrentTokenCount() > targetTokens &&\n this.messages.length > 0\n ) {\n const batchSize = Math.min(\n MemoryWindow.PRUNING_BATCH_SIZE,\n this.messages.length\n );\n\n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n\n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve =\n currentTokens + messageTokens > this.maxTokens - this.reserveTokens;\n\n if (messageTokens > this.maxTokens) {\n return false;\n }\n\n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens =\n this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig(): {\n maxTokens: number;\n reserveTokens: number;\n currentTokens: number;\n messageCount: number;\n systemPromptTokens: number;\n } {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens,\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > this.maxTokens - this.reserveTokens) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats(): {\n totalMessages: number;\n currentTokens: number;\n maxTokens: number;\n reserveTokens: number;\n systemPromptTokens: number;\n usagePercentage: number;\n remainingCapacity: number;\n canAcceptMore: boolean;\n } {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n\n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens,\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}\n"],"names":[],"mappings":";AAqBO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAYxB,YACE,YAAoB,cAAa,oBACjC,gBAAwB,cAAa,wBACrC,cACA;AAfF,SAAQ,WAA0B,CAAA;AAIlC,SAAQ,eAAuB;AAC/B,SAAQ,qBAA6B;AAWnC,QAAI,iBAAiB,WAAW;AAC9B,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AAEA,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,eAAe,gBAAgB,IAAI,aAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,SAAwC;AACjD,SAAK,aAAa,mBAAmB,OAAO;AAE5C,SAAK,SAAS,KAAK,OAAO;AAE1B,UAAM,gBAAgB,KAAK,qBAAA;AAC3B,UAAM,kBAAkB,KAAK,YAAY,KAAK;AAE9C,QAAI,iBAAgC,CAAA;AAEpC,QAAI,gBAAgB,iBAAiB;AACnC,WAAK,SAAS,IAAA;AAEd,uBAAiB,KAAK,WAAA;AAEtB,WAAK,SAAS,KAAK,OAAO;AAAA,IAC5B;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA,mBAAmB,KAAK,qBAAA;AAAA,MACxB,mBAAmB,KAAK,0BAAA;AAAA,IAA0B;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAA4B;AAC1B,UAAM,iBAAgC,CAAA;AACtC,UAAM,eAAe,KAAK,YAAY,KAAK;AAE3C,WACE,KAAK,yBAAyB,gBAC9B,KAAK,SAAS,SAAS,GACvB;AACA,YAAM,YAAY,KAAK;AAAA,QACrB,cAAa;AAAA,QACb,KAAK,SAAS;AAAA,MAAA;AAGhB,eAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,cAAM,gBAAgB,KAAK,SAAS,MAAA;AACpC,YAAI,eAAe;AACjB,yBAAe,KAAK,aAAa;AAAA,QACnC;AAAA,MACF;AAEA,UAAI,eAAe,SAAS,KAAM;AAChC;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAA+B;AAC7B,UAAM,gBAAgB,KAAK,aAAa,oBAAoB,KAAK,QAAQ;AACzE,WAAO,KAAK,qBAAqB;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,4BAAoC;AAClC,WAAO,KAAK,IAAI,GAAG,KAAK,YAAY,KAAK,sBAAsB;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,SAA+B;AAC3C,UAAM,gBAAgB,KAAK,aAAa,mBAAmB,OAAO;AAClE,UAAM,gBAAgB,KAAK,qBAAA;AAC3B,UAAM,qBACJ,gBAAgB,gBAAgB,KAAK,YAAY,KAAK;AAExD,QAAI,gBAAgB,KAAK,WAAW;AAClC,aAAO;AAAA,IACT;AAEA,WAAO,CAAC,sBAAsB,KAAK,SAAS,SAAS;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,WAAW,CAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,cAA4B;AAC1C,SAAK,eAAe;AACpB,SAAK,qBACH,KAAK,aAAa,2BAA2B,YAAY;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAME;AACA,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,eAAe,KAAK,qBAAA;AAAA,MACpB,cAAc,KAAK,SAAS;AAAA,MAC5B,oBAAoB,KAAK;AAAA,IAAA;AAAA,EAE7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,WAAmB,eAA8B;AAC5D,QAAI,kBAAkB,UAAa,iBAAiB,WAAW;AAC7D,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AAEA,SAAK,YAAY;AACjB,QAAI,kBAAkB,QAAW;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,KAAK,qBAAA,IAAyB,KAAK,YAAY,KAAK,eAAe;AACrE,WAAK,WAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WASE;AACA,UAAM,gBAAgB,KAAK,qBAAA;AAC3B,UAAM,WAAW,KAAK;AACtB,UAAM,kBAAmB,gBAAgB,WAAY;AAErD,WAAO;AAAA,MACL,eAAe,KAAK,SAAS;AAAA,MAC7B;AAAA,MACA,WAAW;AAAA,MACX,eAAe,KAAK;AAAA,MACpB,oBAAoB,KAAK;AAAA,MACzB,iBAAiB,KAAK,MAAM,kBAAkB,GAAG,IAAI;AAAA,MACrD,mBAAmB,KAAK,0BAAA;AAAA,MACxB,eAAe,KAAK,0BAAA,IAA8B,KAAK;AAAA,IAAA;AAAA,EAE3D;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,MAAA;AACL,SAAK,aAAa,QAAA;AAAA,EACpB;AACF;AAnOE,cAAuB,qBAAqB;AAC5C,cAAuB,yBAAyB;AAChD,cAAuB,qBAAqB;AAVvC,IAAM,eAAN;"}
1
+ {"version":3,"file":"index20.js","sources":["../../src/memory/token-counter.ts"],"sourcesContent":["import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}"],"names":[],"mappings":";AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAOxB,YAAY,YAAoC,UAAU;AACxD,SAAK,YAAY,OAAO,SAAS;AACjC,QAAI;AACF,WAAK,WAAW,mBAAmB,SAA0B;AAAA,IAC/D,QAAQ;AACN,WAAK,WAAW,mBAAmB,QAAQ;AAC3C,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAsB;AAChC,QAAI,CAAC,QAAQ,KAAK,KAAA,MAAW,IAAI;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,SAAS,OAAO,IAAI;AACxC,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,aAAO,KAAK,KAAK,KAAK,MAAM,KAAK,EAAE,SAAS,GAAG;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAA8B;AAC/C,UAAM,gBAAgB,KAAK,YAAY,OAAO,QAAQ,WAAW,EAAE,CAAC;AACpE,UAAM,aAAa,KAAK,YAAY,KAAK,eAAe,OAAO,CAAC;AAEhE,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,UAAiC;AACnD,QAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ;AACZ,eAAW,WAAW,UAAU;AAC9B,eAAS,KAAK,mBAAmB,OAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAA2B,cAA8B;AACvD,QAAI,CAAC,gBAAgB,aAAa,KAAA,MAAW,IAAI;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,KAAK,YAAY,YAAY;AACnD,UAAM,aAAa,KAAK,YAAY,QAAQ;AAE5C,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,cAAsB,UAAiC;AACzE,UAAM,eAAe,KAAK,2BAA2B,YAAY;AACjE,UAAM,gBAAgB,KAAK,oBAAoB,QAAQ;AAEvD,UAAM,qBAAqB;AAE3B,WAAO,eAAe,gBAAgB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,SAA8B;AACnD,UAAM,cAAc,QAAQ,SAAA;AAC5B,YAAQ,aAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI;AACF,WAAK,SAAS,KAAA;AAAA,IAChB,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AApIE,cAAwB,mBAAmB;AAC3C,cAAwB,gBAAgB;AALnC,IAAM,eAAN;"}