@animalabs/agent-framework 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/README.md +204 -14
  2. package/dist/src/admission/admit.d.ts +18 -0
  3. package/dist/src/admission/admit.d.ts.map +1 -1
  4. package/dist/src/admission/admit.js +16 -3
  5. package/dist/src/admission/admit.js.map +1 -1
  6. package/dist/src/agent.d.ts +185 -78
  7. package/dist/src/agent.d.ts.map +1 -1
  8. package/dist/src/agent.js +279 -102
  9. package/dist/src/agent.js.map +1 -1
  10. package/dist/src/api/mcp-server-core.d.ts.map +1 -1
  11. package/dist/src/api/mcp-server-core.js +50 -12
  12. package/dist/src/api/mcp-server-core.js.map +1 -1
  13. package/dist/src/api/server.d.ts.map +1 -1
  14. package/dist/src/api/server.js +4 -20
  15. package/dist/src/api/server.js.map +1 -1
  16. package/dist/src/code-execution/isolate/scripts.d.ts +12 -8
  17. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
  18. package/dist/src/code-execution/isolate/scripts.js +24 -0
  19. package/dist/src/code-execution/isolate/scripts.js.map +1 -1
  20. package/dist/src/config-checks.d.ts +7 -0
  21. package/dist/src/config-checks.d.ts.map +1 -1
  22. package/dist/src/config-checks.js +14 -0
  23. package/dist/src/config-checks.js.map +1 -1
  24. package/dist/src/context-manager-errors.d.ts +25 -0
  25. package/dist/src/context-manager-errors.d.ts.map +1 -0
  26. package/dist/src/context-manager-errors.js +31 -0
  27. package/dist/src/context-manager-errors.js.map +1 -0
  28. package/dist/src/context-options.d.ts +67 -0
  29. package/dist/src/context-options.d.ts.map +1 -0
  30. package/dist/src/context-options.js +85 -0
  31. package/dist/src/context-options.js.map +1 -0
  32. package/dist/src/deferred-import.d.ts +93 -0
  33. package/dist/src/deferred-import.d.ts.map +1 -0
  34. package/dist/src/deferred-import.js +177 -0
  35. package/dist/src/deferred-import.js.map +1 -0
  36. package/dist/src/dendrite/audience.d.ts +223 -0
  37. package/dist/src/dendrite/audience.d.ts.map +1 -0
  38. package/dist/src/dendrite/audience.js +202 -0
  39. package/dist/src/dendrite/audience.js.map +1 -0
  40. package/dist/src/dendrite/index.d.ts +5 -3
  41. package/dist/src/dendrite/index.d.ts.map +1 -1
  42. package/dist/src/dendrite/index.js +2 -1
  43. package/dist/src/dendrite/index.js.map +1 -1
  44. package/dist/src/dendrite/presets.d.ts +10 -5
  45. package/dist/src/dendrite/presets.d.ts.map +1 -1
  46. package/dist/src/dendrite/presets.js +17 -5
  47. package/dist/src/dendrite/presets.js.map +1 -1
  48. package/dist/src/dendrite/registry.d.ts +62 -7
  49. package/dist/src/dendrite/registry.d.ts.map +1 -1
  50. package/dist/src/dendrite/registry.js +179 -10
  51. package/dist/src/dendrite/registry.js.map +1 -1
  52. package/dist/src/dendrite/types.d.ts +91 -8
  53. package/dist/src/dendrite/types.d.ts.map +1 -1
  54. package/dist/src/foreign-rounds.d.ts +69 -0
  55. package/dist/src/foreign-rounds.d.ts.map +1 -0
  56. package/dist/src/foreign-rounds.js +152 -0
  57. package/dist/src/foreign-rounds.js.map +1 -0
  58. package/dist/src/framework.d.ts +1977 -820
  59. package/dist/src/framework.d.ts.map +1 -1
  60. package/dist/src/framework.js +7571 -3457
  61. package/dist/src/framework.js.map +1 -1
  62. package/dist/src/gate/event-gate.d.ts +85 -15
  63. package/dist/src/gate/event-gate.d.ts.map +1 -1
  64. package/dist/src/gate/event-gate.js +421 -47
  65. package/dist/src/gate/event-gate.js.map +1 -1
  66. package/dist/src/gate/index.d.ts +1 -1
  67. package/dist/src/gate/index.d.ts.map +1 -1
  68. package/dist/src/gate/index.js.map +1 -1
  69. package/dist/src/gate/rule-scope.d.ts +30 -0
  70. package/dist/src/gate/rule-scope.d.ts.map +1 -0
  71. package/dist/src/gate/rule-scope.js +41 -0
  72. package/dist/src/gate/rule-scope.js.map +1 -0
  73. package/dist/src/gate/suppress-script-worker.d.ts +2 -0
  74. package/dist/src/gate/suppress-script-worker.d.ts.map +1 -0
  75. package/dist/src/gate/suppress-script-worker.js +103 -0
  76. package/dist/src/gate/suppress-script-worker.js.map +1 -0
  77. package/dist/src/gate/suppress-scripts.d.ts +105 -0
  78. package/dist/src/gate/suppress-scripts.d.ts.map +1 -0
  79. package/dist/src/gate/suppress-scripts.js +403 -0
  80. package/dist/src/gate/suppress-scripts.js.map +1 -0
  81. package/dist/src/gate/suppression-review.d.ts +143 -0
  82. package/dist/src/gate/suppression-review.d.ts.map +1 -0
  83. package/dist/src/gate/suppression-review.js +463 -0
  84. package/dist/src/gate/suppression-review.js.map +1 -0
  85. package/dist/src/gate/suppression-stats.d.ts +125 -0
  86. package/dist/src/gate/suppression-stats.d.ts.map +1 -0
  87. package/dist/src/gate/suppression-stats.js +214 -0
  88. package/dist/src/gate/suppression-stats.js.map +1 -0
  89. package/dist/src/gate/types.d.ts +135 -7
  90. package/dist/src/gate/types.d.ts.map +1 -1
  91. package/dist/src/gate/wake-onboarding.d.ts +119 -0
  92. package/dist/src/gate/wake-onboarding.d.ts.map +1 -0
  93. package/dist/src/gate/wake-onboarding.js +277 -0
  94. package/dist/src/gate/wake-onboarding.js.map +1 -0
  95. package/dist/src/held-writes.d.ts +31 -23
  96. package/dist/src/held-writes.d.ts.map +1 -1
  97. package/dist/src/held-writes.js +44 -59
  98. package/dist/src/held-writes.js.map +1 -1
  99. package/dist/src/index.d.ts +5 -2
  100. package/dist/src/index.d.ts.map +1 -1
  101. package/dist/src/index.js +3 -0
  102. package/dist/src/index.js.map +1 -1
  103. package/dist/src/jsonrpc-envelope.d.ts +69 -0
  104. package/dist/src/jsonrpc-envelope.d.ts.map +1 -0
  105. package/dist/src/jsonrpc-envelope.js +66 -0
  106. package/dist/src/jsonrpc-envelope.js.map +1 -0
  107. package/dist/src/mcpl/channel-registry.d.ts +131 -15
  108. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  109. package/dist/src/mcpl/channel-registry.js +290 -46
  110. package/dist/src/mcpl/channel-registry.js.map +1 -1
  111. package/dist/src/mcpl/checkpoint-manager.d.ts +2 -4
  112. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  113. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  114. package/dist/src/mcpl/feature-set-manager.d.ts +2 -4
  115. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  116. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  117. package/dist/src/mcpl/inbound-source.d.ts +2 -1
  118. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  119. package/dist/src/mcpl/inbound-source.js +2 -1
  120. package/dist/src/mcpl/inbound-source.js.map +1 -1
  121. package/dist/src/mcpl/inference-router.d.ts +6 -6
  122. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  123. package/dist/src/mcpl/inference-router.js.map +1 -1
  124. package/dist/src/mcpl/push-coalescer.d.ts +132 -22
  125. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  126. package/dist/src/mcpl/push-coalescer.js +105 -15
  127. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  128. package/dist/src/mcpl/push-handler.d.ts +9 -7
  129. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  130. package/dist/src/mcpl/push-handler.js.map +1 -1
  131. package/dist/src/mcpl/server-connection.d.ts +13 -10
  132. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  133. package/dist/src/mcpl/server-connection.js +134 -56
  134. package/dist/src/mcpl/server-connection.js.map +1 -1
  135. package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
  136. package/dist/src/mcpl/tool-classes.js +3 -0
  137. package/dist/src/mcpl/tool-classes.js.map +1 -1
  138. package/dist/src/mcpl/types.d.ts +8 -2
  139. package/dist/src/mcpl/types.d.ts.map +1 -1
  140. package/dist/src/mcpl/types.js.map +1 -1
  141. package/dist/src/module-registry.d.ts +24 -1
  142. package/dist/src/module-registry.d.ts.map +1 -1
  143. package/dist/src/module-registry.js +68 -18
  144. package/dist/src/module-registry.js.map +1 -1
  145. package/dist/src/modules/discord/index.d.ts +45 -8
  146. package/dist/src/modules/discord/index.d.ts.map +1 -1
  147. package/dist/src/modules/discord/index.js +237 -86
  148. package/dist/src/modules/discord/index.js.map +1 -1
  149. package/dist/src/modules/history/index.d.ts +59 -0
  150. package/dist/src/modules/history/index.d.ts.map +1 -1
  151. package/dist/src/modules/history/index.js +432 -67
  152. package/dist/src/modules/history/index.js.map +1 -1
  153. package/dist/src/modules/history/semantic.d.ts +6 -5
  154. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  155. package/dist/src/modules/history/semantic.js +15 -22
  156. package/dist/src/modules/history/semantic.js.map +1 -1
  157. package/dist/src/modules/workspace/disk-agreement.d.ts +1 -1
  158. package/dist/src/modules/workspace/disk-agreement.js +1 -1
  159. package/dist/src/modules/workspace/index.d.ts +28 -7
  160. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  161. package/dist/src/modules/workspace/index.js +76 -22
  162. package/dist/src/modules/workspace/index.js.map +1 -1
  163. package/dist/src/notice-tags.d.ts +10 -1
  164. package/dist/src/notice-tags.d.ts.map +1 -1
  165. package/dist/src/notice-tags.js +10 -1
  166. package/dist/src/notice-tags.js.map +1 -1
  167. package/dist/src/operator-log.d.ts +36 -3
  168. package/dist/src/operator-log.d.ts.map +1 -1
  169. package/dist/src/operator-log.js +2 -2
  170. package/dist/src/operator-log.js.map +1 -1
  171. package/dist/src/presentation.d.ts +746 -0
  172. package/dist/src/presentation.d.ts.map +1 -0
  173. package/dist/src/presentation.js +1435 -0
  174. package/dist/src/presentation.js.map +1 -0
  175. package/dist/src/prose-drafts.d.ts +15 -11
  176. package/dist/src/prose-drafts.d.ts.map +1 -1
  177. package/dist/src/prose-drafts.js +16 -12
  178. package/dist/src/prose-drafts.js.map +1 -1
  179. package/dist/src/read-marks.d.ts +192 -0
  180. package/dist/src/read-marks.d.ts.map +1 -0
  181. package/dist/src/read-marks.js +242 -0
  182. package/dist/src/read-marks.js.map +1 -0
  183. package/dist/src/recovery/offline-branch.d.ts +91 -6
  184. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  185. package/dist/src/recovery/offline-branch.js +273 -29
  186. package/dist/src/recovery/offline-branch.js.map +1 -1
  187. package/dist/src/recovery/recover-cli.js +22 -3
  188. package/dist/src/recovery/recover-cli.js.map +1 -1
  189. package/dist/src/send-tools.d.ts +5 -9
  190. package/dist/src/send-tools.d.ts.map +1 -1
  191. package/dist/src/send-tools.js +40 -7
  192. package/dist/src/send-tools.js.map +1 -1
  193. package/dist/src/stored-injections.d.ts +2 -2
  194. package/dist/src/stored-injections.js +2 -2
  195. package/dist/src/stored-removal.d.ts +17 -4
  196. package/dist/src/stored-removal.d.ts.map +1 -1
  197. package/dist/src/stored-removal.js +29 -5
  198. package/dist/src/stored-removal.js.map +1 -1
  199. package/dist/src/tool-result-guard.d.ts +12 -1
  200. package/dist/src/tool-result-guard.d.ts.map +1 -1
  201. package/dist/src/tool-result-guard.js +42 -8
  202. package/dist/src/tool-result-guard.js.map +1 -1
  203. package/dist/src/tune-out/coordinator.d.ts +1159 -79
  204. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  205. package/dist/src/tune-out/coordinator.js +3709 -363
  206. package/dist/src/tune-out/coordinator.js.map +1 -1
  207. package/dist/src/tune-out/tools.d.ts +114 -17
  208. package/dist/src/tune-out/tools.d.ts.map +1 -1
  209. package/dist/src/tune-out/tools.js +87 -27
  210. package/dist/src/tune-out/tools.js.map +1 -1
  211. package/dist/src/tune-out/window-anchor.d.ts +143 -0
  212. package/dist/src/tune-out/window-anchor.d.ts.map +1 -0
  213. package/dist/src/tune-out/window-anchor.js +202 -0
  214. package/dist/src/tune-out/window-anchor.js.map +1 -0
  215. package/dist/src/types/agent.d.ts +86 -31
  216. package/dist/src/types/agent.d.ts.map +1 -1
  217. package/dist/src/types/events.d.ts +2 -0
  218. package/dist/src/types/events.d.ts.map +1 -1
  219. package/dist/src/types/framework.d.ts +43 -21
  220. package/dist/src/types/framework.d.ts.map +1 -1
  221. package/dist/src/types/module.d.ts +180 -69
  222. package/dist/src/types/module.d.ts.map +1 -1
  223. package/dist/src/types/trace.d.ts +510 -36
  224. package/dist/src/types/trace.d.ts.map +1 -1
  225. package/package.json +3 -3
  226. package/src/admission/admit.ts +32 -3
  227. package/src/agent.ts +323 -120
  228. package/src/api/mcp-server-core.ts +54 -17
  229. package/src/api/server.ts +4 -23
  230. package/src/code-execution/isolate/scripts.ts +28 -3
  231. package/src/config-checks.ts +14 -0
  232. package/src/context-manager-errors.ts +37 -0
  233. package/src/context-options.ts +96 -0
  234. package/src/deferred-import.ts +239 -0
  235. package/src/dendrite/audience.ts +315 -0
  236. package/src/dendrite/index.ts +14 -2
  237. package/src/dendrite/presets.ts +18 -6
  238. package/src/dendrite/registry.ts +209 -12
  239. package/src/dendrite/types.ts +92 -8
  240. package/src/foreign-rounds.ts +199 -0
  241. package/src/framework.ts +7814 -3585
  242. package/src/gate/event-gate.ts +428 -65
  243. package/src/gate/index.ts +3 -0
  244. package/src/gate/rule-scope.ts +45 -0
  245. package/src/gate/suppress-script-worker.ts +89 -0
  246. package/src/gate/suppress-scripts.ts +414 -0
  247. package/src/gate/suppression-review.ts +517 -0
  248. package/src/gate/suppression-stats.ts +314 -0
  249. package/src/gate/types.ts +141 -7
  250. package/src/gate/wake-onboarding.ts +309 -0
  251. package/src/held-writes.ts +49 -60
  252. package/src/index.ts +9 -2
  253. package/src/jsonrpc-envelope.ts +81 -0
  254. package/src/mcpl/channel-registry.ts +353 -85
  255. package/src/mcpl/checkpoint-manager.ts +3 -2
  256. package/src/mcpl/feature-set-manager.ts +2 -1
  257. package/src/mcpl/inbound-source.ts +2 -1
  258. package/src/mcpl/inference-router.ts +7 -4
  259. package/src/mcpl/push-coalescer.ts +193 -34
  260. package/src/mcpl/push-handler.ts +10 -5
  261. package/src/mcpl/server-connection.ts +141 -60
  262. package/src/mcpl/tool-classes.ts +3 -0
  263. package/src/mcpl/types.ts +8 -2
  264. package/src/module-registry.ts +73 -17
  265. package/src/modules/discord/index.ts +229 -81
  266. package/src/modules/history/index.ts +439 -70
  267. package/src/modules/history/semantic.ts +15 -21
  268. package/src/modules/workspace/disk-agreement.ts +1 -1
  269. package/src/modules/workspace/index.ts +85 -23
  270. package/src/notice-tags.ts +10 -1
  271. package/src/operator-log.ts +36 -3
  272. package/src/presentation.ts +1676 -0
  273. package/src/prose-drafts.ts +16 -12
  274. package/src/read-marks.ts +328 -0
  275. package/src/recovery/offline-branch.ts +346 -32
  276. package/src/recovery/recover-cli.ts +21 -3
  277. package/src/send-tools.ts +40 -7
  278. package/src/stored-injections.ts +2 -2
  279. package/src/stored-removal.ts +31 -7
  280. package/src/tool-result-guard.ts +41 -7
  281. package/src/tune-out/coordinator.ts +4089 -457
  282. package/src/tune-out/tools.ts +160 -43
  283. package/src/tune-out/window-anchor.ts +277 -0
  284. package/src/types/agent.ts +90 -31
  285. package/src/types/events.ts +2 -0
  286. package/src/types/framework.ts +43 -21
  287. package/src/types/module.ts +181 -68
  288. package/src/types/trace.ts +542 -40
  289. package/dist/src/reasoning-loss-notice.d.ts +0 -23
  290. package/dist/src/reasoning-loss-notice.d.ts.map +0 -1
  291. package/dist/src/reasoning-loss-notice.js +0 -52
  292. package/dist/src/reasoning-loss-notice.js.map +0 -1
  293. package/dist/src/reasoning-loss.d.ts +0 -24
  294. package/dist/src/reasoning-loss.d.ts.map +0 -1
  295. package/dist/src/reasoning-loss.js +0 -102
  296. package/dist/src/reasoning-loss.js.map +0 -1
  297. package/src/reasoning-loss-notice.ts +0 -64
  298. package/src/reasoning-loss.ts +0 -120
@@ -0,0 +1,93 @@
1
+ import type { ContentBlock } from '@animalabs/membrane';
2
+ import type { MessageMetadata } from '@animalabs/context-manager';
3
+ /** One write an earlier release queued, as its record held it. */
4
+ export interface PersistedDeferredWrite {
5
+ /** Its durable identity: a copy of it that landed carries it as `metadata.deferredWriteId`. */
6
+ id: string;
7
+ /** Where it came in arrival order, 1..N over the entries kept. */
8
+ seq: number;
9
+ participant: string;
10
+ content: ContentBlock[];
11
+ metadata?: MessageMetadata;
12
+ /** The agent it was for. Absent means the primary. */
13
+ forAgent?: string;
14
+ /** When the earlier release first held it, in ms since the epoch, where the record says. */
15
+ heldAt?: number;
16
+ /**
17
+ * Set where a write of it threw and its store couldn't be read to tell
18
+ * whether it landed: before it is stored, its target's whole branch is
19
+ * searched for its id.
20
+ */
21
+ landing?: 'unknown';
22
+ }
23
+ /** What a queue's record held, as the importer takes it. */
24
+ export interface PersistedQueue {
25
+ /** Its writes, in arrival order. */
26
+ entries: PersistedDeferredWrite[];
27
+ /**
28
+ * Per target agent, where its store stood when the oldest write handed to
29
+ * it and not yet acknowledged was handed over: the boot dedup scans from
30
+ * there (0 for an agent not named, the whole store).
31
+ */
32
+ scanFrom: Map<string, number>;
33
+ /**
34
+ * Whether reading it dropped, renumbered or named anything (a malformed
35
+ * entry, a repeated id, a missing or invalid seq, an entry given an id),
36
+ * so a record cleared or written again doesn't name those again.
37
+ */
38
+ changed: boolean;
39
+ /**
40
+ * The ids this read gave entries that had none. A read gives each a new
41
+ * one, so until the record holds it, a copy stored under it is one no
42
+ * later read finds by its id.
43
+ */
44
+ given: ReadonlySet<string>;
45
+ }
46
+ /** Where a queue's record is: the recovery file, or the store's slot. */
47
+ export interface DeferredWritesRecord {
48
+ /** The recovery file the value was read from; absent where it was the slot's. */
49
+ file?: string;
50
+ /** The store's slot for it (framework/deferred-writes). */
51
+ slotId: string;
52
+ }
53
+ /**
54
+ * The refusal of a boot whose queue record can't be taken: it could not be
55
+ * read (`cause`), or it holds something other than a queue (`problem`
56
+ * alone). Either way the record is left as it is, and the error says what
57
+ * lets the framework start.
58
+ */
59
+ export declare function deferredWritesRefusal(record: DeferredWritesRecord, problem: string, cause?: unknown): Error;
60
+ /**
61
+ * Read a queue record's value: the recovery file's document, or the slot's
62
+ * value where there is no file (`record.file` absent).
63
+ *
64
+ * - Nothing stored is an empty queue: no file and nothing in the slot. A file
65
+ * that holds null isn't a queue, since no release writes one.
66
+ * - The forms releases wrote are read: a bare array (the slot's first form),
67
+ * and `{ pending, scanFrom? }` (version 1 and 2 files, version 2 slots).
68
+ * Anything else is refused (deferredWritesRefusal).
69
+ * - An entry the importer can't store is dropped with a line naming it: one
70
+ * whose participant isn't text, whose content isn't an array, that holds a
71
+ * block that isn't an object, or whose `forAgent` is present but not a
72
+ * name. A release wrote `forAgent` only as a non-empty name, so another
73
+ * value is damage or a hand edit, and the agent it meant can't be known.
74
+ * - One entry per id: an id that comes again is dropped with a line, the
75
+ * first entry with it kept. An entry with no id is given one, with a line
76
+ * (`given`, and the queue reads as `changed`): a copy of it that landed
77
+ * carries the id it lost, so the boot dedup can't find it, and it may be
78
+ * stored again. Each read gives it a new id, so the importer writes the
79
+ * record with the ids given before it stores any of them.
80
+ * - `heldAt` is kept where it is a time a Date can hold.
81
+ * - Arrival order: entries whose seq is a positive whole number up to
82
+ * Number.MAX_SAFE_INTEGER by seq, then, in record order, those without one
83
+ * (a record from before seq, in write order already) or with another value,
84
+ * which is named. They are numbered 1..N in that order.
85
+ */
86
+ export declare function readPersistedDeferredWrites(raw: unknown, record: DeferredWritesRecord, log: (line: string) => void): PersistedQueue;
87
+ /**
88
+ * Whether an entry holds a tool block (tool_use or tool_result): of what a
89
+ * release queued, only the puppet's pair, which was the agent's own round,
90
+ * queued behind a turn that had replaced the puppet's reservation.
91
+ */
92
+ export declare function isToolBlockEntry(entry: Pick<PersistedDeferredWrite, 'content'>): boolean;
93
+ //# sourceMappingURL=deferred-import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred-import.d.ts","sourceRoot":"","sources":["../../src/deferred-import.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,+FAA+F;IAC/F,EAAE,EAAE,MAAM,CAAC;IACX,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC;;;;OAIG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;AAUD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAiB3G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC1B,cAAc,CAoFhB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAC,GAAG,OAAO,CAExF"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * The deferred-write queue an earlier release left on disk, read once at
3
+ * boot (#291, AF-6).
4
+ *
5
+ * Releases before #291's presentation index held a context write in a queue
6
+ * while its agent's turn was alive or the host was quiesced, and stored it
7
+ * at that agent's next boundary. While quiesced, and from a write that
8
+ * reached or may have reached its record until the queue drained, the queue
9
+ * was mirrored to `recovery/deferred-writes.json` beside the store, or, with
10
+ * no recovery path, to the store's `framework/deferred-writes` slot. This
11
+ * release stores every write at once and keeps no queue, so a record such a
12
+ * release left is read here, and the framework stores each of its writes
13
+ * once at boot (AgentFramework.importPersistedDeferredWrites), passes on or
14
+ * drops, logged, a write for an agent gone or one refused as malformed,
15
+ * keeps for the next boot one it can't store or check, with what follows it
16
+ * for that agent, and rewrites the record with only those. Like that
17
+ * importer, this module is for one release: the release
18
+ * after it deletes both. A host boots this release until its record is
19
+ * empty (the `deferred-import` alert says when writes stay queued), and
20
+ * doesn't upgrade past it from a release that kept a queue.
21
+ *
22
+ * Nothing here touches a store. It reads the record's value, refuses one
23
+ * that isn't a queue, drops entries its readers can't handle, keeps one entry
24
+ * per id, and orders them as they arrived.
25
+ */
26
+ import { randomUUID } from 'node:crypto';
27
+ /** A stored JSON value's kind, for a refusal that names what it found without its content. */
28
+ function jsonKind(value) {
29
+ return value === null ? 'null'
30
+ : Array.isArray(value) ? 'an array'
31
+ : typeof value === 'object' ? 'an object'
32
+ : `a ${typeof value}`;
33
+ }
34
+ /**
35
+ * The refusal of a boot whose queue record can't be taken: it could not be
36
+ * read (`cause`), or it holds something other than a queue (`problem`
37
+ * alone). Either way the record is left as it is, and the error says what
38
+ * lets the framework start.
39
+ */
40
+ export function deferredWritesRefusal(record, problem, cause) {
41
+ const { file, slotId } = record;
42
+ return new Error(`the deferred context writes (${file ?? slotId}) ${problem}. The framework doesn't start without them: an earlier ` +
43
+ `version left them queued, and they are stored at boot, ahead of anything written once the modules have ` +
44
+ `started. ` +
45
+ (file
46
+ ? `The file is unchanged, and the framework starts once ${cause === undefined
47
+ ? 'it holds a queue of writes, such as {"version":1,"pending":[]} for none. Removing it reads the queue ' +
48
+ `from ${slotId} instead, which the file's writes don't keep, so it imports whatever older ` +
49
+ `queue is there, or none`
50
+ : 'it can be read'}.`
51
+ : cause === undefined
52
+ ? `They're unchanged, and starting again won't help until they're repaired.`
53
+ : `They're unchanged, and the framework starts once they can be read.`), cause === undefined ? undefined : { cause });
54
+ }
55
+ /**
56
+ * Read a queue record's value: the recovery file's document, or the slot's
57
+ * value where there is no file (`record.file` absent).
58
+ *
59
+ * - Nothing stored is an empty queue: no file and nothing in the slot. A file
60
+ * that holds null isn't a queue, since no release writes one.
61
+ * - The forms releases wrote are read: a bare array (the slot's first form),
62
+ * and `{ pending, scanFrom? }` (version 1 and 2 files, version 2 slots).
63
+ * Anything else is refused (deferredWritesRefusal).
64
+ * - An entry the importer can't store is dropped with a line naming it: one
65
+ * whose participant isn't text, whose content isn't an array, that holds a
66
+ * block that isn't an object, or whose `forAgent` is present but not a
67
+ * name. A release wrote `forAgent` only as a non-empty name, so another
68
+ * value is damage or a hand edit, and the agent it meant can't be known.
69
+ * - One entry per id: an id that comes again is dropped with a line, the
70
+ * first entry with it kept. An entry with no id is given one, with a line
71
+ * (`given`, and the queue reads as `changed`): a copy of it that landed
72
+ * carries the id it lost, so the boot dedup can't find it, and it may be
73
+ * stored again. Each read gives it a new id, so the importer writes the
74
+ * record with the ids given before it stores any of them.
75
+ * - `heldAt` is kept where it is a time a Date can hold.
76
+ * - Arrival order: entries whose seq is a positive whole number up to
77
+ * Number.MAX_SAFE_INTEGER by seq, then, in record order, those without one
78
+ * (a record from before seq, in write order already) or with another value,
79
+ * which is named. They are numbered 1..N in that order.
80
+ */
81
+ export function readPersistedDeferredWrites(raw, record, log) {
82
+ const empty = { entries: [], scanFrom: new Map(), changed: false, given: new Set() };
83
+ if (!record.file && (raw === null || raw === undefined))
84
+ return empty;
85
+ const doc = (Array.isArray(raw) ? { pending: raw } : raw !== null && typeof raw === 'object' ? raw : undefined);
86
+ if (!doc || !Array.isArray(doc.pending)) {
87
+ throw deferredWritesRefusal(record, doc
88
+ ? `hold an object whose pending is ${doc.pending === undefined ? 'missing' : jsonKind(doc.pending)}, not a list of writes`
89
+ : `hold ${jsonKind(raw)}, not a queue of writes`);
90
+ }
91
+ const data = doc.pending;
92
+ if (data.length === 0)
93
+ return empty;
94
+ const scanFrom = new Map();
95
+ if (doc.scanFrom && typeof doc.scanFrom === 'object') {
96
+ for (const [k, v] of Object.entries(doc.scanFrom)) {
97
+ if (typeof v === 'number' && Number.isFinite(v))
98
+ scanFrom.set(k, Math.max(0, Math.floor(v)));
99
+ }
100
+ }
101
+ const wellFormed = (m) => {
102
+ if (!m || typeof m !== 'object')
103
+ return false;
104
+ const { participant, content, forAgent } = m;
105
+ return typeof participant === 'string'
106
+ && Array.isArray(content) && content.every((b) => !!b && typeof b === 'object')
107
+ && (forAgent === undefined || (typeof forAgent === 'string' && forAgent !== ''));
108
+ };
109
+ const malformed = data.filter((m) => !wellFormed(m));
110
+ for (const m of malformed) {
111
+ // What the entry holds there: a value that isn't text by its type.
112
+ const field = (key) => {
113
+ const value = m && typeof m === 'object' ? m[key] : undefined;
114
+ if (typeof value === 'string')
115
+ return value;
116
+ if (value === undefined)
117
+ return `no ${key}`;
118
+ return `${key} ${value === null ? 'null' : `of type ${typeof value}`}`;
119
+ };
120
+ log(`[host-mode] a recovered deferred context write is malformed and was dropped: ${field('id')} (${field('participant')})`);
121
+ }
122
+ const seen = new Set();
123
+ const given = new Set();
124
+ const kept = [];
125
+ let duplicates = 0;
126
+ for (const m of data.filter(wellFormed)) {
127
+ const hasId = typeof m.id === 'string' && m.id !== '';
128
+ const id = hasId ? m.id : randomUUID();
129
+ if (!hasId) {
130
+ given.add(id);
131
+ log(`[host-mode] a recovered deferred context write (${m.participant}) has no id; it is given ${id}`);
132
+ }
133
+ if (seen.has(id)) {
134
+ duplicates++;
135
+ log(`[host-mode] a recovered deferred context write repeats id ${id} (${m.participant}) and was dropped; the first entry with that id is kept`);
136
+ continue;
137
+ }
138
+ seen.add(id);
139
+ kept.push({
140
+ id,
141
+ seq: m.seq,
142
+ participant: m.participant,
143
+ content: m.content,
144
+ ...(m.metadata !== undefined ? { metadata: m.metadata } : {}),
145
+ ...(m.forAgent !== undefined ? { forAgent: m.forAgent } : {}),
146
+ // A Date holds times within 8.64e15 ms of the epoch.
147
+ ...(typeof m.heldAt === 'number' && Math.abs(m.heldAt) <= 8.64e15 ? { heldAt: m.heldAt } : {}),
148
+ ...(m.landing === 'unknown' ? { landing: 'unknown' } : {}),
149
+ });
150
+ }
151
+ const validSeq = (seq) => Number.isSafeInteger(seq) && seq > 0;
152
+ const unnumbered = kept.filter((m) => !validSeq(m.seq));
153
+ for (const m of unnumbered) {
154
+ if (m.seq === undefined)
155
+ continue;
156
+ // A value that isn't a number is named by its type: it could be any size.
157
+ const seq = typeof m.seq === 'number' ? String(m.seq) : m.seq === null ? 'null' : `of type ${typeof m.seq}`;
158
+ log(`[host-mode] a recovered deferred context write (${m.id}) has seq ${seq}, not a positive ` +
159
+ `whole number up to Number.MAX_SAFE_INTEGER; it is queued after the others`);
160
+ }
161
+ const ordered = [...kept.filter((m) => validSeq(m.seq)).sort((a, b) => a.seq - b.seq), ...unnumbered];
162
+ return {
163
+ entries: ordered.map((m, i) => ({ ...m, seq: i + 1 })),
164
+ scanFrom,
165
+ changed: malformed.length > 0 || duplicates > 0 || unnumbered.length > 0 || given.size > 0,
166
+ given,
167
+ };
168
+ }
169
+ /**
170
+ * Whether an entry holds a tool block (tool_use or tool_result): of what a
171
+ * release queued, only the puppet's pair, which was the agent's own round,
172
+ * queued behind a turn that had replaced the puppet's reservation.
173
+ */
174
+ export function isToolBlockEntry(entry) {
175
+ return entry.content.some((block) => block.type === 'tool_use' || block.type === 'tool_result');
176
+ }
177
+ //# sourceMappingURL=deferred-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred-import.js","sourceRoot":"","sources":["../../src/deferred-import.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * The audience stamp (#291): who a stored row is for, written on the row
3
+ * when it is stored, in its metadata.
4
+ *
5
+ * A row's target used to live only in the write that stored it: the
6
+ * `forAgent` option, or which agent's context manager a writer called. In
7
+ * the residents' shared slot, rows meant for different agents then look
8
+ * alike in the store, and nothing read later can tell whose a row is. #291's
9
+ * presentation index decides from the row which agents it is presented to,
10
+ * and at boot which rows an agent has to be presented that it wasn't, so the
11
+ * framework now writes that on every row it stores:
12
+ *
13
+ * - `metadata.audience` lists the agents the row is meant for, computed when
14
+ * it is written: the agent a write names (`forAgent`); for an admitted
15
+ * inbound message, the recipients admission delivered it to; for a
16
+ * module's process response whose inference request names agents, those
17
+ * of them registered that read the slot it lands in. A write that names
18
+ * no agent (a module's write, a process response that asks every agent
19
+ * or none to read, or only agents that don't read that slot) is for the
20
+ * agents that take untargeted inbound and own the slot it lands in: on a
21
+ * residents' host every resident, as each reads the shared slot; with one
22
+ * resident that resident alone, as before. It falls back to the agent the
23
+ * write is delivered to when there are none.
24
+ * This is the rule #291's presentation index presents an untargeted row
25
+ * in the shared slot by, applied when the row is written, so the record
26
+ * tells an untargeted row from one written for the primary. A message a
27
+ * tune-out holds is meant for none of them, so its list is empty, unless
28
+ * the write names an agent whose own view keeps held traffic (the
29
+ * persistent subconscious), which it is for.
30
+ * Observers of a slot (the subconscious watching the residents' slot) are
31
+ * a relationship in the registry, not part of the list. An inbound
32
+ * message's target is stamped as named even where it doesn't read the
33
+ * slot the row lands in (a worker or a conversation fork, stored in the
34
+ * residents' slot): how such a row is presented is left to the
35
+ * presentation index. A process response's messages and the gate's
36
+ * batched line are stamped for the agents they name that read that slot,
37
+ * and as a write that names no agent when none of them does, so they
38
+ * reach the windows that read the slot, as on main. The wake-onboarding
39
+ * notice is stamped for its recipients that read that slot; one that
40
+ * doesn't (a conversation fork) gets its own copy where it reads, stamped
41
+ * for it, and the notice for an event with no recipients is for the
42
+ * agents that take untargeted inbound.
43
+ * - `metadata.ownRowOf` names the agent whose own row it is: one stored by
44
+ * that agent's turn or act (its rounds, its tool results, a puppeted
45
+ * call), or by the framework for that agent's own turn (a clock row, a
46
+ * `[continue]` row, a batched wake's line, a notice about its own speech
47
+ * or failure, a derived agent's inheritance and framing). Its audience is
48
+ * that agent alone. "Own" goes by who stored the row, never by its
49
+ * participant: a shared fork presents its parent's name as its own voice,
50
+ * but mail its parent sends it is the parent's, meant for the fork, and
51
+ * isn't the fork's own row.
52
+ *
53
+ * Both keys are the framework's. A write through the framework's
54
+ * `addMessage` is stamped there and a stamp its metadata carried (a copy of
55
+ * a stored row's, say) is replaced, as `deferredWriteId` is, but on an
56
+ * imported write, which keeps the stamp it was queued with. The compile
57
+ * (context-manager's) doesn't read the stamp, so a window compiles as the
58
+ * same rows unstamped do; the presentation index does, so another
59
+ * resident's own rows no longer enter a resident's window unless it
60
+ * observes that resident (AgentConfig.observes). Rows stored before the
61
+ * stamp existed carry none; `audienceOf` says so by returning undefined. A
62
+ * write an earlier version left in its deferred queue is stamped when the
63
+ * importer stores it at boot, as any write through `addMessage` is, unless
64
+ * it was queued stamped, so it isn't stored unstamped after the upgrade.
65
+ */
66
+ import type { ContentBlock } from '@animalabs/membrane';
67
+ import type { AddMessageOptions, ContextManager, MessageId, MessageMetadata } from '@animalabs/context-manager';
68
+ import type { AgentName, ObserveEdge } from './types.js';
69
+ /** The metadata key listing who a row is for. */
70
+ export declare const AUDIENCE_KEY = "audience";
71
+ /** The metadata key naming whose own row a row is. */
72
+ export declare const OWN_ROW_KEY = "ownRowOf";
73
+ /** A row's audience stamp, as `audienceOf` reads it. */
74
+ export interface AudienceStamp {
75
+ /** The agents the row is meant for, as computed when it was written. */
76
+ audience: AgentName[];
77
+ /** Set when the row is that agent's own (see the module comment). */
78
+ ownRowOf?: AgentName;
79
+ }
80
+ /**
81
+ * `metadata` stamped as a row meant for `audience`, and as nobody's own
82
+ * row: a stamp it carried is replaced. A new object; `metadata` is unchanged.
83
+ */
84
+ export declare function withAudience(metadata: MessageMetadata | undefined, audience: readonly AgentName[]): MessageMetadata;
85
+ /**
86
+ * `metadata` stamped as `owner`'s own row, meant for `owner` alone: a stamp
87
+ * it carried is replaced. A new object; `metadata` is unchanged.
88
+ */
89
+ export declare function asOwnRow(metadata: MessageMetadata | undefined, owner: AgentName): MessageMetadata;
90
+ /**
91
+ * The audience stamp a row's metadata carries, or undefined when it carries
92
+ * none (a row stored before the stamp existed) or carries one that isn't a
93
+ * list of names.
94
+ */
95
+ export declare function audienceOf(metadata: unknown): AudienceStamp | undefined;
96
+ /** Whether a row's metadata stamps it as `agent`'s own row. */
97
+ export declare function isOwnRowOf(metadata: unknown, agent: AgentName): boolean;
98
+ /**
99
+ * The admission record on a stored message: it was held from the residents
100
+ * by a policy epoch (`metadata.tuneOut = { epochId }`). ONE predicate for
101
+ * "held from the resident", read by the compiled-view filter, the mid-turn
102
+ * injection and the presentation index (#291) alike (#232 H1), so the window
103
+ * and the wire agree. Such a row is stamped for nobody (an empty audience),
104
+ * whatever store it lands in, unless its write names an agent whose own
105
+ * view keeps held traffic, such as the persistent subconscious, which it is
106
+ * for.
107
+ */
108
+ export declare const heldFromResidents: (metadata: Record<string, unknown> | undefined) => boolean;
109
+ /**
110
+ * The suppression record on a stored message: a suppress rule took it as it
111
+ * arrived (`metadata.suppressed = { rule, eventType }`, stamped by addMessage
112
+ * from the gate's suppressionFor). ONE predicate for "never rendered", read
113
+ * by every view filter the framework sets (the residents', the
114
+ * subconscious's, and through them every derived view's, context-options.ts)
115
+ * and so by agentSees too: the compile, a tool boundary's injection and the
116
+ * arrival and unread checks agree. The presentation index (#291) presents
117
+ * such a row to nobody (bearingOf, observedRowFor), the reader of held
118
+ * traffic included, and addMessage stamps it for nobody (an empty
119
+ * audience). The stamp never changes, so the view stays deterministic per
120
+ * row, as context-manager's viewFilter requires.
121
+ */
122
+ export declare const suppressedRow: (metadata: Record<string, unknown> | undefined) => boolean;
123
+ /**
124
+ * Whether a row of a slot an agent observes is for that agent (#291,
125
+ * decision 1): what an observe edge shows of the slot it reads. `observer`
126
+ * is the agent the edge is on, and `owners` are the agents whose own slot it
127
+ * reads (the registry's `slotOwners`).
128
+ *
129
+ * - Another agent's stored context injection: no. It is that agent's
130
+ * context, not conversation, as every view of the framework's leaves out.
131
+ * - A row stored under the observer's own name: no. It is the observer's
132
+ * delivery into the slot (the subconscious's summary or note into the
133
+ * residents' slot), which its own round already holds.
134
+ * - A row a suppress rule hid (suppressedRow): no. It renders for no
135
+ * reader, the reader of held traffic included.
136
+ * - A row a tune-out holds: only through an edge that shows held traffic
137
+ * (`includeHeld`, the subconscious's).
138
+ * - A row with no audience stamp (stored before the stamp, or by a host's
139
+ * writer that doesn't stamp): yes, as the merged view showed it.
140
+ * - An owner's own row (its rounds, results, clock rows, notices about its
141
+ * own turn), and a row whose audience names an owner (channel traffic,
142
+ * mail, module rows): yes.
143
+ * - A row whose audience names the observer itself, and that is nobody's
144
+ * own row (an operator's message or a module's write addressed to the
145
+ * subconscious alone, which lands in the residents' slot it watches):
146
+ * yes. The edge is how the observer reads that slot, and the merged view
147
+ * showed the row before the presentation index, so no window would hold
148
+ * it otherwise (#291).
149
+ * - Anything else, such as the own row of an agent that doesn't own the
150
+ * slot (the observer's own included), a row stamped only for an agent
151
+ * that neither owns nor observes the slot, or one for a derived agent on
152
+ * another branch: no.
153
+ */
154
+ export declare function observedRowFor(edge: Pick<ObserveEdge, 'includeHeld'>, row: {
155
+ participant: string;
156
+ metadata?: unknown;
157
+ }, context: {
158
+ observer: AgentName;
159
+ owners: readonly AgentName[];
160
+ }): boolean;
161
+ /** What `storeOwnRow` writes through: an agent, or anything that names one and holds its context. */
162
+ export interface OwnRowWriter {
163
+ readonly name: AgentName;
164
+ /** With `getMessage`, a write whose outcome the store can't tell presents
165
+ * the rows it may have stored that the store reads as held
166
+ * (presentLandedThenRethrow); without it, only those it knows landed. */
167
+ getContextManager(): Pick<ContextManager, 'addMessage'> & Partial<Pick<ContextManager, 'getMessage'>>;
168
+ /**
169
+ * Told the ids of the agent's own rows once they are stored (the
170
+ * presentation index's own-row sink, #291), each once its write has
171
+ * returned. A writer without it is told nothing.
172
+ */
173
+ ownRowsStored?(ids: readonly MessageId[]): void;
174
+ }
175
+ /**
176
+ * Store a row in `agent`'s own context, stamped as its own row (asOwnRow).
177
+ * Every writer that stores into an agent's context directly, past the
178
+ * framework's `addMessage`, stores the agent's own rows through this, but
179
+ * the tool-result guard, which stamps the results it writes itself
180
+ * (asOwnRow, ToolResultGuard.storeResults) and tells its own-row sink of
181
+ * them, so none of them goes unstamped.
182
+ *
183
+ * With `present` (the default), the writer is told of the row once the add
184
+ * has returned (`ownRowsStored`), never from inside it, where a sharded body
185
+ * may still be storing its shards: under the presentation index (#291) that
186
+ * presents the row in the agent's window at once. That is right for a row
187
+ * the agent's stream carries (its round, its results, a notice injected at
188
+ * its boundary), one written before its next compile or after its stream's
189
+ * last request, and one written while the agent has no turn alive. A row
190
+ * written at another moment, where a turn the row isn't part of may be
191
+ * alive, passes `present: false`: it stays stored and out of the window,
192
+ * and the index's own-row sweep at the agent's next presentation point
193
+ * presents it there.
194
+ */
195
+ export declare function storeOwnRow(agent: OwnRowWriter, participant: string, content: ContentBlock[], metadata?: MessageMetadata, options?: AddMessageOptions, present?: boolean): MessageId;
196
+ /**
197
+ * The catch of a write of an agent's own row whose add threw (storeOwnRow,
198
+ * and the tool-result guard's two writes of the results row): the rows of
199
+ * the write the store holds are told to `told`, the own-row sink, as the
200
+ * write's id would have been, then the add's error is thrown on. The write
201
+ * is answered by that error, as before the presentation index: what its
202
+ * caller does on it is the caller's. A row of it that is stored is out of
203
+ * the window until presented, like any stored row, and presented here so
204
+ * that an own row written after it can't enter the window ahead of it.
205
+ *
206
+ * - WriteLandedError: its `landed` rows, in store order.
207
+ * - WriteOutcomeUnknownError: its `landed` rows, then those its `unknown`
208
+ * names (the store holds all of these or none) that `holds` reads as
209
+ * stored, as addMessage presents such a write's rows (presentedThoughUnknown
210
+ * in framework.ts, whose afterStore reads the rows too). Where that read
211
+ * throws, every row `unknown` names, as presentedThoughUnknown gives them:
212
+ * the sink keeps a row it can't present and presents it ahead of the next
213
+ * own row, dropping one the store doesn't hold (presentOwn), so a landed
214
+ * row isn't put behind an own row written after it. Without `holds`, its
215
+ * `landed` rows only.
216
+ * - Any other error: none of the write is stored, so nothing is told.
217
+ *
218
+ * Without `told` (a writer that holds its row back, storeOwnRow's
219
+ * `present: false`, or one with no sink) nothing is told. A sink that
220
+ * throws is logged; the add's error is the one thrown.
221
+ */
222
+ export declare function presentLandedThenRethrow(error: unknown, agentName: string, told: ((ids: readonly MessageId[]) => void) | undefined, holds?: (id: MessageId) => boolean): never;
223
+ //# sourceMappingURL=audience.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../../../src/dendrite/audience.ts"],"names":[],"mappings":"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"}