@soleri/core 2.10.0 → 2.11.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 (499) hide show
  1. package/dist/agency/agency-manager.d.ts +47 -0
  2. package/dist/agency/agency-manager.d.ts.map +1 -0
  3. package/dist/agency/agency-manager.js +281 -0
  4. package/dist/agency/agency-manager.js.map +1 -0
  5. package/dist/agency/index.d.ts +3 -0
  6. package/dist/agency/index.d.ts.map +1 -0
  7. package/dist/agency/index.js +2 -0
  8. package/dist/agency/index.js.map +1 -0
  9. package/dist/agency/types.d.ts +69 -0
  10. package/dist/agency/types.d.ts.map +1 -0
  11. package/dist/agency/types.js +5 -0
  12. package/dist/agency/types.js.map +1 -0
  13. package/dist/brain/brain.d.ts +0 -1
  14. package/dist/brain/brain.d.ts.map +1 -1
  15. package/dist/brain/brain.js +14 -0
  16. package/dist/brain/brain.js.map +1 -1
  17. package/dist/brain/intelligence.d.ts +5 -1
  18. package/dist/brain/intelligence.d.ts.map +1 -1
  19. package/dist/brain/intelligence.js +83 -0
  20. package/dist/brain/intelligence.js.map +1 -1
  21. package/dist/brain/types.d.ts +21 -0
  22. package/dist/brain/types.d.ts.map +1 -1
  23. package/dist/chat/agent-loop-types.d.ts +82 -0
  24. package/dist/chat/agent-loop-types.d.ts.map +1 -0
  25. package/dist/chat/agent-loop-types.js +8 -0
  26. package/dist/chat/agent-loop-types.js.map +1 -0
  27. package/dist/chat/agent-loop.d.ts +19 -0
  28. package/dist/chat/agent-loop.d.ts.map +1 -0
  29. package/dist/chat/agent-loop.js +261 -0
  30. package/dist/chat/agent-loop.js.map +1 -0
  31. package/dist/chat/auth-manager.d.ts +49 -0
  32. package/dist/chat/auth-manager.d.ts.map +1 -0
  33. package/dist/chat/auth-manager.js +152 -0
  34. package/dist/chat/auth-manager.js.map +1 -0
  35. package/dist/chat/browser-session.d.ts +86 -0
  36. package/dist/chat/browser-session.d.ts.map +1 -0
  37. package/dist/chat/browser-session.js +143 -0
  38. package/dist/chat/browser-session.js.map +1 -0
  39. package/dist/chat/cancellation.d.ts +54 -0
  40. package/dist/chat/cancellation.d.ts.map +1 -0
  41. package/dist/chat/cancellation.js +80 -0
  42. package/dist/chat/cancellation.js.map +1 -0
  43. package/dist/chat/chat-session.d.ts +86 -0
  44. package/dist/chat/chat-session.d.ts.map +1 -0
  45. package/dist/chat/chat-session.js +252 -0
  46. package/dist/chat/chat-session.js.map +1 -0
  47. package/dist/chat/file-handler.d.ts +63 -0
  48. package/dist/chat/file-handler.d.ts.map +1 -0
  49. package/dist/chat/file-handler.js +182 -0
  50. package/dist/chat/file-handler.js.map +1 -0
  51. package/dist/chat/fragment-buffer.d.ts +49 -0
  52. package/dist/chat/fragment-buffer.d.ts.map +1 -0
  53. package/dist/chat/fragment-buffer.js +130 -0
  54. package/dist/chat/fragment-buffer.js.map +1 -0
  55. package/dist/chat/index.d.ts +24 -0
  56. package/dist/chat/index.d.ts.map +1 -0
  57. package/dist/chat/index.js +15 -0
  58. package/dist/chat/index.js.map +1 -0
  59. package/dist/chat/mcp-bridge.d.ts +60 -0
  60. package/dist/chat/mcp-bridge.d.ts.map +1 -0
  61. package/dist/chat/mcp-bridge.js +111 -0
  62. package/dist/chat/mcp-bridge.js.map +1 -0
  63. package/dist/chat/notifications.d.ts +82 -0
  64. package/dist/chat/notifications.d.ts.map +1 -0
  65. package/dist/chat/notifications.js +119 -0
  66. package/dist/chat/notifications.js.map +1 -0
  67. package/dist/chat/output-compressor.d.ts +30 -0
  68. package/dist/chat/output-compressor.d.ts.map +1 -0
  69. package/dist/chat/output-compressor.js +95 -0
  70. package/dist/chat/output-compressor.js.map +1 -0
  71. package/dist/chat/queue.d.ts +91 -0
  72. package/dist/chat/queue.d.ts.map +1 -0
  73. package/dist/chat/queue.js +146 -0
  74. package/dist/chat/queue.js.map +1 -0
  75. package/dist/chat/response-chunker.d.ts +29 -0
  76. package/dist/chat/response-chunker.d.ts.map +1 -0
  77. package/dist/chat/response-chunker.js +163 -0
  78. package/dist/chat/response-chunker.js.map +1 -0
  79. package/dist/chat/self-update.d.ts +62 -0
  80. package/dist/chat/self-update.d.ts.map +1 -0
  81. package/dist/chat/self-update.js +90 -0
  82. package/dist/chat/self-update.js.map +1 -0
  83. package/dist/chat/types.d.ts +105 -0
  84. package/dist/chat/types.d.ts.map +1 -0
  85. package/dist/chat/types.js +8 -0
  86. package/dist/chat/types.js.map +1 -0
  87. package/dist/chat/voice.d.ts +39 -0
  88. package/dist/chat/voice.d.ts.map +1 -0
  89. package/dist/chat/voice.js +80 -0
  90. package/dist/chat/voice.js.map +1 -0
  91. package/dist/claudemd/compose.d.ts +31 -0
  92. package/dist/claudemd/compose.d.ts.map +1 -0
  93. package/dist/claudemd/compose.js +105 -0
  94. package/dist/claudemd/compose.js.map +1 -0
  95. package/dist/claudemd/index.d.ts +5 -0
  96. package/dist/claudemd/index.d.ts.map +1 -0
  97. package/dist/claudemd/index.js +3 -0
  98. package/dist/claudemd/index.js.map +1 -0
  99. package/dist/claudemd/inject.d.ts +31 -0
  100. package/dist/claudemd/inject.d.ts.map +1 -0
  101. package/dist/claudemd/inject.js +157 -0
  102. package/dist/claudemd/inject.js.map +1 -0
  103. package/dist/claudemd/types.d.ts +41 -0
  104. package/dist/claudemd/types.d.ts.map +1 -0
  105. package/dist/claudemd/types.js +5 -0
  106. package/dist/claudemd/types.js.map +1 -0
  107. package/dist/context/context-engine.d.ts +31 -0
  108. package/dist/context/context-engine.d.ts.map +1 -0
  109. package/dist/context/context-engine.js +245 -0
  110. package/dist/context/context-engine.js.map +1 -0
  111. package/dist/context/index.d.ts +3 -0
  112. package/dist/context/index.d.ts.map +1 -0
  113. package/dist/context/index.js +2 -0
  114. package/dist/context/index.js.map +1 -0
  115. package/dist/context/types.d.ts +54 -0
  116. package/dist/context/types.d.ts.map +1 -0
  117. package/dist/context/types.js +5 -0
  118. package/dist/context/types.js.map +1 -0
  119. package/dist/enforcement/adapters/claude-code.d.ts +18 -0
  120. package/dist/enforcement/adapters/claude-code.d.ts.map +1 -0
  121. package/dist/enforcement/adapters/claude-code.js +106 -0
  122. package/dist/enforcement/adapters/claude-code.js.map +1 -0
  123. package/dist/enforcement/adapters/index.d.ts +2 -0
  124. package/dist/enforcement/adapters/index.d.ts.map +1 -0
  125. package/dist/enforcement/adapters/index.js +2 -0
  126. package/dist/enforcement/adapters/index.js.map +1 -0
  127. package/dist/enforcement/index.d.ts +4 -0
  128. package/dist/enforcement/index.d.ts.map +1 -0
  129. package/dist/enforcement/index.js +3 -0
  130. package/dist/enforcement/index.js.map +1 -0
  131. package/dist/enforcement/registry.d.ts +23 -0
  132. package/dist/enforcement/registry.d.ts.map +1 -0
  133. package/dist/enforcement/registry.js +63 -0
  134. package/dist/enforcement/registry.js.map +1 -0
  135. package/dist/enforcement/types.d.ts +51 -0
  136. package/dist/enforcement/types.d.ts.map +1 -0
  137. package/dist/enforcement/types.js +8 -0
  138. package/dist/enforcement/types.js.map +1 -0
  139. package/dist/facades/facade-factory.d.ts +10 -3
  140. package/dist/facades/facade-factory.d.ts.map +1 -1
  141. package/dist/facades/facade-factory.js +94 -5
  142. package/dist/facades/facade-factory.js.map +1 -1
  143. package/dist/facades/types.d.ts +15 -1
  144. package/dist/facades/types.d.ts.map +1 -1
  145. package/dist/facades/types.js +6 -0
  146. package/dist/facades/types.js.map +1 -1
  147. package/dist/health/health-registry.d.ts +40 -0
  148. package/dist/health/health-registry.d.ts.map +1 -0
  149. package/dist/health/health-registry.js +134 -0
  150. package/dist/health/health-registry.js.map +1 -0
  151. package/dist/health/index.d.ts +5 -0
  152. package/dist/health/index.d.ts.map +1 -0
  153. package/dist/health/index.js +3 -0
  154. package/dist/health/index.js.map +1 -0
  155. package/dist/health/vault-integrity.d.ts +13 -0
  156. package/dist/health/vault-integrity.d.ts.map +1 -0
  157. package/dist/health/vault-integrity.js +49 -0
  158. package/dist/health/vault-integrity.js.map +1 -0
  159. package/dist/index.d.ts +67 -6
  160. package/dist/index.d.ts.map +1 -1
  161. package/dist/index.js +51 -3
  162. package/dist/index.js.map +1 -1
  163. package/dist/intake/intake-pipeline.d.ts +0 -7
  164. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  165. package/dist/intake/intake-pipeline.js +1 -1
  166. package/dist/intake/intake-pipeline.js.map +1 -1
  167. package/dist/intelligence/types.d.ts +1 -0
  168. package/dist/intelligence/types.d.ts.map +1 -1
  169. package/dist/migrations/index.d.ts +6 -0
  170. package/dist/migrations/index.d.ts.map +1 -0
  171. package/dist/migrations/index.js +5 -0
  172. package/dist/migrations/index.js.map +1 -0
  173. package/dist/migrations/migration-runner.d.ts +51 -0
  174. package/dist/migrations/migration-runner.d.ts.map +1 -0
  175. package/dist/migrations/migration-runner.js +141 -0
  176. package/dist/migrations/migration-runner.js.map +1 -0
  177. package/dist/packs/index.d.ts +10 -0
  178. package/dist/packs/index.d.ts.map +1 -0
  179. package/dist/packs/index.js +8 -0
  180. package/dist/packs/index.js.map +1 -0
  181. package/dist/packs/lockfile.d.ts +97 -0
  182. package/dist/packs/lockfile.d.ts.map +1 -0
  183. package/dist/packs/lockfile.js +129 -0
  184. package/dist/packs/lockfile.js.map +1 -0
  185. package/dist/packs/pack-installer.d.ts +41 -0
  186. package/dist/packs/pack-installer.d.ts.map +1 -0
  187. package/dist/packs/pack-installer.js +253 -0
  188. package/dist/packs/pack-installer.js.map +1 -0
  189. package/dist/packs/resolver.d.ts +51 -0
  190. package/dist/packs/resolver.d.ts.map +1 -0
  191. package/dist/packs/resolver.js +195 -0
  192. package/dist/packs/resolver.js.map +1 -0
  193. package/dist/packs/types.d.ts +186 -0
  194. package/dist/packs/types.d.ts.map +1 -0
  195. package/dist/packs/types.js +69 -0
  196. package/dist/packs/types.js.map +1 -0
  197. package/dist/persistence/postgres-provider.d.ts +42 -7
  198. package/dist/persistence/postgres-provider.d.ts.map +1 -1
  199. package/dist/persistence/postgres-provider.js +187 -46
  200. package/dist/persistence/postgres-provider.js.map +1 -1
  201. package/dist/playbooks/index.d.ts +2 -0
  202. package/dist/playbooks/index.d.ts.map +1 -1
  203. package/dist/playbooks/index.js +2 -0
  204. package/dist/playbooks/index.js.map +1 -1
  205. package/dist/playbooks/playbook-executor.d.ts +100 -0
  206. package/dist/playbooks/playbook-executor.d.ts.map +1 -0
  207. package/dist/playbooks/playbook-executor.js +207 -0
  208. package/dist/playbooks/playbook-executor.js.map +1 -0
  209. package/dist/plugins/index.d.ts +7 -0
  210. package/dist/plugins/index.d.ts.map +1 -0
  211. package/dist/plugins/index.js +7 -0
  212. package/dist/plugins/index.js.map +1 -0
  213. package/dist/plugins/plugin-loader.d.ts +28 -0
  214. package/dist/plugins/plugin-loader.d.ts.map +1 -0
  215. package/dist/plugins/plugin-loader.js +150 -0
  216. package/dist/plugins/plugin-loader.js.map +1 -0
  217. package/dist/plugins/plugin-registry.d.ts +58 -0
  218. package/dist/plugins/plugin-registry.d.ts.map +1 -0
  219. package/dist/plugins/plugin-registry.js +157 -0
  220. package/dist/plugins/plugin-registry.js.map +1 -0
  221. package/dist/plugins/types.d.ts +180 -0
  222. package/dist/plugins/types.d.ts.map +1 -0
  223. package/dist/plugins/types.js +48 -0
  224. package/dist/plugins/types.js.map +1 -0
  225. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  226. package/dist/runtime/admin-extra-ops.js +181 -8
  227. package/dist/runtime/admin-extra-ops.js.map +1 -1
  228. package/dist/runtime/capture-ops.d.ts.map +1 -1
  229. package/dist/runtime/capture-ops.js +106 -7
  230. package/dist/runtime/capture-ops.js.map +1 -1
  231. package/dist/runtime/deprecation.d.ts +33 -0
  232. package/dist/runtime/deprecation.d.ts.map +1 -0
  233. package/dist/runtime/deprecation.js +41 -0
  234. package/dist/runtime/deprecation.js.map +1 -0
  235. package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
  236. package/dist/runtime/facades/admin-facade.js +12 -1
  237. package/dist/runtime/facades/admin-facade.js.map +1 -1
  238. package/dist/runtime/facades/agency-facade.d.ts +7 -0
  239. package/dist/runtime/facades/agency-facade.d.ts.map +1 -0
  240. package/dist/runtime/facades/agency-facade.js +103 -0
  241. package/dist/runtime/facades/agency-facade.js.map +1 -0
  242. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  243. package/dist/runtime/facades/brain-facade.js +58 -0
  244. package/dist/runtime/facades/brain-facade.js.map +1 -1
  245. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  246. package/dist/runtime/facades/chat-facade.d.ts.map +1 -0
  247. package/dist/runtime/facades/chat-facade.js +808 -0
  248. package/dist/runtime/facades/chat-facade.js.map +1 -0
  249. package/dist/runtime/facades/context-facade.d.ts +7 -0
  250. package/dist/runtime/facades/context-facade.d.ts.map +1 -0
  251. package/dist/runtime/facades/context-facade.js +45 -0
  252. package/dist/runtime/facades/context-facade.js.map +1 -0
  253. package/dist/runtime/facades/index.d.ts.map +1 -1
  254. package/dist/runtime/facades/index.js +18 -0
  255. package/dist/runtime/facades/index.js.map +1 -1
  256. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  257. package/dist/runtime/facades/vault-facade.js +247 -1
  258. package/dist/runtime/facades/vault-facade.js.map +1 -1
  259. package/dist/runtime/feature-flags.d.ts +18 -0
  260. package/dist/runtime/feature-flags.d.ts.map +1 -0
  261. package/dist/runtime/feature-flags.js +90 -0
  262. package/dist/runtime/feature-flags.js.map +1 -0
  263. package/dist/runtime/pack-ops.d.ts +9 -0
  264. package/dist/runtime/pack-ops.d.ts.map +1 -0
  265. package/dist/runtime/pack-ops.js +76 -0
  266. package/dist/runtime/pack-ops.js.map +1 -0
  267. package/dist/runtime/playbook-ops.d.ts +3 -7
  268. package/dist/runtime/playbook-ops.d.ts.map +1 -1
  269. package/dist/runtime/playbook-ops.js +101 -10
  270. package/dist/runtime/playbook-ops.js.map +1 -1
  271. package/dist/runtime/plugin-ops.d.ts +9 -0
  272. package/dist/runtime/plugin-ops.d.ts.map +1 -0
  273. package/dist/runtime/plugin-ops.js +235 -0
  274. package/dist/runtime/plugin-ops.js.map +1 -0
  275. package/dist/runtime/runtime.d.ts.map +1 -1
  276. package/dist/runtime/runtime.js +72 -5
  277. package/dist/runtime/runtime.js.map +1 -1
  278. package/dist/runtime/telemetry-ops.d.ts +10 -0
  279. package/dist/runtime/telemetry-ops.d.ts.map +1 -0
  280. package/dist/runtime/telemetry-ops.js +53 -0
  281. package/dist/runtime/telemetry-ops.js.map +1 -0
  282. package/dist/runtime/types.d.ts +35 -0
  283. package/dist/runtime/types.d.ts.map +1 -1
  284. package/dist/runtime/vault-sharing-ops.d.ts +13 -0
  285. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -0
  286. package/dist/runtime/vault-sharing-ops.js +345 -0
  287. package/dist/runtime/vault-sharing-ops.js.map +1 -0
  288. package/dist/streams/index.d.ts +1 -1
  289. package/dist/streams/index.d.ts.map +1 -1
  290. package/dist/streams/index.js +1 -1
  291. package/dist/streams/index.js.map +1 -1
  292. package/dist/streams/replayable-stream.d.ts +13 -1
  293. package/dist/streams/replayable-stream.d.ts.map +1 -1
  294. package/dist/streams/replayable-stream.js +27 -3
  295. package/dist/streams/replayable-stream.js.map +1 -1
  296. package/dist/text/similarity.d.ts +0 -1
  297. package/dist/text/similarity.d.ts.map +1 -1
  298. package/dist/text/similarity.js +1 -1
  299. package/dist/text/similarity.js.map +1 -1
  300. package/dist/transport/http-server.d.ts +56 -0
  301. package/dist/transport/http-server.d.ts.map +1 -0
  302. package/dist/transport/http-server.js +210 -0
  303. package/dist/transport/http-server.js.map +1 -0
  304. package/dist/transport/index.d.ts +11 -0
  305. package/dist/transport/index.d.ts.map +1 -0
  306. package/dist/transport/index.js +10 -0
  307. package/dist/transport/index.js.map +1 -0
  308. package/dist/transport/lsp-server.d.ts +140 -0
  309. package/dist/transport/lsp-server.d.ts.map +1 -0
  310. package/dist/transport/lsp-server.js +239 -0
  311. package/dist/transport/lsp-server.js.map +1 -0
  312. package/dist/transport/rate-limiter.d.ts +35 -0
  313. package/dist/transport/rate-limiter.d.ts.map +1 -0
  314. package/dist/transport/rate-limiter.js +72 -0
  315. package/dist/transport/rate-limiter.js.map +1 -0
  316. package/dist/transport/session-manager.d.ts +49 -0
  317. package/dist/transport/session-manager.d.ts.map +1 -0
  318. package/dist/transport/session-manager.js +83 -0
  319. package/dist/transport/session-manager.js.map +1 -0
  320. package/dist/transport/token-auth.d.ts +29 -0
  321. package/dist/transport/token-auth.d.ts.map +1 -0
  322. package/dist/transport/token-auth.js +84 -0
  323. package/dist/transport/token-auth.js.map +1 -0
  324. package/dist/transport/types.d.ts +61 -0
  325. package/dist/transport/types.d.ts.map +1 -0
  326. package/dist/transport/types.js +5 -0
  327. package/dist/transport/types.js.map +1 -0
  328. package/dist/transport/ws-server.d.ts +78 -0
  329. package/dist/transport/ws-server.d.ts.map +1 -0
  330. package/dist/transport/ws-server.js +342 -0
  331. package/dist/transport/ws-server.js.map +1 -0
  332. package/dist/vault/git-vault-sync.d.ts +107 -0
  333. package/dist/vault/git-vault-sync.d.ts.map +1 -0
  334. package/dist/vault/git-vault-sync.js +251 -0
  335. package/dist/vault/git-vault-sync.js.map +1 -0
  336. package/dist/vault/knowledge-review.d.ts +67 -0
  337. package/dist/vault/knowledge-review.d.ts.map +1 -0
  338. package/dist/vault/knowledge-review.js +133 -0
  339. package/dist/vault/knowledge-review.js.map +1 -0
  340. package/dist/vault/obsidian-sync.d.ts +94 -0
  341. package/dist/vault/obsidian-sync.d.ts.map +1 -0
  342. package/dist/vault/obsidian-sync.js +247 -0
  343. package/dist/vault/obsidian-sync.js.map +1 -0
  344. package/dist/vault/scope-detector.d.ts +31 -0
  345. package/dist/vault/scope-detector.d.ts.map +1 -0
  346. package/dist/vault/scope-detector.js +182 -0
  347. package/dist/vault/scope-detector.js.map +1 -0
  348. package/dist/vault/vault-branching.d.ts +71 -0
  349. package/dist/vault/vault-branching.d.ts.map +1 -0
  350. package/dist/vault/vault-branching.js +180 -0
  351. package/dist/vault/vault-branching.js.map +1 -0
  352. package/dist/vault/vault-manager.d.ts +89 -0
  353. package/dist/vault/vault-manager.d.ts.map +1 -0
  354. package/dist/vault/vault-manager.js +199 -0
  355. package/dist/vault/vault-manager.js.map +1 -0
  356. package/dist/vault/vault-types.d.ts +30 -0
  357. package/dist/vault/vault-types.d.ts.map +1 -0
  358. package/dist/vault/vault-types.js +10 -0
  359. package/dist/vault/vault-types.js.map +1 -0
  360. package/dist/vault/vault.d.ts +10 -0
  361. package/dist/vault/vault.d.ts.map +1 -1
  362. package/dist/vault/vault.js +36 -3
  363. package/dist/vault/vault.js.map +1 -1
  364. package/package.json +1 -1
  365. package/src/__tests__/admin-extra-ops.test.ts +31 -11
  366. package/src/__tests__/agency-manager.test.ts +374 -0
  367. package/src/__tests__/agent-loop.test.ts +256 -0
  368. package/src/__tests__/capture-ops.test.ts +275 -0
  369. package/src/__tests__/chat-differentiators.test.ts +251 -0
  370. package/src/__tests__/chat-enhanced.test.ts +390 -0
  371. package/src/__tests__/chat-transport.test.ts +665 -0
  372. package/src/__tests__/claudemd.test.ts +282 -0
  373. package/src/__tests__/context-engine.test.ts +256 -0
  374. package/src/__tests__/core-ops.test.ts +97 -5
  375. package/src/__tests__/deprecation.test.ts +78 -0
  376. package/src/__tests__/enforcement.test.ts +153 -0
  377. package/src/__tests__/facade-factory.test.ts +271 -0
  378. package/src/__tests__/feature-flags.test.ts +138 -0
  379. package/src/__tests__/git-vault-sync.test.ts +230 -0
  380. package/src/__tests__/health-registry.test.ts +173 -0
  381. package/src/__tests__/knowledge-review.test.ts +104 -0
  382. package/src/__tests__/lsp-transport.test.ts +442 -0
  383. package/src/__tests__/migration-runner.test.ts +170 -0
  384. package/src/__tests__/normalize.test.ts +10 -0
  385. package/src/__tests__/obsidian-sync.test.ts +354 -0
  386. package/src/__tests__/pack-lockfile.test.ts +261 -0
  387. package/src/__tests__/pack-ops.test.ts +146 -0
  388. package/src/__tests__/pack-system.test.ts +423 -0
  389. package/src/__tests__/playbook-executor.test.ts +249 -0
  390. package/src/__tests__/playbook-ops-execution.test.ts +189 -0
  391. package/src/__tests__/plugin-ops.test.ts +411 -0
  392. package/src/__tests__/plugin-system.test.ts +509 -0
  393. package/src/__tests__/postgres-provider.test.ts +64 -6
  394. package/src/__tests__/replayable-stream.test.ts +112 -1
  395. package/src/__tests__/scope-detector.test.ts +121 -0
  396. package/src/__tests__/session-lifecycle.test.ts +259 -0
  397. package/src/__tests__/transport.test.ts +758 -0
  398. package/src/__tests__/vault-branching.test.ts +274 -0
  399. package/src/__tests__/vault-connect.test.ts +179 -0
  400. package/src/__tests__/vault-integrity.test.ts +71 -0
  401. package/src/__tests__/vault-manager.test.ts +238 -0
  402. package/src/__tests__/vault-scaling.test.ts +281 -0
  403. package/src/__tests__/vault-sharing.test.ts +270 -0
  404. package/src/__tests__/ws-transport.test.ts +479 -0
  405. package/src/agency/agency-manager.ts +326 -0
  406. package/src/agency/index.ts +13 -0
  407. package/src/agency/types.ts +88 -0
  408. package/src/brain/brain.ts +15 -11
  409. package/src/brain/intelligence.ts +103 -0
  410. package/src/brain/types.ts +26 -0
  411. package/src/chat/agent-loop-types.ts +99 -0
  412. package/src/chat/agent-loop.ts +357 -0
  413. package/src/chat/auth-manager.ts +171 -0
  414. package/src/chat/browser-session.ts +188 -0
  415. package/src/chat/cancellation.ts +99 -0
  416. package/src/chat/chat-session.ts +283 -0
  417. package/src/chat/file-handler.ts +230 -0
  418. package/src/chat/fragment-buffer.ts +160 -0
  419. package/src/chat/index.ts +72 -0
  420. package/src/chat/mcp-bridge.ts +135 -0
  421. package/src/chat/notifications.ts +164 -0
  422. package/src/chat/output-compressor.ts +116 -0
  423. package/src/chat/queue.ts +208 -0
  424. package/src/chat/response-chunker.ts +200 -0
  425. package/src/chat/self-update.ts +117 -0
  426. package/src/chat/types.ts +126 -0
  427. package/src/chat/voice.ts +134 -0
  428. package/src/claudemd/compose.ts +142 -0
  429. package/src/claudemd/index.ts +17 -0
  430. package/src/claudemd/inject.ts +170 -0
  431. package/src/claudemd/types.ts +45 -0
  432. package/src/context/context-engine.ts +302 -0
  433. package/src/context/index.ts +11 -0
  434. package/src/context/types.ts +69 -0
  435. package/src/enforcement/adapters/claude-code.ts +135 -0
  436. package/src/enforcement/adapters/index.ts +1 -0
  437. package/src/enforcement/index.ts +10 -0
  438. package/src/enforcement/registry.ts +82 -0
  439. package/src/enforcement/types.ts +56 -0
  440. package/src/facades/facade-factory.ts +138 -5
  441. package/src/facades/types.ts +21 -0
  442. package/src/health/health-registry.ts +165 -0
  443. package/src/health/index.ts +11 -0
  444. package/src/health/vault-integrity.ts +66 -0
  445. package/src/index.ts +294 -2
  446. package/src/intake/intake-pipeline.ts +1 -1
  447. package/src/intelligence/types.ts +1 -0
  448. package/src/migrations/index.ts +6 -0
  449. package/src/migrations/migration-runner.ts +185 -0
  450. package/src/packs/index.ts +20 -0
  451. package/src/packs/lockfile.ts +180 -0
  452. package/src/packs/pack-installer.ts +289 -0
  453. package/src/packs/resolver.ts +237 -0
  454. package/src/packs/types.ts +125 -0
  455. package/src/persistence/postgres-provider.ts +211 -58
  456. package/src/playbooks/index.ts +11 -0
  457. package/src/playbooks/playbook-executor.ts +301 -0
  458. package/src/plugins/index.ts +19 -0
  459. package/src/plugins/plugin-loader.ts +183 -0
  460. package/src/plugins/plugin-registry.ts +187 -0
  461. package/src/plugins/types.ts +119 -0
  462. package/src/runtime/admin-extra-ops.ts +193 -8
  463. package/src/runtime/capture-ops.ts +113 -8
  464. package/src/runtime/deprecation.ts +58 -0
  465. package/src/runtime/facades/admin-facade.ts +16 -1
  466. package/src/runtime/facades/agency-facade.ts +111 -0
  467. package/src/runtime/facades/brain-facade.ts +60 -0
  468. package/src/runtime/facades/chat-facade.ts +918 -0
  469. package/src/runtime/facades/context-facade.ts +55 -0
  470. package/src/runtime/facades/index.ts +22 -1
  471. package/src/runtime/facades/vault-facade.ts +261 -1
  472. package/src/runtime/feature-flags.ts +101 -0
  473. package/src/runtime/pack-ops.ts +85 -0
  474. package/src/runtime/playbook-ops.ts +113 -9
  475. package/src/runtime/plugin-ops.ts +258 -0
  476. package/src/runtime/runtime.ts +84 -5
  477. package/src/runtime/telemetry-ops.ts +57 -0
  478. package/src/runtime/types.ts +35 -0
  479. package/src/runtime/vault-sharing-ops.ts +372 -0
  480. package/src/streams/index.ts +1 -1
  481. package/src/streams/replayable-stream.ts +34 -3
  482. package/src/text/similarity.ts +1 -1
  483. package/src/transport/http-server.ts +269 -0
  484. package/src/transport/index.ts +48 -0
  485. package/src/transport/lsp-server.ts +401 -0
  486. package/src/transport/rate-limiter.ts +97 -0
  487. package/src/transport/session-manager.ts +120 -0
  488. package/src/transport/token-auth.ts +96 -0
  489. package/src/transport/types.ts +66 -0
  490. package/src/transport/ws-server.ts +415 -0
  491. package/src/vault/git-vault-sync.ts +318 -0
  492. package/src/vault/knowledge-review.ts +221 -0
  493. package/src/vault/obsidian-sync.ts +346 -0
  494. package/src/vault/scope-detector.ts +219 -0
  495. package/src/vault/vault-branching.ts +264 -0
  496. package/src/vault/vault-manager.ts +237 -0
  497. package/src/vault/vault-types.ts +50 -0
  498. package/src/vault/vault.ts +41 -3
  499. package/src/governance/index.ts +0 -18
@@ -0,0 +1,230 @@
1
+ /**
2
+ * File Handler — intent detection and multimodal message building for chat transports.
3
+ *
4
+ * Provides transport-agnostic utilities for handling files sent by users:
5
+ * - Intent detection: should this file be viewed (vision), read as text, or ingested?
6
+ * - Multimodal message building for Anthropic API (ImageBlock, DocumentBlock)
7
+ * - Temp file management
8
+ *
9
+ * The actual file download is transport-specific (Telegram, Discord, etc.)
10
+ * and belongs in forge templates.
11
+ */
12
+
13
+ import { mkdirSync, writeFileSync, readdirSync, rmSync, statSync } from 'node:fs';
14
+ import { join, extname } from 'node:path';
15
+
16
+ // ─── Constants ────────────────────────────────────────────────────────
17
+
18
+ /** Maximum file size in bytes (Telegram limit). */
19
+ export const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20MB
20
+
21
+ /** File extensions treated as readable text. */
22
+ export const TEXT_EXTENSIONS = new Set([
23
+ '.ts',
24
+ '.tsx',
25
+ '.js',
26
+ '.jsx',
27
+ '.py',
28
+ '.rb',
29
+ '.rs',
30
+ '.go',
31
+ '.java',
32
+ '.kt',
33
+ '.swift',
34
+ '.c',
35
+ '.cpp',
36
+ '.h',
37
+ '.cs',
38
+ '.php',
39
+ '.sh',
40
+ '.bash',
41
+ '.zsh',
42
+ '.fish',
43
+ '.md',
44
+ '.txt',
45
+ '.json',
46
+ '.yaml',
47
+ '.yml',
48
+ '.toml',
49
+ '.xml',
50
+ '.html',
51
+ '.css',
52
+ '.scss',
53
+ '.sql',
54
+ '.graphql',
55
+ '.prisma',
56
+ '.env',
57
+ '.gitignore',
58
+ '.dockerfile',
59
+ '.csv',
60
+ '.log',
61
+ ]);
62
+
63
+ /** MIME types supported for vision (ImageBlock). */
64
+ export const IMAGE_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/gif', 'image/webp']);
65
+
66
+ /** Keywords that indicate the user wants to ingest/learn from the file. */
67
+ export const INTAKE_KEYWORDS = [
68
+ 'learn',
69
+ 'ingest',
70
+ 'absorb',
71
+ 'study',
72
+ 'memorize',
73
+ 'remember',
74
+ 'read this',
75
+ 'save this',
76
+ 'store this',
77
+ 'add to vault',
78
+ 'add to knowledge',
79
+ ];
80
+
81
+ // ─── Types ────────────────────────────────────────────────────────────
82
+
83
+ export type FileIntent = 'vision' | 'text' | 'intake';
84
+
85
+ export interface FileInfo {
86
+ /** Original filename. */
87
+ name: string;
88
+ /** MIME type. */
89
+ mimeType: string;
90
+ /** File size in bytes. */
91
+ size: number;
92
+ /** File content as Buffer. */
93
+ data: Buffer;
94
+ }
95
+
96
+ export interface MultimodalContent {
97
+ type: 'image' | 'document' | 'text';
98
+ /** For image: base64 data. For document: base64 data. For text: the text content. */
99
+ content: string;
100
+ /** MIME type (for image/document). */
101
+ mimeType?: string;
102
+ /** Source filename. */
103
+ filename?: string;
104
+ }
105
+
106
+ // ─── Intent Detection ─────────────────────────────────────────────────
107
+
108
+ /**
109
+ * Detect what the user wants to do with a file based on its type and
110
+ * any accompanying text message.
111
+ */
112
+ export function detectFileIntent(
113
+ filename: string,
114
+ mimeType: string,
115
+ userText?: string,
116
+ ): FileIntent {
117
+ const ext = extname(filename).toLowerCase();
118
+ const textLower = userText?.toLowerCase() ?? '';
119
+
120
+ // Check for intake keywords first
121
+ if (userText && INTAKE_KEYWORDS.some((kw) => textLower.includes(kw))) {
122
+ return 'intake';
123
+ }
124
+
125
+ // Text files → read as text
126
+ if (TEXT_EXTENSIONS.has(ext)) {
127
+ return 'text';
128
+ }
129
+
130
+ // Images → vision
131
+ if (IMAGE_MIME_TYPES.has(mimeType) || mimeType.startsWith('image/')) {
132
+ return 'vision';
133
+ }
134
+
135
+ // PDFs → vision (DocumentBlock)
136
+ if (mimeType === 'application/pdf' || ext === '.pdf') {
137
+ return 'vision';
138
+ }
139
+
140
+ // Default: try vision
141
+ return 'vision';
142
+ }
143
+
144
+ // ─── Multimodal Message Building ──────────────────────────────────────
145
+
146
+ /**
147
+ * Build multimodal content from a file for the Anthropic API.
148
+ */
149
+ export function buildMultimodalContent(file: FileInfo, intent: FileIntent): MultimodalContent {
150
+ const ext = extname(file.name).toLowerCase();
151
+
152
+ if (intent === 'text' || TEXT_EXTENSIONS.has(ext)) {
153
+ return {
154
+ type: 'text',
155
+ content: file.data.toString('utf-8'),
156
+ filename: file.name,
157
+ };
158
+ }
159
+
160
+ if (IMAGE_MIME_TYPES.has(file.mimeType)) {
161
+ return {
162
+ type: 'image',
163
+ content: file.data.toString('base64'),
164
+ mimeType: file.mimeType,
165
+ filename: file.name,
166
+ };
167
+ }
168
+
169
+ // PDF and other documents
170
+ return {
171
+ type: 'document',
172
+ content: file.data.toString('base64'),
173
+ mimeType: file.mimeType,
174
+ filename: file.name,
175
+ };
176
+ }
177
+
178
+ // ─── Temp File Management ─────────────────────────────────────────────
179
+
180
+ /**
181
+ * Save a file to a temp directory with timestamp prefix.
182
+ * Returns the full path.
183
+ */
184
+ export function saveTempFile(uploadDir: string, filename: string, data: Buffer): string {
185
+ mkdirSync(uploadDir, { recursive: true });
186
+ const safeName = filename.replace(/[^\w.-]/g, '_');
187
+ const path = join(uploadDir, `${Date.now()}-${safeName}`);
188
+ writeFileSync(path, data);
189
+ return path;
190
+ }
191
+
192
+ /**
193
+ * Clean up temp files older than maxAgeMs.
194
+ */
195
+ export function cleanupTempFiles(uploadDir: string, maxAgeMs: number = 3_600_000): number {
196
+ let removed = 0;
197
+ try {
198
+ const cutoff = Date.now() - maxAgeMs;
199
+ const files = readdirSync(uploadDir);
200
+ for (const file of files) {
201
+ const filePath = join(uploadDir, file);
202
+ try {
203
+ const stat = statSync(filePath);
204
+ if (stat.mtimeMs < cutoff) {
205
+ rmSync(filePath);
206
+ removed++;
207
+ }
208
+ } catch {
209
+ // Skip files we can't stat
210
+ }
211
+ }
212
+ } catch {
213
+ // Directory doesn't exist or can't be read
214
+ }
215
+ return removed;
216
+ }
217
+
218
+ /**
219
+ * Strip base64 data from multimodal content for session persistence.
220
+ * Replaces binary content with a size placeholder to prevent session bloat.
221
+ */
222
+ export function sanitizeForPersistence(content: MultimodalContent): MultimodalContent {
223
+ if (content.type === 'text') return content;
224
+
225
+ const sizeKb = Math.round(Buffer.byteLength(content.content, 'base64') / 1024);
226
+ return {
227
+ ...content,
228
+ content: `[${content.type}: ${content.filename ?? 'file'}, ${sizeKb}KB]`,
229
+ };
230
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Fragment Buffer — merges split messages from chat platforms.
3
+ *
4
+ * Telegram, Discord, and other platforms split long pastes into multiple
5
+ * messages (e.g. Telegram's 4096 char limit). This buffer detects near-limit
6
+ * messages and waits briefly for follow-up parts before flushing as one unit.
7
+ *
8
+ * Ported from Salvador's handler-messages.ts with improvements:
9
+ * - Transport-agnostic (works for any chat platform)
10
+ * - Callback-based flush (no transport dependency)
11
+ * - Configurable thresholds
12
+ */
13
+
14
+ import type { Fragment, FragmentBufferConfig } from './types.js';
15
+
16
+ const DEFAULT_START_THRESHOLD = 4000;
17
+ const DEFAULT_MAX_GAP_MS = 1500;
18
+ const DEFAULT_MAX_PARTS = 12;
19
+ const DEFAULT_MAX_TOTAL_BYTES = 50_000;
20
+
21
+ interface PendingBuffer {
22
+ key: string;
23
+ fragments: Fragment[];
24
+ totalBytes: number;
25
+ timer: ReturnType<typeof setTimeout>;
26
+ }
27
+
28
+ export class FragmentBuffer {
29
+ private buffers = new Map<string, PendingBuffer>();
30
+ private config: Required<FragmentBufferConfig>;
31
+ private onFlush: (key: string, merged: string) => void;
32
+
33
+ constructor(
34
+ config: FragmentBufferConfig | undefined,
35
+ onFlush: (key: string, merged: string) => void,
36
+ ) {
37
+ this.config = {
38
+ startThreshold: config?.startThreshold ?? DEFAULT_START_THRESHOLD,
39
+ maxGapMs: config?.maxGapMs ?? DEFAULT_MAX_GAP_MS,
40
+ maxParts: config?.maxParts ?? DEFAULT_MAX_PARTS,
41
+ maxTotalBytes: config?.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES,
42
+ };
43
+ this.onFlush = onFlush;
44
+ }
45
+
46
+ /**
47
+ * Receive a message. Returns true if the message was buffered (caller should wait),
48
+ * false if the message should be processed immediately.
49
+ */
50
+ receive(key: string, fragment: Fragment): boolean {
51
+ const existing = this.buffers.get(key);
52
+
53
+ if (existing) {
54
+ // Append to existing buffer
55
+ return this.appendToBuffer(existing, fragment);
56
+ }
57
+
58
+ // Check if this message is long enough to start buffering
59
+ if (fragment.text.length >= this.config.startThreshold) {
60
+ this.startBuffer(key, fragment);
61
+ return true;
62
+ }
63
+
64
+ // Short message — process immediately
65
+ return false;
66
+ }
67
+
68
+ /**
69
+ * Force-flush a specific buffer. Returns the merged text or null if no buffer.
70
+ */
71
+ flush(key: string): string | null {
72
+ const buffer = this.buffers.get(key);
73
+ if (!buffer) return null;
74
+
75
+ clearTimeout(buffer.timer);
76
+ const merged = this.mergeFragments(buffer.fragments);
77
+ this.buffers.delete(key);
78
+ return merged;
79
+ }
80
+
81
+ /**
82
+ * Force-flush all pending buffers.
83
+ */
84
+ flushAll(): void {
85
+ for (const [key, buffer] of this.buffers) {
86
+ clearTimeout(buffer.timer);
87
+ const merged = this.mergeFragments(buffer.fragments);
88
+ this.buffers.delete(key);
89
+ this.onFlush(key, merged);
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Number of keys with pending fragments.
95
+ */
96
+ get pendingCount(): number {
97
+ return this.buffers.size;
98
+ }
99
+
100
+ /**
101
+ * Check if a key has pending fragments.
102
+ */
103
+ hasPending(key: string): boolean {
104
+ return this.buffers.has(key);
105
+ }
106
+
107
+ /**
108
+ * Close the buffer — flush all and clean up timers.
109
+ */
110
+ close(): void {
111
+ for (const buffer of this.buffers.values()) {
112
+ clearTimeout(buffer.timer);
113
+ }
114
+ this.buffers.clear();
115
+ }
116
+
117
+ // ─── Private ───────────────────────────────────────────────────
118
+
119
+ private startBuffer(key: string, fragment: Fragment): void {
120
+ const timer = setTimeout(() => this.autoFlush(key), this.config.maxGapMs);
121
+ this.buffers.set(key, {
122
+ key,
123
+ fragments: [fragment],
124
+ totalBytes: fragment.text.length,
125
+ timer,
126
+ });
127
+ }
128
+
129
+ private appendToBuffer(buffer: PendingBuffer, fragment: Fragment): boolean {
130
+ const newTotal = buffer.totalBytes + fragment.text.length;
131
+
132
+ // Force-flush if limits exceeded
133
+ if (buffer.fragments.length >= this.config.maxParts || newTotal > this.config.maxTotalBytes) {
134
+ this.autoFlush(buffer.key);
135
+ // The new fragment starts fresh — don't buffer it
136
+ return false;
137
+ }
138
+
139
+ // Append and reset timer
140
+ clearTimeout(buffer.timer);
141
+ buffer.fragments.push(fragment);
142
+ buffer.totalBytes = newTotal;
143
+ buffer.timer = setTimeout(() => this.autoFlush(buffer.key), this.config.maxGapMs);
144
+ return true;
145
+ }
146
+
147
+ private autoFlush(key: string): void {
148
+ const buffer = this.buffers.get(key);
149
+ if (!buffer) return;
150
+
151
+ clearTimeout(buffer.timer);
152
+ const merged = this.mergeFragments(buffer.fragments);
153
+ this.buffers.delete(key);
154
+ this.onFlush(key, merged);
155
+ }
156
+
157
+ private mergeFragments(fragments: Fragment[]): string {
158
+ return fragments.map((f) => f.text).join('\n');
159
+ }
160
+ }
@@ -0,0 +1,72 @@
1
+ export { ChatSessionManager } from './chat-session.js';
2
+ export { FragmentBuffer } from './fragment-buffer.js';
3
+ export { ChatAuthManager } from './auth-manager.js';
4
+ export { TaskCancellationManager } from './cancellation.js';
5
+ export { SelfUpdateManager, RESTART_EXIT_CODE } from './self-update.js';
6
+ export { NotificationEngine } from './notifications.js';
7
+ export {
8
+ detectFileIntent,
9
+ buildMultimodalContent,
10
+ saveTempFile,
11
+ cleanupTempFiles,
12
+ sanitizeForPersistence,
13
+ MAX_FILE_SIZE,
14
+ TEXT_EXTENSIONS,
15
+ IMAGE_MIME_TYPES,
16
+ INTAKE_KEYWORDS,
17
+ } from './file-handler.js';
18
+ export { transcribeAudio, synthesizeSpeech } from './voice.js';
19
+ export { MessageQueue } from './queue.js';
20
+ export { BrowserSessionManager } from './browser-session.js';
21
+ export { chunkResponse, convertMarkup, markdownToHtml } from './response-chunker.js';
22
+ export { runAgentLoop } from './agent-loop.js';
23
+ export { McpToolBridge } from './mcp-bridge.js';
24
+ export {
25
+ createOutputCompressor,
26
+ registerCompressor,
27
+ clearCompressors,
28
+ } from './output-compressor.js';
29
+
30
+ export type {
31
+ ChatRole,
32
+ ChatMessage,
33
+ ChatSession,
34
+ ChatSessionConfig,
35
+ Fragment,
36
+ FragmentBufferConfig,
37
+ MarkupFormat,
38
+ ChunkConfig,
39
+ ChatAuthConfig,
40
+ AuthRecord,
41
+ AuthState,
42
+ ChatManagerConfig,
43
+ ChatManagerStatus,
44
+ } from './types.js';
45
+
46
+ export type {
47
+ AgentTool,
48
+ ToolResult,
49
+ ToolExecutor,
50
+ AgentLoopConfig,
51
+ AgentCallbacks,
52
+ AgentLoopResult,
53
+ McpToolRegistration,
54
+ OutputCompressor,
55
+ } from './agent-loop-types.js';
56
+
57
+ export type { CancellationInfo } from './cancellation.js';
58
+ export type { RestartContext, RestartResult } from './self-update.js';
59
+ export type {
60
+ NotificationCheck,
61
+ NotificationEngineConfig,
62
+ NotificationStats,
63
+ } from './notifications.js';
64
+ export type { FileIntent, FileInfo, MultimodalContent } from './file-handler.js';
65
+ export type { VoiceConfig, TranscriptionResult, SpeechResult } from './voice.js';
66
+ export type { QueuedMessage, QueuedResponse, QueueConfig } from './queue.js';
67
+ export type {
68
+ BrowserSessionConfig,
69
+ BrowserSession,
70
+ BrowserTool,
71
+ BrowserToolResult,
72
+ } from './browser-session.js';
@@ -0,0 +1,135 @@
1
+ /**
2
+ * MCP Tool Bridge — intercepts MCP tool registrations and executes locally.
3
+ *
4
+ * Ported from Salvador's mcp-bridge.ts with improvements:
5
+ * - Simpler API (no Zod dependency — accepts JSON Schema directly)
6
+ * - Optional allowlist for tool filtering
7
+ * - Generic output compression hook
8
+ *
9
+ * Used by Telegram (and other chat transports) to bridge the agent's MCP tools
10
+ * into the agent loop without network round-trips.
11
+ */
12
+
13
+ import type {
14
+ AgentTool,
15
+ ToolResult,
16
+ McpToolRegistration,
17
+ OutputCompressor,
18
+ } from './agent-loop-types.js';
19
+
20
+ const DEFAULT_MAX_OUTPUT = 10_000; // 10KB
21
+
22
+ export class McpToolBridge {
23
+ private tools = new Map<string, McpToolRegistration>();
24
+ private allowlist: Set<string> | null;
25
+ private compressor: OutputCompressor | null;
26
+ private maxOutput: number;
27
+
28
+ constructor(options?: {
29
+ allowlist?: string[];
30
+ compressor?: OutputCompressor;
31
+ maxOutput?: number;
32
+ }) {
33
+ this.allowlist = options?.allowlist ? new Set(options.allowlist) : null;
34
+ this.compressor = options?.compressor ?? null;
35
+ this.maxOutput = options?.maxOutput ?? DEFAULT_MAX_OUTPUT;
36
+ }
37
+
38
+ /**
39
+ * Register a tool. If an allowlist is set, only allowed tools are registered.
40
+ */
41
+ register(tool: McpToolRegistration): void {
42
+ if (this.allowlist && !this.allowlist.has(tool.name)) return;
43
+ this.tools.set(tool.name, tool);
44
+ }
45
+
46
+ /**
47
+ * Register multiple tools at once.
48
+ */
49
+ registerAll(tools: McpToolRegistration[]): void {
50
+ for (const tool of tools) {
51
+ this.register(tool);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Check if a tool is registered.
57
+ */
58
+ has(name: string): boolean {
59
+ return this.tools.has(name);
60
+ }
61
+
62
+ /**
63
+ * Get registered tools as AgentTool array (for the agent loop).
64
+ */
65
+ getTools(): AgentTool[] {
66
+ return [...this.tools.values()].map((t) => ({
67
+ name: t.name,
68
+ description: t.description,
69
+ inputSchema: t.inputSchema,
70
+ }));
71
+ }
72
+
73
+ /**
74
+ * Execute a tool by name.
75
+ */
76
+ async execute(name: string, input: Record<string, unknown>): Promise<ToolResult> {
77
+ const tool = this.tools.get(name);
78
+ if (!tool) {
79
+ return {
80
+ output: `Unknown tool: ${name}`,
81
+ isError: true,
82
+ };
83
+ }
84
+
85
+ try {
86
+ const rawResult = await tool.handler(input);
87
+ let output = typeof rawResult === 'string' ? rawResult : JSON.stringify(rawResult);
88
+
89
+ // Apply compression if available
90
+ if (this.compressor) {
91
+ output = this.compressor(name, output, this.maxOutput);
92
+ }
93
+
94
+ // Truncate if still too long
95
+ if (output.length > this.maxOutput) {
96
+ output = output.slice(0, this.maxOutput) + `\n... (truncated at ${this.maxOutput} chars)`;
97
+ }
98
+
99
+ return { output, isError: false };
100
+ } catch (error) {
101
+ return {
102
+ output: `Tool error: ${error instanceof Error ? error.message : String(error)}`,
103
+ isError: true,
104
+ };
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Create a ToolExecutor function for use with the agent loop.
110
+ */
111
+ createExecutor(): (name: string, input: Record<string, unknown>) => Promise<ToolResult> {
112
+ return (name, input) => this.execute(name, input);
113
+ }
114
+
115
+ /**
116
+ * Number of registered tools.
117
+ */
118
+ get size(): number {
119
+ return this.tools.size;
120
+ }
121
+
122
+ /**
123
+ * List registered tool names.
124
+ */
125
+ listTools(): string[] {
126
+ return [...this.tools.keys()];
127
+ }
128
+
129
+ /**
130
+ * Clear all registered tools.
131
+ */
132
+ clear(): void {
133
+ this.tools.clear();
134
+ }
135
+ }