@animalabs/agent-framework 0.22.2 → 0.22.4

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 (940) hide show
  1. package/README.md +3 -1
  2. package/dist/src/agent.d.ts +77 -12
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +143 -41
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.js +1 -1
  7. package/dist/src/api/mcp-server-core.js.map +1 -1
  8. package/dist/src/api/server.d.ts.map +1 -1
  9. package/dist/src/api/server.js +5 -1
  10. package/dist/src/api/server.js.map +1 -1
  11. package/dist/src/api/types.d.ts +1 -1
  12. package/dist/src/api/types.d.ts.map +1 -1
  13. package/dist/src/branch-names.d.ts +14 -0
  14. package/dist/src/branch-names.d.ts.map +1 -0
  15. package/dist/src/branch-names.js +22 -0
  16. package/dist/src/branch-names.js.map +1 -0
  17. package/dist/src/closest-names.d.ts +28 -0
  18. package/dist/src/closest-names.d.ts.map +1 -0
  19. package/dist/src/closest-names.js +98 -0
  20. package/dist/src/closest-names.js.map +1 -0
  21. package/dist/src/code-execution/py-runner.d.ts +16 -5
  22. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  23. package/dist/src/code-execution/py-runner.js +186 -74
  24. package/dist/src/code-execution/py-runner.js.map +1 -1
  25. package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
  26. package/dist/src/code-execution/runtime-py.js +49 -3
  27. package/dist/src/code-execution/runtime-py.js.map +1 -1
  28. package/dist/src/code-execution/tool-definition.d.ts +12 -1
  29. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  30. package/dist/src/code-execution/tool-definition.js +21 -3
  31. package/dist/src/code-execution/tool-definition.js.map +1 -1
  32. package/dist/src/config-checks.d.ts +28 -0
  33. package/dist/src/config-checks.d.ts.map +1 -0
  34. package/dist/src/config-checks.js +52 -0
  35. package/dist/src/config-checks.js.map +1 -0
  36. package/dist/src/deadline-timer.d.ts +21 -0
  37. package/dist/src/deadline-timer.d.ts.map +1 -0
  38. package/dist/src/deadline-timer.js +43 -0
  39. package/dist/src/deadline-timer.js.map +1 -0
  40. package/dist/src/error-message.d.ts +30 -0
  41. package/dist/src/error-message.d.ts.map +1 -0
  42. package/dist/src/error-message.js +50 -0
  43. package/dist/src/error-message.js.map +1 -0
  44. package/dist/src/framework.d.ts +828 -88
  45. package/dist/src/framework.d.ts.map +1 -1
  46. package/dist/src/framework.js +5011 -1326
  47. package/dist/src/framework.js.map +1 -1
  48. package/dist/src/gate/event-gate.d.ts +8 -0
  49. package/dist/src/gate/event-gate.d.ts.map +1 -1
  50. package/dist/src/gate/event-gate.js +27 -3
  51. package/dist/src/gate/event-gate.js.map +1 -1
  52. package/dist/src/index.d.ts +4 -2
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/index.js +4 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/mcpl/channel-registry.d.ts +144 -6
  57. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  58. package/dist/src/mcpl/channel-registry.js +424 -263
  59. package/dist/src/mcpl/channel-registry.js.map +1 -1
  60. package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
  61. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  62. package/dist/src/mcpl/checkpoint-manager.js +91 -30
  63. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  64. package/dist/src/mcpl/conversation-router.d.ts +19 -3
  65. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  66. package/dist/src/mcpl/conversation-router.js +23 -8
  67. package/dist/src/mcpl/conversation-router.js.map +1 -1
  68. package/dist/src/mcpl/convert-block.d.ts +20 -0
  69. package/dist/src/mcpl/convert-block.d.ts.map +1 -0
  70. package/dist/src/mcpl/convert-block.js +89 -0
  71. package/dist/src/mcpl/convert-block.js.map +1 -0
  72. package/dist/src/mcpl/errors.d.ts +13 -0
  73. package/dist/src/mcpl/errors.d.ts.map +1 -1
  74. package/dist/src/mcpl/errors.js +28 -0
  75. package/dist/src/mcpl/errors.js.map +1 -1
  76. package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
  77. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  78. package/dist/src/mcpl/hook-orchestrator.js +83 -72
  79. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  80. package/dist/src/mcpl/inbound-source.d.ts +114 -0
  81. package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
  82. package/dist/src/mcpl/inbound-source.js +83 -0
  83. package/dist/src/mcpl/inbound-source.js.map +1 -0
  84. package/dist/src/mcpl/index.d.ts +3 -1
  85. package/dist/src/mcpl/index.d.ts.map +1 -1
  86. package/dist/src/mcpl/index.js +3 -1
  87. package/dist/src/mcpl/index.js.map +1 -1
  88. package/dist/src/mcpl/inference-router.d.ts +15 -11
  89. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  90. package/dist/src/mcpl/inference-router.js +153 -84
  91. package/dist/src/mcpl/inference-router.js.map +1 -1
  92. package/dist/src/mcpl/push-coalescer.d.ts +33 -11
  93. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  94. package/dist/src/mcpl/push-coalescer.js +52 -20
  95. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  96. package/dist/src/mcpl/push-handler.d.ts +16 -9
  97. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  98. package/dist/src/mcpl/push-handler.js +18 -83
  99. package/dist/src/mcpl/push-handler.js.map +1 -1
  100. package/dist/src/mcpl/reference-fetcher.d.ts +14 -2
  101. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  102. package/dist/src/mcpl/reference-fetcher.js +72 -30
  103. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  104. package/dist/src/mcpl/references.d.ts +47 -12
  105. package/dist/src/mcpl/references.d.ts.map +1 -1
  106. package/dist/src/mcpl/references.js +74 -21
  107. package/dist/src/mcpl/references.js.map +1 -1
  108. package/dist/src/mcpl/server-connection.d.ts +89 -10
  109. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  110. package/dist/src/mcpl/server-connection.js +405 -129
  111. package/dist/src/mcpl/server-connection.js.map +1 -1
  112. package/dist/src/mcpl/server-registry.d.ts +10 -1
  113. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  114. package/dist/src/mcpl/server-registry.js +14 -3
  115. package/dist/src/mcpl/server-registry.js.map +1 -1
  116. package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
  117. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
  118. package/dist/src/mcpl/skip-reply-wake.js +55 -0
  119. package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
  120. package/dist/src/mcpl/transport.d.ts +51 -2
  121. package/dist/src/mcpl/transport.d.ts.map +1 -1
  122. package/dist/src/mcpl/transport.js +114 -20
  123. package/dist/src/mcpl/transport.js.map +1 -1
  124. package/dist/src/mcpl/types.d.ts +14 -3
  125. package/dist/src/mcpl/types.d.ts.map +1 -1
  126. package/dist/src/mcpl/types.js.map +1 -1
  127. package/dist/src/mcpl/visible-content.d.ts +15 -0
  128. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  129. package/dist/src/mcpl/visible-content.js +25 -0
  130. package/dist/src/mcpl/visible-content.js.map +1 -1
  131. package/dist/src/module-registry.d.ts +19 -1
  132. package/dist/src/module-registry.d.ts.map +1 -1
  133. package/dist/src/module-registry.js +54 -25
  134. package/dist/src/module-registry.js.map +1 -1
  135. package/dist/src/modules/api/index.js +1 -1
  136. package/dist/src/modules/api/index.js.map +1 -1
  137. package/dist/src/modules/discord/discord-js-client.d.ts +1 -0
  138. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  139. package/dist/src/modules/discord/discord-js-client.js +25 -9
  140. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  141. package/dist/src/modules/discord/index.d.ts +29 -3
  142. package/dist/src/modules/discord/index.d.ts.map +1 -1
  143. package/dist/src/modules/discord/index.js +379 -143
  144. package/dist/src/modules/discord/index.js.map +1 -1
  145. package/dist/src/modules/discord/types.d.ts +14 -1
  146. package/dist/src/modules/discord/types.d.ts.map +1 -1
  147. package/dist/src/modules/health/index.d.ts.map +1 -1
  148. package/dist/src/modules/health/index.js +2 -1
  149. package/dist/src/modules/health/index.js.map +1 -1
  150. package/dist/src/modules/history/index.d.ts +3 -1
  151. package/dist/src/modules/history/index.d.ts.map +1 -1
  152. package/dist/src/modules/history/index.js +359 -127
  153. package/dist/src/modules/history/index.js.map +1 -1
  154. package/dist/src/modules/history/semantic.d.ts +28 -1
  155. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  156. package/dist/src/modules/history/semantic.js +177 -32
  157. package/dist/src/modules/history/semantic.js.map +1 -1
  158. package/dist/src/modules/unknown-tool.d.ts +10 -0
  159. package/dist/src/modules/unknown-tool.d.ts.map +1 -0
  160. package/dist/src/modules/unknown-tool.js +17 -0
  161. package/dist/src/modules/unknown-tool.js.map +1 -0
  162. package/dist/src/modules/workspace/disk-agreement.d.ts +32 -2
  163. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  164. package/dist/src/modules/workspace/disk-agreement.js +30 -2
  165. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  166. package/dist/src/modules/workspace/effects.d.ts +64 -6
  167. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  168. package/dist/src/modules/workspace/effects.js +291 -44
  169. package/dist/src/modules/workspace/effects.js.map +1 -1
  170. package/dist/src/modules/workspace/index.d.ts +119 -23
  171. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  172. package/dist/src/modules/workspace/index.js +793 -247
  173. package/dist/src/modules/workspace/index.js.map +1 -1
  174. package/dist/src/modules/workspace/observe.d.ts +75 -8
  175. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  176. package/dist/src/modules/workspace/observe.js +174 -14
  177. package/dist/src/modules/workspace/observe.js.map +1 -1
  178. package/dist/src/modules/workspace/reconcile.d.ts +58 -7
  179. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  180. package/dist/src/modules/workspace/reconcile.js +521 -56
  181. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  182. package/dist/src/modules/workspace/types.d.ts +18 -4
  183. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  184. package/dist/src/modules/workspace/types.js.map +1 -1
  185. package/dist/src/modules/workspace/watcher.d.ts +7 -2
  186. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  187. package/dist/src/modules/workspace/watcher.js +28 -4
  188. package/dist/src/modules/workspace/watcher.js.map +1 -1
  189. package/dist/src/prose-drafts.d.ts +240 -0
  190. package/dist/src/prose-drafts.d.ts.map +1 -0
  191. package/dist/src/prose-drafts.js +362 -0
  192. package/dist/src/prose-drafts.js.map +1 -0
  193. package/dist/src/prose-segments.d.ts +21 -2
  194. package/dist/src/prose-segments.d.ts.map +1 -1
  195. package/dist/src/prose-segments.js +46 -9
  196. package/dist/src/prose-segments.js.map +1 -1
  197. package/dist/src/recovery/offline-branch.d.ts +1 -0
  198. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  199. package/dist/src/recovery/offline-branch.js +3 -1
  200. package/dist/src/recovery/offline-branch.js.map +1 -1
  201. package/dist/src/safe-slice.d.ts +5 -1
  202. package/dist/src/safe-slice.d.ts.map +1 -1
  203. package/dist/src/safe-slice.js +9 -1
  204. package/dist/src/safe-slice.js.map +1 -1
  205. package/dist/src/thinking-token-stamp.d.ts +12 -0
  206. package/dist/src/thinking-token-stamp.d.ts.map +1 -1
  207. package/dist/src/thinking-token-stamp.js +34 -3
  208. package/dist/src/thinking-token-stamp.js.map +1 -1
  209. package/dist/src/tool-image-ledger.d.ts +87 -19
  210. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  211. package/dist/src/tool-image-ledger.js +135 -32
  212. package/dist/src/tool-image-ledger.js.map +1 -1
  213. package/dist/src/tool-presentation.d.ts +9 -0
  214. package/dist/src/tool-presentation.d.ts.map +1 -1
  215. package/dist/src/tool-presentation.js +257 -60
  216. package/dist/src/tool-presentation.js.map +1 -1
  217. package/dist/src/tool-result-guard.d.ts.map +1 -1
  218. package/dist/src/tool-result-guard.js +7 -10
  219. package/dist/src/tool-result-guard.js.map +1 -1
  220. package/dist/src/tool-result-history.d.ts +32 -3
  221. package/dist/src/tool-result-history.d.ts.map +1 -1
  222. package/dist/src/tool-result-history.js +106 -19
  223. package/dist/src/tool-result-history.js.map +1 -1
  224. package/dist/src/tune-out/coordinator.d.ts +25 -1
  225. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  226. package/dist/src/tune-out/coordinator.js +260 -65
  227. package/dist/src/tune-out/coordinator.js.map +1 -1
  228. package/dist/src/types/agent.d.ts +17 -5
  229. package/dist/src/types/agent.d.ts.map +1 -1
  230. package/dist/src/types/events.d.ts +17 -0
  231. package/dist/src/types/events.d.ts.map +1 -1
  232. package/dist/src/types/framework.d.ts +21 -5
  233. package/dist/src/types/framework.d.ts.map +1 -1
  234. package/dist/src/types/inference-log.d.ts +1 -1
  235. package/dist/src/types/inference-log.d.ts.map +1 -1
  236. package/dist/src/types/module.d.ts +23 -4
  237. package/dist/src/types/module.d.ts.map +1 -1
  238. package/dist/src/types/trace.d.ts +95 -6
  239. package/dist/src/types/trace.d.ts.map +1 -1
  240. package/dist/src/usage/usage-tracker.d.ts +5 -0
  241. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  242. package/dist/src/usage/usage-tracker.js +35 -8
  243. package/dist/src/usage/usage-tracker.js.map +1 -1
  244. package/package.json +6 -4
  245. package/src/agent.ts +169 -41
  246. package/src/api/mcp-server-core.ts +1 -1
  247. package/src/api/server.ts +4 -1
  248. package/src/api/types.ts +1 -1
  249. package/src/branch-names.ts +19 -0
  250. package/src/closest-names.ts +94 -0
  251. package/src/code-execution/py-runner.ts +200 -76
  252. package/src/code-execution/runtime-py.ts +49 -3
  253. package/src/code-execution/tool-definition.ts +28 -4
  254. package/src/config-checks.ts +48 -0
  255. package/src/deadline-timer.ts +44 -0
  256. package/src/error-message.ts +48 -0
  257. package/src/framework.ts +5352 -1388
  258. package/src/gate/event-gate.ts +28 -3
  259. package/src/index.ts +11 -2
  260. package/src/mcpl/channel-registry.ts +517 -286
  261. package/src/mcpl/checkpoint-manager.ts +104 -29
  262. package/src/mcpl/conversation-router.ts +28 -8
  263. package/src/mcpl/convert-block.ts +97 -0
  264. package/src/mcpl/errors.ts +28 -0
  265. package/src/mcpl/hook-orchestrator.ts +84 -77
  266. package/src/mcpl/inbound-source.ts +156 -0
  267. package/src/mcpl/index.ts +10 -1
  268. package/src/mcpl/inference-router.ts +174 -99
  269. package/src/mcpl/push-coalescer.ts +60 -24
  270. package/src/mcpl/push-handler.ts +20 -90
  271. package/src/mcpl/reference-fetcher.ts +71 -26
  272. package/src/mcpl/references.ts +81 -22
  273. package/src/mcpl/server-connection.ts +427 -132
  274. package/src/mcpl/server-registry.ts +15 -4
  275. package/src/mcpl/skip-reply-wake.ts +73 -0
  276. package/src/mcpl/transport.ts +120 -18
  277. package/src/mcpl/types.ts +14 -3
  278. package/src/mcpl/visible-content.ts +27 -0
  279. package/src/module-registry.ts +58 -23
  280. package/src/modules/api/index.ts +1 -1
  281. package/src/modules/discord/discord-js-client.ts +26 -10
  282. package/src/modules/discord/index.ts +391 -158
  283. package/src/modules/discord/types.ts +15 -2
  284. package/src/modules/health/index.ts +2 -1
  285. package/src/modules/history/index.ts +410 -120
  286. package/src/modules/history/semantic.ts +189 -32
  287. package/src/modules/unknown-tool.ts +16 -0
  288. package/src/modules/workspace/disk-agreement.ts +51 -3
  289. package/src/modules/workspace/effects.ts +279 -35
  290. package/src/modules/workspace/index.ts +810 -260
  291. package/src/modules/workspace/observe.ts +194 -20
  292. package/src/modules/workspace/reconcile.ts +619 -64
  293. package/src/modules/workspace/types.ts +18 -4
  294. package/src/modules/workspace/watcher.ts +27 -4
  295. package/src/prose-drafts.ts +481 -0
  296. package/src/prose-segments.ts +51 -8
  297. package/src/recovery/offline-branch.ts +4 -1
  298. package/src/safe-slice.ts +9 -1
  299. package/src/thinking-token-stamp.ts +34 -3
  300. package/src/tool-image-ledger.ts +153 -34
  301. package/src/tool-presentation.ts +224 -40
  302. package/src/tool-result-guard.ts +7 -8
  303. package/src/tool-result-history.ts +124 -20
  304. package/src/tune-out/coordinator.ts +259 -65
  305. package/src/types/agent.ts +17 -7
  306. package/src/types/events.ts +17 -0
  307. package/src/types/framework.ts +21 -5
  308. package/src/types/inference-log.ts +1 -1
  309. package/src/types/module.ts +24 -4
  310. package/src/types/trace.ts +101 -6
  311. package/src/usage/usage-tracker.ts +32 -8
  312. package/dist/test/activation-request-sanitize.test.d.ts +0 -2
  313. package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
  314. package/dist/test/activation-request-sanitize.test.js +0 -89
  315. package/dist/test/activation-request-sanitize.test.js.map +0 -1
  316. package/dist/test/agent-cache-ttl.test.d.ts +0 -2
  317. package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
  318. package/dist/test/agent-cache-ttl.test.js +0 -41
  319. package/dist/test/agent-cache-ttl.test.js.map +0 -1
  320. package/dist/test/agent-runtime-settings.test.d.ts +0 -2
  321. package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
  322. package/dist/test/agent-runtime-settings.test.js +0 -1598
  323. package/dist/test/agent-runtime-settings.test.js.map +0 -1
  324. package/dist/test/api-admin-gate.test.d.ts +0 -2
  325. package/dist/test/api-admin-gate.test.d.ts.map +0 -1
  326. package/dist/test/api-admin-gate.test.js +0 -116
  327. package/dist/test/api-admin-gate.test.js.map +0 -1
  328. package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
  329. package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
  330. package/dist/test/assistant-persist-refusal.test.js +0 -63
  331. package/dist/test/assistant-persist-refusal.test.js.map +0 -1
  332. package/dist/test/batched-wake-locus.test.d.ts +0 -2
  333. package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
  334. package/dist/test/batched-wake-locus.test.js +0 -166
  335. package/dist/test/batched-wake-locus.test.js.map +0 -1
  336. package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
  337. package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
  338. package/dist/test/busy-agent-scheduler.test.js +0 -92
  339. package/dist/test/busy-agent-scheduler.test.js.map +0 -1
  340. package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
  341. package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
  342. package/dist/test/channel-incoming-targeting.test.js +0 -81
  343. package/dist/test/channel-incoming-targeting.test.js.map +0 -1
  344. package/dist/test/channel-label-history.test.d.ts +0 -2
  345. package/dist/test/channel-label-history.test.d.ts.map +0 -1
  346. package/dist/test/channel-label-history.test.js +0 -424
  347. package/dist/test/channel-label-history.test.js.map +0 -1
  348. package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
  349. package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
  350. package/dist/test/channel-lifecycle-provenance.test.js +0 -47
  351. package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
  352. package/dist/test/channel-registry-routing.test.d.ts +0 -2
  353. package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
  354. package/dist/test/channel-registry-routing.test.js +0 -446
  355. package/dist/test/channel-registry-routing.test.js.map +0 -1
  356. package/dist/test/channel-registry-typing.test.d.ts +0 -2
  357. package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
  358. package/dist/test/channel-registry-typing.test.js +0 -91
  359. package/dist/test/channel-registry-typing.test.js.map +0 -1
  360. package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
  361. package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
  362. package/dist/test/channels-changed-respond-first.test.js +0 -74
  363. package/dist/test/channels-changed-respond-first.test.js.map +0 -1
  364. package/dist/test/checkpoint-attribution.test.d.ts +0 -2
  365. package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
  366. package/dist/test/checkpoint-attribution.test.js +0 -200
  367. package/dist/test/checkpoint-attribution.test.js.map +0 -1
  368. package/dist/test/code-execution.test.d.ts +0 -11
  369. package/dist/test/code-execution.test.d.ts.map +0 -1
  370. package/dist/test/code-execution.test.js +0 -1272
  371. package/dist/test/code-execution.test.js.map +0 -1
  372. package/dist/test/component-defaults.test.d.ts +0 -2
  373. package/dist/test/component-defaults.test.d.ts.map +0 -1
  374. package/dist/test/component-defaults.test.js +0 -54
  375. package/dist/test/component-defaults.test.js.map +0 -1
  376. package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
  377. package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
  378. package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
  379. package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
  380. package/dist/test/conversation-router.test.d.ts +0 -2
  381. package/dist/test/conversation-router.test.d.ts.map +0 -1
  382. package/dist/test/conversation-router.test.js +0 -174
  383. package/dist/test/conversation-router.test.js.map +0 -1
  384. package/dist/test/conversation-routing.test.d.ts +0 -7
  385. package/dist/test/conversation-routing.test.d.ts.map +0 -1
  386. package/dist/test/conversation-routing.test.js +0 -621
  387. package/dist/test/conversation-routing.test.js.map +0 -1
  388. package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
  389. package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
  390. package/dist/test/deferred-wake-integrity.test.js +0 -320
  391. package/dist/test/deferred-wake-integrity.test.js.map +0 -1
  392. package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
  393. package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
  394. package/dist/test/discord-awareness-outbox.test.js +0 -371
  395. package/dist/test/discord-awareness-outbox.test.js.map +0 -1
  396. package/dist/test/discord-history-delete-window.test.d.ts +0 -2
  397. package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
  398. package/dist/test/discord-history-delete-window.test.js +0 -81
  399. package/dist/test/discord-history-delete-window.test.js.map +0 -1
  400. package/dist/test/discord-history-sync.test.d.ts +0 -2
  401. package/dist/test/discord-history-sync.test.d.ts.map +0 -1
  402. package/dist/test/discord-history-sync.test.js +0 -56
  403. package/dist/test/discord-history-sync.test.js.map +0 -1
  404. package/dist/test/discord-typing-keepalive.test.d.ts +0 -2
  405. package/dist/test/discord-typing-keepalive.test.d.ts.map +0 -1
  406. package/dist/test/discord-typing-keepalive.test.js +0 -77
  407. package/dist/test/discord-typing-keepalive.test.js.map +0 -1
  408. package/dist/test/ephemeral-settle.test.d.ts +0 -2
  409. package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
  410. package/dist/test/ephemeral-settle.test.js +0 -354
  411. package/dist/test/ephemeral-settle.test.js.map +0 -1
  412. package/dist/test/event-gate-passthrough.test.d.ts +0 -15
  413. package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
  414. package/dist/test/event-gate-passthrough.test.js +0 -289
  415. package/dist/test/event-gate-passthrough.test.js.map +0 -1
  416. package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
  417. package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
  418. package/dist/test/event-gate-policy-mutation.test.js +0 -137
  419. package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
  420. package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
  421. package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
  422. package/dist/test/event-gate-rate-limit.test.js +0 -627
  423. package/dist/test/event-gate-rate-limit.test.js.map +0 -1
  424. package/dist/test/event-gate-script.test.d.ts +0 -2
  425. package/dist/test/event-gate-script.test.d.ts.map +0 -1
  426. package/dist/test/event-gate-script.test.js +0 -95
  427. package/dist/test/event-gate-script.test.js.map +0 -1
  428. package/dist/test/event-gate-selfwake.test.d.ts +0 -15
  429. package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
  430. package/dist/test/event-gate-selfwake.test.js +0 -125
  431. package/dist/test/event-gate-selfwake.test.js.map +0 -1
  432. package/dist/test/event-gate-tags.test.d.ts +0 -2
  433. package/dist/test/event-gate-tags.test.d.ts.map +0 -1
  434. package/dist/test/event-gate-tags.test.js +0 -76
  435. package/dist/test/event-gate-tags.test.js.map +0 -1
  436. package/dist/test/event-gate.test.d.ts +0 -2
  437. package/dist/test/event-gate.test.d.ts.map +0 -1
  438. package/dist/test/event-gate.test.js +0 -919
  439. package/dist/test/event-gate.test.js.map +0 -1
  440. package/dist/test/explicit-prose-routing.test.d.ts +0 -11
  441. package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
  442. package/dist/test/explicit-prose-routing.test.js +0 -1715
  443. package/dist/test/explicit-prose-routing.test.js.map +0 -1
  444. package/dist/test/framework.test.d.ts +0 -5
  445. package/dist/test/framework.test.d.ts.map +0 -1
  446. package/dist/test/framework.test.js +0 -1048
  447. package/dist/test/framework.test.js.map +0 -1
  448. package/dist/test/gather-context-timeout.test.d.ts +0 -2
  449. package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
  450. package/dist/test/gather-context-timeout.test.js +0 -120
  451. package/dist/test/gather-context-timeout.test.js.map +0 -1
  452. package/dist/test/health-snapshot.test.d.ts +0 -2
  453. package/dist/test/health-snapshot.test.d.ts.map +0 -1
  454. package/dist/test/health-snapshot.test.js +0 -74
  455. package/dist/test/health-snapshot.test.js.map +0 -1
  456. package/dist/test/helpers/coalescing-fixture.d.ts +0 -74
  457. package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
  458. package/dist/test/helpers/coalescing-fixture.js +0 -152
  459. package/dist/test/helpers/coalescing-fixture.js.map +0 -1
  460. package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
  461. package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
  462. package/dist/test/helpers/coalescing-kill-child.js +0 -24
  463. package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
  464. package/dist/test/helpers/mock-membrane.d.ts +0 -53
  465. package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
  466. package/dist/test/helpers/mock-membrane.js +0 -168
  467. package/dist/test/helpers/mock-membrane.js.map +0 -1
  468. package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
  469. package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
  470. package/dist/test/helpers/pytc-stop-rows.js +0 -143
  471. package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
  472. package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
  473. package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
  474. package/dist/test/helpers/quiesce-crash-child.js +0 -156
  475. package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
  476. package/dist/test/hide-then-turn.test.d.ts +0 -2
  477. package/dist/test/hide-then-turn.test.d.ts.map +0 -1
  478. package/dist/test/hide-then-turn.test.js +0 -101
  479. package/dist/test/hide-then-turn.test.js.map +0 -1
  480. package/dist/test/history-module-overview.test.d.ts +0 -2
  481. package/dist/test/history-module-overview.test.d.ts.map +0 -1
  482. package/dist/test/history-module-overview.test.js +0 -711
  483. package/dist/test/history-module-overview.test.js.map +0 -1
  484. package/dist/test/history-module-realstore.test.d.ts +0 -2
  485. package/dist/test/history-module-realstore.test.d.ts.map +0 -1
  486. package/dist/test/history-module-realstore.test.js +0 -363
  487. package/dist/test/history-module-realstore.test.js.map +0 -1
  488. package/dist/test/history-module-semantic.test.d.ts +0 -2
  489. package/dist/test/history-module-semantic.test.d.ts.map +0 -1
  490. package/dist/test/history-module-semantic.test.js +0 -213
  491. package/dist/test/history-module-semantic.test.js.map +0 -1
  492. package/dist/test/history-module-ux.test.d.ts +0 -2
  493. package/dist/test/history-module-ux.test.d.ts.map +0 -1
  494. package/dist/test/history-module-ux.test.js +0 -304
  495. package/dist/test/history-module-ux.test.js.map +0 -1
  496. package/dist/test/history-module.test.d.ts +0 -2
  497. package/dist/test/history-module.test.d.ts.map +0 -1
  498. package/dist/test/history-module.test.js +0 -619
  499. package/dist/test/history-module.test.js.map +0 -1
  500. package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
  501. package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
  502. package/dist/test/history-semantic-review-findings.test.js +0 -338
  503. package/dist/test/history-semantic-review-findings.test.js.map +0 -1
  504. package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
  505. package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
  506. package/dist/test/history-semantic-sync-converges.test.js +0 -109
  507. package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
  508. package/dist/test/host-quiesce.test.d.ts +0 -2
  509. package/dist/test/host-quiesce.test.d.ts.map +0 -1
  510. package/dist/test/host-quiesce.test.js +0 -988
  511. package/dist/test/host-quiesce.test.js.map +0 -1
  512. package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
  513. package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
  514. package/dist/test/inference-exhaustion-rewind.test.js +0 -387
  515. package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
  516. package/dist/test/inference-failure-bounds.test.d.ts +0 -2
  517. package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
  518. package/dist/test/inference-failure-bounds.test.js +0 -1202
  519. package/dist/test/inference-failure-bounds.test.js.map +0 -1
  520. package/dist/test/inference-failure-observability.test.d.ts +0 -2
  521. package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
  522. package/dist/test/inference-failure-observability.test.js +0 -84
  523. package/dist/test/inference-failure-observability.test.js.map +0 -1
  524. package/dist/test/journal-tool.test.d.ts +0 -2
  525. package/dist/test/journal-tool.test.d.ts.map +0 -1
  526. package/dist/test/journal-tool.test.js +0 -33
  527. package/dist/test/journal-tool.test.js.map +0 -1
  528. package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
  529. package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
  530. package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
  531. package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
  532. package/dist/test/kv-unified-wiring.test.d.ts +0 -2
  533. package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
  534. package/dist/test/kv-unified-wiring.test.js +0 -95
  535. package/dist/test/kv-unified-wiring.test.js.map +0 -1
  536. package/dist/test/late-events-after-stop.test.d.ts +0 -2
  537. package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
  538. package/dist/test/late-events-after-stop.test.js +0 -122
  539. package/dist/test/late-events-after-stop.test.js.map +0 -1
  540. package/dist/test/liveness-watchdog.test.d.ts +0 -2
  541. package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
  542. package/dist/test/liveness-watchdog.test.js +0 -94
  543. package/dist/test/liveness-watchdog.test.js.map +0 -1
  544. package/dist/test/machine-close-provenance.test.d.ts +0 -2
  545. package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
  546. package/dist/test/machine-close-provenance.test.js +0 -116
  547. package/dist/test/machine-close-provenance.test.js.map +0 -1
  548. package/dist/test/maintenance-timer.test.d.ts +0 -2
  549. package/dist/test/maintenance-timer.test.d.ts.map +0 -1
  550. package/dist/test/maintenance-timer.test.js +0 -1827
  551. package/dist/test/maintenance-timer.test.js.map +0 -1
  552. package/dist/test/mcp-server-bin.test.d.ts +0 -2
  553. package/dist/test/mcp-server-bin.test.d.ts.map +0 -1
  554. package/dist/test/mcp-server-bin.test.js +0 -142
  555. package/dist/test/mcp-server-bin.test.js.map +0 -1
  556. package/dist/test/mcpl-access-provider.test.d.ts +0 -2
  557. package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
  558. package/dist/test/mcpl-access-provider.test.js +0 -20
  559. package/dist/test/mcpl-access-provider.test.js.map +0 -1
  560. package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
  561. package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
  562. package/dist/test/mcpl-awareness-barrier.test.js +0 -769
  563. package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
  564. package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
  565. package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
  566. package/dist/test/mcpl-capability-grant.test.js +0 -111
  567. package/dist/test/mcpl-capability-grant.test.js.map +0 -1
  568. package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
  569. package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
  570. package/dist/test/mcpl-capability-scoping.test.js +0 -266
  571. package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
  572. package/dist/test/mcpl-child-env.test.d.ts +0 -2
  573. package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
  574. package/dist/test/mcpl-child-env.test.js +0 -158
  575. package/dist/test/mcpl-child-env.test.js.map +0 -1
  576. package/dist/test/mcpl-coalesced-content-parity.test.d.ts +0 -2
  577. package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +0 -1
  578. package/dist/test/mcpl-coalesced-content-parity.test.js +0 -532
  579. package/dist/test/mcpl-coalesced-content-parity.test.js.map +0 -1
  580. package/dist/test/mcpl-coalescing.test.d.ts +0 -2
  581. package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
  582. package/dist/test/mcpl-coalescing.test.js +0 -1125
  583. package/dist/test/mcpl-coalescing.test.js.map +0 -1
  584. package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
  585. package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
  586. package/dist/test/mcpl-config-diagnostics.test.js +0 -452
  587. package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
  588. package/dist/test/mcpl-empty-content.test.d.ts +0 -2
  589. package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
  590. package/dist/test/mcpl-empty-content.test.js +0 -368
  591. package/dist/test/mcpl-empty-content.test.js.map +0 -1
  592. package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
  593. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
  594. package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
  595. package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
  596. package/dist/test/mcpl-list-status.test.d.ts +0 -2
  597. package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
  598. package/dist/test/mcpl-list-status.test.js +0 -82
  599. package/dist/test/mcpl-list-status.test.js.map +0 -1
  600. package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
  601. package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
  602. package/dist/test/mcpl-manifest-changed.test.js +0 -178
  603. package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
  604. package/dist/test/mcpl-push-convert.test.d.ts +0 -2
  605. package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
  606. package/dist/test/mcpl-push-convert.test.js +0 -42
  607. package/dist/test/mcpl-push-convert.test.js.map +0 -1
  608. package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
  609. package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
  610. package/dist/test/mcpl-reconnect-events.test.js +0 -144
  611. package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
  612. package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
  613. package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
  614. package/dist/test/mcpl-reconnect-reregistration.test.js +0 -238
  615. package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
  616. package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
  617. package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
  618. package/dist/test/mcpl-reference-fetcher.test.js +0 -427
  619. package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
  620. package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
  621. package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
  622. package/dist/test/mcpl-reference-fields.test.js +0 -149
  623. package/dist/test/mcpl-reference-fields.test.js.map +0 -1
  624. package/dist/test/mcpl-rejection-log-lines.test.d.ts +0 -2
  625. package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +0 -1
  626. package/dist/test/mcpl-rejection-log-lines.test.js +0 -349
  627. package/dist/test/mcpl-rejection-log-lines.test.js.map +0 -1
  628. package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
  629. package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
  630. package/dist/test/mcpl-request-timeout.test.js +0 -138
  631. package/dist/test/mcpl-request-timeout.test.js.map +0 -1
  632. package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
  633. package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
  634. package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
  635. package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
  636. package/dist/test/mcpl-stderr-tail.test.d.ts +0 -2
  637. package/dist/test/mcpl-stderr-tail.test.d.ts.map +0 -1
  638. package/dist/test/mcpl-stderr-tail.test.js +0 -210
  639. package/dist/test/mcpl-stderr-tail.test.js.map +0 -1
  640. package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
  641. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
  642. package/dist/test/mcpl-tool-class-listing.test.js +0 -147
  643. package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
  644. package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
  645. package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
  646. package/dist/test/mcpl-tool-classes.test.js +0 -80
  647. package/dist/test/mcpl-tool-classes.test.js.map +0 -1
  648. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
  649. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
  650. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
  651. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
  652. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
  653. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
  654. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
  655. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
  656. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
  657. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
  658. package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
  659. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
  660. package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
  661. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
  662. package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
  663. package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
  664. package/dist/test/mcpl-transport-close.test.d.ts +0 -2
  665. package/dist/test/mcpl-transport-close.test.d.ts.map +0 -1
  666. package/dist/test/mcpl-transport-close.test.js +0 -373
  667. package/dist/test/mcpl-transport-close.test.js.map +0 -1
  668. package/dist/test/mcpl-transport-spawn.test.d.ts +0 -2
  669. package/dist/test/mcpl-transport-spawn.test.d.ts.map +0 -1
  670. package/dist/test/mcpl-transport-spawn.test.js +0 -58
  671. package/dist/test/mcpl-transport-spawn.test.js.map +0 -1
  672. package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
  673. package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
  674. package/dist/test/mcpl-ws-transport.test.js +0 -259
  675. package/dist/test/mcpl-ws-transport.test.js.map +0 -1
  676. package/dist/test/module-context-integration.test.d.ts +0 -18
  677. package/dist/test/module-context-integration.test.d.ts.map +0 -1
  678. package/dist/test/module-context-integration.test.js +0 -181
  679. package/dist/test/module-context-integration.test.js.map +0 -1
  680. package/dist/test/offline-recovery-branch.test.d.ts +0 -2
  681. package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
  682. package/dist/test/offline-recovery-branch.test.js +0 -570
  683. package/dist/test/offline-recovery-branch.test.js.map +0 -1
  684. package/dist/test/operator-surgery.test.d.ts +0 -2
  685. package/dist/test/operator-surgery.test.d.ts.map +0 -1
  686. package/dist/test/operator-surgery.test.js +0 -595
  687. package/dist/test/operator-surgery.test.js.map +0 -1
  688. package/dist/test/ops-alert.test.d.ts +0 -2
  689. package/dist/test/ops-alert.test.d.ts.map +0 -1
  690. package/dist/test/ops-alert.test.js +0 -153
  691. package/dist/test/ops-alert.test.js.map +0 -1
  692. package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
  693. package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
  694. package/dist/test/overbudget-drain-breaker.test.js +0 -198
  695. package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
  696. package/dist/test/pack-installs-alone.test.d.ts +0 -2
  697. package/dist/test/pack-installs-alone.test.d.ts.map +0 -1
  698. package/dist/test/pack-installs-alone.test.js +0 -284
  699. package/dist/test/pack-installs-alone.test.js.map +0 -1
  700. package/dist/test/per-agent-delivery.test.d.ts +0 -2
  701. package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
  702. package/dist/test/per-agent-delivery.test.js +0 -108
  703. package/dist/test/per-agent-delivery.test.js.map +0 -1
  704. package/dist/test/physical-window-restart.test.d.ts +0 -16
  705. package/dist/test/physical-window-restart.test.d.ts.map +0 -1
  706. package/dist/test/physical-window-restart.test.js +0 -487
  707. package/dist/test/physical-window-restart.test.js.map +0 -1
  708. package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
  709. package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
  710. package/dist/test/placed-reaction-baseline.test.js +0 -312
  711. package/dist/test/placed-reaction-baseline.test.js.map +0 -1
  712. package/dist/test/present-while-acting.test.d.ts +0 -19
  713. package/dist/test/present-while-acting.test.d.ts.map +0 -1
  714. package/dist/test/present-while-acting.test.js +0 -1649
  715. package/dist/test/present-while-acting.test.js.map +0 -1
  716. package/dist/test/prose-segments.test.d.ts +0 -2
  717. package/dist/test/prose-segments.test.d.ts.map +0 -1
  718. package/dist/test/prose-segments.test.js +0 -52
  719. package/dist/test/prose-segments.test.js.map +0 -1
  720. package/dist/test/prose-stream-router.test.d.ts +0 -2
  721. package/dist/test/prose-stream-router.test.d.ts.map +0 -1
  722. package/dist/test/prose-stream-router.test.js +0 -171
  723. package/dist/test/prose-stream-router.test.js.map +0 -1
  724. package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
  725. package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
  726. package/dist/test/provider-acceleration-cooldown.test.js +0 -435
  727. package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
  728. package/dist/test/provider-waits.test.d.ts +0 -2
  729. package/dist/test/provider-waits.test.d.ts.map +0 -1
  730. package/dist/test/provider-waits.test.js +0 -2259
  731. package/dist/test/provider-waits.test.js.map +0 -1
  732. package/dist/test/puppet-tool-call.test.d.ts +0 -2
  733. package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
  734. package/dist/test/puppet-tool-call.test.js +0 -226
  735. package/dist/test/puppet-tool-call.test.js.map +0 -1
  736. package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
  737. package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
  738. package/dist/test/puppet-turn-reservation.test.js +0 -139
  739. package/dist/test/puppet-turn-reservation.test.js.map +0 -1
  740. package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
  741. package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
  742. package/dist/test/reaction-baseline-platform.test.js +0 -124
  743. package/dist/test/reaction-baseline-platform.test.js.map +0 -1
  744. package/dist/test/record-journal.test.d.ts +0 -6
  745. package/dist/test/record-journal.test.d.ts.map +0 -1
  746. package/dist/test/record-journal.test.js +0 -269
  747. package/dist/test/record-journal.test.js.map +0 -1
  748. package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
  749. package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
  750. package/dist/test/refusal-reaction-baseline.test.js +0 -81
  751. package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
  752. package/dist/test/refusal-rewind.test.d.ts +0 -2
  753. package/dist/test/refusal-rewind.test.d.ts.map +0 -1
  754. package/dist/test/refusal-rewind.test.js +0 -117
  755. package/dist/test/refusal-rewind.test.js.map +0 -1
  756. package/dist/test/refusal-single-call.test.d.ts +0 -2
  757. package/dist/test/refusal-single-call.test.d.ts.map +0 -1
  758. package/dist/test/refusal-single-call.test.js +0 -177
  759. package/dist/test/refusal-single-call.test.js.map +0 -1
  760. package/dist/test/release-bump.test.d.ts +0 -2
  761. package/dist/test/release-bump.test.d.ts.map +0 -1
  762. package/dist/test/release-bump.test.js +0 -248
  763. package/dist/test/release-bump.test.js.map +0 -1
  764. package/dist/test/release-changelog.test.d.ts +0 -2
  765. package/dist/test/release-changelog.test.d.ts.map +0 -1
  766. package/dist/test/release-changelog.test.js +0 -159
  767. package/dist/test/release-changelog.test.js.map +0 -1
  768. package/dist/test/release-holds.test.d.ts +0 -2
  769. package/dist/test/release-holds.test.d.ts.map +0 -1
  770. package/dist/test/release-holds.test.js +0 -456
  771. package/dist/test/release-holds.test.js.map +0 -1
  772. package/dist/test/same-round-think-policy.test.d.ts +0 -2
  773. package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
  774. package/dist/test/same-round-think-policy.test.js +0 -853
  775. package/dist/test/same-round-think-policy.test.js.map +0 -1
  776. package/dist/test/save-recent-image.test.d.ts +0 -26
  777. package/dist/test/save-recent-image.test.d.ts.map +0 -1
  778. package/dist/test/save-recent-image.test.js +0 -974
  779. package/dist/test/save-recent-image.test.js.map +0 -1
  780. package/dist/test/shutdown-errors.test.d.ts +0 -2
  781. package/dist/test/shutdown-errors.test.d.ts.map +0 -1
  782. package/dist/test/shutdown-errors.test.js +0 -662
  783. package/dist/test/shutdown-errors.test.js.map +0 -1
  784. package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
  785. package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
  786. package/dist/test/silent-heartbeat-rows.test.js +0 -451
  787. package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
  788. package/dist/test/silent-heartbeat.test.d.ts +0 -2
  789. package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
  790. package/dist/test/silent-heartbeat.test.js +0 -165
  791. package/dist/test/silent-heartbeat.test.js.map +0 -1
  792. package/dist/test/state-scaling-e2e.test.d.ts +0 -22
  793. package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
  794. package/dist/test/state-scaling-e2e.test.js +0 -206
  795. package/dist/test/state-scaling-e2e.test.js.map +0 -1
  796. package/dist/test/state-scaling.test.d.ts +0 -12
  797. package/dist/test/state-scaling.test.d.ts.map +0 -1
  798. package/dist/test/state-scaling.test.js +0 -251
  799. package/dist/test/state-scaling.test.js.map +0 -1
  800. package/dist/test/stop-with-host-operations.test.d.ts +0 -20
  801. package/dist/test/stop-with-host-operations.test.d.ts.map +0 -1
  802. package/dist/test/stop-with-host-operations.test.js +0 -1174
  803. package/dist/test/stop-with-host-operations.test.js.map +0 -1
  804. package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
  805. package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
  806. package/dist/test/stop-with-work-in-flight.test.js +0 -784
  807. package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
  808. package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
  809. package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
  810. package/dist/test/surgery-marks-receipt.test.js +0 -540
  811. package/dist/test/surgery-marks-receipt.test.js.map +0 -1
  812. package/dist/test/thinking-token-stamp.test.d.ts +0 -12
  813. package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
  814. package/dist/test/thinking-token-stamp.test.js +0 -129
  815. package/dist/test/thinking-token-stamp.test.js.map +0 -1
  816. package/dist/test/timezone.test.d.ts +0 -2
  817. package/dist/test/timezone.test.d.ts.map +0 -1
  818. package/dist/test/timezone.test.js +0 -18
  819. package/dist/test/timezone.test.js.map +0 -1
  820. package/dist/test/tool-batch-hook.test.d.ts +0 -8
  821. package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
  822. package/dist/test/tool-batch-hook.test.js +0 -275
  823. package/dist/test/tool-batch-hook.test.js.map +0 -1
  824. package/dist/test/tool-policy.test.d.ts +0 -2
  825. package/dist/test/tool-policy.test.d.ts.map +0 -1
  826. package/dist/test/tool-policy.test.js +0 -51
  827. package/dist/test/tool-policy.test.js.map +0 -1
  828. package/dist/test/tool-presentation.test.d.ts +0 -2
  829. package/dist/test/tool-presentation.test.d.ts.map +0 -1
  830. package/dist/test/tool-presentation.test.js +0 -268
  831. package/dist/test/tool-presentation.test.js.map +0 -1
  832. package/dist/test/tool-result-content.test.d.ts +0 -2
  833. package/dist/test/tool-result-content.test.d.ts.map +0 -1
  834. package/dist/test/tool-result-content.test.js +0 -37
  835. package/dist/test/tool-result-content.test.js.map +0 -1
  836. package/dist/test/tool-result-guard.test.d.ts +0 -2
  837. package/dist/test/tool-result-guard.test.d.ts.map +0 -1
  838. package/dist/test/tool-result-guard.test.js +0 -3729
  839. package/dist/test/tool-result-guard.test.js.map +0 -1
  840. package/dist/test/tool-result-history.test.d.ts +0 -7
  841. package/dist/test/tool-result-history.test.d.ts.map +0 -1
  842. package/dist/test/tool-result-history.test.js +0 -156
  843. package/dist/test/tool-result-history.test.js.map +0 -1
  844. package/dist/test/tool-result-spill.test.d.ts +0 -13
  845. package/dist/test/tool-result-spill.test.d.ts.map +0 -1
  846. package/dist/test/tool-result-spill.test.js +0 -586
  847. package/dist/test/tool-result-spill.test.js.map +0 -1
  848. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
  849. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
  850. package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
  851. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
  852. package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
  853. package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
  854. package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
  855. package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
  856. package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
  857. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
  858. package/dist/test/tools-observe-parser-conformance.test.js +0 -129
  859. package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
  860. package/dist/test/trunk-channel-routing.test.d.ts +0 -19
  861. package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
  862. package/dist/test/trunk-channel-routing.test.js +0 -652
  863. package/dist/test/trunk-channel-routing.test.js.map +0 -1
  864. package/dist/test/tune-out-e2e.test.d.ts +0 -2
  865. package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
  866. package/dist/test/tune-out-e2e.test.js +0 -142
  867. package/dist/test/tune-out-e2e.test.js.map +0 -1
  868. package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
  869. package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
  870. package/dist/test/tune-out-gate-composition.test.js +0 -221
  871. package/dist/test/tune-out-gate-composition.test.js.map +0 -1
  872. package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
  873. package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
  874. package/dist/test/tune-out-lifecycle.test.js +0 -121
  875. package/dist/test/tune-out-lifecycle.test.js.map +0 -1
  876. package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
  877. package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
  878. package/dist/test/turn-trigger-provenance.test.js +0 -137
  879. package/dist/test/turn-trigger-provenance.test.js.map +0 -1
  880. package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
  881. package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
  882. package/dist/test/unconvertible-tool-result.test.js +0 -358
  883. package/dist/test/unconvertible-tool-result.test.js.map +0 -1
  884. package/dist/test/unsent-compiles.test.d.ts +0 -2
  885. package/dist/test/unsent-compiles.test.d.ts.map +0 -1
  886. package/dist/test/unsent-compiles.test.js +0 -139
  887. package/dist/test/unsent-compiles.test.js.map +0 -1
  888. package/dist/test/usage-accounting.test.d.ts +0 -2
  889. package/dist/test/usage-accounting.test.d.ts.map +0 -1
  890. package/dist/test/usage-accounting.test.js +0 -13
  891. package/dist/test/usage-accounting.test.js.map +0 -1
  892. package/dist/test/usage-tracker.test.d.ts +0 -2
  893. package/dist/test/usage-tracker.test.d.ts.map +0 -1
  894. package/dist/test/usage-tracker.test.js +0 -129
  895. package/dist/test/usage-tracker.test.js.map +0 -1
  896. package/dist/test/utils-surface.test.d.ts +0 -2
  897. package/dist/test/utils-surface.test.d.ts.map +0 -1
  898. package/dist/test/utils-surface.test.js +0 -145
  899. package/dist/test/utils-surface.test.js.map +0 -1
  900. package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
  901. package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
  902. package/dist/test/workspace-branch-continuation.test.js +0 -183
  903. package/dist/test/workspace-branch-continuation.test.js.map +0 -1
  904. package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
  905. package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
  906. package/dist/test/workspace-materialize-freshness.test.js +0 -252
  907. package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
  908. package/dist/test/workspace-path-containment.test.d.ts +0 -19
  909. package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
  910. package/dist/test/workspace-path-containment.test.js +0 -91
  911. package/dist/test/workspace-path-containment.test.js.map +0 -1
  912. package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
  913. package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
  914. package/dist/test/workspace-read-file-from-disk.test.js +0 -174
  915. package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
  916. package/dist/test/workspace-read-image.test.d.ts +0 -2
  917. package/dist/test/workspace-read-image.test.d.ts.map +0 -1
  918. package/dist/test/workspace-read-image.test.js +0 -597
  919. package/dist/test/workspace-read-image.test.js.map +0 -1
  920. package/dist/test/workspace-read-text.test.d.ts +0 -2
  921. package/dist/test/workspace-read-text.test.d.ts.map +0 -1
  922. package/dist/test/workspace-read-text.test.js +0 -101
  923. package/dist/test/workspace-read-text.test.js.map +0 -1
  924. package/dist/test/workspace-restore-order.test.d.ts +0 -16
  925. package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
  926. package/dist/test/workspace-restore-order.test.js +0 -140
  927. package/dist/test/workspace-restore-order.test.js.map +0 -1
  928. package/dist/test/workspace-three-way.test.d.ts +0 -12
  929. package/dist/test/workspace-three-way.test.d.ts.map +0 -1
  930. package/dist/test/workspace-three-way.test.js +0 -4094
  931. package/dist/test/workspace-three-way.test.js.map +0 -1
  932. package/dist/test/workspace-watcher.test.d.ts +0 -2
  933. package/dist/test/workspace-watcher.test.d.ts.map +0 -1
  934. package/dist/test/workspace-watcher.test.js +0 -281
  935. package/dist/test/workspace-watcher.test.js.map +0 -1
  936. package/dist/test/xml-round-persist.test.d.ts +0 -19
  937. package/dist/test/xml-round-persist.test.d.ts.map +0 -1
  938. package/dist/test/xml-round-persist.test.js +0 -235
  939. package/dist/test/xml-round-persist.test.js.map +0 -1
  940. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -7,6 +7,7 @@
7
7
  * - Tools for explicit Discord operations (send, DM, react, etc.)
8
8
  */
9
9
  import { formatZonedDateTime, resolveTimeZone } from '../../timezone.js';
10
+ import { logValue } from '../../mcpl/log-value.js';
10
11
  export * from './types.js';
11
12
  export { DiscordJsClient } from './discord-js-client.js';
12
13
  const DEFAULT_CONFIG = {
@@ -24,6 +25,13 @@ const TYPING_REFRESH_MS = 8_000;
24
25
  // is somehow missed (crash, dropped stream), this guarantees typing can't get
25
26
  // stuck on forever.
26
27
  const TYPING_MAX_MS = 5 * 60_000;
28
+ // The most agents whose latest post the module keeps for their turn's
29
+ // thoughts (lastPosts). Past it, the entry recorded longest ago goes, which
30
+ // bounds the entries of agents that are gone, such as closed conversations'.
31
+ // An entry is wanted only until its turn's speech arrives, so one goes while
32
+ // still wanted only if this many other agents post in that time, and its
33
+ // turn's thoughts then go into no message.
34
+ const MAX_LAST_POSTS = 1_024;
27
35
  // Trace event types that end an agent's turn (onTrace's contract) — any of
28
36
  // these stops the typing keepalive. A turn's tool-call cycles stay inside its
29
37
  // stream, so they come after them. inference:completed is the normal end.
@@ -48,6 +56,122 @@ const TEXT_FILE_EXTENSIONS = [
48
56
  '.html', '.css', '.xml', '.csv', '.log', '.sh', '.bash',
49
57
  ];
50
58
  const CONVERSATION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
59
+ /** What the agent reads for a text attachment whose contents couldn't be
60
+ * fetched: by an error, or by an answer that wasn't OK. */
61
+ function attachmentNotFetched(filename) {
62
+ return { type: 'text', text: `[Attachment: ${filename} (failed to fetch)]` };
63
+ }
64
+ /** What a stored message reads when it has no text of its own and nothing the
65
+ * host added, so the agent still sees that a message was there. */
66
+ const EMPTY_MESSAGE = '[Empty message]';
67
+ /**
68
+ * Metadata on a stored Discord message whose first block is its own text,
69
+ * '' when it has none, and every block after it the host's: images, inlined
70
+ * file text, attachment notes and EMPTY_MESSAGE. An edit replaces content and
71
+ * can't touch metadata, so the mark holds for the row's life, and it tells an
72
+ * edit or a sync which block is Discord's to replace. For the same reason a
73
+ * row stored before the mark never gets it, even once a history sync
74
+ * rebuilds it in this layout. The request builder drops an empty text block,
75
+ * as it does wherever one occurs.
76
+ */
77
+ const TEXT_FIRST = 'discordTextFirst';
78
+ /** A message's own text as a stored row holds it: '' when it's blank. */
79
+ function ownText(content) {
80
+ return content.trim() ? content : '';
81
+ }
82
+ const isEmptyMarker = (block) => block.type === 'text' && block.text === EMPTY_MESSAGE;
83
+ const isBlankText = (block) => block.type === 'text' && !block.text.trim();
84
+ /**
85
+ * A text-first row's content: the message's own text, '' when it has none,
86
+ * then `after`, what the host added; EMPTY_MESSAGE when there's neither.
87
+ */
88
+ function textFirst(text, after = []) {
89
+ return [{ type: 'text', text }, ...(text || after.length > 0 ? after : [{ type: 'text', text: EMPTY_MESSAGE }])];
90
+ }
91
+ /** A text-first row's content with `text` as the message's own text, in
92
+ * place of its first block, keeping what the host added after it. */
93
+ function withOwnText(content, text) {
94
+ return textFirst(ownText(text), content.slice(1).filter((block) => !isEmptyMarker(block)));
95
+ }
96
+ /**
97
+ * The content a stored Discord message should hold once Discord's text for it
98
+ * is `discordText`, or null when it holds that already.
99
+ *
100
+ * A text-first row keeps every block the host added and replaces only its own
101
+ * text; EMPTY_MESSAGE goes once there is text, and comes back when nothing is
102
+ * left. A row stored before that layout held its own text first when it had
103
+ * any, but a message without text began with what the host added, which may
104
+ * be text, a file's contents or a note, so its first block can't be told
105
+ * apart. Such a row is left alone unless Discord's text is there and differs
106
+ * from its first block, and then that text takes the first block's place
107
+ * when it's text, and goes before it when it isn't, and EMPTY_MESSAGE goes.
108
+ * So a message without text, stored beginning with a file's contents or a
109
+ * note, loses that block. The history sync, which has the message's
110
+ * attachments, rebuilds such a row instead (needsRebuild).
111
+ */
112
+ function contentForText(stored, discordText) {
113
+ const text = ownText(discordText);
114
+ const [first, ...rest] = stored.content;
115
+ if (stored.metadata?.[TEXT_FIRST] === true) {
116
+ if (first?.type === 'text' && first.text === text)
117
+ return null;
118
+ return withOwnText(stored.content, text);
119
+ }
120
+ if (!text || (first?.type === 'text' && first.text === discordText))
121
+ return null;
122
+ return [{ type: 'text', text: discordText }, ...(first?.type === 'text' ? rest : stored.content).filter((block) => !isEmptyMarker(block))];
123
+ }
124
+ /**
125
+ * Whether a stored row lacks or holds more than the live conversion gives
126
+ * Discord's `message` now, its own text aside, so the history sync stores it
127
+ * through that conversion again. The conversion gives each attachment one
128
+ * block: an image, a file's text, or a note when it isn't fetched or isn't
129
+ * read. So a text-first row holds one block per attachment after its text,
130
+ * EMPTY_MESSAGE aside, which the text's rule keeps. A row stored before that
131
+ * layout held its text, when it had any, then those blocks, or EMPTY_MESSAGE
132
+ * alone; one that doesn't was blanked or stripped by an earlier edit or sync,
133
+ * or its message gained or lost text, or lost an attachment. Its first block,
134
+ * when it is the message's own text, counts as that text, even when the text
135
+ * reads as EMPTY_MESSAGE. For a message without text of its own, a first
136
+ * block that's text may be what the host added or a caption the message has
137
+ * since lost, which no count tells apart, so that row is stored again; it
138
+ * then begins with its own '' text. One whose text alone changed is left to
139
+ * the text's rule, which keeps the blocks after it. History without
140
+ * attachments can't be compared, so it rebuilds nothing.
141
+ */
142
+ function needsRebuild(stored, message) {
143
+ if (message.attachments === undefined)
144
+ return false;
145
+ const attachments = message.attachments.length;
146
+ const held = (blocks) => blocks.filter((block) => !isBlankText(block) && !isEmptyMarker(block)).length;
147
+ if (stored.metadata?.[TEXT_FIRST] === true)
148
+ return held(stored.content.slice(1)) !== attachments;
149
+ const own = ownText(message.content);
150
+ const [first, ...rest] = stored.content;
151
+ if (!own && first?.type === 'text' && !isBlankText(first) && !isEmptyMarker(first))
152
+ return true;
153
+ const expected = (own ? 1 : 0) + attachments;
154
+ const counted = own && first?.type === 'text' && first.text === own ? 1 + held(rest) : held(stored.content);
155
+ return counted !== expected || (expected === 0 && !stored.content.some(isEmptyMarker));
156
+ }
157
+ /**
158
+ * Whether a row holds non-blank text besides its message's own text now,
159
+ * which may be what a file gave. A marked row whose message's text changed
160
+ * counts its old text here too, which can delay its rebuild until a fetch
161
+ * succeeds but never loses text.
162
+ */
163
+ function holdsOtherText(stored, message) {
164
+ const own = ownText(message.content);
165
+ const [first, ...rest] = stored.content;
166
+ const others = own && first?.type === 'text' && first.text === own ? rest : stored.content;
167
+ return others.some((block) => block.type === 'text' && !isBlankText(block) && !isEmptyMarker(block));
168
+ }
169
+ /** Whether a message's conversion holds, after the message's own text, the
170
+ * note for an attachment of its whose text wasn't fetched. */
171
+ function holdsNotFetched(content, message) {
172
+ const notes = new Set((message.attachments ?? []).map((attachment) => attachmentNotFetched(attachment.filename).text));
173
+ return content.slice(1).some((block) => block.type === 'text' && notes.has(block.text));
174
+ }
51
175
  /**
52
176
  * Discord module for the agent framework.
53
177
  */
@@ -65,8 +189,24 @@ export class DiscordModule {
65
189
  };
66
190
  // Track current reply context per agent
67
191
  replyContexts = new Map();
68
- // Last message sent by a tool (for thought-editing)
69
- lastSentMessage = null;
192
+ // Where a tool turn's thoughts go (onAgentSpeech edits them in as a
193
+ // spoiler): each agent's latest message posted in a turn, with that turn's
194
+ // id (notePost). A `send` or `reply` records the message its client call
195
+ // returns, and so does the module's own speech. Thoughts go into it only
196
+ // when their speech ends the same turn, and taking them removes it. So
197
+ // neither another agent's message nor one from an earlier turn takes them,
198
+ // and an attempt in the turn that is refused or throws leaves the turn's own
199
+ // post in place. Turn ids increase, so an earlier turn's post that finishes
200
+ // after a later turn's leaves the later one in place. A DM records nothing,
201
+ // since its channel isn't known here, and neither does a post whose call or
202
+ // speech carries no turn. An entry goes when its thoughts are taken, when
203
+ // the agent's next post replaces it, or past MAX_LAST_POSTS agents.
204
+ lastPosts = new Map();
205
+ // One set per running history sync: the Discord messages the live path
206
+ // stored, edited or was told were deleted since that sync began. What the
207
+ // live path saw is newer than what the sync fetched, so the sync leaves
208
+ // those messages alone.
209
+ liveDuringSync = new Set();
70
210
  // Typing keepalive: agentName -> { interval, deadline }. Started on
71
211
  // inference:started, stopped on the turn's terminal trace event. Discord's
72
212
  // typing indicator auto-expires after ~10s, so we re-trigger on an interval
@@ -339,7 +479,7 @@ export class DiscordModule {
339
479
  },
340
480
  {
341
481
  name: 'fetch_history',
342
- description: 'Fetch recent message history from a channel',
482
+ description: 'Fetch recent message history from a channel. A message with attachments lists each one\'s filename, type and size; their contents aren\'t included.',
343
483
  inputSchema: {
344
484
  type: 'object',
345
485
  properties: {
@@ -356,11 +496,11 @@ export class DiscordModule {
356
496
  try {
357
497
  switch (call.name) {
358
498
  case 'send':
359
- return await this.handleSend(call.input);
499
+ return await this.handleSend(call.input, call);
360
500
  case 'dm':
361
501
  return await this.handleDM(call.input);
362
502
  case 'reply':
363
- return await this.handleReply(call.input);
503
+ return await this.handleReply(call.input, call);
364
504
  case 'react':
365
505
  return await this.handleReact(call.input);
366
506
  case 'edit':
@@ -435,8 +575,10 @@ export class DiscordModule {
435
575
  console.warn('Discord: Failed to send typing indicator:', err);
436
576
  });
437
577
  }
438
- // Build content blocks from message and attachments
439
- const contentBlocks = msg.contentBlocks ?? [{ type: 'text', text: msg.content }];
578
+ // Built from the message and its attachments, or from its text alone
579
+ // when an event carries no blocks; text first, as TEXT_FIRST marks.
580
+ const contentBlocks = msg.contentBlocks ?? textFirst(ownText(msg.content));
581
+ this.noteLive(msg.discordMessageId);
440
582
  // Return declarative response - framework applies all writes atomically
441
583
  return {
442
584
  addMessages: [
@@ -447,6 +589,7 @@ export class DiscordModule {
447
589
  external: { source: 'discord', id: msg.discordMessageId },
448
590
  channelId: msg.channelId,
449
591
  timestamp: msg.timestamp,
592
+ [TEXT_FIRST]: true,
450
593
  },
451
594
  },
452
595
  ],
@@ -457,28 +600,42 @@ export class DiscordModule {
457
600
  // Handle Discord message edit
458
601
  if (event.type === 'discord:edit') {
459
602
  const edit = event;
460
- const internalId = state.findMessageByExternalId('discord', edit.discordMessageId);
461
- if (!internalId) {
603
+ // The stored row, not only its id: an edit changes the message's own
604
+ // text and keeps what the host added beside it.
605
+ // An edit to a message nobody has stored yet is dropped: whatever
606
+ // stores the message, its live add or a history sync running now,
607
+ // stores the text it got, and the next sync's text rule changes it.
608
+ // A row stored in shards can't be edited one shard at a time, so it
609
+ // keeps its text, and the host's log says so. Only an edit that writes
610
+ // marks the message live, so an update that changes nothing leaves a
611
+ // running sync free to rewrite the row.
612
+ const stored = this.storedRow(edit.discordMessageId);
613
+ if (!stored)
614
+ return {};
615
+ if (stored.bodyGroupId) {
616
+ console.warn(`Discord: An update to message ${edit.discordMessageId} wasn't applied: it's stored in shards, which can't be edited, so if its text changed, the agent still has the earlier text`);
462
617
  return {};
463
618
  }
464
- return {
465
- editMessages: [
466
- {
467
- messageId: internalId,
468
- content: [{ type: 'text', text: edit.newContent }],
469
- },
470
- ],
471
- };
619
+ const content = contentForText(stored, edit.newContent);
620
+ if (!content)
621
+ return {};
622
+ this.noteLive(edit.discordMessageId);
623
+ return { editMessages: [{ messageId: stored.id, content }] };
472
624
  }
473
625
  // Handle Discord message delete
474
626
  if (event.type === 'discord:delete') {
475
627
  const del = event;
476
- const internalId = state.findMessageByExternalId('discord', del.discordMessageId);
477
- if (!internalId) {
628
+ // A row stored in shards is removed whole: the framework takes out the
629
+ // body a shard belongs to. The message is the live path's even when no
630
+ // row is found, so a running sync doesn't store what its fetch may
631
+ // still hold.
632
+ this.noteLive(del.discordMessageId);
633
+ const stored = this.storedRow(del.discordMessageId);
634
+ if (!stored) {
478
635
  return {};
479
636
  }
480
637
  return {
481
- removeMessages: [internalId],
638
+ removeMessages: [stored.id],
482
639
  };
483
640
  }
484
641
  return {};
@@ -487,13 +644,15 @@ export class DiscordModule {
487
644
  * Handle agent speech - send to Discord.
488
645
  */
489
646
  async onAgentSpeech(agentName, content, context) {
490
- // If thoughts are present and we have a recently sent message, edit it
491
- // to prepend the thoughts as spoiler text.
492
- if (context.thoughts && context.thoughts.length > 0 && this.lastSentMessage) {
647
+ // If thoughts are present and this agent posted a message in the turn
648
+ // they end (lastPosts), edit it to prepend the thoughts as spoiler text.
649
+ const post = this.lastPosts.get(agentName);
650
+ if (context.thoughts && context.thoughts.length > 0 && post && post.turnId === context.turnId) {
651
+ this.lastPosts.delete(agentName);
493
652
  const thoughtText = this.extractText(context.thoughts);
494
653
  if (thoughtText) {
495
654
  try {
496
- const { channelId, messageId } = this.lastSentMessage;
655
+ const { channelId, messageId } = post;
497
656
  // Fetch the current message content via the client isn't available,
498
657
  // but we know the tool just sent it — reconstruct by editing with
499
658
  // spoiler-wrapped thoughts prepended.
@@ -506,7 +665,6 @@ export class DiscordModule {
506
665
  console.warn('Discord: Failed to edit thoughts into message:', err);
507
666
  }
508
667
  }
509
- this.lastSentMessage = null;
510
668
  }
511
669
  // Get reply context for this agent
512
670
  const replyCtx = this.replyContexts.get(agentName) ?? this.replyContexts.get('default');
@@ -530,8 +688,8 @@ export class DiscordModule {
530
688
  const result = await this.client.sendMessage(targetChannel, text, {
531
689
  replyTo: replyCtx.replyToMessageId,
532
690
  });
533
- // Track for thought-editing (in case of chained speech)
534
- this.lastSentMessage = { channelId: targetChannel, messageId: result.messageId };
691
+ // Track for thought-editing (in case of chained speech in the same turn)
692
+ this.notePost(agentName, context.turnId, targetChannel, result.messageId);
535
693
  // Clear reply-to after sending (don't keep replying to same message)
536
694
  replyCtx.replyToMessageId = undefined;
537
695
  replyCtx.lastActivity = Date.now();
@@ -613,110 +771,164 @@ export class DiscordModule {
613
771
  /**
614
772
  * Sync history for a specific channel - compare with Context Manager and update.
615
773
  * Uses queryMessages() to enumerate stored messages for proper edit/delete detection.
774
+ *
775
+ * The live path can store, edit or remove a row whenever the sync awaits.
776
+ * So the sync fetches history and runs the live conversion it needs first,
777
+ * then reads the store again and writes with no await between that read
778
+ * and its writes. It leaves alone any message the live path stored,
779
+ * changed or was told was deleted while it ran (liveDuringSync), an update
780
+ * that changed nothing aside. A live edit to a message nobody had stored
781
+ * yet is dropped, so a message the sync stores holds the text it fetched
782
+ * until the next sync's text rule changes it. The framework writes an
783
+ * event's response only once every module has processed the event, so an
784
+ * event processed before the sync began can still be written after the
785
+ * sync's own writes, which this doesn't cover.
616
786
  */
617
787
  async syncChannelHistory(channelId) {
618
- if (!this.ctx) {
619
- return { newMessages: 0, editedMessages: 0, deletedMessages: 0 };
788
+ const unchanged = { newMessages: 0, editedMessages: 0, deletedMessages: 0 };
789
+ const ctx = this.ctx;
790
+ if (!ctx) {
791
+ return unchanged;
620
792
  }
621
- const scrollback = this.config.historyScrollback ?? 50;
622
- // Fetch recent history from Discord
623
- const discordMessages = await this.client.fetchHistory(channelId, { limit: scrollback });
624
- // Build a map of Discord message ID -> content for comparison
625
- const discordMessageMap = new Map();
626
- for (const msg of discordMessages) {
627
- discordMessageMap.set(msg.id, {
628
- content: msg.content,
629
- authorName: msg.authorName,
630
- timestamp: msg.timestamp,
631
- });
632
- }
633
- // Query Context Manager for all Discord messages from this channel
634
- const { messages: storedMessages } = this.ctx.queryMessages({
635
- source: 'discord',
636
- metadata: { channelId },
637
- });
638
- // Build a map of stored message external IDs -> internal data
639
- const storedMessageMap = new Map();
640
- for (const msg of storedMessages) {
641
- const external = msg.metadata?.external;
642
- if (external?.id) {
643
- // Extract text content for comparison
644
- const textContent = msg.content
645
- .filter((block) => block.type === 'text')
646
- .map((block) => block.text)
647
- .join('\n');
648
- storedMessageMap.set(external.id, {
649
- internalId: msg.id,
650
- content: textContent,
651
- sourceTimestamp: typeof msg.metadata?.timestamp === 'number'
652
- ? msg.metadata.timestamp
653
- : undefined,
654
- });
793
+ const live = new Set();
794
+ this.liveDuringSync.add(live);
795
+ try {
796
+ const scrollback = this.config.historyScrollback ?? 50;
797
+ // The rows stored as the sync begins. One that is gone by the time it
798
+ // writes was removed meanwhile, and isn't the sync's to bring back.
799
+ const before = this.storedByDiscordId(ctx, channelId);
800
+ // Fetch recent history from Discord. If the module stopped or restarted
801
+ // meanwhile, this sync's context is gone and it writes nothing.
802
+ const discordMessages = await this.client.fetchHistory(channelId, { limit: scrollback });
803
+ if (this.ctx !== ctx)
804
+ return unchanged;
805
+ // Discord's ids, for delete detection inside the fetched window.
806
+ const discordIds = new Set(discordMessages.map((msg) => msg.id));
807
+ // Discord history is newest-first, while addMessage appends to the stored
808
+ // conversation. Process oldest-first so missed messages retain chronology.
809
+ const chronologicalMessages = [...discordMessages].reverse();
810
+ // The live conversion, which fetches attachments, for a message the
811
+ // store lacks and for a row that doesn't hold what the conversion gives
812
+ // the message now (needsRebuild). A row stored in shards can't be
813
+ // edited one shard at a time, so it's left as it is.
814
+ const converted = new Map();
815
+ for (const discordMsg of chronologicalMessages) {
816
+ const stored = before.get(discordMsg.id);
817
+ if (stored && (stored.bodyGroupId || !needsRebuild(stored, discordMsg)))
818
+ continue;
819
+ const content = await this.convertMessageToContent(discordMsg);
820
+ if (this.ctx !== ctx)
821
+ return unchanged;
822
+ // A failed fetch never costs a row the text it holds: when a file
823
+ // wasn't fetched, a row holding other text, which may be that file's,
824
+ // keeps what it holds, and the next sync tries again.
825
+ if (stored && holdsNotFetched(content, discordMsg) && holdsOtherText(stored, discordMsg))
826
+ continue;
827
+ converted.set(discordMsg.id, content);
655
828
  }
656
- }
657
- let newMessages = 0;
658
- let editedMessages = 0;
659
- let deletedMessages = 0;
660
- // Discord history is newest-first, while addMessage appends to the stored
661
- // conversation. Process oldest-first so missed messages retain chronology.
662
- const chronologicalMessages = [...discordMessages].reverse();
663
- for (const discordMsg of chronologicalMessages) {
664
- const stored = storedMessageMap.get(discordMsg.id);
665
- if (!stored) {
666
- // New message we haven't seen
667
- // For bot's own messages (from previous sessions), use the agent name
668
- // This ensures continuity of conversation history
669
- const isBotMessage = discordMsg.authorId === this.state.botUserId;
670
- const agentName = this.ctx.getAgents()[0]?.name;
671
- const participantName = isBotMessage
672
- ? (agentName ?? discordMsg.authorName)
673
- : discordMsg.authorName;
674
- this.ctx.addMessage(participantName, [{ type: 'text', text: discordMsg.content }], {
675
- external: { source: 'discord', id: discordMsg.id },
676
- channelId,
677
- timestamp: discordMsg.timestamp.getTime(),
678
- isOwnMessage: isBotMessage, // Mark as our own for reference
679
- });
680
- newMessages++;
829
+ // From here on nothing awaits, so the rows read now are the rows written.
830
+ const storedMessageMap = this.storedByDiscordId(ctx, channelId);
831
+ let newMessages = 0;
832
+ let editedMessages = 0;
833
+ let deletedMessages = 0;
834
+ for (const discordMsg of chronologicalMessages) {
835
+ if (live.has(discordMsg.id))
836
+ continue;
837
+ const stored = storedMessageMap.get(discordMsg.id);
838
+ if (!stored) {
839
+ // A message we haven't stored. One that was stored when the sync
840
+ // began, and isn't now, was removed meanwhile: not the sync's to
841
+ // bring back.
842
+ const content = converted.get(discordMsg.id);
843
+ if (!content || before.has(discordMsg.id))
844
+ continue;
845
+ // For bot's own messages (from previous sessions), use the agent name
846
+ // This ensures continuity of conversation history
847
+ const isBotMessage = discordMsg.authorId === this.state.botUserId;
848
+ const agentName = ctx.getAgents()[0]?.name;
849
+ const participantName = isBotMessage
850
+ ? (agentName ?? discordMsg.authorName)
851
+ : discordMsg.authorName;
852
+ ctx.addMessage(participantName, content, {
853
+ external: { source: 'discord', id: discordMsg.id },
854
+ channelId,
855
+ timestamp: discordMsg.timestamp.getTime(),
856
+ isOwnMessage: isBotMessage, // Mark as our own for reference
857
+ [TEXT_FIRST]: true,
858
+ });
859
+ newMessages++;
860
+ }
861
+ else if (!stored.bodyGroupId) {
862
+ // We have this message - check whether it changed (offline edit detection)
863
+ const content = needsRebuild(stored, discordMsg)
864
+ ? converted.get(discordMsg.id)
865
+ : contentForText(stored, discordMsg.content);
866
+ if (content) {
867
+ ctx.editMessage(stored.id, content);
868
+ editedMessages++;
869
+ }
870
+ }
681
871
  }
682
- else {
683
- // We have this message - check if content changed (offline edit detection)
684
- if (stored.content !== discordMsg.content) {
685
- this.ctx.editMessage(stored.internalId, [
686
- { type: 'text', text: discordMsg.content },
687
- ]);
688
- editedMessages++;
872
+ // Check for deletes only inside the history we actually fetched. A short
873
+ // response covers complete available history; a full page has an older
874
+ // boundary whose tied millisecond must be preserved.
875
+ const fetchedCompleteHistory = discordMessages.length < scrollback;
876
+ const oldestFetchedTimestamp = discordMessages.length > 0
877
+ ? Math.min(...discordMessages.map((msg) => msg.timestamp.getTime()))
878
+ : undefined;
879
+ for (const [externalId, stored] of storedMessageMap) {
880
+ const sourceTimestamp = typeof stored.metadata?.timestamp === 'number'
881
+ ? stored.metadata.timestamp
882
+ : undefined;
883
+ const isInsideFetchedWindow = fetchedCompleteHistory || (sourceTimestamp !== undefined &&
884
+ oldestFetchedTimestamp !== undefined &&
885
+ // Discord timestamps are millisecond-precise, so an older message just
886
+ // beyond the page can tie the oldest fetched timestamp. Preserve ties
887
+ // rather than guessing that an unseen boundary message was deleted.
888
+ sourceTimestamp > oldestFetchedTimestamp);
889
+ if (isInsideFetchedWindow && !discordIds.has(externalId) && !live.has(externalId)) {
890
+ // Message exists in our store but not in Discord - it was deleted
891
+ // Note: This only catches deletes within the scrollback window.
892
+ // A message the live path wrote while the sync ran is newer than
893
+ // the fetch, so it stays. One shard's id takes out a body whole.
894
+ ctx.removeMessage(stored.id);
895
+ deletedMessages++;
689
896
  }
690
897
  }
691
- }
692
- // Check for deletes only inside the history we actually fetched. A short
693
- // response covers complete available history; a full page has an older
694
- // boundary whose tied millisecond must be preserved.
695
- const fetchedCompleteHistory = discordMessages.length < scrollback;
696
- const oldestFetchedTimestamp = discordMessages.length > 0
697
- ? Math.min(...discordMessages.map((msg) => msg.timestamp.getTime()))
698
- : undefined;
699
- for (const [externalId, stored] of storedMessageMap) {
700
- const isInsideFetchedWindow = fetchedCompleteHistory || (stored.sourceTimestamp !== undefined &&
701
- oldestFetchedTimestamp !== undefined &&
702
- // Discord timestamps are millisecond-precise, so an older message just
703
- // beyond the page can tie the oldest fetched timestamp. Preserve ties
704
- // rather than guessing that an unseen boundary message was deleted.
705
- stored.sourceTimestamp > oldestFetchedTimestamp);
706
- if (isInsideFetchedWindow && !discordMessageMap.has(externalId)) {
707
- // Message exists in our store but not in Discord - it was deleted
708
- // Note: This only catches deletes within the scrollback window
709
- this.ctx.removeMessage(stored.internalId);
710
- deletedMessages++;
898
+ // Update last read
899
+ if (discordMessages.length > 0) {
900
+ // Messages are typically newest first
901
+ const newestId = discordMessages[0].id;
902
+ this.state.lastReadMessageId[channelId] = newestId;
711
903
  }
904
+ return { newMessages, editedMessages, deletedMessages };
712
905
  }
713
- // Update last read
714
- if (discordMessages.length > 0) {
715
- // Messages are typically newest first
716
- const newestId = discordMessages[0].id;
717
- this.state.lastReadMessageId[channelId] = newestId;
906
+ finally {
907
+ this.liveDuringSync.delete(live);
718
908
  }
719
- return { newMessages, editedMessages, deletedMessages };
909
+ }
910
+ /** A channel's stored Discord rows by their Discord message id, whole: an
911
+ * edit replaces a row's own text and keeps what the host added beside it. */
912
+ storedByDiscordId(ctx, channelId) {
913
+ const rows = new Map();
914
+ for (const msg of ctx.queryMessages({ source: 'discord', metadata: { channelId } }).messages) {
915
+ const external = msg.metadata?.external;
916
+ if (external?.id)
917
+ rows.set(external.id, msg);
918
+ }
919
+ return rows;
920
+ }
921
+ /** The stored row of a Discord message, by its id in the row's metadata.
922
+ * The module context's findMessageByExternalId holds only rows the module
923
+ * stored through its context, not those a process response added, so it
924
+ * misses what the live path stored. */
925
+ storedRow(discordMessageId) {
926
+ return this.ctx?.queryMessages({ source: 'discord', externalIds: [discordMessageId] }).messages[0];
927
+ }
928
+ /** Marks a Discord message as the live path's for every history sync running now. */
929
+ noteLive(discordMessageId) {
930
+ for (const live of this.liveDuringSync)
931
+ live.add(discordMessageId);
720
932
  }
721
933
  async handleDiscordMessage(message) {
722
934
  if (!this.ctx)
@@ -764,17 +976,15 @@ export class DiscordModule {
764
976
  });
765
977
  }
766
978
  /**
767
- * Convert Discord message to ContentBlock array.
768
- * Includes text content and any supported attachments (images, text files).
979
+ * Convert a Discord message, live or from history, to ContentBlock array:
980
+ * its own text first, '' when it has none, then any supported attachments
981
+ * (images, text files) and notes for the rest, as TEXT_FIRST marks.
769
982
  */
770
983
  async convertMessageToContent(message) {
984
+ // What the host adds after the message's own text: one block per attachment.
771
985
  const blocks = [];
772
- // Add text content if present
773
- if (message.content.trim()) {
774
- blocks.push({ type: 'text', text: message.content });
775
- }
776
986
  // Process attachments
777
- for (const attachment of message.attachments) {
987
+ for (const attachment of message.attachments ?? []) {
778
988
  const contentType = attachment.contentType?.toLowerCase() ?? '';
779
989
  const filename = attachment.filename.toLowerCase();
780
990
  // Check for supported image types
@@ -800,13 +1010,16 @@ export class DiscordModule {
800
1010
  text: `\n--- File: ${attachment.filename} ---\n${textContent}\n--- End of ${attachment.filename} ---\n`,
801
1011
  });
802
1012
  }
1013
+ else {
1014
+ // An answer whose body is never read holds its connection.
1015
+ await response.body?.cancel().catch(() => { });
1016
+ console.warn(`Discord: Attachment ${logValue(attachment.filename)} in message ${message.id} wasn't fetched: HTTP ${response.status}`);
1017
+ blocks.push(attachmentNotFetched(attachment.filename));
1018
+ }
803
1019
  }
804
1020
  catch (error) {
805
- // If fetch fails, just note the attachment
806
- blocks.push({
807
- type: 'text',
808
- text: `[Attachment: ${attachment.filename} (failed to fetch)]`,
809
- });
1021
+ console.warn(`Discord: Attachment ${logValue(attachment.filename)} in message ${message.id} wasn't fetched:`, error);
1022
+ blocks.push(attachmentNotFetched(attachment.filename));
810
1023
  }
811
1024
  continue;
812
1025
  }
@@ -816,11 +1029,7 @@ export class DiscordModule {
816
1029
  text: `[Attachment: ${attachment.filename} (${contentType || 'unknown type'})]`,
817
1030
  });
818
1031
  }
819
- // Ensure we have at least empty text if nothing else
820
- if (blocks.length === 0) {
821
- blocks.push({ type: 'text', text: '[Empty message]' });
822
- }
823
- return blocks;
1032
+ return textFirst(ownText(message.content), blocks);
824
1033
  }
825
1034
  /**
826
1035
  * Determine if a message should trigger agent inference based on config.
@@ -876,7 +1085,25 @@ export class DiscordModule {
876
1085
  // ==========================================================================
877
1086
  // Tool Handlers
878
1087
  // ==========================================================================
879
- async handleSend(input) {
1088
+ /** Record a message the agent posted in a turn, for that turn's thoughts (lastPosts). */
1089
+ notePost(agentName, turnId, channelId, messageId) {
1090
+ if (agentName === undefined || turnId === undefined)
1091
+ return;
1092
+ // A later turn's post stays: this one's turn has ended, and its thoughts
1093
+ // have gone or will go nowhere.
1094
+ const current = this.lastPosts.get(agentName);
1095
+ if (current && current.turnId > turnId)
1096
+ return;
1097
+ // Set it last, so the entry recorded longest ago is the first to go.
1098
+ this.lastPosts.delete(agentName);
1099
+ this.lastPosts.set(agentName, { turnId, channelId, messageId });
1100
+ if (this.lastPosts.size > MAX_LAST_POSTS) {
1101
+ const oldest = this.lastPosts.keys().next().value;
1102
+ if (oldest !== undefined)
1103
+ this.lastPosts.delete(oldest);
1104
+ }
1105
+ }
1106
+ async handleSend(input, call) {
880
1107
  if (!this.checkRateLimit(input.channelId)) {
881
1108
  return { success: false, error: 'Rate limited', isError: true };
882
1109
  }
@@ -884,15 +1111,19 @@ export class DiscordModule {
884
1111
  replyTo: input.replyTo,
885
1112
  createThread: input.createThread,
886
1113
  });
887
- // Track for thought-editing
888
- this.lastSentMessage = { channelId: input.channelId, messageId: result.messageId };
1114
+ // Track for thought-editing: the message is out, whether or not its
1115
+ // thread was started.
1116
+ this.notePost(call.callerAgentName, call.callerTurnId, input.channelId, result.messageId);
1117
+ if (result.threadFailure !== undefined) {
1118
+ return { success: false, error: result.threadFailure, isError: true };
1119
+ }
889
1120
  return { success: true, data: { messageId: result.messageId } };
890
1121
  }
891
1122
  async handleDM(input) {
892
1123
  const result = await this.client.sendDM(input.userId, input.content);
893
1124
  return { success: true, data: { messageId: result.messageId } };
894
1125
  }
895
- async handleReply(input) {
1126
+ async handleReply(input, call) {
896
1127
  const replyCtx = this.replyContexts.get('default');
897
1128
  if (!replyCtx) {
898
1129
  return { success: false, error: 'No conversation context', isError: true };
@@ -909,7 +1140,7 @@ export class DiscordModule {
909
1140
  replyTo: replyCtx.replyToMessageId,
910
1141
  });
911
1142
  // Track for thought-editing
912
- this.lastSentMessage = { channelId: targetChannel, messageId: result.messageId };
1143
+ this.notePost(call.callerAgentName, call.callerTurnId, targetChannel, result.messageId);
913
1144
  // Clear reply-to after sending
914
1145
  replyCtx.replyToMessageId = undefined;
915
1146
  replyCtx.lastActivity = Date.now();
@@ -1020,6 +1251,11 @@ export class DiscordModule {
1020
1251
  authorId: m.authorId,
1021
1252
  isBot: m.isBot,
1022
1253
  content: m.content,
1254
+ // Not their URLs: a link Discord signs works for anyone holding it
1255
+ // until it expires, and an agent could repeat it where others read.
1256
+ ...(m.attachments?.length
1257
+ ? { attachments: m.attachments.map(({ filename, contentType, size }) => ({ filename, contentType, size })) }
1258
+ : {}),
1023
1259
  timestamp: formatZonedDateTime(m.timestamp, this.timeZone),
1024
1260
  replyTo: m.replyTo,
1025
1261
  })),