@animalabs/agent-framework 0.22.1 → 0.22.2

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 (359) hide show
  1. package/README.md +1 -1
  2. package/dist/src/agent.d.ts +192 -19
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +404 -65
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.d.ts +41 -0
  7. package/dist/src/api/mcp-server-core.d.ts.map +1 -0
  8. package/dist/src/api/mcp-server-core.js +593 -0
  9. package/dist/src/api/mcp-server-core.js.map +1 -0
  10. package/dist/src/api/mcp-server.d.ts +2 -36
  11. package/dist/src/api/mcp-server.d.ts.map +1 -1
  12. package/dist/src/api/mcp-server.js +15 -595
  13. package/dist/src/api/mcp-server.js.map +1 -1
  14. package/dist/src/api/server.d.ts +9 -1
  15. package/dist/src/api/server.d.ts.map +1 -1
  16. package/dist/src/api/server.js +50 -26
  17. package/dist/src/api/server.js.map +1 -1
  18. package/dist/src/api/types.d.ts +9 -1
  19. package/dist/src/api/types.d.ts.map +1 -1
  20. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  21. package/dist/src/code-execution/py-runner.js.map +1 -1
  22. package/dist/src/framework.d.ts +393 -113
  23. package/dist/src/framework.d.ts.map +1 -1
  24. package/dist/src/framework.js +1748 -582
  25. package/dist/src/framework.js.map +1 -1
  26. package/dist/src/gate/event-gate.d.ts.map +1 -1
  27. package/dist/src/gate/gate-script.d.ts.map +1 -1
  28. package/dist/src/gate/gate-script.js.map +1 -1
  29. package/dist/src/index.d.ts +2 -2
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js +2 -2
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
  34. package/dist/src/mcpl/channel-registry.d.ts +26 -7
  35. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  36. package/dist/src/mcpl/channel-registry.js +102 -22
  37. package/dist/src/mcpl/channel-registry.js.map +1 -1
  38. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  39. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  40. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  41. package/dist/src/mcpl/errors.js.map +1 -1
  42. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  43. package/dist/src/mcpl/feature-set-manager.js +4 -3
  44. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  45. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  46. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  47. package/dist/src/mcpl/log-value.d.ts +54 -0
  48. package/dist/src/mcpl/log-value.d.ts.map +1 -0
  49. package/dist/src/mcpl/log-value.js +109 -0
  50. package/dist/src/mcpl/log-value.js.map +1 -0
  51. package/dist/src/mcpl/prose-stream-router.d.ts +6 -6
  52. package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -1
  53. package/dist/src/mcpl/prose-stream-router.js +4 -4
  54. package/dist/src/mcpl/prose-stream-router.js.map +1 -1
  55. package/dist/src/mcpl/push-coalescer.d.ts +38 -3
  56. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  57. package/dist/src/mcpl/push-coalescer.js +81 -16
  58. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  59. package/dist/src/mcpl/push-handler.d.ts +26 -3
  60. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  61. package/dist/src/mcpl/push-handler.js +87 -23
  62. package/dist/src/mcpl/push-handler.js.map +1 -1
  63. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  64. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  65. package/dist/src/mcpl/references.d.ts +2 -2
  66. package/dist/src/mcpl/references.d.ts.map +1 -1
  67. package/dist/src/mcpl/references.js.map +1 -1
  68. package/dist/src/mcpl/refusal-lines.d.ts +37 -0
  69. package/dist/src/mcpl/refusal-lines.d.ts.map +1 -0
  70. package/dist/src/mcpl/refusal-lines.js +61 -0
  71. package/dist/src/mcpl/refusal-lines.js.map +1 -0
  72. package/dist/src/mcpl/scope-manager.d.ts.map +1 -1
  73. package/dist/src/mcpl/server-connection.d.ts +18 -2
  74. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  75. package/dist/src/mcpl/server-connection.js +66 -11
  76. package/dist/src/mcpl/server-connection.js.map +1 -1
  77. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  78. package/dist/src/mcpl/tool-classes.d.ts +1 -1
  79. package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
  80. package/dist/src/mcpl/tool-classes.js +3 -2
  81. package/dist/src/mcpl/tool-classes.js.map +1 -1
  82. package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
  83. package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
  84. package/dist/src/mcpl/transport.d.ts +23 -5
  85. package/dist/src/mcpl/transport.d.ts.map +1 -1
  86. package/dist/src/mcpl/transport.js +103 -10
  87. package/dist/src/mcpl/transport.js.map +1 -1
  88. package/dist/src/mcpl/types.d.ts +30 -26
  89. package/dist/src/mcpl/types.d.ts.map +1 -1
  90. package/dist/src/mcpl/types.js.map +1 -1
  91. package/dist/src/module-registry.d.ts.map +1 -1
  92. package/dist/src/module-registry.js.map +1 -1
  93. package/dist/src/modules/api/index.d.ts.map +1 -1
  94. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  95. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  96. package/dist/src/modules/discord/index.d.ts.map +1 -1
  97. package/dist/src/modules/discord/index.js +4 -2
  98. package/dist/src/modules/discord/index.js.map +1 -1
  99. package/dist/src/modules/health/index.d.ts.map +1 -1
  100. package/dist/src/modules/health/index.js.map +1 -1
  101. package/dist/src/modules/history/index.d.ts.map +1 -1
  102. package/dist/src/modules/history/index.js.map +1 -1
  103. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  104. package/dist/src/modules/history/semantic.js.map +1 -1
  105. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  106. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  107. package/dist/src/modules/workspace/disk-agreement.d.ts +22 -4
  108. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  109. package/dist/src/modules/workspace/disk-agreement.js +63 -25
  110. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  111. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  112. package/dist/src/modules/workspace/index.d.ts +8 -4
  113. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  114. package/dist/src/modules/workspace/index.js +39 -12
  115. package/dist/src/modules/workspace/index.js.map +1 -1
  116. package/dist/src/modules/workspace/observe.d.ts +43 -8
  117. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  118. package/dist/src/modules/workspace/observe.js +264 -39
  119. package/dist/src/modules/workspace/observe.js.map +1 -1
  120. package/dist/src/modules/workspace/reconcile.d.ts +17 -1
  121. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  122. package/dist/src/modules/workspace/reconcile.js +57 -14
  123. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  124. package/dist/src/modules/workspace/types.d.ts +27 -2
  125. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  126. package/dist/src/modules/workspace/types.js.map +1 -1
  127. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  128. package/dist/src/modules/workspace/watcher.js.map +1 -1
  129. package/dist/src/operator-log.d.ts.map +1 -1
  130. package/dist/src/operator-log.js.map +1 -1
  131. package/dist/src/provider-waits.d.ts.map +1 -1
  132. package/dist/src/provider-waits.js.map +1 -1
  133. package/dist/src/queue.d.ts.map +1 -1
  134. package/dist/src/record-journal.d.ts.map +1 -1
  135. package/dist/src/record-journal.js.map +1 -1
  136. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  137. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  138. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  139. package/dist/src/recovery/offline-branch.js +29 -24
  140. package/dist/src/recovery/offline-branch.js.map +1 -1
  141. package/dist/src/recovery/recover-cli.js.map +1 -1
  142. package/dist/src/runtime/liveness-watchdog.d.ts.map +1 -1
  143. package/dist/src/runtime/liveness-watchdog.js.map +1 -1
  144. package/dist/src/shutdown.d.ts.map +1 -1
  145. package/dist/src/shutdown.js.map +1 -1
  146. package/dist/src/stored-removal.d.ts +73 -0
  147. package/dist/src/stored-removal.d.ts.map +1 -0
  148. package/dist/src/stored-removal.js +100 -0
  149. package/dist/src/stored-removal.js.map +1 -0
  150. package/dist/src/thinking-token-stamp.js.map +1 -1
  151. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  152. package/dist/src/tool-image-ledger.js.map +1 -1
  153. package/dist/src/tool-presentation.d.ts.map +1 -1
  154. package/dist/src/tool-presentation.js.map +1 -1
  155. package/dist/src/tool-result-guard.d.ts.map +1 -1
  156. package/dist/src/tool-result-guard.js.map +1 -1
  157. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  158. package/dist/src/tune-out/coordinator.js.map +1 -1
  159. package/dist/src/tune-out/tools.d.ts +1 -1
  160. package/dist/src/tune-out/tools.d.ts.map +1 -1
  161. package/dist/src/types/agent.d.ts +42 -6
  162. package/dist/src/types/agent.d.ts.map +1 -1
  163. package/dist/src/types/framework.d.ts +10 -0
  164. package/dist/src/types/framework.d.ts.map +1 -1
  165. package/dist/src/types/module.d.ts +8 -4
  166. package/dist/src/types/module.d.ts.map +1 -1
  167. package/dist/src/types/trace.d.ts +61 -10
  168. package/dist/src/types/trace.d.ts.map +1 -1
  169. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  170. package/dist/test/agent-runtime-settings.test.js +1139 -3
  171. package/dist/test/agent-runtime-settings.test.js.map +1 -1
  172. package/dist/test/batched-wake-locus.test.js.map +1 -1
  173. package/dist/test/channel-label-history.test.js.map +1 -1
  174. package/dist/test/code-execution.test.js.map +1 -1
  175. package/dist/test/conversation-fork-injection-scoping.test.js.map +1 -1
  176. package/dist/test/conversation-router.test.js.map +1 -1
  177. package/dist/test/conversation-routing.test.js +240 -6
  178. package/dist/test/conversation-routing.test.js.map +1 -1
  179. package/dist/test/discord-awareness-outbox.test.js +104 -0
  180. package/dist/test/discord-awareness-outbox.test.js.map +1 -1
  181. package/dist/test/discord-typing-keepalive.test.d.ts +2 -0
  182. package/dist/test/discord-typing-keepalive.test.d.ts.map +1 -0
  183. package/dist/test/discord-typing-keepalive.test.js +77 -0
  184. package/dist/test/discord-typing-keepalive.test.js.map +1 -0
  185. package/dist/test/ephemeral-settle.test.js.map +1 -1
  186. package/dist/test/event-gate-passthrough.test.js.map +1 -1
  187. package/dist/test/event-gate-policy-mutation.test.js.map +1 -1
  188. package/dist/test/event-gate-rate-limit.test.js.map +1 -1
  189. package/dist/test/event-gate-script.test.js.map +1 -1
  190. package/dist/test/event-gate-selfwake.test.js.map +1 -1
  191. package/dist/test/event-gate-tags.test.js.map +1 -1
  192. package/dist/test/event-gate.test.js.map +1 -1
  193. package/dist/test/explicit-prose-routing.test.js +363 -42
  194. package/dist/test/explicit-prose-routing.test.js.map +1 -1
  195. package/dist/test/framework.test.js.map +1 -1
  196. package/dist/test/helpers/coalescing-fixture.d.ts +2 -0
  197. package/dist/test/helpers/coalescing-fixture.d.ts.map +1 -1
  198. package/dist/test/helpers/coalescing-fixture.js +8 -2
  199. package/dist/test/helpers/coalescing-fixture.js.map +1 -1
  200. package/dist/test/helpers/mock-membrane.d.ts.map +1 -1
  201. package/dist/test/helpers/mock-membrane.js.map +1 -1
  202. package/dist/test/hide-then-turn.test.d.ts +2 -0
  203. package/dist/test/hide-then-turn.test.d.ts.map +1 -0
  204. package/dist/test/hide-then-turn.test.js +101 -0
  205. package/dist/test/hide-then-turn.test.js.map +1 -0
  206. package/dist/test/history-module-overview.test.js.map +1 -1
  207. package/dist/test/history-module-semantic.test.js.map +1 -1
  208. package/dist/test/history-module.test.js.map +1 -1
  209. package/dist/test/history-semantic-review-findings.test.js.map +1 -1
  210. package/dist/test/host-quiesce.test.js +125 -0
  211. package/dist/test/host-quiesce.test.js.map +1 -1
  212. package/dist/test/inference-exhaustion-rewind.test.js +81 -3
  213. package/dist/test/inference-exhaustion-rewind.test.js.map +1 -1
  214. package/dist/test/inference-failure-bounds.test.js +1 -0
  215. package/dist/test/inference-failure-bounds.test.js.map +1 -1
  216. package/dist/test/kv-unified-open-flight-retry.test.js.map +1 -1
  217. package/dist/test/liveness-watchdog.test.js.map +1 -1
  218. package/dist/test/maintenance-timer.test.js +1564 -2
  219. package/dist/test/maintenance-timer.test.js.map +1 -1
  220. package/dist/test/mcp-server-bin.test.d.ts +2 -0
  221. package/dist/test/mcp-server-bin.test.d.ts.map +1 -0
  222. package/dist/test/mcp-server-bin.test.js +142 -0
  223. package/dist/test/mcp-server-bin.test.js.map +1 -0
  224. package/dist/test/mcpl-awareness-barrier.test.js.map +1 -1
  225. package/dist/test/mcpl-child-env.test.js +1 -1
  226. package/dist/test/mcpl-child-env.test.js.map +1 -1
  227. package/dist/test/mcpl-coalesced-content-parity.test.d.ts +2 -0
  228. package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +1 -0
  229. package/dist/test/mcpl-coalesced-content-parity.test.js +532 -0
  230. package/dist/test/mcpl-coalesced-content-parity.test.js.map +1 -0
  231. package/dist/test/mcpl-coalescing.test.js.map +1 -1
  232. package/dist/test/mcpl-config-diagnostics.test.js.map +1 -1
  233. package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -1
  234. package/dist/test/mcpl-manifest-changed.test.js.map +1 -1
  235. package/dist/test/mcpl-reconnect-events.test.js.map +1 -1
  236. package/dist/test/mcpl-reconnect-reregistration.test.js +2 -0
  237. package/dist/test/mcpl-reconnect-reregistration.test.js.map +1 -1
  238. package/dist/test/mcpl-reference-fetcher.test.js.map +1 -1
  239. package/dist/test/mcpl-reference-fields.test.js.map +1 -1
  240. package/dist/test/mcpl-rejection-log-lines.test.d.ts +2 -0
  241. package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +1 -0
  242. package/dist/test/mcpl-rejection-log-lines.test.js +349 -0
  243. package/dist/test/mcpl-rejection-log-lines.test.js.map +1 -0
  244. package/dist/test/mcpl-stderr-tail.test.d.ts +2 -0
  245. package/dist/test/mcpl-stderr-tail.test.d.ts.map +1 -0
  246. package/dist/test/mcpl-stderr-tail.test.js +210 -0
  247. package/dist/test/mcpl-stderr-tail.test.js.map +1 -0
  248. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +1 -1
  249. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +1 -1
  250. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +1 -1
  251. package/dist/test/mcpl-tool-lifecycle.test.js.map +1 -1
  252. package/dist/test/mcpl-transport-close.test.d.ts +2 -0
  253. package/dist/test/mcpl-transport-close.test.d.ts.map +1 -0
  254. package/dist/test/mcpl-transport-close.test.js +373 -0
  255. package/dist/test/mcpl-transport-close.test.js.map +1 -0
  256. package/dist/test/mcpl-transport-spawn.test.d.ts +2 -0
  257. package/dist/test/mcpl-transport-spawn.test.d.ts.map +1 -0
  258. package/dist/test/mcpl-transport-spawn.test.js +58 -0
  259. package/dist/test/mcpl-transport-spawn.test.js.map +1 -0
  260. package/dist/test/mcpl-ws-transport.test.js +1 -0
  261. package/dist/test/mcpl-ws-transport.test.js.map +1 -1
  262. package/dist/test/offline-recovery-branch.test.js +344 -0
  263. package/dist/test/offline-recovery-branch.test.js.map +1 -1
  264. package/dist/test/operator-surgery.test.js +197 -0
  265. package/dist/test/operator-surgery.test.js.map +1 -1
  266. package/dist/test/overbudget-drain-breaker.test.js +1 -0
  267. package/dist/test/overbudget-drain-breaker.test.js.map +1 -1
  268. package/dist/test/pack-installs-alone.test.d.ts +2 -0
  269. package/dist/test/pack-installs-alone.test.d.ts.map +1 -0
  270. package/dist/test/pack-installs-alone.test.js +284 -0
  271. package/dist/test/pack-installs-alone.test.js.map +1 -0
  272. package/dist/test/physical-window-restart.test.d.ts +6 -4
  273. package/dist/test/physical-window-restart.test.d.ts.map +1 -1
  274. package/dist/test/physical-window-restart.test.js +275 -10
  275. package/dist/test/physical-window-restart.test.js.map +1 -1
  276. package/dist/test/placed-reaction-baseline.test.js.map +1 -1
  277. package/dist/test/present-while-acting.test.js +949 -6
  278. package/dist/test/present-while-acting.test.js.map +1 -1
  279. package/dist/test/provider-acceleration-cooldown.test.js.map +1 -1
  280. package/dist/test/provider-waits.test.js +67 -4
  281. package/dist/test/provider-waits.test.js.map +1 -1
  282. package/dist/test/puppet-tool-call.test.js +2 -0
  283. package/dist/test/puppet-tool-call.test.js.map +1 -1
  284. package/dist/test/reaction-baseline-platform.test.js.map +1 -1
  285. package/dist/test/record-journal.test.js.map +1 -1
  286. package/dist/test/refusal-rewind.test.js +9 -0
  287. package/dist/test/refusal-rewind.test.js.map +1 -1
  288. package/dist/test/refusal-single-call.test.js.map +1 -1
  289. package/dist/test/release-bump.test.d.ts +2 -0
  290. package/dist/test/release-bump.test.d.ts.map +1 -0
  291. package/dist/test/release-bump.test.js +248 -0
  292. package/dist/test/release-bump.test.js.map +1 -0
  293. package/dist/test/release-changelog.test.js.map +1 -1
  294. package/dist/test/release-holds.test.d.ts +2 -0
  295. package/dist/test/release-holds.test.d.ts.map +1 -0
  296. package/dist/test/release-holds.test.js +456 -0
  297. package/dist/test/release-holds.test.js.map +1 -0
  298. package/dist/test/same-round-think-policy.test.js.map +1 -1
  299. package/dist/test/shutdown-errors.test.js.map +1 -1
  300. package/dist/test/silent-heartbeat-rows.test.js.map +1 -1
  301. package/dist/test/stop-with-host-operations.test.d.ts +20 -0
  302. package/dist/test/stop-with-host-operations.test.d.ts.map +1 -0
  303. package/dist/test/stop-with-host-operations.test.js +1174 -0
  304. package/dist/test/stop-with-host-operations.test.js.map +1 -0
  305. package/dist/test/stop-with-work-in-flight.test.js +162 -50
  306. package/dist/test/stop-with-work-in-flight.test.js.map +1 -1
  307. package/dist/test/surgery-marks-receipt.test.js.map +1 -1
  308. package/dist/test/tool-batch-hook.test.js.map +1 -1
  309. package/dist/test/tool-result-guard.test.js +131 -9
  310. package/dist/test/tool-result-guard.test.js.map +1 -1
  311. package/dist/test/tool-result-spill.test.js.map +1 -1
  312. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +1 -1
  313. package/dist/test/trunk-channel-routing.test.js +330 -7
  314. package/dist/test/trunk-channel-routing.test.js.map +1 -1
  315. package/dist/test/tune-out-e2e.test.js.map +1 -1
  316. package/dist/test/unconvertible-tool-result.test.js.map +1 -1
  317. package/dist/test/unsent-compiles.test.d.ts +2 -0
  318. package/dist/test/unsent-compiles.test.d.ts.map +1 -0
  319. package/dist/test/unsent-compiles.test.js +139 -0
  320. package/dist/test/unsent-compiles.test.js.map +1 -0
  321. package/dist/test/workspace-branch-continuation.test.js.map +1 -1
  322. package/dist/test/workspace-materialize-freshness.test.js.map +1 -1
  323. package/dist/test/workspace-read-text.test.js.map +1 -1
  324. package/dist/test/workspace-three-way.test.js +907 -7
  325. package/dist/test/workspace-three-way.test.js.map +1 -1
  326. package/dist/test/workspace-watcher.test.js.map +1 -1
  327. package/dist/test/xml-round-persist.test.js.map +1 -1
  328. package/dist/tsconfig.tsbuildinfo +1 -1
  329. package/package.json +8 -6
  330. package/src/agent.ts +411 -66
  331. package/src/api/mcp-server-core.ts +681 -0
  332. package/src/api/mcp-server.ts +16 -685
  333. package/src/api/server.ts +51 -29
  334. package/src/api/types.ts +9 -1
  335. package/src/framework.ts +1899 -641
  336. package/src/index.ts +2 -2
  337. package/src/mcpl/channel-registry.ts +126 -31
  338. package/src/mcpl/feature-set-manager.ts +4 -3
  339. package/src/mcpl/log-value.ts +116 -0
  340. package/src/mcpl/prose-stream-router.ts +6 -6
  341. package/src/mcpl/push-coalescer.ts +76 -12
  342. package/src/mcpl/push-handler.ts +95 -23
  343. package/src/mcpl/refusal-lines.ts +59 -0
  344. package/src/mcpl/server-connection.ts +70 -11
  345. package/src/mcpl/tool-classes.ts +3 -2
  346. package/src/mcpl/transport.ts +105 -14
  347. package/src/mcpl/types.ts +5 -1
  348. package/src/modules/discord/index.ts +4 -2
  349. package/src/modules/workspace/disk-agreement.ts +74 -18
  350. package/src/modules/workspace/index.ts +41 -11
  351. package/src/modules/workspace/observe.ts +265 -39
  352. package/src/modules/workspace/reconcile.ts +71 -14
  353. package/src/modules/workspace/types.ts +26 -1
  354. package/src/recovery/offline-branch.ts +32 -28
  355. package/src/stored-removal.ts +126 -0
  356. package/src/types/agent.ts +42 -6
  357. package/src/types/framework.ts +10 -0
  358. package/src/types/module.ts +8 -4
  359. package/src/types/trace.ts +62 -11
@@ -0,0 +1,681 @@
1
+ /**
2
+ * MCP Server for Claude Code integration
3
+ *
4
+ * Exposes agent framework capabilities as MCP tools that can be called
5
+ * from Claude Code or other MCP clients.
6
+ *
7
+ * Communicates with the WebSocket API server to perform operations.
8
+ *
9
+ * This module only defines the server, so importing or bundling the package
10
+ * never starts one. The `agent-framework-mcp` command, ./mcp-server.ts,
11
+ * starts it.
12
+ */
13
+
14
+ import WebSocket from 'ws';
15
+ import { createInterface } from 'node:readline';
16
+ import type { ApiRequest, ApiResponse, ApiEvent } from './types.js';
17
+
18
+ // ============================================================================
19
+ // MCP Protocol Types
20
+ // ============================================================================
21
+
22
+ interface JsonRpcRequest {
23
+ jsonrpc: '2.0';
24
+ id: string | number;
25
+ method: string;
26
+ params?: unknown;
27
+ }
28
+
29
+ interface JsonRpcResponse {
30
+ jsonrpc: '2.0';
31
+ id: string | number | null;
32
+ result?: unknown;
33
+ error?: {
34
+ code: number;
35
+ message: string;
36
+ data?: unknown;
37
+ };
38
+ }
39
+
40
+ interface JsonRpcNotification {
41
+ jsonrpc: '2.0';
42
+ method: string;
43
+ params?: unknown;
44
+ }
45
+
46
+ interface McpTool {
47
+ name: string;
48
+ description: string;
49
+ inputSchema: {
50
+ type: 'object';
51
+ properties: Record<string, unknown>;
52
+ required?: string[];
53
+ };
54
+ }
55
+
56
+ interface McpToolCall {
57
+ name: string;
58
+ arguments: Record<string, unknown>;
59
+ }
60
+
61
+ // ============================================================================
62
+ // MCP Server Implementation
63
+ // ============================================================================
64
+
65
+ export class McpServer {
66
+ private ws: WebSocket | null = null;
67
+ private wsUrl: string;
68
+ private requestId = 0;
69
+ private pendingRequests = new Map<
70
+ string,
71
+ { resolve: (value: unknown) => void; reject: (error: Error) => void }
72
+ >();
73
+ private connected = false;
74
+ private reconnecting = false;
75
+ private reconnectInterval = 2000; // Retry every 2s
76
+ private closing = false;
77
+
78
+ constructor(wsUrl: string = 'ws://localhost:8765/ws') {
79
+ this.wsUrl = wsUrl;
80
+ }
81
+
82
+ /**
83
+ * Start the MCP server (stdio mode).
84
+ */
85
+ async start(): Promise<void> {
86
+ // Connect to WebSocket API
87
+ await this.connectWs();
88
+
89
+ // Set up stdio interface
90
+ const rl = createInterface({
91
+ input: process.stdin,
92
+ output: process.stdout,
93
+ terminal: false,
94
+ });
95
+
96
+ rl.on('line', (line) => {
97
+ this.handleInput(line);
98
+ });
99
+
100
+ rl.on('close', () => {
101
+ this.close();
102
+ process.exit(0);
103
+ });
104
+
105
+ // Handle SIGINT gracefully
106
+ process.on('SIGINT', () => {
107
+ this.close();
108
+ process.exit(0);
109
+ });
110
+ }
111
+
112
+ private async connectWs(): Promise<void> {
113
+ return new Promise((resolve, reject) => {
114
+ this.ws = new WebSocket(this.wsUrl);
115
+
116
+ this.ws.on('open', () => {
117
+ this.connected = true;
118
+ this.reconnecting = false;
119
+ resolve();
120
+ });
121
+
122
+ this.ws.on('message', (data) => {
123
+ this.handleWsMessage(data.toString());
124
+ });
125
+
126
+ this.ws.on('close', () => {
127
+ this.connected = false;
128
+ if (!this.closing) {
129
+ this.scheduleReconnect();
130
+ }
131
+ });
132
+
133
+ this.ws.on('error', (error) => {
134
+ if (!this.connected) {
135
+ // Connection failed - reject so we can retry
136
+ reject(error);
137
+ } else {
138
+ // Connected but got an error - just log it
139
+ this.sendNotification('notifications/message', {
140
+ level: 'error',
141
+ logger: 'agent-framework',
142
+ data: `WebSocket error: ${error.message}`,
143
+ });
144
+ }
145
+ });
146
+ });
147
+ }
148
+
149
+ private scheduleReconnect(): void {
150
+ if (this.reconnecting || this.closing) return;
151
+ this.reconnecting = true;
152
+
153
+ setTimeout(() => {
154
+ if (this.closing) return;
155
+ this.connectWs().catch(() => {
156
+ this.reconnecting = false;
157
+ this.scheduleReconnect();
158
+ });
159
+ }, this.reconnectInterval);
160
+ }
161
+
162
+ private handleWsMessage(data: string): void {
163
+ try {
164
+ const message = JSON.parse(data) as ApiResponse | ApiEvent;
165
+
166
+ if (message.type === 'response' && 'id' in message && message.id) {
167
+ // Handle response to our request
168
+ const pending = this.pendingRequests.get(message.id);
169
+ if (pending) {
170
+ this.pendingRequests.delete(message.id);
171
+ if (message.success) {
172
+ pending.resolve(message.data);
173
+ } else {
174
+ pending.reject(new Error(message.error ?? 'Unknown error'));
175
+ }
176
+ }
177
+ } else if (message.type === 'event') {
178
+ // Forward events as MCP notifications
179
+ this.sendNotification('notifications/message', {
180
+ level: 'info',
181
+ logger: 'agent-framework',
182
+ data: `Event: ${message.event} - ${JSON.stringify(message.data)}`,
183
+ });
184
+ }
185
+ } catch {
186
+ // Ignore parse errors
187
+ }
188
+ }
189
+
190
+ private handleInput(line: string): void {
191
+ try {
192
+ const message = JSON.parse(line);
193
+
194
+ // Check if this is a notification (no id) or a request (has id)
195
+ if (!('id' in message) || message.id === undefined) {
196
+ // This is a notification - handle silently without response
197
+ // Common notifications: notifications/initialized, notifications/cancelled
198
+ return;
199
+ }
200
+
201
+ // This is a request - process and respond
202
+ this.handleRequest(message as JsonRpcRequest);
203
+ } catch {
204
+ this.sendError(null, -32700, 'Parse error');
205
+ }
206
+ }
207
+
208
+ private async handleRequest(request: JsonRpcRequest): Promise<void> {
209
+ try {
210
+ switch (request.method) {
211
+ case 'initialize':
212
+ this.sendResult(request.id, {
213
+ protocolVersion: '2024-11-05',
214
+ capabilities: {
215
+ tools: {},
216
+ },
217
+ serverInfo: {
218
+ name: 'agent-framework',
219
+ version: '0.1.0',
220
+ },
221
+ });
222
+ break;
223
+
224
+ case 'initialized':
225
+ // Client acknowledgment, no response needed
226
+ break;
227
+
228
+ case 'tools/list':
229
+ this.sendResult(request.id, { tools: this.getTools() });
230
+ break;
231
+
232
+ case 'tools/call':
233
+ await this.handleToolCall(request);
234
+ break;
235
+
236
+ case 'ping':
237
+ this.sendResult(request.id, {});
238
+ break;
239
+
240
+ default:
241
+ this.sendError(request.id, -32601, `Method not found: ${request.method}`);
242
+ }
243
+ } catch (error) {
244
+ this.sendError(
245
+ request.id,
246
+ -32603,
247
+ error instanceof Error ? error.message : String(error)
248
+ );
249
+ }
250
+ }
251
+
252
+ private getTools(): McpTool[] {
253
+ return [
254
+ {
255
+ name: 'agent_send_message',
256
+ description:
257
+ 'Send a message to the agent framework. This will add the message to the conversation and optionally trigger inference.',
258
+ inputSchema: {
259
+ type: 'object',
260
+ properties: {
261
+ participant: {
262
+ type: 'string',
263
+ description: 'Name of the participant sending the message (e.g., "user")',
264
+ },
265
+ content: {
266
+ type: 'string',
267
+ description: 'The message content',
268
+ },
269
+ triggerInference: {
270
+ type: 'boolean',
271
+ description: 'Whether to trigger agent inference after sending (default: true)',
272
+ },
273
+ targetAgents: {
274
+ type: 'array',
275
+ items: { type: 'string' },
276
+ description: 'Specific agents to trigger (optional, defaults to all)',
277
+ },
278
+ },
279
+ required: ['participant', 'content'],
280
+ },
281
+ },
282
+ {
283
+ name: 'agent_list_messages',
284
+ description: 'List recent messages in the conversation',
285
+ inputSchema: {
286
+ type: 'object',
287
+ properties: {
288
+ limit: {
289
+ type: 'number',
290
+ description: 'Maximum number of messages to return (default: 50)',
291
+ },
292
+ offset: {
293
+ type: 'number',
294
+ description: 'Offset from the most recent message (default: 0)',
295
+ },
296
+ },
297
+ },
298
+ },
299
+ {
300
+ name: 'agent_request_inference',
301
+ description: 'Request the agent to run inference and generate a response',
302
+ inputSchema: {
303
+ type: 'object',
304
+ properties: {
305
+ agentName: {
306
+ type: 'string',
307
+ description: 'Specific agent to run (optional, defaults to all)',
308
+ },
309
+ reason: {
310
+ type: 'string',
311
+ description: 'Reason for the inference request',
312
+ },
313
+ },
314
+ },
315
+ },
316
+ {
317
+ name: 'branch_list',
318
+ description: 'List all branches in the agent framework',
319
+ inputSchema: {
320
+ type: 'object',
321
+ properties: {},
322
+ },
323
+ },
324
+ {
325
+ name: 'branch_create',
326
+ description: 'Create a new branch from the current state',
327
+ inputSchema: {
328
+ type: 'object',
329
+ properties: {
330
+ name: {
331
+ type: 'string',
332
+ description: 'Name for the new branch',
333
+ },
334
+ switchTo: {
335
+ type: 'boolean',
336
+ description: 'Whether to switch to the new branch after creation (default: false)',
337
+ },
338
+ },
339
+ required: ['name'],
340
+ },
341
+ },
342
+ {
343
+ name: 'branch_switch',
344
+ description: 'Switch to a different branch',
345
+ inputSchema: {
346
+ type: 'object',
347
+ properties: {
348
+ name: {
349
+ type: 'string',
350
+ description: 'Name of the branch to switch to',
351
+ },
352
+ },
353
+ required: ['name'],
354
+ },
355
+ },
356
+ {
357
+ name: 'branch_current',
358
+ description: 'Get the name of the current branch',
359
+ inputSchema: {
360
+ type: 'object',
361
+ properties: {},
362
+ },
363
+ },
364
+ {
365
+ name: 'branch_delete',
366
+ description: 'Delete a branch (cannot delete current or main branch)',
367
+ inputSchema: {
368
+ type: 'object',
369
+ properties: {
370
+ name: {
371
+ type: 'string',
372
+ description: 'Name of the branch to delete',
373
+ },
374
+ },
375
+ required: ['name'],
376
+ },
377
+ },
378
+ {
379
+ name: 'agent_list',
380
+ description: 'List all agents in the framework',
381
+ inputSchema: {
382
+ type: 'object',
383
+ properties: {},
384
+ },
385
+ },
386
+ {
387
+ name: 'agent_context',
388
+ description: "Get an agent's current context (compiled messages)",
389
+ inputSchema: {
390
+ type: 'object',
391
+ properties: {
392
+ agentName: {
393
+ type: 'string',
394
+ description: 'Name of the agent',
395
+ },
396
+ maxTokens: {
397
+ type: 'number',
398
+ description:
399
+ "A hypothetical budget to compile the context at (optional; without it, the context manager's " +
400
+ "default of 100000, not the agent's own window). Under the autobiographical strategy, a budget " +
401
+ "the context can't fit fails the call with the context manager's refusal, which names the tokens " +
402
+ 'and the limit. Passthrough keeps the newest messages that fit (none, if the newest alone is ' +
403
+ 'larger), and windowed passthrough returns the newest message alone, larger than the budget.',
404
+ },
405
+ },
406
+ required: ['agentName'],
407
+ },
408
+ },
409
+ {
410
+ name: 'module_list',
411
+ description: 'List all modules registered with the framework',
412
+ inputSchema: {
413
+ type: 'object',
414
+ properties: {},
415
+ },
416
+ },
417
+ {
418
+ name: 'module_state',
419
+ description: "Get a module's current state",
420
+ inputSchema: {
421
+ type: 'object',
422
+ properties: {
423
+ moduleName: {
424
+ type: 'string',
425
+ description: 'Name of the module',
426
+ },
427
+ },
428
+ required: ['moduleName'],
429
+ },
430
+ },
431
+ {
432
+ name: 'store_states',
433
+ description: 'List all states in the store',
434
+ inputSchema: {
435
+ type: 'object',
436
+ properties: {
437
+ namespace: {
438
+ type: 'string',
439
+ description: "Filter by namespace prefix (e.g., 'agents/', 'modules/')",
440
+ },
441
+ limit: {
442
+ type: 'number',
443
+ description: 'Maximum number of states to return (default: 50)',
444
+ },
445
+ },
446
+ },
447
+ },
448
+ {
449
+ name: 'store_search',
450
+ description: 'Search through store states by namespace and/or content pattern',
451
+ inputSchema: {
452
+ type: 'object',
453
+ properties: {
454
+ namespace: {
455
+ type: 'string',
456
+ description: 'Filter by namespace prefix',
457
+ },
458
+ contentPattern: {
459
+ type: 'string',
460
+ description: 'Regex pattern to match against state content (JSON stringified)',
461
+ },
462
+ limit: {
463
+ type: 'number',
464
+ description: 'Maximum number of results (default: 20)',
465
+ },
466
+ offset: {
467
+ type: 'number',
468
+ description: 'Skip first N results for pagination (default: 0)',
469
+ },
470
+ previewLength: {
471
+ type: 'number',
472
+ description: 'Preview length in characters (default: 300)',
473
+ },
474
+ },
475
+ },
476
+ },
477
+ {
478
+ name: 'store_inspect',
479
+ description: 'Inspect a specific state in the store',
480
+ inputSchema: {
481
+ type: 'object',
482
+ properties: {
483
+ stateId: {
484
+ type: 'string',
485
+ description: 'ID of the state to inspect',
486
+ },
487
+ },
488
+ required: ['stateId'],
489
+ },
490
+ },
491
+ // Inference logging tools
492
+ {
493
+ name: 'inference_tail',
494
+ description: 'Get the most recent inference log entries. Shows raw LLM requests and responses for debugging.',
495
+ inputSchema: {
496
+ type: 'object',
497
+ properties: {
498
+ count: {
499
+ type: 'number',
500
+ description: 'Number of recent entries to return (default: 10)',
501
+ },
502
+ agentName: {
503
+ type: 'string',
504
+ description: 'Filter by agent name (optional)',
505
+ },
506
+ },
507
+ },
508
+ },
509
+ {
510
+ name: 'inference_inspect',
511
+ description: 'Inspect a specific inference log entry by sequence number. Returns full raw request and response.',
512
+ inputSchema: {
513
+ type: 'object',
514
+ properties: {
515
+ sequence: {
516
+ type: 'number',
517
+ description: 'Sequence number of the log entry to inspect',
518
+ },
519
+ },
520
+ required: ['sequence'],
521
+ },
522
+ },
523
+ {
524
+ name: 'inference_search',
525
+ description: 'Search through inference logs by agent, pattern, or error status. Useful for debugging specific issues.',
526
+ inputSchema: {
527
+ type: 'object',
528
+ properties: {
529
+ agentName: {
530
+ type: 'string',
531
+ description: 'Filter by agent name',
532
+ },
533
+ pattern: {
534
+ type: 'string',
535
+ description: 'Regex pattern to search in log content',
536
+ },
537
+ errorsOnly: {
538
+ type: 'boolean',
539
+ description: 'Only show failed inferences',
540
+ },
541
+ limit: {
542
+ type: 'number',
543
+ description: 'Maximum number of results (default: 20)',
544
+ },
545
+ offset: {
546
+ type: 'number',
547
+ description: 'Skip first N results for pagination (default: 0)',
548
+ },
549
+ },
550
+ },
551
+ },
552
+ ];
553
+ }
554
+
555
+ private async handleToolCall(request: JsonRpcRequest): Promise<void> {
556
+ const params = request.params as { name: string; arguments: Record<string, unknown> };
557
+ const { name, arguments: args } = params;
558
+
559
+ // Map MCP tool names to API commands
560
+ const toolToCommand: Record<string, string> = {
561
+ agent_send_message: 'message.send',
562
+ agent_list_messages: 'message.list',
563
+ agent_request_inference: 'inference.request',
564
+ branch_list: 'branch.list',
565
+ branch_create: 'branch.create',
566
+ branch_switch: 'branch.switch',
567
+ branch_current: 'branch.current',
568
+ branch_delete: 'branch.delete',
569
+ agent_list: 'agent.list',
570
+ agent_context: 'agent.context',
571
+ module_list: 'module.list',
572
+ module_state: 'module.state',
573
+ store_states: 'store.states',
574
+ store_search: 'store.search',
575
+ store_inspect: 'store.inspect',
576
+ inference_tail: 'inference.tail',
577
+ inference_inspect: 'inference.inspect',
578
+ inference_search: 'inference.search',
579
+ };
580
+
581
+ const command = toolToCommand[name];
582
+ if (!command) {
583
+ this.sendError(request.id, -32602, `Unknown tool: ${name}`);
584
+ return;
585
+ }
586
+
587
+ try {
588
+ const result = await this.sendApiRequest(command, args);
589
+ this.sendResult(request.id, {
590
+ content: [
591
+ {
592
+ type: 'text',
593
+ text: JSON.stringify(result, null, 2),
594
+ },
595
+ ],
596
+ });
597
+ } catch (error) {
598
+ this.sendResult(request.id, {
599
+ content: [
600
+ {
601
+ type: 'text',
602
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
603
+ },
604
+ ],
605
+ isError: true,
606
+ });
607
+ }
608
+ }
609
+
610
+ private sendApiRequest(
611
+ command: string,
612
+ params: Record<string, unknown>
613
+ ): Promise<unknown> {
614
+ return new Promise((resolve, reject) => {
615
+ if (!this.ws || !this.connected) {
616
+ reject(new Error('Not connected to API server'));
617
+ return;
618
+ }
619
+
620
+ const id = `mcp-${++this.requestId}`;
621
+ this.pendingRequests.set(id, { resolve, reject });
622
+
623
+ const request: ApiRequest = {
624
+ type: 'request',
625
+ id,
626
+ command,
627
+ params,
628
+ };
629
+
630
+ this.ws.send(JSON.stringify(request));
631
+
632
+ // Timeout after 30 seconds
633
+ setTimeout(() => {
634
+ if (this.pendingRequests.has(id)) {
635
+ this.pendingRequests.delete(id);
636
+ reject(new Error('Request timeout'));
637
+ }
638
+ }, 30000);
639
+ });
640
+ }
641
+
642
+ private sendResult(id: string | number, result: unknown): void {
643
+ const response: JsonRpcResponse = {
644
+ jsonrpc: '2.0',
645
+ id,
646
+ result,
647
+ };
648
+ this.send(response);
649
+ }
650
+
651
+ private sendError(id: string | number | null, code: number, message: string): void {
652
+ const response: JsonRpcResponse = {
653
+ jsonrpc: '2.0',
654
+ id,
655
+ error: { code, message },
656
+ };
657
+ this.send(response);
658
+ }
659
+
660
+ private sendNotification(method: string, params: unknown): void {
661
+ const notification: JsonRpcNotification = {
662
+ jsonrpc: '2.0',
663
+ method,
664
+ params,
665
+ };
666
+ this.send(notification);
667
+ }
668
+
669
+ private send(message: JsonRpcResponse | JsonRpcNotification): void {
670
+ process.stdout.write(JSON.stringify(message) + '\n');
671
+ }
672
+
673
+ close(): void {
674
+ this.closing = true;
675
+ if (this.ws) {
676
+ this.ws.close();
677
+ this.ws = null;
678
+ }
679
+ this.connected = false;
680
+ }
681
+ }