@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
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import type { ContentBlock } from '@animalabs/membrane';
11
+ import type { StoredMessage } from '@animalabs/context-manager';
11
12
  import type {
12
13
  Module,
13
14
  ModuleContext,
@@ -24,11 +25,13 @@ import type {
24
25
  DiscordModuleConfig,
25
26
  DiscordModuleState,
26
27
  ConversationContext,
28
+ DiscordAttachment,
27
29
  DiscordClientInterface,
28
30
  DiscordMessageData,
29
31
  DiscordMessageEvent,
30
32
  DiscordEditEvent,
31
33
  DiscordDeleteEvent,
34
+ HistoryMessage,
32
35
  SendInput,
33
36
  SendDMInput,
34
37
  ReplyInput,
@@ -42,6 +45,7 @@ import type {
42
45
  FetchHistoryInput,
43
46
  } from './types.js';
44
47
  import { formatZonedDateTime, resolveTimeZone } from '../../timezone.js';
48
+ import { logValue } from '../../mcpl/log-value.js';
45
49
 
46
50
  // Re-export event types for consumers who want to handle them
47
51
  export type { DiscordMessageEvent, DiscordEditEvent, DiscordDeleteEvent } from './types.js';
@@ -67,6 +71,14 @@ const TYPING_REFRESH_MS = 8_000;
67
71
  // stuck on forever.
68
72
  const TYPING_MAX_MS = 5 * 60_000;
69
73
 
74
+ // The most agents whose latest post the module keeps for their turn's
75
+ // thoughts (lastPosts). Past it, the entry recorded longest ago goes, which
76
+ // bounds the entries of agents that are gone, such as closed conversations'.
77
+ // An entry is wanted only until its turn's speech arrives, so one goes while
78
+ // still wanted only if this many other agents post in that time, and its
79
+ // turn's thoughts then go into no message.
80
+ const MAX_LAST_POSTS = 1_024;
81
+
70
82
  // Trace event types that end an agent's turn (onTrace's contract) — any of
71
83
  // these stops the typing keepalive. A turn's tool-call cycles stay inside its
72
84
  // stream, so they come after them. inference:completed is the normal end.
@@ -95,6 +107,128 @@ const TEXT_FILE_EXTENSIONS = [
95
107
 
96
108
  const CONVERSATION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
97
109
 
110
+ /** What the agent reads for a text attachment whose contents couldn't be
111
+ * fetched: by an error, or by an answer that wasn't OK. */
112
+ function attachmentNotFetched(filename: string): { type: 'text'; text: string } {
113
+ return { type: 'text', text: `[Attachment: ${filename} (failed to fetch)]` };
114
+ }
115
+
116
+ /** What a stored message reads when it has no text of its own and nothing the
117
+ * host added, so the agent still sees that a message was there. */
118
+ const EMPTY_MESSAGE = '[Empty message]';
119
+
120
+ /**
121
+ * Metadata on a stored Discord message whose first block is its own text,
122
+ * '' when it has none, and every block after it the host's: images, inlined
123
+ * file text, attachment notes and EMPTY_MESSAGE. An edit replaces content and
124
+ * can't touch metadata, so the mark holds for the row's life, and it tells an
125
+ * edit or a sync which block is Discord's to replace. For the same reason a
126
+ * row stored before the mark never gets it, even once a history sync
127
+ * rebuilds it in this layout. The request builder drops an empty text block,
128
+ * as it does wherever one occurs.
129
+ */
130
+ const TEXT_FIRST = 'discordTextFirst';
131
+
132
+ /** A message's own text as a stored row holds it: '' when it's blank. */
133
+ function ownText(content: string): string {
134
+ return content.trim() ? content : '';
135
+ }
136
+
137
+ const isEmptyMarker = (block: ContentBlock): boolean => block.type === 'text' && block.text === EMPTY_MESSAGE;
138
+ const isBlankText = (block: ContentBlock): boolean => block.type === 'text' && !block.text.trim();
139
+
140
+ /**
141
+ * A text-first row's content: the message's own text, '' when it has none,
142
+ * then `after`, what the host added; EMPTY_MESSAGE when there's neither.
143
+ */
144
+ function textFirst(text: string, after: ContentBlock[] = []): ContentBlock[] {
145
+ return [{ type: 'text', text }, ...(text || after.length > 0 ? after : [{ type: 'text' as const, text: EMPTY_MESSAGE }])];
146
+ }
147
+
148
+ /** A text-first row's content with `text` as the message's own text, in
149
+ * place of its first block, keeping what the host added after it. */
150
+ function withOwnText(content: ContentBlock[], text: string): ContentBlock[] {
151
+ return textFirst(ownText(text), content.slice(1).filter((block) => !isEmptyMarker(block)));
152
+ }
153
+
154
+ /**
155
+ * The content a stored Discord message should hold once Discord's text for it
156
+ * is `discordText`, or null when it holds that already.
157
+ *
158
+ * A text-first row keeps every block the host added and replaces only its own
159
+ * text; EMPTY_MESSAGE goes once there is text, and comes back when nothing is
160
+ * left. A row stored before that layout held its own text first when it had
161
+ * any, but a message without text began with what the host added, which may
162
+ * be text, a file's contents or a note, so its first block can't be told
163
+ * apart. Such a row is left alone unless Discord's text is there and differs
164
+ * from its first block, and then that text takes the first block's place
165
+ * when it's text, and goes before it when it isn't, and EMPTY_MESSAGE goes.
166
+ * So a message without text, stored beginning with a file's contents or a
167
+ * note, loses that block. The history sync, which has the message's
168
+ * attachments, rebuilds such a row instead (needsRebuild).
169
+ */
170
+ function contentForText(stored: StoredMessage, discordText: string): ContentBlock[] | null {
171
+ const text = ownText(discordText);
172
+ const [first, ...rest] = stored.content;
173
+ if (stored.metadata?.[TEXT_FIRST] === true) {
174
+ if (first?.type === 'text' && first.text === text) return null;
175
+ return withOwnText(stored.content, text);
176
+ }
177
+ if (!text || (first?.type === 'text' && first.text === discordText)) return null;
178
+ return [{ type: 'text', text: discordText }, ...(first?.type === 'text' ? rest : stored.content).filter((block) => !isEmptyMarker(block))];
179
+ }
180
+
181
+ /**
182
+ * Whether a stored row lacks or holds more than the live conversion gives
183
+ * Discord's `message` now, its own text aside, so the history sync stores it
184
+ * through that conversion again. The conversion gives each attachment one
185
+ * block: an image, a file's text, or a note when it isn't fetched or isn't
186
+ * read. So a text-first row holds one block per attachment after its text,
187
+ * EMPTY_MESSAGE aside, which the text's rule keeps. A row stored before that
188
+ * layout held its text, when it had any, then those blocks, or EMPTY_MESSAGE
189
+ * alone; one that doesn't was blanked or stripped by an earlier edit or sync,
190
+ * or its message gained or lost text, or lost an attachment. Its first block,
191
+ * when it is the message's own text, counts as that text, even when the text
192
+ * reads as EMPTY_MESSAGE. For a message without text of its own, a first
193
+ * block that's text may be what the host added or a caption the message has
194
+ * since lost, which no count tells apart, so that row is stored again; it
195
+ * then begins with its own '' text. One whose text alone changed is left to
196
+ * the text's rule, which keeps the blocks after it. History without
197
+ * attachments can't be compared, so it rebuilds nothing.
198
+ */
199
+ function needsRebuild(stored: StoredMessage, message: HistoryMessage): boolean {
200
+ if (message.attachments === undefined) return false;
201
+ const attachments = message.attachments.length;
202
+ const held = (blocks: ContentBlock[]) => blocks.filter((block) => !isBlankText(block) && !isEmptyMarker(block)).length;
203
+ if (stored.metadata?.[TEXT_FIRST] === true) return held(stored.content.slice(1)) !== attachments;
204
+ const own = ownText(message.content);
205
+ const [first, ...rest] = stored.content;
206
+ if (!own && first?.type === 'text' && !isBlankText(first) && !isEmptyMarker(first)) return true;
207
+ const expected = (own ? 1 : 0) + attachments;
208
+ const counted = own && first?.type === 'text' && first.text === own ? 1 + held(rest) : held(stored.content);
209
+ return counted !== expected || (expected === 0 && !stored.content.some(isEmptyMarker));
210
+ }
211
+
212
+ /**
213
+ * Whether a row holds non-blank text besides its message's own text now,
214
+ * which may be what a file gave. A marked row whose message's text changed
215
+ * counts its old text here too, which can delay its rebuild until a fetch
216
+ * succeeds but never loses text.
217
+ */
218
+ function holdsOtherText(stored: StoredMessage, message: HistoryMessage): boolean {
219
+ const own = ownText(message.content);
220
+ const [first, ...rest] = stored.content;
221
+ const others = own && first?.type === 'text' && first.text === own ? rest : stored.content;
222
+ return others.some((block) => block.type === 'text' && !isBlankText(block) && !isEmptyMarker(block));
223
+ }
224
+
225
+ /** Whether a message's conversion holds, after the message's own text, the
226
+ * note for an attachment of its whose text wasn't fetched. */
227
+ function holdsNotFetched(content: ContentBlock[], message: HistoryMessage): boolean {
228
+ const notes = new Set((message.attachments ?? []).map((attachment) => attachmentNotFetched(attachment.filename).text));
229
+ return content.slice(1).some((block) => block.type === 'text' && notes.has(block.text));
230
+ }
231
+
98
232
  /**
99
233
  * Discord module for the agent framework.
100
234
  */
@@ -115,8 +249,25 @@ export class DiscordModule implements Module {
115
249
  // Track current reply context per agent
116
250
  private replyContexts: Map<string, ConversationContext> = new Map();
117
251
 
118
- // Last message sent by a tool (for thought-editing)
119
- private lastSentMessage: { channelId: string; messageId: string } | null = null;
252
+ // Where a tool turn's thoughts go (onAgentSpeech edits them in as a
253
+ // spoiler): each agent's latest message posted in a turn, with that turn's
254
+ // id (notePost). A `send` or `reply` records the message its client call
255
+ // returns, and so does the module's own speech. Thoughts go into it only
256
+ // when their speech ends the same turn, and taking them removes it. So
257
+ // neither another agent's message nor one from an earlier turn takes them,
258
+ // and an attempt in the turn that is refused or throws leaves the turn's own
259
+ // post in place. Turn ids increase, so an earlier turn's post that finishes
260
+ // after a later turn's leaves the later one in place. A DM records nothing,
261
+ // since its channel isn't known here, and neither does a post whose call or
262
+ // speech carries no turn. An entry goes when its thoughts are taken, when
263
+ // the agent's next post replaces it, or past MAX_LAST_POSTS agents.
264
+ private lastPosts: Map<string, { turnId: number; channelId: string; messageId: string }> = new Map();
265
+
266
+ // One set per running history sync: the Discord messages the live path
267
+ // stored, edited or was told were deleted since that sync began. What the
268
+ // live path saw is newer than what the sync fetched, so the sync leaves
269
+ // those messages alone.
270
+ private readonly liveDuringSync = new Set<Set<string>>();
120
271
 
121
272
  // Typing keepalive: agentName -> { interval, deadline }. Started on
122
273
  // inference:started, stopped on the turn's terminal trace event. Discord's
@@ -406,7 +557,7 @@ export class DiscordModule implements Module {
406
557
  },
407
558
  {
408
559
  name: 'fetch_history',
409
- description: 'Fetch recent message history from a channel',
560
+ 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.',
410
561
  inputSchema: {
411
562
  type: 'object',
412
563
  properties: {
@@ -424,11 +575,11 @@ export class DiscordModule implements Module {
424
575
  try {
425
576
  switch (call.name) {
426
577
  case 'send':
427
- return await this.handleSend(call.input as SendInput);
578
+ return await this.handleSend(call.input as SendInput, call);
428
579
  case 'dm':
429
580
  return await this.handleDM(call.input as SendDMInput);
430
581
  case 'reply':
431
- return await this.handleReply(call.input as ReplyInput);
582
+ return await this.handleReply(call.input as ReplyInput, call);
432
583
  case 'react':
433
584
  return await this.handleReact(call.input as ReactInput);
434
585
  case 'edit':
@@ -509,8 +660,10 @@ export class DiscordModule implements Module {
509
660
  });
510
661
  }
511
662
 
512
- // Build content blocks from message and attachments
513
- const contentBlocks = msg.contentBlocks ?? [{ type: 'text' as const, text: msg.content }];
663
+ // Built from the message and its attachments, or from its text alone
664
+ // when an event carries no blocks; text first, as TEXT_FIRST marks.
665
+ const contentBlocks = msg.contentBlocks ?? textFirst(ownText(msg.content));
666
+ this.noteLive(msg.discordMessageId);
514
667
 
515
668
  // Return declarative response - framework applies all writes atomically
516
669
  return {
@@ -522,6 +675,7 @@ export class DiscordModule implements Module {
522
675
  external: { source: 'discord', id: msg.discordMessageId },
523
676
  channelId: msg.channelId,
524
677
  timestamp: msg.timestamp,
678
+ [TEXT_FIRST]: true,
525
679
  },
526
680
  },
527
681
  ],
@@ -533,29 +687,41 @@ export class DiscordModule implements Module {
533
687
  // Handle Discord message edit
534
688
  if (event.type === 'discord:edit') {
535
689
  const edit = event as DiscordEditEvent;
536
- const internalId = state.findMessageByExternalId('discord', edit.discordMessageId);
537
- if (!internalId) {
690
+ // The stored row, not only its id: an edit changes the message's own
691
+ // text and keeps what the host added beside it.
692
+ // An edit to a message nobody has stored yet is dropped: whatever
693
+ // stores the message, its live add or a history sync running now,
694
+ // stores the text it got, and the next sync's text rule changes it.
695
+ // A row stored in shards can't be edited one shard at a time, so it
696
+ // keeps its text, and the host's log says so. Only an edit that writes
697
+ // marks the message live, so an update that changes nothing leaves a
698
+ // running sync free to rewrite the row.
699
+ const stored = this.storedRow(edit.discordMessageId);
700
+ if (!stored) return {};
701
+ if (stored.bodyGroupId) {
702
+ 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`);
538
703
  return {};
539
704
  }
540
- return {
541
- editMessages: [
542
- {
543
- messageId: internalId,
544
- content: [{ type: 'text', text: edit.newContent }],
545
- },
546
- ],
547
- };
705
+ const content = contentForText(stored, edit.newContent);
706
+ if (!content) return {};
707
+ this.noteLive(edit.discordMessageId);
708
+ return { editMessages: [{ messageId: stored.id, content }] };
548
709
  }
549
710
 
550
711
  // Handle Discord message delete
551
712
  if (event.type === 'discord:delete') {
552
713
  const del = event as DiscordDeleteEvent;
553
- const internalId = state.findMessageByExternalId('discord', del.discordMessageId);
554
- if (!internalId) {
714
+ // A row stored in shards is removed whole: the framework takes out the
715
+ // body a shard belongs to. The message is the live path's even when no
716
+ // row is found, so a running sync doesn't store what its fetch may
717
+ // still hold.
718
+ this.noteLive(del.discordMessageId);
719
+ const stored = this.storedRow(del.discordMessageId);
720
+ if (!stored) {
555
721
  return {};
556
722
  }
557
723
  return {
558
- removeMessages: [internalId],
724
+ removeMessages: [stored.id],
559
725
  };
560
726
  }
561
727
 
@@ -570,13 +736,15 @@ export class DiscordModule implements Module {
570
736
  content: ContentBlock[],
571
737
  context: SpeechContext
572
738
  ): Promise<void> {
573
- // If thoughts are present and we have a recently sent message, edit it
574
- // to prepend the thoughts as spoiler text.
575
- if (context.thoughts && context.thoughts.length > 0 && this.lastSentMessage) {
739
+ // If thoughts are present and this agent posted a message in the turn
740
+ // they end (lastPosts), edit it to prepend the thoughts as spoiler text.
741
+ const post = this.lastPosts.get(agentName);
742
+ if (context.thoughts && context.thoughts.length > 0 && post && post.turnId === context.turnId) {
743
+ this.lastPosts.delete(agentName);
576
744
  const thoughtText = this.extractText(context.thoughts);
577
745
  if (thoughtText) {
578
746
  try {
579
- const { channelId, messageId } = this.lastSentMessage;
747
+ const { channelId, messageId } = post;
580
748
  // Fetch the current message content via the client isn't available,
581
749
  // but we know the tool just sent it — reconstruct by editing with
582
750
  // spoiler-wrapped thoughts prepended.
@@ -588,7 +756,6 @@ export class DiscordModule implements Module {
588
756
  console.warn('Discord: Failed to edit thoughts into message:', err);
589
757
  }
590
758
  }
591
- this.lastSentMessage = null;
592
759
  }
593
760
 
594
761
  // Get reply context for this agent
@@ -617,8 +784,8 @@ export class DiscordModule implements Module {
617
784
  replyTo: replyCtx.replyToMessageId,
618
785
  });
619
786
 
620
- // Track for thought-editing (in case of chained speech)
621
- this.lastSentMessage = { channelId: targetChannel, messageId: result.messageId };
787
+ // Track for thought-editing (in case of chained speech in the same turn)
788
+ this.notePost(agentName, context.turnId, targetChannel, result.messageId);
622
789
 
623
790
  // Clear reply-to after sending (don't keep replying to same message)
624
791
  replyCtx.replyToMessageId = undefined;
@@ -724,131 +891,176 @@ export class DiscordModule implements Module {
724
891
  /**
725
892
  * Sync history for a specific channel - compare with Context Manager and update.
726
893
  * Uses queryMessages() to enumerate stored messages for proper edit/delete detection.
894
+ *
895
+ * The live path can store, edit or remove a row whenever the sync awaits.
896
+ * So the sync fetches history and runs the live conversion it needs first,
897
+ * then reads the store again and writes with no await between that read
898
+ * and its writes. It leaves alone any message the live path stored,
899
+ * changed or was told was deleted while it ran (liveDuringSync), an update
900
+ * that changed nothing aside. A live edit to a message nobody had stored
901
+ * yet is dropped, so a message the sync stores holds the text it fetched
902
+ * until the next sync's text rule changes it. The framework writes an
903
+ * event's response only once every module has processed the event, so an
904
+ * event processed before the sync began can still be written after the
905
+ * sync's own writes, which this doesn't cover.
727
906
  */
728
907
  private async syncChannelHistory(channelId: string): Promise<{
729
908
  newMessages: number;
730
909
  editedMessages: number;
731
910
  deletedMessages: number;
732
911
  }> {
733
- if (!this.ctx) {
734
- return { newMessages: 0, editedMessages: 0, deletedMessages: 0 };
912
+ const unchanged = { newMessages: 0, editedMessages: 0, deletedMessages: 0 };
913
+ const ctx = this.ctx;
914
+ if (!ctx) {
915
+ return unchanged;
735
916
  }
736
-
737
- const scrollback = this.config.historyScrollback ?? 50;
738
-
739
- // Fetch recent history from Discord
740
- const discordMessages = await this.client.fetchHistory(channelId, { limit: scrollback });
741
-
742
- // Build a map of Discord message ID -> content for comparison
743
- const discordMessageMap = new Map<string, { content: string; authorName: string; timestamp: Date }>();
744
- for (const msg of discordMessages) {
745
- discordMessageMap.set(msg.id, {
746
- content: msg.content,
747
- authorName: msg.authorName,
748
- timestamp: msg.timestamp,
749
- });
750
- }
751
-
752
- // Query Context Manager for all Discord messages from this channel
753
- const { messages: storedMessages } = this.ctx.queryMessages({
754
- source: 'discord',
755
- metadata: { channelId },
756
- });
757
-
758
- // Build a map of stored message external IDs -> internal data
759
- const storedMessageMap = new Map<string, { internalId: string; content: string; sourceTimestamp?: number }>();
760
- for (const msg of storedMessages) {
761
- const external = msg.metadata?.external as { id?: string } | undefined;
762
- if (external?.id) {
763
- // Extract text content for comparison
764
- const textContent = msg.content
765
- .filter((block): block is { type: 'text'; text: string } => block.type === 'text')
766
- .map((block) => block.text)
767
- .join('\n');
768
- storedMessageMap.set(external.id, {
769
- internalId: msg.id,
770
- content: textContent,
771
- sourceTimestamp: typeof msg.metadata?.timestamp === 'number'
772
- ? msg.metadata.timestamp
773
- : undefined,
774
- });
917
+ const live = new Set<string>();
918
+ this.liveDuringSync.add(live);
919
+ try {
920
+ const scrollback = this.config.historyScrollback ?? 50;
921
+ // The rows stored as the sync begins. One that is gone by the time it
922
+ // writes was removed meanwhile, and isn't the sync's to bring back.
923
+ const before = this.storedByDiscordId(ctx, channelId);
924
+
925
+ // Fetch recent history from Discord. If the module stopped or restarted
926
+ // meanwhile, this sync's context is gone and it writes nothing.
927
+ const discordMessages = await this.client.fetchHistory(channelId, { limit: scrollback });
928
+ if (this.ctx !== ctx) return unchanged;
929
+
930
+ // Discord's ids, for delete detection inside the fetched window.
931
+ const discordIds = new Set(discordMessages.map((msg) => msg.id));
932
+
933
+ // Discord history is newest-first, while addMessage appends to the stored
934
+ // conversation. Process oldest-first so missed messages retain chronology.
935
+ const chronologicalMessages = [...discordMessages].reverse();
936
+
937
+ // The live conversion, which fetches attachments, for a message the
938
+ // store lacks and for a row that doesn't hold what the conversion gives
939
+ // the message now (needsRebuild). A row stored in shards can't be
940
+ // edited one shard at a time, so it's left as it is.
941
+ const converted = new Map<string, ContentBlock[]>();
942
+ for (const discordMsg of chronologicalMessages) {
943
+ const stored = before.get(discordMsg.id);
944
+ if (stored && (stored.bodyGroupId || !needsRebuild(stored, discordMsg))) continue;
945
+ const content = await this.convertMessageToContent(discordMsg);
946
+ if (this.ctx !== ctx) return unchanged;
947
+ // A failed fetch never costs a row the text it holds: when a file
948
+ // wasn't fetched, a row holding other text, which may be that file's,
949
+ // keeps what it holds, and the next sync tries again.
950
+ if (stored && holdsNotFetched(content, discordMsg) && holdsOtherText(stored, discordMsg)) continue;
951
+ converted.set(discordMsg.id, content);
775
952
  }
776
- }
777
953
 
778
- let newMessages = 0;
779
- let editedMessages = 0;
780
- let deletedMessages = 0;
781
-
782
- // Discord history is newest-first, while addMessage appends to the stored
783
- // conversation. Process oldest-first so missed messages retain chronology.
784
- const chronologicalMessages = [...discordMessages].reverse();
785
- for (const discordMsg of chronologicalMessages) {
786
- const stored = storedMessageMap.get(discordMsg.id);
787
-
788
- if (!stored) {
789
- // New message we haven't seen
790
- // For bot's own messages (from previous sessions), use the agent name
791
- // This ensures continuity of conversation history
792
- const isBotMessage = discordMsg.authorId === this.state.botUserId;
793
- const agentName = this.ctx.getAgents()[0]?.name;
794
- const participantName = isBotMessage
795
- ? (agentName ?? discordMsg.authorName)
796
- : discordMsg.authorName;
797
-
798
- this.ctx.addMessage(
799
- participantName,
800
- [{ type: 'text', text: discordMsg.content }],
801
- {
802
- external: { source: 'discord', id: discordMsg.id },
803
- channelId,
804
- timestamp: discordMsg.timestamp.getTime(),
805
- isOwnMessage: isBotMessage, // Mark as our own for reference
954
+ // From here on nothing awaits, so the rows read now are the rows written.
955
+ const storedMessageMap = this.storedByDiscordId(ctx, channelId);
956
+ let newMessages = 0;
957
+ let editedMessages = 0;
958
+ let deletedMessages = 0;
959
+ for (const discordMsg of chronologicalMessages) {
960
+ if (live.has(discordMsg.id)) continue;
961
+ const stored = storedMessageMap.get(discordMsg.id);
962
+
963
+ if (!stored) {
964
+ // A message we haven't stored. One that was stored when the sync
965
+ // began, and isn't now, was removed meanwhile: not the sync's to
966
+ // bring back.
967
+ const content = converted.get(discordMsg.id);
968
+ if (!content || before.has(discordMsg.id)) continue;
969
+ // For bot's own messages (from previous sessions), use the agent name
970
+ // This ensures continuity of conversation history
971
+ const isBotMessage = discordMsg.authorId === this.state.botUserId;
972
+ const agentName = ctx.getAgents()[0]?.name;
973
+ const participantName = isBotMessage
974
+ ? (agentName ?? discordMsg.authorName)
975
+ : discordMsg.authorName;
976
+ ctx.addMessage(
977
+ participantName,
978
+ content,
979
+ {
980
+ external: { source: 'discord', id: discordMsg.id },
981
+ channelId,
982
+ timestamp: discordMsg.timestamp.getTime(),
983
+ isOwnMessage: isBotMessage, // Mark as our own for reference
984
+ [TEXT_FIRST]: true,
985
+ }
986
+ );
987
+ newMessages++;
988
+ } else if (!stored.bodyGroupId) {
989
+ // We have this message - check whether it changed (offline edit detection)
990
+ const content = needsRebuild(stored, discordMsg)
991
+ ? converted.get(discordMsg.id)
992
+ : contentForText(stored, discordMsg.content);
993
+ if (content) {
994
+ ctx.editMessage(stored.id, content);
995
+ editedMessages++;
806
996
  }
997
+ }
998
+ }
999
+
1000
+ // Check for deletes only inside the history we actually fetched. A short
1001
+ // response covers complete available history; a full page has an older
1002
+ // boundary whose tied millisecond must be preserved.
1003
+ const fetchedCompleteHistory = discordMessages.length < scrollback;
1004
+ const oldestFetchedTimestamp = discordMessages.length > 0
1005
+ ? Math.min(...discordMessages.map((msg) => msg.timestamp.getTime()))
1006
+ : undefined;
1007
+ for (const [externalId, stored] of storedMessageMap) {
1008
+ const sourceTimestamp = typeof stored.metadata?.timestamp === 'number'
1009
+ ? stored.metadata.timestamp
1010
+ : undefined;
1011
+ const isInsideFetchedWindow = fetchedCompleteHistory || (
1012
+ sourceTimestamp !== undefined &&
1013
+ oldestFetchedTimestamp !== undefined &&
1014
+ // Discord timestamps are millisecond-precise, so an older message just
1015
+ // beyond the page can tie the oldest fetched timestamp. Preserve ties
1016
+ // rather than guessing that an unseen boundary message was deleted.
1017
+ sourceTimestamp > oldestFetchedTimestamp
807
1018
  );
808
- newMessages++;
809
- } else {
810
- // We have this message - check if content changed (offline edit detection)
811
- if (stored.content !== discordMsg.content) {
812
- this.ctx.editMessage(stored.internalId, [
813
- { type: 'text', text: discordMsg.content },
814
- ]);
815
- editedMessages++;
1019
+ if (isInsideFetchedWindow && !discordIds.has(externalId) && !live.has(externalId)) {
1020
+ // Message exists in our store but not in Discord - it was deleted
1021
+ // Note: This only catches deletes within the scrollback window.
1022
+ // A message the live path wrote while the sync ran is newer than
1023
+ // the fetch, so it stays. One shard's id takes out a body whole.
1024
+ ctx.removeMessage(stored.id);
1025
+ deletedMessages++;
816
1026
  }
817
1027
  }
818
- }
819
1028
 
820
- // Check for deletes only inside the history we actually fetched. A short
821
- // response covers complete available history; a full page has an older
822
- // boundary whose tied millisecond must be preserved.
823
- const fetchedCompleteHistory = discordMessages.length < scrollback;
824
- const oldestFetchedTimestamp = discordMessages.length > 0
825
- ? Math.min(...discordMessages.map((msg) => msg.timestamp.getTime()))
826
- : undefined;
827
- for (const [externalId, stored] of storedMessageMap) {
828
- const isInsideFetchedWindow = fetchedCompleteHistory || (
829
- stored.sourceTimestamp !== undefined &&
830
- oldestFetchedTimestamp !== undefined &&
831
- // Discord timestamps are millisecond-precise, so an older message just
832
- // beyond the page can tie the oldest fetched timestamp. Preserve ties
833
- // rather than guessing that an unseen boundary message was deleted.
834
- stored.sourceTimestamp > oldestFetchedTimestamp
835
- );
836
- if (isInsideFetchedWindow && !discordMessageMap.has(externalId)) {
837
- // Message exists in our store but not in Discord - it was deleted
838
- // Note: This only catches deletes within the scrollback window
839
- this.ctx.removeMessage(stored.internalId);
840
- deletedMessages++;
1029
+ // Update last read
1030
+ if (discordMessages.length > 0) {
1031
+ // Messages are typically newest first
1032
+ const newestId = discordMessages[0].id;
1033
+ this.state.lastReadMessageId[channelId] = newestId;
841
1034
  }
1035
+
1036
+ return { newMessages, editedMessages, deletedMessages };
1037
+ } finally {
1038
+ this.liveDuringSync.delete(live);
842
1039
  }
1040
+ }
843
1041
 
844
- // Update last read
845
- if (discordMessages.length > 0) {
846
- // Messages are typically newest first
847
- const newestId = discordMessages[0].id;
848
- this.state.lastReadMessageId[channelId] = newestId;
1042
+ /** A channel's stored Discord rows by their Discord message id, whole: an
1043
+ * edit replaces a row's own text and keeps what the host added beside it. */
1044
+ private storedByDiscordId(ctx: ModuleContext, channelId: string): Map<string, StoredMessage> {
1045
+ const rows = new Map<string, StoredMessage>();
1046
+ for (const msg of ctx.queryMessages({ source: 'discord', metadata: { channelId } }).messages) {
1047
+ const external = msg.metadata?.external as { id?: string } | undefined;
1048
+ if (external?.id) rows.set(external.id, msg);
849
1049
  }
1050
+ return rows;
1051
+ }
1052
+
1053
+ /** The stored row of a Discord message, by its id in the row's metadata.
1054
+ * The module context's findMessageByExternalId holds only rows the module
1055
+ * stored through its context, not those a process response added, so it
1056
+ * misses what the live path stored. */
1057
+ private storedRow(discordMessageId: string): StoredMessage | undefined {
1058
+ return this.ctx?.queryMessages({ source: 'discord', externalIds: [discordMessageId] }).messages[0];
1059
+ }
850
1060
 
851
- return { newMessages, editedMessages, deletedMessages };
1061
+ /** Marks a Discord message as the live path's for every history sync running now. */
1062
+ private noteLive(discordMessageId: string): void {
1063
+ for (const live of this.liveDuringSync) live.add(discordMessageId);
852
1064
  }
853
1065
 
854
1066
  private async handleDiscordMessage(message: DiscordMessageData): Promise<void> {
@@ -907,19 +1119,18 @@ export class DiscordModule implements Module {
907
1119
  }
908
1120
 
909
1121
  /**
910
- * Convert Discord message to ContentBlock array.
911
- * Includes text content and any supported attachments (images, text files).
1122
+ * Convert a Discord message, live or from history, to ContentBlock array:
1123
+ * its own text first, '' when it has none, then any supported attachments
1124
+ * (images, text files) and notes for the rest, as TEXT_FIRST marks.
912
1125
  */
913
- private async convertMessageToContent(message: DiscordMessageData): Promise<ContentBlock[]> {
1126
+ private async convertMessageToContent(
1127
+ message: { id: string; content: string; attachments?: readonly DiscordAttachment[] },
1128
+ ): Promise<ContentBlock[]> {
1129
+ // What the host adds after the message's own text: one block per attachment.
914
1130
  const blocks: ContentBlock[] = [];
915
1131
 
916
- // Add text content if present
917
- if (message.content.trim()) {
918
- blocks.push({ type: 'text', text: message.content });
919
- }
920
-
921
1132
  // Process attachments
922
- for (const attachment of message.attachments) {
1133
+ for (const attachment of message.attachments ?? []) {
923
1134
  const contentType = attachment.contentType?.toLowerCase() ?? '';
924
1135
  const filename = attachment.filename.toLowerCase();
925
1136
 
@@ -946,13 +1157,15 @@ export class DiscordModule implements Module {
946
1157
  type: 'text',
947
1158
  text: `\n--- File: ${attachment.filename} ---\n${textContent}\n--- End of ${attachment.filename} ---\n`,
948
1159
  });
1160
+ } else {
1161
+ // An answer whose body is never read holds its connection.
1162
+ await response.body?.cancel().catch(() => {});
1163
+ console.warn(`Discord: Attachment ${logValue(attachment.filename)} in message ${message.id} wasn't fetched: HTTP ${response.status}`);
1164
+ blocks.push(attachmentNotFetched(attachment.filename));
949
1165
  }
950
1166
  } catch (error) {
951
- // If fetch fails, just note the attachment
952
- blocks.push({
953
- type: 'text',
954
- text: `[Attachment: ${attachment.filename} (failed to fetch)]`,
955
- });
1167
+ console.warn(`Discord: Attachment ${logValue(attachment.filename)} in message ${message.id} wasn't fetched:`, error);
1168
+ blocks.push(attachmentNotFetched(attachment.filename));
956
1169
  }
957
1170
  continue;
958
1171
  }
@@ -964,12 +1177,7 @@ export class DiscordModule implements Module {
964
1177
  });
965
1178
  }
966
1179
 
967
- // Ensure we have at least empty text if nothing else
968
- if (blocks.length === 0) {
969
- blocks.push({ type: 'text', text: '[Empty message]' });
970
- }
971
-
972
- return blocks;
1180
+ return textFirst(ownText(message.content), blocks);
973
1181
  }
974
1182
 
975
1183
  /**
@@ -1037,7 +1245,23 @@ export class DiscordModule implements Module {
1037
1245
  // Tool Handlers
1038
1246
  // ==========================================================================
1039
1247
 
1040
- private async handleSend(input: SendInput): Promise<ToolResult> {
1248
+ /** Record a message the agent posted in a turn, for that turn's thoughts (lastPosts). */
1249
+ private notePost(agentName: string | undefined, turnId: number | undefined, channelId: string, messageId: string): void {
1250
+ if (agentName === undefined || turnId === undefined) return;
1251
+ // A later turn's post stays: this one's turn has ended, and its thoughts
1252
+ // have gone or will go nowhere.
1253
+ const current = this.lastPosts.get(agentName);
1254
+ if (current && current.turnId > turnId) return;
1255
+ // Set it last, so the entry recorded longest ago is the first to go.
1256
+ this.lastPosts.delete(agentName);
1257
+ this.lastPosts.set(agentName, { turnId, channelId, messageId });
1258
+ if (this.lastPosts.size > MAX_LAST_POSTS) {
1259
+ const oldest = this.lastPosts.keys().next().value;
1260
+ if (oldest !== undefined) this.lastPosts.delete(oldest);
1261
+ }
1262
+ }
1263
+
1264
+ private async handleSend(input: SendInput, call: ToolCall): Promise<ToolResult> {
1041
1265
  if (!this.checkRateLimit(input.channelId)) {
1042
1266
  return { success: false, error: 'Rate limited', isError: true };
1043
1267
  }
@@ -1047,9 +1271,13 @@ export class DiscordModule implements Module {
1047
1271
  createThread: input.createThread,
1048
1272
  });
1049
1273
 
1050
- // Track for thought-editing
1051
- this.lastSentMessage = { channelId: input.channelId, messageId: result.messageId };
1274
+ // Track for thought-editing: the message is out, whether or not its
1275
+ // thread was started.
1276
+ this.notePost(call.callerAgentName, call.callerTurnId, input.channelId, result.messageId);
1052
1277
 
1278
+ if (result.threadFailure !== undefined) {
1279
+ return { success: false, error: result.threadFailure, isError: true };
1280
+ }
1053
1281
  return { success: true, data: { messageId: result.messageId } };
1054
1282
  }
1055
1283
 
@@ -1058,7 +1286,7 @@ export class DiscordModule implements Module {
1058
1286
  return { success: true, data: { messageId: result.messageId } };
1059
1287
  }
1060
1288
 
1061
- private async handleReply(input: ReplyInput): Promise<ToolResult> {
1289
+ private async handleReply(input: ReplyInput, call: ToolCall): Promise<ToolResult> {
1062
1290
  const replyCtx = this.replyContexts.get('default');
1063
1291
  if (!replyCtx) {
1064
1292
  return { success: false, error: 'No conversation context', isError: true };
@@ -1079,7 +1307,7 @@ export class DiscordModule implements Module {
1079
1307
  });
1080
1308
 
1081
1309
  // Track for thought-editing
1082
- this.lastSentMessage = { channelId: targetChannel, messageId: result.messageId };
1310
+ this.notePost(call.callerAgentName, call.callerTurnId, targetChannel, result.messageId);
1083
1311
 
1084
1312
  // Clear reply-to after sending
1085
1313
  replyCtx.replyToMessageId = undefined;
@@ -1213,6 +1441,11 @@ export class DiscordModule implements Module {
1213
1441
  authorId: m.authorId,
1214
1442
  isBot: m.isBot,
1215
1443
  content: m.content,
1444
+ // Not their URLs: a link Discord signs works for anyone holding it
1445
+ // until it expires, and an agent could repeat it where others read.
1446
+ ...(m.attachments?.length
1447
+ ? { attachments: m.attachments.map(({ filename, contentType, size }) => ({ filename, contentType, size })) }
1448
+ : {}),
1216
1449
  timestamp: formatZonedDateTime(m.timestamp, this.timeZone),
1217
1450
  replyTo: m.replyTo,
1218
1451
  })),