@animalabs/agent-framework 0.22.1 → 0.22.3

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 (946) hide show
  1. package/README.md +4 -2
  2. package/dist/src/agent.d.ts +266 -28
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +539 -104
  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 +55 -27
  17. package/dist/src/api/server.js.map +1 -1
  18. package/dist/src/api/types.d.ts +10 -2
  19. package/dist/src/api/types.d.ts.map +1 -1
  20. package/dist/src/branch-names.d.ts +14 -0
  21. package/dist/src/branch-names.d.ts.map +1 -0
  22. package/dist/src/branch-names.js +22 -0
  23. package/dist/src/branch-names.js.map +1 -0
  24. package/dist/src/closest-names.d.ts +28 -0
  25. package/dist/src/closest-names.d.ts.map +1 -0
  26. package/dist/src/closest-names.js +98 -0
  27. package/dist/src/closest-names.js.map +1 -0
  28. package/dist/src/code-execution/py-runner.d.ts +16 -5
  29. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  30. package/dist/src/code-execution/py-runner.js +186 -74
  31. package/dist/src/code-execution/py-runner.js.map +1 -1
  32. package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
  33. package/dist/src/code-execution/runtime-py.js +49 -3
  34. package/dist/src/code-execution/runtime-py.js.map +1 -1
  35. package/dist/src/code-execution/tool-definition.d.ts +12 -1
  36. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  37. package/dist/src/code-execution/tool-definition.js +21 -3
  38. package/dist/src/code-execution/tool-definition.js.map +1 -1
  39. package/dist/src/config-checks.d.ts +28 -0
  40. package/dist/src/config-checks.d.ts.map +1 -0
  41. package/dist/src/config-checks.js +52 -0
  42. package/dist/src/config-checks.js.map +1 -0
  43. package/dist/src/deadline-timer.d.ts +21 -0
  44. package/dist/src/deadline-timer.d.ts.map +1 -0
  45. package/dist/src/deadline-timer.js +43 -0
  46. package/dist/src/deadline-timer.js.map +1 -0
  47. package/dist/src/error-message.d.ts +30 -0
  48. package/dist/src/error-message.d.ts.map +1 -0
  49. package/dist/src/error-message.js +50 -0
  50. package/dist/src/error-message.js.map +1 -0
  51. package/dist/src/framework.d.ts +1212 -192
  52. package/dist/src/framework.d.ts.map +1 -1
  53. package/dist/src/framework.js +6686 -1835
  54. package/dist/src/framework.js.map +1 -1
  55. package/dist/src/gate/event-gate.d.ts +8 -0
  56. package/dist/src/gate/event-gate.d.ts.map +1 -1
  57. package/dist/src/gate/event-gate.js +27 -3
  58. package/dist/src/gate/event-gate.js.map +1 -1
  59. package/dist/src/gate/gate-script.d.ts.map +1 -1
  60. package/dist/src/gate/gate-script.js.map +1 -1
  61. package/dist/src/index.d.ts +5 -3
  62. package/dist/src/index.d.ts.map +1 -1
  63. package/dist/src/index.js +5 -3
  64. package/dist/src/index.js.map +1 -1
  65. package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
  66. package/dist/src/mcpl/channel-registry.d.ts +170 -13
  67. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  68. package/dist/src/mcpl/channel-registry.js +499 -258
  69. package/dist/src/mcpl/channel-registry.js.map +1 -1
  70. package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
  71. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  72. package/dist/src/mcpl/checkpoint-manager.js +91 -30
  73. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  74. package/dist/src/mcpl/conversation-router.d.ts +19 -3
  75. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  76. package/dist/src/mcpl/conversation-router.js +23 -8
  77. package/dist/src/mcpl/conversation-router.js.map +1 -1
  78. package/dist/src/mcpl/convert-block.d.ts +20 -0
  79. package/dist/src/mcpl/convert-block.d.ts.map +1 -0
  80. package/dist/src/mcpl/convert-block.js +89 -0
  81. package/dist/src/mcpl/convert-block.js.map +1 -0
  82. package/dist/src/mcpl/errors.d.ts +13 -0
  83. package/dist/src/mcpl/errors.d.ts.map +1 -1
  84. package/dist/src/mcpl/errors.js +28 -0
  85. package/dist/src/mcpl/errors.js.map +1 -1
  86. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  87. package/dist/src/mcpl/feature-set-manager.js +4 -3
  88. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  89. package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
  90. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  91. package/dist/src/mcpl/hook-orchestrator.js +83 -72
  92. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  93. package/dist/src/mcpl/inbound-source.d.ts +114 -0
  94. package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
  95. package/dist/src/mcpl/inbound-source.js +83 -0
  96. package/dist/src/mcpl/inbound-source.js.map +1 -0
  97. package/dist/src/mcpl/index.d.ts +3 -1
  98. package/dist/src/mcpl/index.d.ts.map +1 -1
  99. package/dist/src/mcpl/index.js +3 -1
  100. package/dist/src/mcpl/index.js.map +1 -1
  101. package/dist/src/mcpl/inference-router.d.ts +15 -11
  102. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  103. package/dist/src/mcpl/inference-router.js +153 -84
  104. package/dist/src/mcpl/inference-router.js.map +1 -1
  105. package/dist/src/mcpl/log-value.d.ts +54 -0
  106. package/dist/src/mcpl/log-value.d.ts.map +1 -0
  107. package/dist/src/mcpl/log-value.js +109 -0
  108. package/dist/src/mcpl/log-value.js.map +1 -0
  109. package/dist/src/mcpl/prose-stream-router.d.ts +6 -6
  110. package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -1
  111. package/dist/src/mcpl/prose-stream-router.js +4 -4
  112. package/dist/src/mcpl/prose-stream-router.js.map +1 -1
  113. package/dist/src/mcpl/push-coalescer.d.ts +64 -7
  114. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  115. package/dist/src/mcpl/push-coalescer.js +121 -24
  116. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  117. package/dist/src/mcpl/push-handler.d.ts +38 -8
  118. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  119. package/dist/src/mcpl/push-handler.js +77 -78
  120. package/dist/src/mcpl/push-handler.js.map +1 -1
  121. package/dist/src/mcpl/reference-fetcher.d.ts +14 -2
  122. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  123. package/dist/src/mcpl/reference-fetcher.js +72 -30
  124. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  125. package/dist/src/mcpl/references.d.ts +49 -14
  126. package/dist/src/mcpl/references.d.ts.map +1 -1
  127. package/dist/src/mcpl/references.js +74 -21
  128. package/dist/src/mcpl/references.js.map +1 -1
  129. package/dist/src/mcpl/refusal-lines.d.ts +37 -0
  130. package/dist/src/mcpl/refusal-lines.d.ts.map +1 -0
  131. package/dist/src/mcpl/refusal-lines.js +61 -0
  132. package/dist/src/mcpl/refusal-lines.js.map +1 -0
  133. package/dist/src/mcpl/scope-manager.d.ts.map +1 -1
  134. package/dist/src/mcpl/server-connection.d.ts +107 -12
  135. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  136. package/dist/src/mcpl/server-connection.js +470 -139
  137. package/dist/src/mcpl/server-connection.js.map +1 -1
  138. package/dist/src/mcpl/server-registry.d.ts +10 -1
  139. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  140. package/dist/src/mcpl/server-registry.js +14 -3
  141. package/dist/src/mcpl/server-registry.js.map +1 -1
  142. package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
  143. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
  144. package/dist/src/mcpl/skip-reply-wake.js +55 -0
  145. package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
  146. package/dist/src/mcpl/tool-classes.d.ts +1 -1
  147. package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
  148. package/dist/src/mcpl/tool-classes.js +3 -2
  149. package/dist/src/mcpl/tool-classes.js.map +1 -1
  150. package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
  151. package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
  152. package/dist/src/mcpl/transport.d.ts +74 -7
  153. package/dist/src/mcpl/transport.d.ts.map +1 -1
  154. package/dist/src/mcpl/transport.js +209 -22
  155. package/dist/src/mcpl/transport.js.map +1 -1
  156. package/dist/src/mcpl/types.d.ts +43 -28
  157. package/dist/src/mcpl/types.d.ts.map +1 -1
  158. package/dist/src/mcpl/types.js.map +1 -1
  159. package/dist/src/mcpl/visible-content.d.ts +15 -0
  160. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  161. package/dist/src/mcpl/visible-content.js +25 -0
  162. package/dist/src/mcpl/visible-content.js.map +1 -1
  163. package/dist/src/module-registry.d.ts +19 -1
  164. package/dist/src/module-registry.d.ts.map +1 -1
  165. package/dist/src/module-registry.js +54 -25
  166. package/dist/src/module-registry.js.map +1 -1
  167. package/dist/src/modules/api/index.d.ts.map +1 -1
  168. package/dist/src/modules/api/index.js +1 -1
  169. package/dist/src/modules/api/index.js.map +1 -1
  170. package/dist/src/modules/discord/discord-js-client.d.ts +1 -0
  171. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  172. package/dist/src/modules/discord/discord-js-client.js +25 -9
  173. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  174. package/dist/src/modules/discord/index.d.ts +29 -3
  175. package/dist/src/modules/discord/index.d.ts.map +1 -1
  176. package/dist/src/modules/discord/index.js +383 -145
  177. package/dist/src/modules/discord/index.js.map +1 -1
  178. package/dist/src/modules/discord/types.d.ts +14 -1
  179. package/dist/src/modules/discord/types.d.ts.map +1 -1
  180. package/dist/src/modules/health/index.d.ts.map +1 -1
  181. package/dist/src/modules/health/index.js +2 -1
  182. package/dist/src/modules/health/index.js.map +1 -1
  183. package/dist/src/modules/history/index.d.ts +3 -1
  184. package/dist/src/modules/history/index.d.ts.map +1 -1
  185. package/dist/src/modules/history/index.js +359 -127
  186. package/dist/src/modules/history/index.js.map +1 -1
  187. package/dist/src/modules/history/semantic.d.ts +28 -1
  188. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  189. package/dist/src/modules/history/semantic.js +177 -32
  190. package/dist/src/modules/history/semantic.js.map +1 -1
  191. package/dist/src/modules/unknown-tool.d.ts +10 -0
  192. package/dist/src/modules/unknown-tool.d.ts.map +1 -0
  193. package/dist/src/modules/unknown-tool.js +17 -0
  194. package/dist/src/modules/unknown-tool.js.map +1 -0
  195. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  196. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  197. package/dist/src/modules/workspace/disk-agreement.d.ts +54 -6
  198. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  199. package/dist/src/modules/workspace/disk-agreement.js +93 -27
  200. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  201. package/dist/src/modules/workspace/effects.d.ts +64 -6
  202. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  203. package/dist/src/modules/workspace/effects.js +291 -44
  204. package/dist/src/modules/workspace/effects.js.map +1 -1
  205. package/dist/src/modules/workspace/index.d.ts +127 -27
  206. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  207. package/dist/src/modules/workspace/index.js +821 -248
  208. package/dist/src/modules/workspace/index.js.map +1 -1
  209. package/dist/src/modules/workspace/observe.d.ts +117 -15
  210. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  211. package/dist/src/modules/workspace/observe.js +436 -51
  212. package/dist/src/modules/workspace/observe.js.map +1 -1
  213. package/dist/src/modules/workspace/reconcile.d.ts +75 -8
  214. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  215. package/dist/src/modules/workspace/reconcile.js +576 -68
  216. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  217. package/dist/src/modules/workspace/types.d.ts +42 -3
  218. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  219. package/dist/src/modules/workspace/types.js.map +1 -1
  220. package/dist/src/modules/workspace/watcher.d.ts +7 -2
  221. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  222. package/dist/src/modules/workspace/watcher.js +28 -4
  223. package/dist/src/modules/workspace/watcher.js.map +1 -1
  224. package/dist/src/operator-log.d.ts.map +1 -1
  225. package/dist/src/operator-log.js.map +1 -1
  226. package/dist/src/prose-drafts.d.ts +240 -0
  227. package/dist/src/prose-drafts.d.ts.map +1 -0
  228. package/dist/src/prose-drafts.js +362 -0
  229. package/dist/src/prose-drafts.js.map +1 -0
  230. package/dist/src/prose-segments.d.ts +21 -2
  231. package/dist/src/prose-segments.d.ts.map +1 -1
  232. package/dist/src/prose-segments.js +46 -9
  233. package/dist/src/prose-segments.js.map +1 -1
  234. package/dist/src/provider-waits.d.ts.map +1 -1
  235. package/dist/src/provider-waits.js.map +1 -1
  236. package/dist/src/queue.d.ts.map +1 -1
  237. package/dist/src/record-journal.d.ts.map +1 -1
  238. package/dist/src/record-journal.js.map +1 -1
  239. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  240. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  241. package/dist/src/recovery/offline-branch.d.ts +1 -0
  242. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  243. package/dist/src/recovery/offline-branch.js +32 -25
  244. package/dist/src/recovery/offline-branch.js.map +1 -1
  245. package/dist/src/recovery/recover-cli.js.map +1 -1
  246. package/dist/src/runtime/liveness-watchdog.d.ts.map +1 -1
  247. package/dist/src/runtime/liveness-watchdog.js.map +1 -1
  248. package/dist/src/safe-slice.d.ts +5 -1
  249. package/dist/src/safe-slice.d.ts.map +1 -1
  250. package/dist/src/safe-slice.js +9 -1
  251. package/dist/src/safe-slice.js.map +1 -1
  252. package/dist/src/shutdown.d.ts.map +1 -1
  253. package/dist/src/shutdown.js.map +1 -1
  254. package/dist/src/stored-removal.d.ts +73 -0
  255. package/dist/src/stored-removal.d.ts.map +1 -0
  256. package/dist/src/stored-removal.js +100 -0
  257. package/dist/src/stored-removal.js.map +1 -0
  258. package/dist/src/thinking-token-stamp.js.map +1 -1
  259. package/dist/src/tool-image-ledger.d.ts +87 -19
  260. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  261. package/dist/src/tool-image-ledger.js +135 -32
  262. package/dist/src/tool-image-ledger.js.map +1 -1
  263. package/dist/src/tool-presentation.d.ts +9 -0
  264. package/dist/src/tool-presentation.d.ts.map +1 -1
  265. package/dist/src/tool-presentation.js +257 -60
  266. package/dist/src/tool-presentation.js.map +1 -1
  267. package/dist/src/tool-result-guard.d.ts.map +1 -1
  268. package/dist/src/tool-result-guard.js +7 -10
  269. package/dist/src/tool-result-guard.js.map +1 -1
  270. package/dist/src/tool-result-history.d.ts +32 -3
  271. package/dist/src/tool-result-history.d.ts.map +1 -1
  272. package/dist/src/tool-result-history.js +106 -19
  273. package/dist/src/tool-result-history.js.map +1 -1
  274. package/dist/src/tune-out/coordinator.d.ts +25 -1
  275. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  276. package/dist/src/tune-out/coordinator.js +260 -65
  277. package/dist/src/tune-out/coordinator.js.map +1 -1
  278. package/dist/src/tune-out/tools.d.ts +1 -1
  279. package/dist/src/tune-out/tools.d.ts.map +1 -1
  280. package/dist/src/types/agent.d.ts +59 -11
  281. package/dist/src/types/agent.d.ts.map +1 -1
  282. package/dist/src/types/events.d.ts +17 -0
  283. package/dist/src/types/events.d.ts.map +1 -1
  284. package/dist/src/types/framework.d.ts +31 -5
  285. package/dist/src/types/framework.d.ts.map +1 -1
  286. package/dist/src/types/inference-log.d.ts +1 -1
  287. package/dist/src/types/inference-log.d.ts.map +1 -1
  288. package/dist/src/types/module.d.ts +30 -7
  289. package/dist/src/types/module.d.ts.map +1 -1
  290. package/dist/src/types/trace.d.ts +151 -11
  291. package/dist/src/types/trace.d.ts.map +1 -1
  292. package/dist/src/usage/usage-tracker.d.ts +5 -0
  293. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  294. package/dist/src/usage/usage-tracker.js +35 -8
  295. package/dist/src/usage/usage-tracker.js.map +1 -1
  296. package/package.json +10 -9
  297. package/src/agent.ts +572 -105
  298. package/src/api/mcp-server-core.ts +681 -0
  299. package/src/api/mcp-server.ts +16 -685
  300. package/src/api/server.ts +55 -30
  301. package/src/api/types.ts +10 -2
  302. package/src/branch-names.ts +19 -0
  303. package/src/closest-names.ts +94 -0
  304. package/src/code-execution/py-runner.ts +200 -76
  305. package/src/code-execution/runtime-py.ts +49 -3
  306. package/src/code-execution/tool-definition.ts +28 -4
  307. package/src/config-checks.ts +48 -0
  308. package/src/deadline-timer.ts +44 -0
  309. package/src/error-message.ts +48 -0
  310. package/src/framework.ts +7158 -1936
  311. package/src/gate/event-gate.ts +28 -3
  312. package/src/index.ts +12 -3
  313. package/src/mcpl/channel-registry.ts +615 -289
  314. package/src/mcpl/checkpoint-manager.ts +104 -29
  315. package/src/mcpl/conversation-router.ts +28 -8
  316. package/src/mcpl/convert-block.ts +97 -0
  317. package/src/mcpl/errors.ts +28 -0
  318. package/src/mcpl/feature-set-manager.ts +4 -3
  319. package/src/mcpl/hook-orchestrator.ts +84 -77
  320. package/src/mcpl/inbound-source.ts +156 -0
  321. package/src/mcpl/index.ts +10 -1
  322. package/src/mcpl/inference-router.ts +174 -99
  323. package/src/mcpl/log-value.ts +116 -0
  324. package/src/mcpl/prose-stream-router.ts +6 -6
  325. package/src/mcpl/push-coalescer.ts +124 -24
  326. package/src/mcpl/push-handler.ts +86 -84
  327. package/src/mcpl/reference-fetcher.ts +71 -26
  328. package/src/mcpl/references.ts +81 -22
  329. package/src/mcpl/refusal-lines.ts +59 -0
  330. package/src/mcpl/server-connection.ts +496 -142
  331. package/src/mcpl/server-registry.ts +15 -4
  332. package/src/mcpl/skip-reply-wake.ts +73 -0
  333. package/src/mcpl/tool-classes.ts +3 -2
  334. package/src/mcpl/transport.ts +219 -26
  335. package/src/mcpl/types.ts +18 -3
  336. package/src/mcpl/visible-content.ts +27 -0
  337. package/src/module-registry.ts +58 -23
  338. package/src/modules/api/index.ts +1 -1
  339. package/src/modules/discord/discord-js-client.ts +26 -10
  340. package/src/modules/discord/index.ts +395 -160
  341. package/src/modules/discord/types.ts +15 -2
  342. package/src/modules/health/index.ts +2 -1
  343. package/src/modules/history/index.ts +410 -120
  344. package/src/modules/history/semantic.ts +189 -32
  345. package/src/modules/unknown-tool.ts +16 -0
  346. package/src/modules/workspace/disk-agreement.ts +125 -21
  347. package/src/modules/workspace/effects.ts +279 -35
  348. package/src/modules/workspace/index.ts +841 -261
  349. package/src/modules/workspace/observe.ts +456 -56
  350. package/src/modules/workspace/reconcile.ts +688 -76
  351. package/src/modules/workspace/types.ts +41 -2
  352. package/src/modules/workspace/watcher.ts +27 -4
  353. package/src/prose-drafts.ts +481 -0
  354. package/src/prose-segments.ts +51 -8
  355. package/src/recovery/offline-branch.ts +36 -29
  356. package/src/safe-slice.ts +9 -1
  357. package/src/stored-removal.ts +126 -0
  358. package/src/tool-image-ledger.ts +153 -34
  359. package/src/tool-presentation.ts +224 -40
  360. package/src/tool-result-guard.ts +7 -8
  361. package/src/tool-result-history.ts +124 -20
  362. package/src/tune-out/coordinator.ts +259 -65
  363. package/src/types/agent.ts +59 -13
  364. package/src/types/events.ts +17 -0
  365. package/src/types/framework.ts +31 -5
  366. package/src/types/inference-log.ts +1 -1
  367. package/src/types/module.ts +31 -7
  368. package/src/types/trace.ts +158 -12
  369. package/src/usage/usage-tracker.ts +32 -8
  370. package/dist/test/activation-request-sanitize.test.d.ts +0 -2
  371. package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
  372. package/dist/test/activation-request-sanitize.test.js +0 -89
  373. package/dist/test/activation-request-sanitize.test.js.map +0 -1
  374. package/dist/test/agent-cache-ttl.test.d.ts +0 -2
  375. package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
  376. package/dist/test/agent-cache-ttl.test.js +0 -41
  377. package/dist/test/agent-cache-ttl.test.js.map +0 -1
  378. package/dist/test/agent-runtime-settings.test.d.ts +0 -2
  379. package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
  380. package/dist/test/agent-runtime-settings.test.js +0 -462
  381. package/dist/test/agent-runtime-settings.test.js.map +0 -1
  382. package/dist/test/api-admin-gate.test.d.ts +0 -2
  383. package/dist/test/api-admin-gate.test.d.ts.map +0 -1
  384. package/dist/test/api-admin-gate.test.js +0 -116
  385. package/dist/test/api-admin-gate.test.js.map +0 -1
  386. package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
  387. package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
  388. package/dist/test/assistant-persist-refusal.test.js +0 -63
  389. package/dist/test/assistant-persist-refusal.test.js.map +0 -1
  390. package/dist/test/batched-wake-locus.test.d.ts +0 -2
  391. package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
  392. package/dist/test/batched-wake-locus.test.js +0 -166
  393. package/dist/test/batched-wake-locus.test.js.map +0 -1
  394. package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
  395. package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
  396. package/dist/test/busy-agent-scheduler.test.js +0 -92
  397. package/dist/test/busy-agent-scheduler.test.js.map +0 -1
  398. package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
  399. package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
  400. package/dist/test/channel-incoming-targeting.test.js +0 -81
  401. package/dist/test/channel-incoming-targeting.test.js.map +0 -1
  402. package/dist/test/channel-label-history.test.d.ts +0 -2
  403. package/dist/test/channel-label-history.test.d.ts.map +0 -1
  404. package/dist/test/channel-label-history.test.js +0 -424
  405. package/dist/test/channel-label-history.test.js.map +0 -1
  406. package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
  407. package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
  408. package/dist/test/channel-lifecycle-provenance.test.js +0 -47
  409. package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
  410. package/dist/test/channel-registry-routing.test.d.ts +0 -2
  411. package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
  412. package/dist/test/channel-registry-routing.test.js +0 -446
  413. package/dist/test/channel-registry-routing.test.js.map +0 -1
  414. package/dist/test/channel-registry-typing.test.d.ts +0 -2
  415. package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
  416. package/dist/test/channel-registry-typing.test.js +0 -91
  417. package/dist/test/channel-registry-typing.test.js.map +0 -1
  418. package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
  419. package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
  420. package/dist/test/channels-changed-respond-first.test.js +0 -74
  421. package/dist/test/channels-changed-respond-first.test.js.map +0 -1
  422. package/dist/test/checkpoint-attribution.test.d.ts +0 -2
  423. package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
  424. package/dist/test/checkpoint-attribution.test.js +0 -200
  425. package/dist/test/checkpoint-attribution.test.js.map +0 -1
  426. package/dist/test/code-execution.test.d.ts +0 -11
  427. package/dist/test/code-execution.test.d.ts.map +0 -1
  428. package/dist/test/code-execution.test.js +0 -1272
  429. package/dist/test/code-execution.test.js.map +0 -1
  430. package/dist/test/component-defaults.test.d.ts +0 -2
  431. package/dist/test/component-defaults.test.d.ts.map +0 -1
  432. package/dist/test/component-defaults.test.js +0 -54
  433. package/dist/test/component-defaults.test.js.map +0 -1
  434. package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
  435. package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
  436. package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
  437. package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
  438. package/dist/test/conversation-router.test.d.ts +0 -2
  439. package/dist/test/conversation-router.test.d.ts.map +0 -1
  440. package/dist/test/conversation-router.test.js +0 -174
  441. package/dist/test/conversation-router.test.js.map +0 -1
  442. package/dist/test/conversation-routing.test.d.ts +0 -7
  443. package/dist/test/conversation-routing.test.d.ts.map +0 -1
  444. package/dist/test/conversation-routing.test.js +0 -387
  445. package/dist/test/conversation-routing.test.js.map +0 -1
  446. package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
  447. package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
  448. package/dist/test/deferred-wake-integrity.test.js +0 -320
  449. package/dist/test/deferred-wake-integrity.test.js.map +0 -1
  450. package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
  451. package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
  452. package/dist/test/discord-awareness-outbox.test.js +0 -267
  453. package/dist/test/discord-awareness-outbox.test.js.map +0 -1
  454. package/dist/test/discord-history-delete-window.test.d.ts +0 -2
  455. package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
  456. package/dist/test/discord-history-delete-window.test.js +0 -81
  457. package/dist/test/discord-history-delete-window.test.js.map +0 -1
  458. package/dist/test/discord-history-sync.test.d.ts +0 -2
  459. package/dist/test/discord-history-sync.test.d.ts.map +0 -1
  460. package/dist/test/discord-history-sync.test.js +0 -56
  461. package/dist/test/discord-history-sync.test.js.map +0 -1
  462. package/dist/test/ephemeral-settle.test.d.ts +0 -2
  463. package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
  464. package/dist/test/ephemeral-settle.test.js +0 -354
  465. package/dist/test/ephemeral-settle.test.js.map +0 -1
  466. package/dist/test/event-gate-passthrough.test.d.ts +0 -15
  467. package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
  468. package/dist/test/event-gate-passthrough.test.js +0 -289
  469. package/dist/test/event-gate-passthrough.test.js.map +0 -1
  470. package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
  471. package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
  472. package/dist/test/event-gate-policy-mutation.test.js +0 -137
  473. package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
  474. package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
  475. package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
  476. package/dist/test/event-gate-rate-limit.test.js +0 -627
  477. package/dist/test/event-gate-rate-limit.test.js.map +0 -1
  478. package/dist/test/event-gate-script.test.d.ts +0 -2
  479. package/dist/test/event-gate-script.test.d.ts.map +0 -1
  480. package/dist/test/event-gate-script.test.js +0 -95
  481. package/dist/test/event-gate-script.test.js.map +0 -1
  482. package/dist/test/event-gate-selfwake.test.d.ts +0 -15
  483. package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
  484. package/dist/test/event-gate-selfwake.test.js +0 -125
  485. package/dist/test/event-gate-selfwake.test.js.map +0 -1
  486. package/dist/test/event-gate-tags.test.d.ts +0 -2
  487. package/dist/test/event-gate-tags.test.d.ts.map +0 -1
  488. package/dist/test/event-gate-tags.test.js +0 -76
  489. package/dist/test/event-gate-tags.test.js.map +0 -1
  490. package/dist/test/event-gate.test.d.ts +0 -2
  491. package/dist/test/event-gate.test.d.ts.map +0 -1
  492. package/dist/test/event-gate.test.js +0 -919
  493. package/dist/test/event-gate.test.js.map +0 -1
  494. package/dist/test/explicit-prose-routing.test.d.ts +0 -11
  495. package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
  496. package/dist/test/explicit-prose-routing.test.js +0 -1394
  497. package/dist/test/explicit-prose-routing.test.js.map +0 -1
  498. package/dist/test/framework.test.d.ts +0 -5
  499. package/dist/test/framework.test.d.ts.map +0 -1
  500. package/dist/test/framework.test.js +0 -1048
  501. package/dist/test/framework.test.js.map +0 -1
  502. package/dist/test/gather-context-timeout.test.d.ts +0 -2
  503. package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
  504. package/dist/test/gather-context-timeout.test.js +0 -120
  505. package/dist/test/gather-context-timeout.test.js.map +0 -1
  506. package/dist/test/health-snapshot.test.d.ts +0 -2
  507. package/dist/test/health-snapshot.test.d.ts.map +0 -1
  508. package/dist/test/health-snapshot.test.js +0 -74
  509. package/dist/test/health-snapshot.test.js.map +0 -1
  510. package/dist/test/helpers/coalescing-fixture.d.ts +0 -72
  511. package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
  512. package/dist/test/helpers/coalescing-fixture.js +0 -146
  513. package/dist/test/helpers/coalescing-fixture.js.map +0 -1
  514. package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
  515. package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
  516. package/dist/test/helpers/coalescing-kill-child.js +0 -24
  517. package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
  518. package/dist/test/helpers/mock-membrane.d.ts +0 -53
  519. package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
  520. package/dist/test/helpers/mock-membrane.js +0 -168
  521. package/dist/test/helpers/mock-membrane.js.map +0 -1
  522. package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
  523. package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
  524. package/dist/test/helpers/pytc-stop-rows.js +0 -143
  525. package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
  526. package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
  527. package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
  528. package/dist/test/helpers/quiesce-crash-child.js +0 -156
  529. package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
  530. package/dist/test/history-module-overview.test.d.ts +0 -2
  531. package/dist/test/history-module-overview.test.d.ts.map +0 -1
  532. package/dist/test/history-module-overview.test.js +0 -711
  533. package/dist/test/history-module-overview.test.js.map +0 -1
  534. package/dist/test/history-module-realstore.test.d.ts +0 -2
  535. package/dist/test/history-module-realstore.test.d.ts.map +0 -1
  536. package/dist/test/history-module-realstore.test.js +0 -363
  537. package/dist/test/history-module-realstore.test.js.map +0 -1
  538. package/dist/test/history-module-semantic.test.d.ts +0 -2
  539. package/dist/test/history-module-semantic.test.d.ts.map +0 -1
  540. package/dist/test/history-module-semantic.test.js +0 -213
  541. package/dist/test/history-module-semantic.test.js.map +0 -1
  542. package/dist/test/history-module-ux.test.d.ts +0 -2
  543. package/dist/test/history-module-ux.test.d.ts.map +0 -1
  544. package/dist/test/history-module-ux.test.js +0 -304
  545. package/dist/test/history-module-ux.test.js.map +0 -1
  546. package/dist/test/history-module.test.d.ts +0 -2
  547. package/dist/test/history-module.test.d.ts.map +0 -1
  548. package/dist/test/history-module.test.js +0 -619
  549. package/dist/test/history-module.test.js.map +0 -1
  550. package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
  551. package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
  552. package/dist/test/history-semantic-review-findings.test.js +0 -338
  553. package/dist/test/history-semantic-review-findings.test.js.map +0 -1
  554. package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
  555. package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
  556. package/dist/test/history-semantic-sync-converges.test.js +0 -109
  557. package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
  558. package/dist/test/host-quiesce.test.d.ts +0 -2
  559. package/dist/test/host-quiesce.test.d.ts.map +0 -1
  560. package/dist/test/host-quiesce.test.js +0 -863
  561. package/dist/test/host-quiesce.test.js.map +0 -1
  562. package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
  563. package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
  564. package/dist/test/inference-exhaustion-rewind.test.js +0 -309
  565. package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
  566. package/dist/test/inference-failure-bounds.test.d.ts +0 -2
  567. package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
  568. package/dist/test/inference-failure-bounds.test.js +0 -1201
  569. package/dist/test/inference-failure-bounds.test.js.map +0 -1
  570. package/dist/test/inference-failure-observability.test.d.ts +0 -2
  571. package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
  572. package/dist/test/inference-failure-observability.test.js +0 -84
  573. package/dist/test/inference-failure-observability.test.js.map +0 -1
  574. package/dist/test/journal-tool.test.d.ts +0 -2
  575. package/dist/test/journal-tool.test.d.ts.map +0 -1
  576. package/dist/test/journal-tool.test.js +0 -33
  577. package/dist/test/journal-tool.test.js.map +0 -1
  578. package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
  579. package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
  580. package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
  581. package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
  582. package/dist/test/kv-unified-wiring.test.d.ts +0 -2
  583. package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
  584. package/dist/test/kv-unified-wiring.test.js +0 -95
  585. package/dist/test/kv-unified-wiring.test.js.map +0 -1
  586. package/dist/test/late-events-after-stop.test.d.ts +0 -2
  587. package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
  588. package/dist/test/late-events-after-stop.test.js +0 -122
  589. package/dist/test/late-events-after-stop.test.js.map +0 -1
  590. package/dist/test/liveness-watchdog.test.d.ts +0 -2
  591. package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
  592. package/dist/test/liveness-watchdog.test.js +0 -94
  593. package/dist/test/liveness-watchdog.test.js.map +0 -1
  594. package/dist/test/machine-close-provenance.test.d.ts +0 -2
  595. package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
  596. package/dist/test/machine-close-provenance.test.js +0 -116
  597. package/dist/test/machine-close-provenance.test.js.map +0 -1
  598. package/dist/test/maintenance-timer.test.d.ts +0 -2
  599. package/dist/test/maintenance-timer.test.d.ts.map +0 -1
  600. package/dist/test/maintenance-timer.test.js +0 -265
  601. package/dist/test/maintenance-timer.test.js.map +0 -1
  602. package/dist/test/mcpl-access-provider.test.d.ts +0 -2
  603. package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
  604. package/dist/test/mcpl-access-provider.test.js +0 -20
  605. package/dist/test/mcpl-access-provider.test.js.map +0 -1
  606. package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
  607. package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
  608. package/dist/test/mcpl-awareness-barrier.test.js +0 -769
  609. package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
  610. package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
  611. package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
  612. package/dist/test/mcpl-capability-grant.test.js +0 -111
  613. package/dist/test/mcpl-capability-grant.test.js.map +0 -1
  614. package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
  615. package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
  616. package/dist/test/mcpl-capability-scoping.test.js +0 -266
  617. package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
  618. package/dist/test/mcpl-child-env.test.d.ts +0 -2
  619. package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
  620. package/dist/test/mcpl-child-env.test.js +0 -158
  621. package/dist/test/mcpl-child-env.test.js.map +0 -1
  622. package/dist/test/mcpl-coalescing.test.d.ts +0 -2
  623. package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
  624. package/dist/test/mcpl-coalescing.test.js +0 -1125
  625. package/dist/test/mcpl-coalescing.test.js.map +0 -1
  626. package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
  627. package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
  628. package/dist/test/mcpl-config-diagnostics.test.js +0 -452
  629. package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
  630. package/dist/test/mcpl-empty-content.test.d.ts +0 -2
  631. package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
  632. package/dist/test/mcpl-empty-content.test.js +0 -368
  633. package/dist/test/mcpl-empty-content.test.js.map +0 -1
  634. package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
  635. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
  636. package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
  637. package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
  638. package/dist/test/mcpl-list-status.test.d.ts +0 -2
  639. package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
  640. package/dist/test/mcpl-list-status.test.js +0 -82
  641. package/dist/test/mcpl-list-status.test.js.map +0 -1
  642. package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
  643. package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
  644. package/dist/test/mcpl-manifest-changed.test.js +0 -178
  645. package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
  646. package/dist/test/mcpl-push-convert.test.d.ts +0 -2
  647. package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
  648. package/dist/test/mcpl-push-convert.test.js +0 -42
  649. package/dist/test/mcpl-push-convert.test.js.map +0 -1
  650. package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
  651. package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
  652. package/dist/test/mcpl-reconnect-events.test.js +0 -144
  653. package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
  654. package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
  655. package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
  656. package/dist/test/mcpl-reconnect-reregistration.test.js +0 -236
  657. package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
  658. package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
  659. package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
  660. package/dist/test/mcpl-reference-fetcher.test.js +0 -427
  661. package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
  662. package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
  663. package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
  664. package/dist/test/mcpl-reference-fields.test.js +0 -149
  665. package/dist/test/mcpl-reference-fields.test.js.map +0 -1
  666. package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
  667. package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
  668. package/dist/test/mcpl-request-timeout.test.js +0 -138
  669. package/dist/test/mcpl-request-timeout.test.js.map +0 -1
  670. package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
  671. package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
  672. package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
  673. package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
  674. package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
  675. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
  676. package/dist/test/mcpl-tool-class-listing.test.js +0 -147
  677. package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
  678. package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
  679. package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
  680. package/dist/test/mcpl-tool-classes.test.js +0 -80
  681. package/dist/test/mcpl-tool-classes.test.js.map +0 -1
  682. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
  683. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
  684. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
  685. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
  686. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
  687. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
  688. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
  689. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
  690. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
  691. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
  692. package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
  693. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
  694. package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
  695. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
  696. package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
  697. package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
  698. package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
  699. package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
  700. package/dist/test/mcpl-ws-transport.test.js +0 -258
  701. package/dist/test/mcpl-ws-transport.test.js.map +0 -1
  702. package/dist/test/module-context-integration.test.d.ts +0 -18
  703. package/dist/test/module-context-integration.test.d.ts.map +0 -1
  704. package/dist/test/module-context-integration.test.js +0 -181
  705. package/dist/test/module-context-integration.test.js.map +0 -1
  706. package/dist/test/offline-recovery-branch.test.d.ts +0 -2
  707. package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
  708. package/dist/test/offline-recovery-branch.test.js +0 -226
  709. package/dist/test/offline-recovery-branch.test.js.map +0 -1
  710. package/dist/test/operator-surgery.test.d.ts +0 -2
  711. package/dist/test/operator-surgery.test.d.ts.map +0 -1
  712. package/dist/test/operator-surgery.test.js +0 -398
  713. package/dist/test/operator-surgery.test.js.map +0 -1
  714. package/dist/test/ops-alert.test.d.ts +0 -2
  715. package/dist/test/ops-alert.test.d.ts.map +0 -1
  716. package/dist/test/ops-alert.test.js +0 -153
  717. package/dist/test/ops-alert.test.js.map +0 -1
  718. package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
  719. package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
  720. package/dist/test/overbudget-drain-breaker.test.js +0 -197
  721. package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
  722. package/dist/test/per-agent-delivery.test.d.ts +0 -2
  723. package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
  724. package/dist/test/per-agent-delivery.test.js +0 -108
  725. package/dist/test/per-agent-delivery.test.js.map +0 -1
  726. package/dist/test/physical-window-restart.test.d.ts +0 -14
  727. package/dist/test/physical-window-restart.test.d.ts.map +0 -1
  728. package/dist/test/physical-window-restart.test.js +0 -222
  729. package/dist/test/physical-window-restart.test.js.map +0 -1
  730. package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
  731. package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
  732. package/dist/test/placed-reaction-baseline.test.js +0 -312
  733. package/dist/test/placed-reaction-baseline.test.js.map +0 -1
  734. package/dist/test/present-while-acting.test.d.ts +0 -19
  735. package/dist/test/present-while-acting.test.d.ts.map +0 -1
  736. package/dist/test/present-while-acting.test.js +0 -706
  737. package/dist/test/present-while-acting.test.js.map +0 -1
  738. package/dist/test/prose-segments.test.d.ts +0 -2
  739. package/dist/test/prose-segments.test.d.ts.map +0 -1
  740. package/dist/test/prose-segments.test.js +0 -52
  741. package/dist/test/prose-segments.test.js.map +0 -1
  742. package/dist/test/prose-stream-router.test.d.ts +0 -2
  743. package/dist/test/prose-stream-router.test.d.ts.map +0 -1
  744. package/dist/test/prose-stream-router.test.js +0 -171
  745. package/dist/test/prose-stream-router.test.js.map +0 -1
  746. package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
  747. package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
  748. package/dist/test/provider-acceleration-cooldown.test.js +0 -435
  749. package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
  750. package/dist/test/provider-waits.test.d.ts +0 -2
  751. package/dist/test/provider-waits.test.d.ts.map +0 -1
  752. package/dist/test/provider-waits.test.js +0 -2196
  753. package/dist/test/provider-waits.test.js.map +0 -1
  754. package/dist/test/puppet-tool-call.test.d.ts +0 -2
  755. package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
  756. package/dist/test/puppet-tool-call.test.js +0 -224
  757. package/dist/test/puppet-tool-call.test.js.map +0 -1
  758. package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
  759. package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
  760. package/dist/test/puppet-turn-reservation.test.js +0 -139
  761. package/dist/test/puppet-turn-reservation.test.js.map +0 -1
  762. package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
  763. package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
  764. package/dist/test/reaction-baseline-platform.test.js +0 -124
  765. package/dist/test/reaction-baseline-platform.test.js.map +0 -1
  766. package/dist/test/record-journal.test.d.ts +0 -6
  767. package/dist/test/record-journal.test.d.ts.map +0 -1
  768. package/dist/test/record-journal.test.js +0 -269
  769. package/dist/test/record-journal.test.js.map +0 -1
  770. package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
  771. package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
  772. package/dist/test/refusal-reaction-baseline.test.js +0 -81
  773. package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
  774. package/dist/test/refusal-rewind.test.d.ts +0 -2
  775. package/dist/test/refusal-rewind.test.d.ts.map +0 -1
  776. package/dist/test/refusal-rewind.test.js +0 -108
  777. package/dist/test/refusal-rewind.test.js.map +0 -1
  778. package/dist/test/refusal-single-call.test.d.ts +0 -2
  779. package/dist/test/refusal-single-call.test.d.ts.map +0 -1
  780. package/dist/test/refusal-single-call.test.js +0 -177
  781. package/dist/test/refusal-single-call.test.js.map +0 -1
  782. package/dist/test/release-changelog.test.d.ts +0 -2
  783. package/dist/test/release-changelog.test.d.ts.map +0 -1
  784. package/dist/test/release-changelog.test.js +0 -159
  785. package/dist/test/release-changelog.test.js.map +0 -1
  786. package/dist/test/same-round-think-policy.test.d.ts +0 -2
  787. package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
  788. package/dist/test/same-round-think-policy.test.js +0 -853
  789. package/dist/test/same-round-think-policy.test.js.map +0 -1
  790. package/dist/test/save-recent-image.test.d.ts +0 -26
  791. package/dist/test/save-recent-image.test.d.ts.map +0 -1
  792. package/dist/test/save-recent-image.test.js +0 -974
  793. package/dist/test/save-recent-image.test.js.map +0 -1
  794. package/dist/test/shutdown-errors.test.d.ts +0 -2
  795. package/dist/test/shutdown-errors.test.d.ts.map +0 -1
  796. package/dist/test/shutdown-errors.test.js +0 -662
  797. package/dist/test/shutdown-errors.test.js.map +0 -1
  798. package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
  799. package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
  800. package/dist/test/silent-heartbeat-rows.test.js +0 -451
  801. package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
  802. package/dist/test/silent-heartbeat.test.d.ts +0 -2
  803. package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
  804. package/dist/test/silent-heartbeat.test.js +0 -165
  805. package/dist/test/silent-heartbeat.test.js.map +0 -1
  806. package/dist/test/state-scaling-e2e.test.d.ts +0 -22
  807. package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
  808. package/dist/test/state-scaling-e2e.test.js +0 -206
  809. package/dist/test/state-scaling-e2e.test.js.map +0 -1
  810. package/dist/test/state-scaling.test.d.ts +0 -12
  811. package/dist/test/state-scaling.test.d.ts.map +0 -1
  812. package/dist/test/state-scaling.test.js +0 -251
  813. package/dist/test/state-scaling.test.js.map +0 -1
  814. package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
  815. package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
  816. package/dist/test/stop-with-work-in-flight.test.js +0 -672
  817. package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
  818. package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
  819. package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
  820. package/dist/test/surgery-marks-receipt.test.js +0 -540
  821. package/dist/test/surgery-marks-receipt.test.js.map +0 -1
  822. package/dist/test/thinking-token-stamp.test.d.ts +0 -12
  823. package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
  824. package/dist/test/thinking-token-stamp.test.js +0 -129
  825. package/dist/test/thinking-token-stamp.test.js.map +0 -1
  826. package/dist/test/timezone.test.d.ts +0 -2
  827. package/dist/test/timezone.test.d.ts.map +0 -1
  828. package/dist/test/timezone.test.js +0 -18
  829. package/dist/test/timezone.test.js.map +0 -1
  830. package/dist/test/tool-batch-hook.test.d.ts +0 -8
  831. package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
  832. package/dist/test/tool-batch-hook.test.js +0 -275
  833. package/dist/test/tool-batch-hook.test.js.map +0 -1
  834. package/dist/test/tool-policy.test.d.ts +0 -2
  835. package/dist/test/tool-policy.test.d.ts.map +0 -1
  836. package/dist/test/tool-policy.test.js +0 -51
  837. package/dist/test/tool-policy.test.js.map +0 -1
  838. package/dist/test/tool-presentation.test.d.ts +0 -2
  839. package/dist/test/tool-presentation.test.d.ts.map +0 -1
  840. package/dist/test/tool-presentation.test.js +0 -268
  841. package/dist/test/tool-presentation.test.js.map +0 -1
  842. package/dist/test/tool-result-content.test.d.ts +0 -2
  843. package/dist/test/tool-result-content.test.d.ts.map +0 -1
  844. package/dist/test/tool-result-content.test.js +0 -37
  845. package/dist/test/tool-result-content.test.js.map +0 -1
  846. package/dist/test/tool-result-guard.test.d.ts +0 -2
  847. package/dist/test/tool-result-guard.test.d.ts.map +0 -1
  848. package/dist/test/tool-result-guard.test.js +0 -3607
  849. package/dist/test/tool-result-guard.test.js.map +0 -1
  850. package/dist/test/tool-result-history.test.d.ts +0 -7
  851. package/dist/test/tool-result-history.test.d.ts.map +0 -1
  852. package/dist/test/tool-result-history.test.js +0 -156
  853. package/dist/test/tool-result-history.test.js.map +0 -1
  854. package/dist/test/tool-result-spill.test.d.ts +0 -13
  855. package/dist/test/tool-result-spill.test.d.ts.map +0 -1
  856. package/dist/test/tool-result-spill.test.js +0 -586
  857. package/dist/test/tool-result-spill.test.js.map +0 -1
  858. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
  859. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
  860. package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
  861. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
  862. package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
  863. package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
  864. package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
  865. package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
  866. package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
  867. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
  868. package/dist/test/tools-observe-parser-conformance.test.js +0 -129
  869. package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
  870. package/dist/test/trunk-channel-routing.test.d.ts +0 -19
  871. package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
  872. package/dist/test/trunk-channel-routing.test.js +0 -329
  873. package/dist/test/trunk-channel-routing.test.js.map +0 -1
  874. package/dist/test/tune-out-e2e.test.d.ts +0 -2
  875. package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
  876. package/dist/test/tune-out-e2e.test.js +0 -142
  877. package/dist/test/tune-out-e2e.test.js.map +0 -1
  878. package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
  879. package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
  880. package/dist/test/tune-out-gate-composition.test.js +0 -221
  881. package/dist/test/tune-out-gate-composition.test.js.map +0 -1
  882. package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
  883. package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
  884. package/dist/test/tune-out-lifecycle.test.js +0 -121
  885. package/dist/test/tune-out-lifecycle.test.js.map +0 -1
  886. package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
  887. package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
  888. package/dist/test/turn-trigger-provenance.test.js +0 -137
  889. package/dist/test/turn-trigger-provenance.test.js.map +0 -1
  890. package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
  891. package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
  892. package/dist/test/unconvertible-tool-result.test.js +0 -358
  893. package/dist/test/unconvertible-tool-result.test.js.map +0 -1
  894. package/dist/test/usage-accounting.test.d.ts +0 -2
  895. package/dist/test/usage-accounting.test.d.ts.map +0 -1
  896. package/dist/test/usage-accounting.test.js +0 -13
  897. package/dist/test/usage-accounting.test.js.map +0 -1
  898. package/dist/test/usage-tracker.test.d.ts +0 -2
  899. package/dist/test/usage-tracker.test.d.ts.map +0 -1
  900. package/dist/test/usage-tracker.test.js +0 -129
  901. package/dist/test/usage-tracker.test.js.map +0 -1
  902. package/dist/test/utils-surface.test.d.ts +0 -2
  903. package/dist/test/utils-surface.test.d.ts.map +0 -1
  904. package/dist/test/utils-surface.test.js +0 -145
  905. package/dist/test/utils-surface.test.js.map +0 -1
  906. package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
  907. package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
  908. package/dist/test/workspace-branch-continuation.test.js +0 -183
  909. package/dist/test/workspace-branch-continuation.test.js.map +0 -1
  910. package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
  911. package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
  912. package/dist/test/workspace-materialize-freshness.test.js +0 -252
  913. package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
  914. package/dist/test/workspace-path-containment.test.d.ts +0 -19
  915. package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
  916. package/dist/test/workspace-path-containment.test.js +0 -91
  917. package/dist/test/workspace-path-containment.test.js.map +0 -1
  918. package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
  919. package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
  920. package/dist/test/workspace-read-file-from-disk.test.js +0 -174
  921. package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
  922. package/dist/test/workspace-read-image.test.d.ts +0 -2
  923. package/dist/test/workspace-read-image.test.d.ts.map +0 -1
  924. package/dist/test/workspace-read-image.test.js +0 -597
  925. package/dist/test/workspace-read-image.test.js.map +0 -1
  926. package/dist/test/workspace-read-text.test.d.ts +0 -2
  927. package/dist/test/workspace-read-text.test.d.ts.map +0 -1
  928. package/dist/test/workspace-read-text.test.js +0 -101
  929. package/dist/test/workspace-read-text.test.js.map +0 -1
  930. package/dist/test/workspace-restore-order.test.d.ts +0 -16
  931. package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
  932. package/dist/test/workspace-restore-order.test.js +0 -140
  933. package/dist/test/workspace-restore-order.test.js.map +0 -1
  934. package/dist/test/workspace-three-way.test.d.ts +0 -12
  935. package/dist/test/workspace-three-way.test.d.ts.map +0 -1
  936. package/dist/test/workspace-three-way.test.js +0 -3194
  937. package/dist/test/workspace-three-way.test.js.map +0 -1
  938. package/dist/test/workspace-watcher.test.d.ts +0 -2
  939. package/dist/test/workspace-watcher.test.d.ts.map +0 -1
  940. package/dist/test/workspace-watcher.test.js +0 -281
  941. package/dist/test/workspace-watcher.test.js.map +0 -1
  942. package/dist/test/xml-round-persist.test.d.ts +0 -19
  943. package/dist/test/xml-round-persist.test.d.ts.map +0 -1
  944. package/dist/test/xml-round-persist.test.js +0 -235
  945. package/dist/test/xml-round-persist.test.js.map +0 -1
  946. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -12,11 +12,16 @@
12
12
  * - Expose synthesized tools: channel_list, channel_open, channel_close, channel_publish
13
13
  * - Build channel context for beforeInference params
14
14
  */
15
- import { INLINE_WITHHELD_TEXT, isInlineContradiction, referenceStubOrNull } from './references.js';
15
+ import { convertBlock } from './convert-block.js';
16
+ import { ensureStateRegistered } from '../module-registry.js';
16
17
  import { expandCoreTags } from './tags.js';
17
- import { EmptyContentError, validateCoalescedContent } from './push-coalescer.js';
18
- import { isVisiblyEmptyContent } from './visible-content.js';
18
+ import { coalesceRejectionReason, EmptyContentError, validateCoalescedContent } from './push-coalescer.js';
19
+ import { isVisiblyEmptyConversion } from './visible-content.js';
20
+ import { logDetail, logValue } from './log-value.js';
21
+ import { RefusalLines } from './refusal-lines.js';
19
22
  import { CapabilityGrant } from './capability-grant.js';
23
+ import { McplRequestError } from './server-connection.js';
24
+ import { readSkipReplyWake } from './skip-reply-wake.js';
20
25
  // ============================================================================
21
26
  // Typing indicator interval (Discord typing lasts ~10s, so 7s keeps it alive)
22
27
  // ============================================================================
@@ -81,68 +86,6 @@ function shallowEqualRecord(a, b) {
81
86
  return true;
82
87
  }
83
88
  // ============================================================================
84
- // Content Conversion: McplContentBlock → membrane ContentBlock
85
- // ============================================================================
86
- /**
87
- * Convert a single MCPL wire-format content block to a membrane ContentBlock.
88
- */
89
- function convertBlock(block) {
90
- switch (block.type) {
91
- case 'text':
92
- return { type: 'text', text: block.text };
93
- case 'image':
94
- if (isInlineContradiction(block)) {
95
- // RFC-005 vector 2: inline data claiming bulk disposition — fail
96
- // closed, withhold the data (checked BEFORE the data branch).
97
- return { type: 'text', text: INLINE_WITHHELD_TEXT };
98
- }
99
- if (block.uri && block.disposition) {
100
- // RFC-005 uri-form media with a disposition claim: stub, do not
101
- // hand the URI to the provider or inline it.
102
- return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
103
- }
104
- if (block.data && block.mimeType) {
105
- return {
106
- type: 'image',
107
- source: { type: 'base64', data: block.data, mediaType: block.mimeType },
108
- };
109
- }
110
- if (block.uri) {
111
- return {
112
- type: 'image',
113
- source: { type: 'url', url: block.uri },
114
- };
115
- }
116
- return { type: 'text', text: '[Image: no data]' };
117
- case 'audio':
118
- if (isInlineContradiction(block)) {
119
- // RFC-005 vector 2: inline data claiming bulk disposition — fail
120
- // closed, withhold the data (checked BEFORE the data branch).
121
- return { type: 'text', text: INLINE_WITHHELD_TEXT };
122
- }
123
- if (block.uri && block.disposition) {
124
- // RFC-005 uri-form media with a disposition claim: stub, do not
125
- // hand the URI to the provider or inline it.
126
- return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
127
- }
128
- if (block.data && block.mimeType) {
129
- return {
130
- type: 'audio',
131
- source: { type: 'base64', data: block.data, mediaType: block.mimeType },
132
- };
133
- }
134
- return { type: 'text', text: '[Audio: no data]' };
135
- case 'resource':
136
- // RFC-005: reference blocks become bounded stubs — never raw URIs
137
- // (a signed URL is a bearer credential that looks like a location).
138
- return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
139
- default:
140
- // Unknown wire block types previously fell off the exhaustive switch
141
- // and propagated `undefined` into ContentBlock[]. Fail visibly.
142
- return { type: 'text', text: `[unrecognized content block: ${block.type ?? 'untyped'}]` };
143
- }
144
- }
145
- // ============================================================================
146
89
  // Channel Tool Definitions
147
90
  // ============================================================================
148
91
  const CHANNEL_TOOL_DEFINITIONS = [
@@ -153,9 +96,8 @@ const CHANNEL_TOOL_DEFINITIONS = [
153
96
  },
154
97
  {
155
98
  name: 'channel_open',
156
- description: 'Open a channel to start receiving its ordinary ongoing traffic. The MCPL ' +
157
- 'integration performs its own subscribe/join/attach operation. Optionally request ' +
158
- 'history preceding the message that invited you into the channel.',
99
+ description: 'Open a channel. What an open channel delivers to you depends on its MCPL server. ' +
100
+ 'Optionally request history preceding the message that invited you into the channel.',
159
101
  inputSchema: {
160
102
  type: 'object',
161
103
  properties: {
@@ -194,7 +136,8 @@ const CHANNEL_TOOL_DEFINITIONS = [
194
136
  },
195
137
  {
196
138
  name: 'channel_close',
197
- description: 'Close a channel to stop receiving messages',
139
+ description: 'Close a channel. Messages that address you still reach you; what else stops reaching you ' +
140
+ 'depends on its server.',
198
141
  inputSchema: {
199
142
  type: 'object',
200
143
  properties: {
@@ -268,14 +211,90 @@ const CHANNEL_TOOL_DEFINITIONS = [
268
211
  wake_in_seconds: {
269
212
  type: 'number',
270
213
  description: 'Optional self-wake: if nothing else wakes you first, you wake again after this ' +
271
- 'many seconds (1 = go again almost immediately; clamped to 1–3600). Any other ' +
272
- 'wake before then cancels it. Omit to stay idle until the next external wake.',
214
+ 'many seconds, from 1 to 3600; a larger number waits 3600 (1 = go again almost ' +
215
+ 'immediately). Any other wake before then cancels it. Omit to stay idle until the ' +
216
+ 'next external wake.',
273
217
  },
274
218
  },
275
219
  required: [],
276
220
  },
277
221
  },
278
222
  ];
223
+ // ============================================================================
224
+ // Constructor Options
225
+ // ============================================================================
226
+ /** Bound connector values for notices, logs and an outcome's reason. A
227
+ * PublishOutcome keeps the connector's structured data (`detail`) whole. */
228
+ export function connectorText(value) {
229
+ let text;
230
+ try {
231
+ text = typeof value === 'string' ? value : JSON.stringify(value) ?? String(value);
232
+ }
233
+ catch {
234
+ return '[unserializable connector value]';
235
+ }
236
+ const limit = 2000;
237
+ const suffix = '… [truncated]';
238
+ return text.length > limit ? text.slice(0, limit - suffix.length) + suffix : text;
239
+ }
240
+ /**
241
+ * What a channels/publish request that threw establishes. Only a request
242
+ * that never left the host proves nothing was posted. An error response may
243
+ * follow a partial post (a multi-part send whose later part failed), so it
244
+ * is unknown, with the connector's own words, bounded, and its data kept for
245
+ * the resident to judge. The publish executor and channel_publish both read
246
+ * a failed request this way.
247
+ */
248
+ function publishErrorOutcome(err, destination, at) {
249
+ const message = connectorText(err instanceof Error ? err.message : String(err));
250
+ const notSent = err instanceof McplRequestError && err.outcome === 'not-sent';
251
+ const detail = err instanceof McplRequestError ? err.data : undefined;
252
+ return {
253
+ status: notSent ? 'failed' : 'unknown',
254
+ destination,
255
+ reason: notSent ? message : `${message} (delivery uncertain)`,
256
+ ...(detail !== undefined ? { detail } : {}),
257
+ at,
258
+ };
259
+ }
260
+ /**
261
+ * What a channels/publish answer establishes. A final publish is a request,
262
+ * so success requires an explicit receipt; a missing or malformed one leaves
263
+ * delivery uncertain (anima-research/agent-framework#163's rule).
264
+ * `delivered: false` proves nothing went out only when the receipt names no
265
+ * message at all: a message id beside it, valid or malformed, contradicts it,
266
+ * since something may have been posted. The publish executor and
267
+ * channel_publish both read an answer this way.
268
+ */
269
+ function publishReceiptOutcome(result, destination, at) {
270
+ const receipt = (result ?? {});
271
+ const messageId = typeof receipt.messageId === 'string' && receipt.messageId ? receipt.messageId : undefined;
272
+ if (receipt.delivered === true) {
273
+ return { status: 'delivered', destination, ...(messageId ? { messageId } : {}), at };
274
+ }
275
+ if (receipt.delivered === false) {
276
+ if (receipt.messageId === undefined || receipt.messageId === null) {
277
+ return { status: 'failed', destination, reason: `server "${destination.serverId}" reported delivered:false`, at };
278
+ }
279
+ return {
280
+ status: 'unknown',
281
+ destination,
282
+ ...(messageId ? { messageId } : {}),
283
+ reason: messageId
284
+ ? `server "${destination.serverId}" reported delivered:false but named posted message ${connectorText(messageId)} (delivery uncertain)`
285
+ : `server "${destination.serverId}" reported delivered:false beside a malformed message id ` +
286
+ `${connectorText(receipt.messageId)} (contradictory receipt; delivery uncertain)`,
287
+ at,
288
+ };
289
+ }
290
+ return {
291
+ status: 'unknown',
292
+ destination,
293
+ ...(messageId ? { messageId } : {}),
294
+ reason: `server "${destination.serverId}" returned no valid delivery receipt (delivery uncertain)`,
295
+ at,
296
+ };
297
+ }
279
298
  /** The machine decision sources a module-origin channel_close may record.
280
299
  * Closed on purpose: honest provenance means a small, auditable vocabulary,
281
300
  * not arbitrary self-description. */
@@ -294,6 +313,9 @@ export class ChannelRegistry {
294
313
  store;
295
314
  /** Registered channels, keyed by `{serverId}:{channelId}`. */
296
315
  channels = new Map();
316
+ /** Holds back repeats of the line for a message refused because its
317
+ * channel isn't registered (RefusalLines). */
318
+ unknownChannelLines = new RefusalLines();
297
319
  /**
298
320
  * Most-recently-known label per channelId, replayed from
299
321
  * `CHANNEL_LABEL_HISTORY_LOG_ID` (last sighting wins) and kept current by
@@ -357,8 +379,22 @@ export class ChannelRegistry {
357
379
  legacyPolicies = new Map();
358
380
  migratedLegacyPolicies = new Set();
359
381
  handleCoalescedIncoming;
382
+ acceptInbound;
383
+ channelTools;
360
384
  constructor(serverRegistry, featureSetManager, pushEventFn, emitTraceFn, options) {
361
385
  this.handleCoalescedIncoming = options?.handleCoalescedIncoming;
386
+ this.acceptInbound = options?.acceptInbound;
387
+ this.channelTools = CHANNEL_TOOL_DEFINITIONS.map((tool) => {
388
+ if (tool.name !== 'skip_reply' || options?.eventGatePresent === true)
389
+ return tool;
390
+ const schema = tool.inputSchema;
391
+ const { wake_in_seconds: _wake, ...properties } = schema.properties;
392
+ return {
393
+ ...tool,
394
+ description: tool.description.replace(' To end this turn but come back on your own shortly, set wake_in_seconds.', ''),
395
+ inputSchema: { ...schema, properties },
396
+ };
397
+ });
362
398
  this.serverRegistry = serverRegistry;
363
399
  this.featureSetManager = featureSetManager;
364
400
  this.pushEventFn = pushEventFn;
@@ -512,6 +548,37 @@ export class ChannelRegistry {
512
548
  updated: params.updated?.map((c) => c.id) ?? [],
513
549
  });
514
550
  }
551
+ /**
552
+ * A coalesced message the host refused. Until now the host said nothing, so
553
+ * a dropped message (agent-framework#266: every Discord message with a
554
+ * screenshot) left no trace where operators look. The sender gets the
555
+ * per-message result this lane gives: `coalesce_invalid` for a malformed
556
+ * item, or the thrown error's message for anything else. `answered` is the
557
+ * code that result stands for (-32602 for `coalesce_invalid`), and the
558
+ * reason follows it (coalesceRejectionReason): `coalesce-failed` when the
559
+ * host itself failed, `coalesce-invalid` when the sender's item was
560
+ * refused, with the failing `field` and the error's message as `detail`.
561
+ * The line prints the ids the sender sent, whatever their type; the trace
562
+ * carries them when they are strings.
563
+ */
564
+ traceCoalesceRejection(serverId, message, error, answered) {
565
+ const reason = coalesceRejectionReason(answered);
566
+ const field = typeof error.field === 'string' && error.field ? error.field : undefined;
567
+ const channelId = typeof message?.channelId === 'string' ? message.channelId : '';
568
+ const messageId = typeof message?.messageId === 'string' && message.messageId ? message.messageId : undefined;
569
+ console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message?.channelId ?? '')} ` +
570
+ `messageId=${logValue(message?.messageId ?? '')} ` +
571
+ `reason=${reason}${field ? ` field=${logValue(field)}` : ''}: ${logDetail(error.message)}`);
572
+ this.emitTraceFn({
573
+ type: 'mcpl:channel-incoming-rejected',
574
+ serverId,
575
+ channelId,
576
+ ...(messageId ? { messageId } : {}),
577
+ reason,
578
+ ...(field ? { field } : {}),
579
+ detail: error.message,
580
+ });
581
+ }
515
582
  /**
516
583
  * Handle `channels/incoming` from a server.
517
584
  *
@@ -523,10 +590,20 @@ export class ChannelRegistry {
523
590
  for (const message of params.messages) {
524
591
  if (!message || typeof message.channelId !== 'string' || !message.channelId
525
592
  || typeof message.messageId !== 'string' || !message.messageId) {
593
+ // The same gate as admission below: with no coalescer wired, a
594
+ // message carrying `coalesce` is handled uncoalesced, and refused as
595
+ // any uncoalesced message without an identity is.
596
+ const coalescedItem = message?.coalesce !== undefined && !!this.handleCoalescedIncoming;
597
+ if (coalescedItem) {
598
+ this.traceCoalesceRejection(serverId, message, {
599
+ field: typeof message.channelId !== 'string' || !message.channelId ? 'channelId' : 'messageId',
600
+ message: 'a coalesced message needs a channelId and a messageId',
601
+ }, -32602);
602
+ }
526
603
  results.push({
527
604
  messageId: typeof message?.messageId === 'string' ? message.messageId : '',
528
605
  accepted: false,
529
- reason: message?.coalesce !== undefined ? 'coalesce_invalid' : 'invalid channel/message identity',
606
+ reason: coalescedItem ? 'coalesce_invalid' : 'invalid channel/message identity',
530
607
  });
531
608
  continue;
532
609
  }
@@ -557,11 +634,22 @@ export class ChannelRegistry {
557
634
  // routable entry rather than an open self-attested one.
558
635
  const incomingKey = `${serverId}:${message.channelId}`;
559
636
  if (!this.channels.has(incomingKey)) {
637
+ // Loud, coalesced or not, like every other refusal of a message, but
638
+ // at most once a minute per channel (RefusalLines): a server that
639
+ // never registered a busy channel would otherwise print a line for
640
+ // every message in it. Every refusal is traced.
641
+ const held = this.unknownChannelLines.admit(serverId, message.channelId);
642
+ if (held !== null) {
643
+ console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message.channelId)} ` +
644
+ `messageId=${logValue(message.messageId)} reason=unknown-channel ` +
645
+ `(not registered, §14.5${held ? `; ${held} more since the last line` : ''})`);
646
+ }
560
647
  this.emitTraceFn({
561
648
  type: 'mcpl:channel-incoming-rejected',
562
649
  serverId,
563
650
  channelId: message.channelId,
564
- reason: 'unknown channel — not registered (§14.5)',
651
+ messageId: message.messageId,
652
+ reason: 'unknown-channel',
565
653
  });
566
654
  results.push({
567
655
  messageId: message.messageId,
@@ -578,7 +666,7 @@ export class ChannelRegistry {
578
666
  // shows the model nothing would wake it with no visible cause.
579
667
  const emptyAllowed = coalesced && message.coalesce?.retract === true;
580
668
  const rejectEmpty = () => {
581
- console.error(`[channel-incoming-rejected] server=${serverId} channel=${message.channelId} messageId=${message.messageId} reason=empty-content`);
669
+ console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message.channelId)} messageId=${logValue(message.messageId)} reason=empty-content`);
582
670
  this.emitTraceFn({
583
671
  type: 'mcpl:channel-incoming-rejected',
584
672
  serverId,
@@ -592,20 +680,23 @@ export class ChannelRegistry {
592
680
  // RFC-006 §13: malformed content on a coalesced item is that item's
593
681
  // failure, not the batch's — check the shape before converting.
594
682
  try {
595
- validateCoalescedContent(message.content, undefined, { allowEmpty: emptyAllowed });
683
+ validateCoalescedContent(message.content, { allowEmpty: emptyAllowed });
596
684
  }
597
685
  catch (error) {
598
686
  if (error instanceof EmptyContentError)
599
687
  rejectEmpty();
600
- else
688
+ else {
689
+ // Answered coalesce_invalid whatever the error's code: -32602.
690
+ this.traceCoalesceRejection(serverId, message, error, -32602);
601
691
  results.push({ messageId: message.messageId, accepted: false, reason: 'coalesce_invalid' });
692
+ }
602
693
  continue;
603
694
  }
604
695
  }
605
696
  if (message.tags)
606
697
  message.tags = expandCoreTags(message.tags);
607
- const convertedContent = message.content.map(convertBlock);
608
- if (!emptyAllowed && isVisiblyEmptyContent(convertedContent)) {
698
+ const convertedContent = message.content.map((block) => convertBlock(block, 'attachment on channel message', serverId));
699
+ if (!emptyAllowed && isVisiblyEmptyConversion(message.content, convertedContent)) {
609
700
  rejectEmpty();
610
701
  continue;
611
702
  }
@@ -630,7 +721,10 @@ export class ChannelRegistry {
630
721
  // Determine whether to trigger inference
631
722
  let triggerInference = true;
632
723
  if (this.shouldTriggerInference) {
633
- const textContent = message.content
724
+ // The text the agent's context gets, as the push lane's filter reads
725
+ // it: the converted text blocks, a placeholder or reference stub
726
+ // among them, NON_STRING_TEXT_PLACEHOLDER included.
727
+ const textContent = convertedContent
634
728
  .filter((b) => b.type === 'text')
635
729
  .map((b) => b.text)
636
730
  .join('\n');
@@ -658,6 +752,7 @@ export class ChannelRegistry {
658
752
  metadata: message.metadata,
659
753
  ...(message.tags ? { tags: message.tags } : {}),
660
754
  triggerInference,
755
+ acceptedAt: Date.now(),
661
756
  };
662
757
  if (coalesced) {
663
758
  // RFC-006 §14.3: a coalesced message is admitted like any other and
@@ -672,6 +767,9 @@ export class ChannelRegistry {
672
767
  }
673
768
  catch (error) {
674
769
  const err = error;
770
+ // -32602 is answered coalesce_invalid; anything else as its message,
771
+ // a plain Error standing for an internal error (-32603).
772
+ this.traceCoalesceRejection(serverId, message, err, typeof err.code === 'number' ? err.code : -32603);
675
773
  results.push({
676
774
  messageId: message.messageId,
677
775
  accepted: false,
@@ -680,6 +778,12 @@ export class ChannelRegistry {
680
778
  }
681
779
  continue;
682
780
  }
781
+ // The source envelope is frozen here, at admission, before the message
782
+ // is queued or acknowledged: a rename or rebind while it waits in the
783
+ // queue cannot change where it says it came from.
784
+ const inboundSource = this.acceptInbound?.(event);
785
+ if (inboundSource)
786
+ event.inboundSource = inboundSource;
683
787
  // Push to the processing queue
684
788
  // Cast through unknown because McplChannelIncomingEvent matches the
685
789
  // CustomEvent `${string}:${string}` type pattern but lacks an index signature.
@@ -722,27 +826,19 @@ export class ChannelRegistry {
722
826
  // time a message reveals it (labels must show people, not ids).
723
827
  if (existing.descriptor.metadata?.lazyRegistered &&
724
828
  label && existing.descriptor.label === channelId) {
725
- existing.descriptor.label = label;
726
- if (extraMetadata) {
727
- existing.descriptor.metadata = { ...existing.descriptor.metadata, ...extraMetadata };
728
- }
829
+ const metadata = extraMetadata
830
+ ? { ...existing.descriptor.metadata, ...extraMetadata }
831
+ : existing.descriptor.metadata;
729
832
  // The channel now has a real label, not just the bare id — durable.
730
- this.appendLabelSighting(existing.descriptor.id, existing.descriptor.label, extractDmMeta(existing.descriptor.metadata));
833
+ // Recorded before the live descriptor takes it, since this branch's
834
+ // guard reads the descriptor: an append that throws leaves the
835
+ // placeholder, so the next push tries again.
836
+ this.appendLabelSighting(existing.descriptor.id, label, extractDmMeta(metadata));
837
+ existing.descriptor.label = label;
838
+ existing.descriptor.metadata = metadata;
731
839
  }
732
840
  return;
733
841
  }
734
- const key = `${serverId}:${channelId}`;
735
- this.channels.set(key, {
736
- serverId,
737
- descriptor: {
738
- id: channelId,
739
- type: serverId,
740
- label: label ?? channelId,
741
- direction: 'bidirectional',
742
- metadata: { lazyRegistered: true, ...(extraMetadata ?? {}) },
743
- },
744
- open: false,
745
- });
746
842
  // Only persist a REAL label durably. Falling back to the bare
747
843
  // channelId as a placeholder (no server-supplied label at all — e.g. a
748
844
  // Discord DM push missing both channelName and an author name,
@@ -752,11 +848,24 @@ export class ChannelRegistry {
752
848
  // label-less post-restart event takes — recording the placeholder here
753
849
  // would clobber the good label initializeLabelHistoryStore() just
754
850
  // replayed, defeating the entire point of the durable log. The live
755
- // descriptor above still carries the placeholder for in-process
851
+ // descriptor below still carries the placeholder for in-process
756
852
  // routing; only the durable write is skipped when there's no real
757
- // label to record.
853
+ // label to record. A real label is recorded before the entry exists:
854
+ // an append that throws registers nothing, so the next push tries again.
758
855
  if (label)
759
856
  this.appendLabelSighting(channelId, label, extractDmMeta(extraMetadata));
857
+ const key = `${serverId}:${channelId}`;
858
+ this.channels.set(key, {
859
+ serverId,
860
+ descriptor: {
861
+ id: channelId,
862
+ type: serverId,
863
+ label: label ?? channelId,
864
+ direction: 'bidirectional',
865
+ metadata: { lazyRegistered: true, ...(extraMetadata ?? {}) },
866
+ },
867
+ open: false,
868
+ });
760
869
  this.emitTraceFn({
761
870
  type: 'mcpl:channel-lazy-registered',
762
871
  serverId,
@@ -879,6 +988,12 @@ export class ChannelRegistry {
879
988
  getDescriptor(channelId) {
880
989
  return this.findChannelEntry(channelId)?.descriptor;
881
990
  }
991
+ /** The registered label of `channelId` on exactly `serverId` (no
992
+ * cross-server first match), or undefined when it has none. */
993
+ getChannelLabel(serverId, channelId) {
994
+ const label = this.channels.get(`${serverId}:${channelId}`)?.descriptor.label;
995
+ return typeof label === 'string' && label.length > 0 ? label : undefined;
996
+ }
882
997
  isChannelOpen(channelId) {
883
998
  return this.findChannelEntry(channelId)?.open === true;
884
999
  }
@@ -904,7 +1019,7 @@ export class ChannelRegistry {
904
1019
  * Get synthesized tool definitions for channel operations.
905
1020
  */
906
1021
  getChannelTools() {
907
- return CHANNEL_TOOL_DEFINITIONS;
1022
+ return this.channelTools;
908
1023
  }
909
1024
  /**
910
1025
  * Handle a call to one of the synthesized channel tools.
@@ -952,8 +1067,9 @@ export class ChannelRegistry {
952
1067
  const openChannels = this.getOpenChannels();
953
1068
  // Resolve the outbound locus the SAME way routeSpeech does, so the agent is
954
1069
  // told the channel its speech will actually land in: a conversation fork's
955
- // home channel, else this turn's triggering channel (single trunk agent —
956
- // item-3 redux), else the global default (heartbeats). Without this, a fork
1070
+ // home channel, else this turn's channel (single trunk agent — item-3
1071
+ // redux: its locus, else its triggering channel), else the global default
1072
+ // (heartbeats). Without this, a fork
957
1073
  // was advertised the global locus but published somewhere else; and a trunk
958
1074
  // agent was told the wrong channel under concurrency.
959
1075
  const home = agentName ? this.homeChannelResolver?.(agentName) : undefined;
@@ -1032,14 +1148,7 @@ export class ChannelRegistry {
1032
1148
  initializeLifecycleStore() {
1033
1149
  if (!this.store)
1034
1150
  return;
1035
- try {
1036
- this.store.registerState({ id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
1037
- }
1038
- catch (error) {
1039
- if (!(error instanceof Error) || !error.message.includes('State already exists')) {
1040
- throw error;
1041
- }
1042
- }
1151
+ ensureStateRegistered(this.store, { id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
1043
1152
  const raw = this.store.getStateJson(CHANNEL_LIFECYCLE_LOG_ID);
1044
1153
  if (!Array.isArray(raw))
1045
1154
  return;
@@ -1077,6 +1186,15 @@ export class ChannelRegistry {
1077
1186
  }
1078
1187
  }
1079
1188
  }
1189
+ /**
1190
+ * Each writer appends its record here before it changes memory for it, so
1191
+ * an append that throws, as on a full disk, fails the operation with that
1192
+ * change unmade, and memory and the log still agree. A retry then records
1193
+ * the change rather than finding it in memory already, where
1194
+ * setDesiredState's same-state return would record nothing, and a restart
1195
+ * replays what memory held. appendLabelSighting keeps the same order for
1196
+ * the label history.
1197
+ */
1080
1198
  appendLifecycleEvent(event) {
1081
1199
  this.store?.appendToStateJson(CHANNEL_LIFECYCLE_LOG_ID, event);
1082
1200
  }
@@ -1093,14 +1211,7 @@ export class ChannelRegistry {
1093
1211
  initializeLabelHistoryStore() {
1094
1212
  if (!this.store)
1095
1213
  return;
1096
- try {
1097
- this.store.registerState({ id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
1098
- }
1099
- catch (error) {
1100
- if (!(error instanceof Error) || !error.message.includes('State already exists')) {
1101
- throw error;
1102
- }
1103
- }
1214
+ ensureStateRegistered(this.store, { id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
1104
1215
  const raw = this.store.getStateJson(CHANNEL_LABEL_HISTORY_LOG_ID);
1105
1216
  if (!Array.isArray(raw))
1106
1217
  return;
@@ -1180,6 +1291,16 @@ export class ChannelRegistry {
1180
1291
  const isDmUnchanged = isDm === undefined || this.dmClassified.get(channelId) === true;
1181
1292
  if (labelUnchanged && recipientIdUnchanged && recipientNameUnchanged && isDmUnchanged)
1182
1293
  return;
1294
+ // The log first, as for lifecycle events: an append that throws leaves
1295
+ // the history in memory as it was, so the next sighting records it.
1296
+ this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
1297
+ channelId,
1298
+ label,
1299
+ ts: Date.now(),
1300
+ ...(recipientId ? { recipientId } : {}),
1301
+ ...(recipientName ? { recipientName } : {}),
1302
+ ...(isDm ? { isDm } : {}),
1303
+ });
1183
1304
  this.labelHistory.set(channelId, label);
1184
1305
  let seen = this.allLabelsSeen.get(channelId);
1185
1306
  if (!seen) {
@@ -1193,14 +1314,6 @@ export class ChannelRegistry {
1193
1314
  this.dmRecipientNames.set(channelId, recipientName);
1194
1315
  if (isDm)
1195
1316
  this.dmClassified.set(channelId, true);
1196
- this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
1197
- channelId,
1198
- label,
1199
- ts: Date.now(),
1200
- ...(recipientId ? { recipientId } : {}),
1201
- ...(recipientName ? { recipientName } : {}),
1202
- ...(isDm ? { isDm } : {}),
1203
- });
1204
1317
  }
1205
1318
  /**
1206
1319
  * Look up a label spec against label *history* rather than the live
@@ -1418,7 +1531,6 @@ export class ChannelRegistry {
1418
1531
  const key = this.lifecycleKey(serverId, channelId);
1419
1532
  if (this.desiredStates.get(key)?.state === desired)
1420
1533
  return;
1421
- this.desiredStates.set(key, { state: desired, source });
1422
1534
  this.appendLifecycleEvent({
1423
1535
  kind: 'desired-state',
1424
1536
  serverId,
@@ -1427,6 +1539,7 @@ export class ChannelRegistry {
1427
1539
  source,
1428
1540
  timestamp: new Date().toISOString(),
1429
1541
  });
1542
+ this.desiredStates.set(key, { state: desired, source });
1430
1543
  }
1431
1544
  // ==========================================================================
1432
1545
  // Tune-out state (issue #77) — durable in the lifecycle log
@@ -1439,12 +1552,6 @@ export class ChannelRegistry {
1439
1552
  */
1440
1553
  enterTuneOut(serverId, channelId, params, source) {
1441
1554
  const key = this.lifecycleKey(serverId, channelId);
1442
- this.desiredStates.set(key, {
1443
- state: 'tuned-out',
1444
- source,
1445
- tuneOut: params,
1446
- wakeCount: 0,
1447
- });
1448
1555
  this.appendLifecycleEvent({
1449
1556
  kind: 'desired-state',
1450
1557
  serverId,
@@ -1454,6 +1561,12 @@ export class ChannelRegistry {
1454
1561
  source,
1455
1562
  timestamp: new Date().toISOString(),
1456
1563
  });
1564
+ this.desiredStates.set(key, {
1565
+ state: 'tuned-out',
1566
+ source,
1567
+ tuneOut: params,
1568
+ wakeCount: 0,
1569
+ });
1457
1570
  }
1458
1571
  /**
1459
1572
  * End the active tune-out, returning the channel to `nextState`.
@@ -1467,7 +1580,6 @@ export class ChannelRegistry {
1467
1580
  if (current?.state !== 'tuned-out' || !current.tuneOut)
1468
1581
  return null;
1469
1582
  const ended = { params: current.tuneOut, wakeCount: current.wakeCount ?? 0 };
1470
- this.desiredStates.set(key, { state: nextState, source });
1471
1583
  this.appendLifecycleEvent({
1472
1584
  kind: 'desired-state',
1473
1585
  serverId,
@@ -1476,6 +1588,7 @@ export class ChannelRegistry {
1476
1588
  source,
1477
1589
  timestamp: new Date().toISOString(),
1478
1590
  });
1591
+ this.desiredStates.set(key, { state: nextState, source });
1479
1592
  return ended;
1480
1593
  }
1481
1594
  /**
@@ -1490,16 +1603,17 @@ export class ChannelRegistry {
1490
1603
  const current = this.desiredStates.get(key);
1491
1604
  if (current?.state !== 'tuned-out' || !current.tuneOut)
1492
1605
  return null;
1493
- current.wakeCount = (current.wakeCount ?? 0) + 1;
1606
+ const wakeCount = (current.wakeCount ?? 0) + 1;
1494
1607
  this.appendLifecycleEvent({
1495
1608
  kind: 'tune-out-wake',
1496
1609
  serverId,
1497
1610
  channelId,
1498
1611
  epochId: current.tuneOut.epochId,
1499
- wakeCount: current.wakeCount,
1612
+ wakeCount,
1500
1613
  timestamp: new Date().toISOString(),
1501
1614
  });
1502
- return { params: current.tuneOut, wakeCount: current.wakeCount };
1615
+ current.wakeCount = wakeCount;
1616
+ return { params: current.tuneOut, wakeCount };
1503
1617
  }
1504
1618
  /** Active tune-out params + wake count for a channel, or null. */
1505
1619
  getTuneOutState(serverId, channelId) {
@@ -1523,19 +1637,13 @@ export class ChannelRegistry {
1523
1637
  readCoordinatorState(stateId) {
1524
1638
  if (!this.store)
1525
1639
  return null;
1526
- try {
1527
- this.store.registerState({ id: stateId, strategy: 'snapshot' });
1528
- }
1529
- catch { /* already registered */ }
1640
+ ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
1530
1641
  return this.store.getStateJson(stateId);
1531
1642
  }
1532
1643
  writeCoordinatorState(stateId, value) {
1533
1644
  if (!this.store)
1534
1645
  return;
1535
- try {
1536
- this.store.registerState({ id: stateId, strategy: 'snapshot' });
1537
- }
1538
- catch { /* already registered */ }
1646
+ ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
1539
1647
  this.store.setStateJson(stateId, value);
1540
1648
  }
1541
1649
  /**
@@ -1566,13 +1674,13 @@ export class ChannelRegistry {
1566
1674
  : 'closed';
1567
1675
  this.setDesiredState(serverId, channel.id, desired, 'legacy-recipe-migration');
1568
1676
  }
1569
- this.migratedLegacyPolicies.add(serverId);
1570
1677
  this.appendLifecycleEvent({
1571
1678
  kind: 'legacy-policy-migrated',
1572
1679
  serverId,
1573
1680
  source: Array.isArray(policy) ? 'allow-list' : policy,
1574
1681
  timestamp: new Date().toISOString(),
1575
1682
  });
1683
+ this.migratedLegacyPolicies.add(serverId);
1576
1684
  }
1577
1685
  /**
1578
1686
  * True when the server's recipe subscription policy wants this channel
@@ -1688,9 +1796,9 @@ export class ChannelRegistry {
1688
1796
  });
1689
1797
  }
1690
1798
  }
1691
- // Announce policy admissions to the agent — nothing may start flowing
1692
- // traffic into their window without them being told, and told how to
1693
- // opt out (channel_close; their decision outranks policy).
1799
+ // Announce policy admissions to the agent — no channel may open without
1800
+ // them being told, and told how to opt out (channel_close; their
1801
+ // decision outranks policy).
1694
1802
  if (policyOpened.length > 0) {
1695
1803
  try {
1696
1804
  this.onChannelAutoOpened?.({
@@ -2048,11 +2156,13 @@ export class ChannelRegistry {
2048
2156
  // A tuned-out channel is transport-open but attention-diverted; a plain
2049
2157
  // open would silently discard the epoch (and its pending backlog dump).
2050
2158
  // Cancelling is the tune-out coordinator's flow, reached via its own
2051
- // tool — refuse with the pointer rather than eat the state.
2159
+ // tool — refuse with the pointer rather than eat the state. As an error
2160
+ // result, the agent reads the pointer itself; `data` names the refusal
2161
+ // for an in-process caller.
2052
2162
  if (this.getDesiredState(entry.serverId, input.channelId) === 'tuned-out') {
2053
2163
  return {
2054
2164
  success: false,
2055
- isError: false,
2165
+ isError: true,
2056
2166
  error: `Channel ${input.channelId} is tuned out. Cancel the tune-out ` +
2057
2167
  `(tune_out with mode: 'cancel') to resume normal attention — ` +
2058
2168
  `cancelling delivers the diverted backlog.`,
@@ -2189,7 +2299,7 @@ export class ChannelRegistry {
2189
2299
  if (entry.open || this.getDesiredState(entry.serverId, input.channelId) === 'open') {
2190
2300
  return {
2191
2301
  success: false,
2192
- error: `Channel is already open: ${input.channelId}. Use channel_close to leave it.`,
2302
+ error: `Channel is already open: ${input.channelId}. Use channel_close to close it.`,
2193
2303
  isError: true,
2194
2304
  };
2195
2305
  }
@@ -2295,12 +2405,13 @@ export class ChannelRegistry {
2295
2405
  */
2296
2406
  handleToolSkipReply(input) {
2297
2407
  // The self-wake itself is armed by the framework (which owns the
2298
- // EventGate) BEFORE this dispatch; when the gate is absent the framework
2299
- // strips the field so this confirmation stays truthful.
2300
- const wakeSecs = Number(input.wake_in_seconds);
2301
- const selfWake = Number.isFinite(wakeSecs) && wakeSecs > 0
2302
- ? Math.max(1, Math.min(3600, Math.floor(wakeSecs)))
2303
- : undefined;
2408
+ // EventGate) BEFORE its dispatch reaches this handler, from the same
2409
+ // reading, and the framework refuses a wake the host can't set before
2410
+ // dispatching. A caller of this registry's handleChannelToolCall
2411
+ // (AgentFramework.channels) goes past both, so its note names a wake
2412
+ // nothing armed.
2413
+ const wake = readSkipReplyWake(input);
2414
+ const selfWake = wake.kind === 'wake' ? wake.seconds : undefined;
2304
2415
  return {
2305
2416
  success: true,
2306
2417
  // The note says "ended the turn" — make it TRUE. Without endTurn the
@@ -2386,7 +2497,158 @@ export class ChannelRegistry {
2386
2497
  const home = this.homeChannelResolver?.(conversationId);
2387
2498
  return home ?? this.activeChannelResolver?.(conversationId) ?? this.defaultPublishChannel ?? null;
2388
2499
  }
2389
- async routeSpeech(conversationId, text,
2500
+ /**
2501
+ * Resolve a publish target to exactly one registered channel: `serverId`
2502
+ * plus `channelId` when the caller has the server, otherwise a channel id
2503
+ * registered by exactly one server. A shared id is refused, never resolved
2504
+ * to whichever server registered it first.
2505
+ */
2506
+ resolveDestination(target) {
2507
+ const entry = this.findExactEntry(target);
2508
+ if ('error' in entry)
2509
+ return entry;
2510
+ return {
2511
+ destination: {
2512
+ serverId: entry.entry.serverId,
2513
+ channelId: entry.entry.descriptor.id,
2514
+ ...(entry.entry.descriptor.label ? { label: entry.entry.descriptor.label } : {}),
2515
+ },
2516
+ };
2517
+ }
2518
+ findExactEntry(target) {
2519
+ // A supplied selector is checked, never read as omission: an empty or
2520
+ // non-string serverId would otherwise widen to "any server".
2521
+ if (typeof target.channelId !== 'string' || !target.channelId) {
2522
+ return { error: 'the destination names no channel id' };
2523
+ }
2524
+ if (target.serverId !== undefined && (typeof target.serverId !== 'string' || !target.serverId)) {
2525
+ return { error: 'serverId must name a server (omit it to resolve the channel id alone)' };
2526
+ }
2527
+ const matches = [...this.channels.values()].filter((e) => e.descriptor.id === target.channelId && (!target.serverId || e.serverId === target.serverId));
2528
+ if (matches.length === 0) {
2529
+ return {
2530
+ error: target.serverId
2531
+ ? `no registered channel "${target.channelId}" on server "${target.serverId}"`
2532
+ : `no registered channel "${target.channelId}"`,
2533
+ };
2534
+ }
2535
+ if (matches.length > 1) {
2536
+ return {
2537
+ error: `channel id "${target.channelId}" is registered by more than one MCPL server; the destination must name its server`,
2538
+ };
2539
+ }
2540
+ return { entry: matches[0] };
2541
+ }
2542
+ /**
2543
+ * Publish `text` to one registered channel and report what the attempt
2544
+ * established (PublishOutcome). The delivery executor behind plain speech
2545
+ * (deliverSpeech / routeSpeech) and resident resends of held drafts.
2546
+ * channel_publish (and publishForAgent, which shares its handler) resolves
2547
+ * and sends on its own path, and reads its answer through the same
2548
+ * publishReceiptOutcome and publishErrorOutcome.
2549
+ *
2550
+ * Resolution is exact (resolveDestination): `serverId` plus `channelId`
2551
+ * when the caller has the server, otherwise the channel id must be
2552
+ * registered by exactly one server (a shared id is refused, never routed
2553
+ * through whichever server came first). An omitted `serverId` means "not
2554
+ * in use"; a supplied one must be a non-empty server id, and an empty or
2555
+ * non-string selector is refused rather than read as omission. It is not
2556
+ * possible to send into a closed channel: a closed but registered
2557
+ * destination is opened first (`openSource` names why), once its server
2558
+ * and that server's channels.publish grant are known to take the send, so
2559
+ * a refused send opens nothing; and a failed open sends nothing.
2560
+ *
2561
+ * Only the connector's `delivered: true` confirms a post. `failed` means
2562
+ * nothing was posted: the attempt stopped before the request was written,
2563
+ * or the connector answered `delivered: false` and named no message (no
2564
+ * `messageId`, or null). Everything else is `unknown`: once the request
2565
+ * has been handed to the transport, an error response, a timeout, a lost
2566
+ * connection, or a missing, malformed or contradictory receipt (such as
2567
+ * `delivered: false` beside a message id, valid or not) means the post may
2568
+ * or may not exist, and the caller must not treat it as safe to retry
2569
+ * blindly.
2570
+ */
2571
+ async publish(conversationId, text, target, openSource = 'opened-by-delivery') {
2572
+ const at = () => Date.now();
2573
+ const found = this.findExactEntry(target);
2574
+ if ('error' in found)
2575
+ return { status: 'failed', reason: found.error, at: at() };
2576
+ const entry = found.entry;
2577
+ const destination = {
2578
+ serverId: entry.serverId,
2579
+ channelId: entry.descriptor.id,
2580
+ ...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
2581
+ };
2582
+ // A send that would be refused is refused before anything opens: a
2583
+ // closed channel opens only for words that can go out.
2584
+ const server = this.serverRegistry.getServer(entry.serverId);
2585
+ if (!server) {
2586
+ return { status: 'failed', destination, reason: `server "${entry.serverId}" not found`, at: at() };
2587
+ }
2588
+ // §14.1: channels/publish requires channels.publish in the grant. The
2589
+ // host not sending is the enforcement.
2590
+ if (!CapabilityGrant.of(server).has('channels.publish')) {
2591
+ return {
2592
+ status: 'failed',
2593
+ destination,
2594
+ reason: `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`,
2595
+ at: at(),
2596
+ };
2597
+ }
2598
+ if (!entry.open) {
2599
+ try {
2600
+ await this.openChannelNow(entry, openSource);
2601
+ if (target.routed) {
2602
+ console.error(`[routeSpeech] ${conversationId}: locus ${logValue(entry.descriptor.id)} was closed — opened by delivery (speech implies engagement)`);
2603
+ }
2604
+ this.emitTraceFn({
2605
+ type: 'mcpl:channel-opened-by-send',
2606
+ serverId: entry.serverId,
2607
+ channelId: entry.descriptor.id,
2608
+ });
2609
+ if (openSource === 'opened-by-delivery') {
2610
+ try {
2611
+ this.onChannelAutoOpened?.({
2612
+ conversationId,
2613
+ serverId: entry.serverId,
2614
+ source: 'opened-by-delivery',
2615
+ channels: [{ channelId: entry.descriptor.id, label: entry.descriptor.label }],
2616
+ });
2617
+ }
2618
+ catch (err) {
2619
+ console.error('onChannelAutoOpened (delivery) failed:', err);
2620
+ }
2621
+ }
2622
+ }
2623
+ catch (err) {
2624
+ return {
2625
+ status: 'failed',
2626
+ destination,
2627
+ reason: `channel is closed and open failed: ${connectorText(err instanceof Error ? err.message : String(err))}`,
2628
+ at: at(),
2629
+ };
2630
+ }
2631
+ }
2632
+ let result;
2633
+ try {
2634
+ result = await server.sendChannelsPublish({
2635
+ conversationId,
2636
+ channelId: entry.descriptor.id,
2637
+ content: [{ type: 'text', text }],
2638
+ });
2639
+ }
2640
+ catch (err) {
2641
+ return publishErrorOutcome(err, destination, at());
2642
+ }
2643
+ return publishReceiptOutcome(result, destination, at());
2644
+ }
2645
+ /**
2646
+ * Plain speech for one turn segment: publish `text` to the turn's frozen
2647
+ * locus and report the PublishOutcome. A failure (or an uncertain outcome)
2648
+ * is surfaced as a trace and through onRouteFailure, so the agent learns
2649
+ * its words did not (or may not have) reached anyone.
2650
+ */
2651
+ async deliverSpeech(conversationId, text,
2390
2652
  /** The turn's FROZEN locus, snapshotted once by the caller (resolveLocus
2391
2653
  * at turn start) and passed to every segment of the turn. Mandatory:
2392
2654
  * there is deliberately no live-resolution fallback here — a late
@@ -2394,110 +2656,75 @@ export class ChannelRegistry {
2394
2656
  * stale global default and land the reply in the wrong channel (item-3,
2395
2657
  * PR #32, and the 2026-07-22 Sol DM misroute). Explicit `null` means
2396
2658
  * "this turn is pinned to no locus": fail loudly rather than guess. */
2397
- locusChannelId) {
2398
- // Surface a routing failure: emit a trace AND notify the host (which drops
2399
- // a `[discord-send-failed]` marker into chronicle) so the agent learns her
2400
- // reply never reached the human, instead of it vanishing silently.
2401
- const fail = (channelId, reason) => {
2402
- console.error(`[routeSpeech] ${conversationId}: ${reason} — speech NOT routed (${text.length} chars stay in chronicle)`);
2659
+ locusChannelId,
2660
+ /** `heldOnFailure`: the caller holds a `failed` delivery's words as a
2661
+ * draft with its own notice, so no failure marker is written for it.
2662
+ * An `unknown` outcome still gets its marker. */
2663
+ opts) {
2664
+ const fail = (channelId, reason, outcome) => {
2665
+ const status = outcome.status === 'unknown' ? 'unknown' : 'failed';
2666
+ const detail = outcome.detail !== undefined ? connectorText(outcome.detail) : undefined;
2667
+ const detailText = detail !== undefined ? `; connector detail: ${detail}` : '';
2668
+ console.error(`[routeSpeech] ${conversationId}: ${reason}${detailText} — speech ${status === 'unknown' ? 'delivery NOT confirmed' : 'NOT routed'} (${text.length} chars stay in chronicle)`);
2403
2669
  this.emitTraceFn({
2404
2670
  type: 'mcpl:speech-route-failed',
2405
2671
  conversationId,
2406
2672
  channelId: channelId ?? '',
2407
2673
  reason,
2408
2674
  textLen: text.length,
2675
+ outcome: status,
2676
+ ...(detail !== undefined ? { detail } : {}),
2409
2677
  });
2410
- this.onRouteFailure?.({ conversationId, channelId, reason, textLen: text.length });
2411
- return null;
2678
+ if (status === 'unknown' || !opts?.heldOnFailure) {
2679
+ this.onRouteFailure?.({ conversationId, channelId, reason, textLen: text.length, outcome: status, ...(detail !== undefined ? { detail } : {}) });
2680
+ }
2681
+ return outcome;
2412
2682
  };
2413
2683
  // Runtime backstop for JS callers the compiler can't see: an omitted
2414
2684
  // locus is a routing bug at the call site, never something to paper over
2415
2685
  // with a live re-resolution.
2416
2686
  if (locusChannelId === undefined) {
2417
- return fail(null, 'caller passed no locus (routing bug: every speech path must snapshot the turn locus)');
2687
+ const reason = 'caller passed no locus (routing bug: every speech path must snapshot the turn locus)';
2688
+ return fail(null, reason, { status: 'failed', reason, at: Date.now() });
2418
2689
  }
2419
- const channelId = locusChannelId;
2420
- if (!channelId) {
2690
+ if (!locusChannelId) {
2421
2691
  // The turn froze with no locus (no home, no triggering channel, no
2422
2692
  // global inbound ever seen) — the agent was told its prose stays in
2423
2693
  // the archive; honor that.
2424
- return fail(null, 'turn has no locus (no home/trigger channel; nothing to deliver into)');
2694
+ const reason = 'turn has no locus (no home/trigger channel; nothing to deliver into)';
2695
+ return fail(null, reason, { status: 'failed', reason, at: Date.now() });
2425
2696
  }
2426
- const entry = this.findChannelEntry(channelId);
2427
- if (!entry) {
2428
- return fail(channelId, `no registered channel for locus "${channelId}"`);
2429
- }
2430
- // INVARIANT: it is not possible to send into a closed channel. Speech
2431
- // routed into a closed-but-registered locus (the canonical case: a DM
2432
- // that woke the agent — DMs register closed) OPENS the channel first,
2433
- // so typing indicators, reaction machinery, and inbound forwarding come
2434
- // alive with the reply. If the open fails, the speech does NOT go out:
2435
- // a half-alive delivery is worse than a loud marker.
2436
- if (!entry.open) {
2437
- try {
2438
- await this.openChannelNow(entry, 'opened-by-delivery');
2439
- console.error(`[routeSpeech] ${conversationId}: locus ${channelId} was closed — opened by delivery (speech implies engagement)`);
2440
- this.emitTraceFn({
2441
- type: 'mcpl:channel-opened-by-send',
2442
- serverId: entry.serverId,
2443
- channelId,
2444
- });
2445
- try {
2446
- this.onChannelAutoOpened?.({
2447
- conversationId,
2448
- serverId: entry.serverId,
2449
- source: 'opened-by-delivery',
2450
- channels: [{ channelId, label: entry.descriptor.label }],
2451
- });
2452
- }
2453
- catch (err) {
2454
- console.error('onChannelAutoOpened (delivery) failed:', err);
2455
- }
2456
- }
2457
- catch (err) {
2458
- return fail(channelId, `locus channel is closed and open failed: ${err.message}`);
2459
- }
2697
+ const outcome = await this.publish(conversationId, text, { channelId: locusChannelId, routed: true });
2698
+ const channelId = outcome.destination?.channelId ?? locusChannelId;
2699
+ if (outcome.status !== 'delivered') {
2700
+ return fail(channelId, outcome.reason ?? 'delivery not confirmed', outcome);
2460
2701
  }
2461
- const server = this.serverRegistry.getServer(entry.serverId);
2462
- if (!server) {
2463
- return fail(channelId, `server "${entry.serverId}" not found`);
2464
- }
2465
- // §14.1: channels/publish requires channels.publish in the grant. The
2466
- // host not sending is the enforcement — a send to an ungranted server
2467
- // would have it act on authority it was never told it has.
2468
- if (!CapabilityGrant.of(server).has('channels.publish')) {
2469
- return fail(channelId, `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`);
2470
- }
2471
- const publishParams = {
2472
- conversationId,
2473
- channelId,
2474
- content: [{ type: 'text', text }],
2475
- };
2476
- const result = await server.sendChannelsPublish(publishParams);
2477
- const delivered = result?.delivered ?? true;
2478
- // Surface the posted message's id (ChannelsPublishResult.messageId) so
2479
- // trace consumers can act on the just-posted message — e.g. a TTS-relay
2480
- // tap editing it down to the words actually voiced on interruption.
2481
- // Previously this was silently dropped here.
2482
- const messageId = result?.messageId;
2483
- // The server accepted the publish RPC but reported the message was not
2484
- // actually delivered (e.g. missing Send Messages permission). Previously
2485
- // this returned `{ delivered: true }`, masking the failure. Surface it.
2486
- if (delivered === false) {
2487
- return fail(channelId, `server "${entry.serverId}" reported delivered:false for "${channelId}"`);
2488
- }
2489
- console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${channelId} (server=${entry.serverId}, delivered=${delivered})`);
2702
+ console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${logValue(channelId)} (server=${outcome.destination.serverId}, delivered=true)`);
2490
2703
  this.emitTraceFn({
2491
2704
  type: 'mcpl:speech-routed',
2492
2705
  conversationId,
2493
- serverId: entry.serverId,
2706
+ serverId: outcome.destination.serverId,
2494
2707
  channelId,
2495
- delivered,
2708
+ delivered: true,
2496
2709
  textLen: text.length,
2497
2710
  text,
2498
- ...(messageId !== undefined ? { messageId } : {}),
2711
+ // Surface the posted message's id (ChannelsPublishResult.messageId) so
2712
+ // trace consumers can act on the just-posted message — e.g. a TTS-relay
2713
+ // tap editing it down to the words actually voiced on interruption.
2714
+ ...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
2499
2715
  });
2500
- return { delivered, channelId, ...(messageId !== undefined ? { messageId } : {}) };
2716
+ return outcome;
2717
+ }
2718
+ /** deliverSpeech, reduced to the confirmed delivery (null when there was none). */
2719
+ async routeSpeech(conversationId, text, locusChannelId) {
2720
+ const outcome = await this.deliverSpeech(conversationId, text, locusChannelId);
2721
+ if (outcome.status !== 'delivered')
2722
+ return null;
2723
+ return {
2724
+ delivered: true,
2725
+ channelId: outcome.destination.channelId,
2726
+ ...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
2727
+ };
2501
2728
  }
2502
2729
  async handleToolPublish(input) {
2503
2730
  // Resolve content: accept both `content` and `text` (backward compat)
@@ -2534,32 +2761,46 @@ export class ChannelRegistry {
2534
2761
  isError: true,
2535
2762
  };
2536
2763
  }
2537
- try {
2538
- if (!CapabilityGrant.of(server).has('channels.publish')) {
2539
- return {
2540
- success: false,
2541
- error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
2542
- isError: true,
2543
- };
2544
- }
2545
- const publishParams = {
2546
- conversationId: '', // Framework will fill this when wired
2547
- channelId,
2548
- content: [{ type: 'text', text: messageText }],
2549
- };
2550
- const result = await server.sendChannelsPublish(publishParams);
2551
- return {
2552
- success: true,
2553
- data: result ?? { delivered: true },
2554
- };
2555
- }
2556
- catch (err) {
2764
+ if (!CapabilityGrant.of(server).has('channels.publish')) {
2557
2765
  return {
2558
2766
  success: false,
2559
- error: `Failed to publish to channel: ${err.message}`,
2767
+ error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
2560
2768
  isError: true,
2561
2769
  };
2562
2770
  }
2771
+ const publishParams = {
2772
+ conversationId: '', // Framework will fill this when wired
2773
+ channelId,
2774
+ content: [{ type: 'text', text: messageText }],
2775
+ };
2776
+ const destination = {
2777
+ serverId: entry.serverId,
2778
+ channelId: entry.descriptor.id,
2779
+ ...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
2780
+ };
2781
+ // The answer counts by the same rule as plain speech's: only the
2782
+ // connector's delivered:true confirms a post.
2783
+ let result;
2784
+ let outcome;
2785
+ try {
2786
+ result = await server.sendChannelsPublish(publishParams);
2787
+ outcome = publishReceiptOutcome(result, destination, Date.now());
2788
+ }
2789
+ catch (err) {
2790
+ outcome = publishErrorOutcome(err, destination, Date.now());
2791
+ }
2792
+ if (outcome.status === 'delivered')
2793
+ return { success: true, data: result };
2794
+ // The connector's data may say what a multi-part send already posted.
2795
+ const detail = outcome.status === 'unknown' && outcome.detail !== undefined ? ` Connector detail: ${connectorText(outcome.detail)}` : '';
2796
+ return {
2797
+ success: false,
2798
+ error: (outcome.status === 'failed'
2799
+ ? `Publish to ${channelId} failed: ${outcome.reason}. Nothing was posted.`
2800
+ : `Publish to ${channelId} wasn't confirmed: ${outcome.reason}. ` +
2801
+ 'It may or may not have been posted, so sending it again could post it twice.') + detail,
2802
+ isError: true,
2803
+ };
2563
2804
  }
2564
2805
  }
2565
2806
  //# sourceMappingURL=channel-registry.js.map