@cello-protocol/daemon 0.0.196 → 0.0.198

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 (213) hide show
  1. package/dist/agent-admin-handlers.d.ts +56 -0
  2. package/dist/agent-admin-handlers.d.ts.map +1 -0
  3. package/dist/agent-admin-handlers.js +70 -0
  4. package/dist/agent-admin-handlers.js.map +1 -0
  5. package/dist/agent-handlers.d.ts +8 -7
  6. package/dist/agent-handlers.d.ts.map +1 -1
  7. package/dist/agent-handlers.js.map +1 -1
  8. package/dist/agent-selection-root.d.ts +29 -0
  9. package/dist/agent-selection-root.d.ts.map +1 -0
  10. package/dist/agent-selection-root.js +126 -0
  11. package/dist/agent-selection-root.js.map +1 -0
  12. package/dist/attendance-wiring.d.ts +44 -0
  13. package/dist/attendance-wiring.d.ts.map +1 -0
  14. package/dist/attendance-wiring.js +432 -0
  15. package/dist/attendance-wiring.js.map +1 -0
  16. package/dist/backup-restore-handlers.d.ts +10 -0
  17. package/dist/backup-restore-handlers.d.ts.map +1 -0
  18. package/dist/backup-restore-handlers.js +82 -0
  19. package/dist/backup-restore-handlers.js.map +1 -0
  20. package/dist/boot-agents.d.ts +64 -0
  21. package/dist/boot-agents.d.ts.map +1 -0
  22. package/dist/boot-agents.js +241 -0
  23. package/dist/boot-agents.js.map +1 -0
  24. package/dist/boot-connection-state.d.ts +40 -0
  25. package/dist/boot-connection-state.d.ts.map +1 -0
  26. package/dist/boot-connection-state.js +136 -0
  27. package/dist/boot-connection-state.js.map +1 -0
  28. package/dist/boot-core.d.ts +36 -0
  29. package/dist/boot-core.d.ts.map +1 -0
  30. package/dist/boot-core.js +292 -0
  31. package/dist/boot-core.js.map +1 -0
  32. package/dist/boot-parked-content.d.ts +34 -0
  33. package/dist/boot-parked-content.d.ts.map +1 -0
  34. package/dist/boot-parked-content.js +527 -0
  35. package/dist/boot-parked-content.js.map +1 -0
  36. package/dist/boot-sweeps.d.ts +22 -0
  37. package/dist/boot-sweeps.d.ts.map +1 -0
  38. package/dist/boot-sweeps.js +50 -0
  39. package/dist/boot-sweeps.js.map +1 -0
  40. package/dist/connection-agents.d.ts +16 -0
  41. package/dist/connection-agents.d.ts.map +1 -0
  42. package/dist/connection-agents.js +68 -0
  43. package/dist/connection-agents.js.map +1 -0
  44. package/dist/content-park.d.ts.map +1 -1
  45. package/dist/content-park.js +274 -25
  46. package/dist/content-park.js.map +1 -1
  47. package/dist/daemon-handle.d.ts +57 -0
  48. package/dist/daemon-handle.d.ts.map +1 -0
  49. package/dist/daemon-handle.js +2 -0
  50. package/dist/daemon-handle.js.map +1 -0
  51. package/dist/daemon-status-report.d.ts +40 -0
  52. package/dist/daemon-status-report.d.ts.map +1 -0
  53. package/dist/daemon-status-report.js +78 -0
  54. package/dist/daemon-status-report.js.map +1 -0
  55. package/dist/daemon.d.ts +5 -66
  56. package/dist/daemon.d.ts.map +1 -1
  57. package/dist/daemon.js +332 -4894
  58. package/dist/daemon.js.map +1 -1
  59. package/dist/delivery-open-registry.d.ts +1 -1
  60. package/dist/delivery-open-registry.js +1 -1
  61. package/dist/directory-connect.d.ts +27 -0
  62. package/dist/directory-connect.d.ts.map +1 -0
  63. package/dist/directory-connect.js +98 -0
  64. package/dist/directory-connect.js.map +1 -0
  65. package/dist/disconnect-cleanup.d.ts +45 -0
  66. package/dist/disconnect-cleanup.d.ts.map +1 -0
  67. package/dist/disconnect-cleanup.js +65 -0
  68. package/dist/disconnect-cleanup.js.map +1 -0
  69. package/dist/document-surface.d.ts +32 -0
  70. package/dist/document-surface.d.ts.map +1 -0
  71. package/dist/document-surface.js +150 -0
  72. package/dist/document-surface.js.map +1 -0
  73. package/dist/document-wiring.d.ts +53 -0
  74. package/dist/document-wiring.d.ts.map +1 -0
  75. package/dist/document-wiring.js +323 -0
  76. package/dist/document-wiring.js.map +1 -0
  77. package/dist/held-content.d.ts +7 -3
  78. package/dist/held-content.d.ts.map +1 -1
  79. package/dist/held-content.js.map +1 -1
  80. package/dist/inbound-sessions.d.ts +9 -1
  81. package/dist/inbound-sessions.d.ts.map +1 -1
  82. package/dist/inbound-sessions.js +9 -1
  83. package/dist/inbound-sessions.js.map +1 -1
  84. package/dist/index.d.ts +1 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +1 -2
  87. package/dist/index.js.map +1 -1
  88. package/dist/ipc-surface.d.ts +44 -0
  89. package/dist/ipc-surface.d.ts.map +1 -0
  90. package/dist/ipc-surface.js +106 -0
  91. package/dist/ipc-surface.js.map +1 -0
  92. package/dist/network-directory-node.d.ts +0 -18
  93. package/dist/network-directory-node.d.ts.map +1 -1
  94. package/dist/network-directory-node.js +1 -38
  95. package/dist/network-directory-node.js.map +1 -1
  96. package/dist/notification-handlers.d.ts.map +1 -1
  97. package/dist/notification-handlers.js +2 -0
  98. package/dist/notification-handlers.js.map +1 -1
  99. package/dist/operator-guidance.d.ts +25 -0
  100. package/dist/operator-guidance.d.ts.map +1 -0
  101. package/dist/operator-guidance.js +50 -0
  102. package/dist/operator-guidance.js.map +1 -0
  103. package/dist/park-recovery.d.ts +22 -1
  104. package/dist/park-recovery.d.ts.map +1 -1
  105. package/dist/park-recovery.js.map +1 -1
  106. package/dist/park-refusals.d.ts +147 -0
  107. package/dist/park-refusals.d.ts.map +1 -0
  108. package/dist/park-refusals.js +331 -0
  109. package/dist/park-refusals.js.map +1 -0
  110. package/dist/refusal-notices.d.ts.map +1 -1
  111. package/dist/refusal-notices.js +22 -2
  112. package/dist/refusal-notices.js.map +1 -1
  113. package/dist/refusal-reasons.d.ts +13 -0
  114. package/dist/refusal-reasons.d.ts.map +1 -1
  115. package/dist/refusal-reasons.js +19 -0
  116. package/dist/refusal-reasons.js.map +1 -1
  117. package/dist/register-handler.d.ts +8 -7
  118. package/dist/register-handler.d.ts.map +1 -1
  119. package/dist/register-handler.js.map +1 -1
  120. package/dist/session-content-context.d.ts +144 -0
  121. package/dist/session-content-context.d.ts.map +1 -0
  122. package/dist/session-content-context.js +2 -0
  123. package/dist/session-content-context.js.map +1 -0
  124. package/dist/session-content-handlers.d.ts.map +1 -1
  125. package/dist/session-content-handlers.js +2 -0
  126. package/dist/session-content-handlers.js.map +1 -1
  127. package/dist/session-content-ingest.d.ts +209 -0
  128. package/dist/session-content-ingest.d.ts.map +1 -0
  129. package/dist/session-content-ingest.js +2216 -0
  130. package/dist/session-content-ingest.js.map +1 -0
  131. package/dist/session-content-send.d.ts +184 -0
  132. package/dist/session-content-send.d.ts.map +1 -0
  133. package/dist/session-content-send.js +1300 -0
  134. package/dist/session-content-send.js.map +1 -0
  135. package/dist/session-lifecycle.d.ts +303 -0
  136. package/dist/session-lifecycle.d.ts.map +1 -0
  137. package/dist/session-lifecycle.js +1643 -0
  138. package/dist/session-lifecycle.js.map +1 -0
  139. package/dist/session-node-factory.d.ts +18 -0
  140. package/dist/session-node-factory.d.ts.map +1 -0
  141. package/dist/session-node-factory.js +182 -0
  142. package/dist/session-node-factory.js.map +1 -0
  143. package/dist/session-node-manager.d.ts +68 -766
  144. package/dist/session-node-manager.d.ts.map +1 -1
  145. package/dist/session-node-manager.js +966 -7940
  146. package/dist/session-node-manager.js.map +1 -1
  147. package/dist/session-node-types.d.ts +30 -0
  148. package/dist/session-node-types.d.ts.map +1 -1
  149. package/dist/session-node-types.js.map +1 -1
  150. package/dist/session-notify.d.ts +46 -0
  151. package/dist/session-notify.d.ts.map +1 -0
  152. package/dist/session-notify.js +115 -0
  153. package/dist/session-notify.js.map +1 -0
  154. package/dist/session-read-handlers.d.ts.map +1 -1
  155. package/dist/session-read-handlers.js +0 -1
  156. package/dist/session-read-handlers.js.map +1 -1
  157. package/dist/session-relay.d.ts +361 -0
  158. package/dist/session-relay.d.ts.map +1 -0
  159. package/dist/session-relay.js +1471 -0
  160. package/dist/session-relay.js.map +1 -0
  161. package/dist/session-salt-agreement.d.ts +0 -7
  162. package/dist/session-salt-agreement.d.ts.map +1 -1
  163. package/dist/session-salt-agreement.js +0 -7
  164. package/dist/session-salt-agreement.js.map +1 -1
  165. package/dist/session-salts.d.ts +13 -0
  166. package/dist/session-salts.d.ts.map +1 -1
  167. package/dist/session-salts.js +13 -0
  168. package/dist/session-salts.js.map +1 -1
  169. package/dist/session-seal.d.ts +336 -0
  170. package/dist/session-seal.d.ts.map +1 -0
  171. package/dist/session-seal.js +948 -0
  172. package/dist/session-seal.js.map +1 -0
  173. package/dist/session-views.d.ts +46 -0
  174. package/dist/session-views.d.ts.map +1 -0
  175. package/dist/session-views.js +197 -0
  176. package/dist/session-views.js.map +1 -0
  177. package/dist/signal-handlers.d.ts +66 -0
  178. package/dist/signal-handlers.d.ts.map +1 -0
  179. package/dist/signal-handlers.js +975 -0
  180. package/dist/signal-handlers.js.map +1 -0
  181. package/dist/signaling-wiring.d.ts +100 -0
  182. package/dist/signaling-wiring.d.ts.map +1 -0
  183. package/dist/signaling-wiring.js +392 -0
  184. package/dist/signaling-wiring.js.map +1 -0
  185. package/dist/start-agent.d.ts +64 -0
  186. package/dist/start-agent.d.ts.map +1 -0
  187. package/dist/start-agent.js +136 -0
  188. package/dist/start-agent.js.map +1 -0
  189. package/dist/status-handler.d.ts +46 -0
  190. package/dist/status-handler.d.ts.map +1 -0
  191. package/dist/status-handler.js +58 -0
  192. package/dist/status-handler.js.map +1 -0
  193. package/dist/test-handlers.d.ts +62 -0
  194. package/dist/test-handlers.d.ts.map +1 -0
  195. package/dist/test-handlers.js +239 -0
  196. package/dist/test-handlers.js.map +1 -0
  197. package/dist/types.d.ts +0 -11
  198. package/dist/types.d.ts.map +1 -1
  199. package/dist/types.js +0 -12
  200. package/dist/types.js.map +1 -1
  201. package/dist/unresolved-nodes-report.d.ts +14 -0
  202. package/dist/unresolved-nodes-report.d.ts.map +1 -0
  203. package/dist/unresolved-nodes-report.js +96 -0
  204. package/dist/unresolved-nodes-report.js.map +1 -0
  205. package/dist/who-resolver.d.ts +15 -0
  206. package/dist/who-resolver.d.ts.map +1 -0
  207. package/dist/who-resolver.js +46 -0
  208. package/dist/who-resolver.js.map +1 -0
  209. package/dist/wire-content-hash.d.ts +0 -2
  210. package/dist/wire-content-hash.d.ts.map +1 -1
  211. package/dist/wire-content-hash.js +0 -4
  212. package/dist/wire-content-hash.js.map +1 -1
  213. package/package.json +5 -5
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Bringing an agent online, and reporting honestly whether it can actually be REACHED.
3
+ *
4
+ * "Online" and "reachable" are two different facts and the whole value of this path is refusing to
5
+ * collapse them. An agent marked online whose standing receiver never came up looks identical to a
6
+ * healthy one at every surface — so a second `cello_start_agent`, which is what an operator runs
7
+ * when the first seemed not to work, reports the receiver's REAL state rather than a bare ok.
8
+ */
9
+ import type { AgentInfo, Logger } from "./types.js";
10
+ import type { SessionNodeManager } from "./session-node-manager.js";
11
+ import type { SignalingManager } from "@cello-protocol/transport";
12
+ import type { KeyProvider } from "@cello-protocol/crypto";
13
+ import type { NotificationDispatcher } from "./notification-dispatcher.js";
14
+ /** What starting an agent can answer. The readiness half is why this is a union and not a boolean. */
15
+ export type StartAgentResult = {
16
+ ok: true;
17
+ standing_receiver: "ready";
18
+ } | {
19
+ ok: true;
20
+ standing_receiver: "starting";
21
+ standing_receiver_cause: string | undefined;
22
+ guidance: string;
23
+ } | {
24
+ ok: false;
25
+ reason: string;
26
+ guidance: string;
27
+ };
28
+ export interface StartAgentDeps {
29
+ logger: Logger;
30
+ sessionNodeManager: SessionNodeManager;
31
+ /** Live containers — a copy would report a stale online set forever. */
32
+ agents: ReadonlyArray<AgentInfo>;
33
+ onlineAgents: Set<string>;
34
+ explicitlyOfflineAgents: Set<string>;
35
+ keyProviders: Map<string, KeyProvider>;
36
+ /**
37
+ * ⚠️ A GETTER. The dispatcher is constructed ~575 lines BELOW this call and is only ever used when
38
+ * an agent is actually started, which is always later. It is a `const`, so by value this would be
39
+ * a temporal-dead-zone crash at boot rather than a silent absence — loud, but still wrong.
40
+ */
41
+ getNotificationDispatcher: () => NotificationDispatcher;
42
+ /** ⚠️ NOT a getter — for an agent with no manager this CONSTRUCTS one and dials. */
43
+ getAgentSignaling: (agentName: string, kp: KeyProvider, pubkeyHex: string) => {
44
+ signaling: SignalingManager;
45
+ };
46
+ autoRecoverForAgent: (agentName: string, trigger?: string) => Promise<void>;
47
+ flushAwaitingContent: (filterAgentName?: string) => Promise<void>;
48
+ }
49
+ export declare function createStartAgent(deps: StartAgentDeps): {
50
+ startAgentInternal: (name: string) => {
51
+ ok: true;
52
+ standing_receiver: "ready";
53
+ } | {
54
+ ok: true;
55
+ standing_receiver: "starting";
56
+ standing_receiver_cause: string | undefined;
57
+ guidance: string;
58
+ } | {
59
+ ok: false;
60
+ reason: string;
61
+ guidance: string;
62
+ };
63
+ };
64
+ //# sourceMappingURL=start-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-agent.d.ts","sourceRoot":"","sources":["../src/start-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAG3E,sGAAsG;AACtG,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,iBAAiB,EAAE,UAAU,CAAC;IAAC,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1G;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,wEAAwE;IACxE,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACjC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,uBAAuB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC;;;;OAIG;IACH,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;IACxD,oFAAoF;IACpF,iBAAiB,EAAE,CACjB,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,KAClD;QAAE,SAAS,EAAE,gBAAgB,CAAA;KAAE,CAAC;IACrC,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,oBAAoB,EAAE,CAAC,eAAe,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc;+BAkBjB,MAAM,KACpC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,GACxC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,iBAAiB,EAAE,UAAU,CAAC;QAAC,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAC1G;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;EAyHpD"}
@@ -0,0 +1,136 @@
1
+ import { extractErrorMessage } from "./error-message.js";
2
+ export function createStartAgent(deps) {
3
+ const { logger, sessionNodeManager, agents, onlineAgents, explicitlyOfflineAgents, keyProviders, getNotificationDispatcher, getAgentSignaling, autoRecoverForAgent, flushAwaitingContent, } = deps;
4
+ // ─── MCP-001: cello_start_agent handler ───
5
+ // M8C-AUTOSTART-1 (A2): the shared start path. Extracted from cello_start_agent so cello_use_agent
6
+ // can AUTO-START an offline agent through the exact same code (idempotent, same signaling +
7
+ // standing-receiver setup, same agent_state_changed event) — never a divergent shim-side retry.
8
+ // Permissive by design (D12): an agent that exists goes online regardless of directory
9
+ // registration state (online-without-registration is an established contract). Returns a
10
+ // structured failure so callers can surface agent_start_failed with a real reason + guidance.
11
+ /**
12
+ * `standing_receiver` is part of the SUCCESS shape, not an optional extra — `DOD-M15-START-AGENT-
13
+ * UNAWAITED-1`. A bare `{ ok: true }` claimed the agent was started and reachable when only the
14
+ * first half was known, and the union makes the two states impossible to conflate at a call site.
15
+ */
16
+ function startAgentInternal(name) {
17
+ const agent = agents.find((a) => a.name === name);
18
+ if (!agent || agent.state === "load_failed") {
19
+ return { ok: false, reason: "agent_not_found", guidance: `Agent '${name}' does not exist. Run 'cello login' to register agents, or check agent names with cello_agents.` };
20
+ }
21
+ if (onlineAgents.has(name)) {
22
+ // Idempotent — already online, no event.
23
+ //
24
+ // It still reports REAL readiness rather than a bare ok. "Already online" says this daemon
25
+ // marked the agent online at some earlier moment; it says nothing about whether the receiver
26
+ // that ensure was firing ever came up. An operator who calls start twice — which is exactly
27
+ // what someone does when the first one seemed not to work — would otherwise get the most
28
+ // reassuring answer in the run on the attempt where something is actually wrong.
29
+ const readyNow = sessionNodeManager.getStandingReceiverInfo(name) !== null;
30
+ if (readyNow)
31
+ return { ok: true, standing_receiver: "ready" };
32
+ const cause = sessionNodeManager.standingReceiverAbsenceReason(name);
33
+ return {
34
+ ok: true,
35
+ standing_receiver: "starting",
36
+ standing_receiver_cause: cause,
37
+ guidance: `'${name}' was already online, and its standing receiver is not up (${cause}). Outbound ` +
38
+ `sends and cello_initiate_session ensure it on demand. An inbound session arriving before ` +
39
+ `it is ready is refused with 'standing_receiver_unavailable' — this daemon, not the ` +
40
+ `counterparty. If it stays this way, stop the agent and start it again.`,
41
+ };
42
+ }
43
+ onlineAgents.add(name);
44
+ // Pressing start clears the deliberate-offline mark — that is what makes the switch reversible.
45
+ explicitlyOfflineAgents.delete(name);
46
+ // CELLO-M7-CONN-001 (DOD-CONN-2, code-review HIGH): the "online" transition establishes THIS
47
+ // agent's OWN directory signaling connection (the documented getAgentSignaling "online" trigger),
48
+ // so the directory has a stream to push inbound session_assignment / seal_interrupted_request to.
49
+ // Without this, a started receiver agent sitting in cello_await_session (notably after a daemon
50
+ // restart, where login does NOT auto-start agents) would have no stream and never receive inbound —
51
+ // a regression of the pre-CONN-001 keystone, which connected the primary at startup. Lazy +
52
+ // idempotent (getAgentSignaling reuses an existing manager); the test path returns the shared one.
53
+ const startKp = keyProviders.get(name);
54
+ if (startKp && agent.pubkey) {
55
+ getAgentSignaling(name, startKp, agent.pubkey);
56
+ logger.info("agent.directory.connection.initiated", { agentName: name, agentPubkey: agent.pubkey });
57
+ }
58
+ // DOD-LOOP-1: each online agent gets its OWN standing receiver, so two agents on one daemon
59
+ // (loopback) never contend for a single one. Fire-and-forget (initiate/accept also ensure on
60
+ // demand); never let it throw out of the handler. Once the SR is up, re-park any of THIS
61
+ // agent's un-acked awaiting content (the crash backstop — its node was unavailable at the
62
+ // pre-IPC startup flush because no agent was online yet).
63
+ // The standing-receiver ensure + sender re-park; a rejection here is a standing-receiver failure.
64
+ void sessionNodeManager.ensureStandingReceiverForAgent(name)
65
+ .then(() => flushAwaitingContent(name))
66
+ .catch((err) => {
67
+ logger.warn("session.standing_receiver.ensure.failed", {
68
+ agentName: name,
69
+ reason: extractErrorMessage(err),
70
+ // `DOD-M15-START-AGENT-UNAWAITED-1`. The operator has ALREADY been told `ok: true` — this
71
+ // handler answered before this promise settled — so nothing corrects that answer if this
72
+ // is permanent. Say what it costs them here, because this line is the only account.
73
+ impact: "cello_start_agent already answered ok for this agent, and its standing receiver did not " +
74
+ "come up. The agent is online to the directory and CANNOT accept an inbound session: a " +
75
+ "counterparty dialling it is refused standing_receiver_unavailable. Initiate and accept " +
76
+ "each re-ensure on demand, so this may still recover on the next attempt; if it does not, " +
77
+ "stop and restart the agent.",
78
+ });
79
+ })
80
+ // DOD-MSG-4 (auto-recover-on-reconnect): RECEIVER drains its parked mailbox from every relay it
81
+ // has sessions on (symmetric to the sender re-park). Its own stage so a failure is labelled
82
+ // correctly (review #4), not as a standing-receiver error. autoRecoverForAgent catches per-relay
83
+ // errors internally, so this .catch is a backstop only.
84
+ .then(() => autoRecoverForAgent(name, "agent_start"))
85
+ .catch((err) => {
86
+ logger.warn("content.recover.auto.failed", { agentName: name, stage: "agent_start", error: extractErrorMessage(err) });
87
+ });
88
+ /**
89
+ * `DOD-M15-START-AGENT-UNAWAITED-1` — SAY WHETHER THE AGENT CAN ACTUALLY HEAR YET.
90
+ *
91
+ * The ensure above is fire-and-forget and that is deliberate: initiate and accept both ensure on
92
+ * demand, and awaiting it here would turn a transient network failure into a failed start. **The
93
+ * defect was never the timing — it was the CLAIM.** `{ ok: true }` with nothing else reads as
94
+ * "your agent is running and reachable", and a session landing in the window before the receiver
95
+ * exists is refused `standing_receiver_unavailable` — a precondition on OUR side, surfacing to
96
+ * the operator as though the counterparty or the directory were at fault.
97
+ *
98
+ * ⚠️ **This field is only worth having because it can genuinely say `ready`.** Computed one line
99
+ * after firing an async ensure, a naive readiness flag would be `starting` on every call — a
100
+ * field that can never take its other value, which is the same defect as a log line reporting a
101
+ * verdict its producer cannot have. It escapes that because `ensureStandingReceiverForAgent` is
102
+ * IDEMPOTENT: an agent that already holds a receiver (a repeat start, or one whose receiver
103
+ * survived) has one at this instant and reports `ready` truthfully.
104
+ *
105
+ * `cause` is read from the same four-way answer the refusal path uses, so the response and the
106
+ * eventual error agree instead of describing the same state in two vocabularies.
107
+ */
108
+ const receiverReady = sessionNodeManager.getStandingReceiverInfo(name) !== null;
109
+ const startingCause = receiverReady ? undefined : sessionNodeManager.standingReceiverAbsenceReason(name);
110
+ logger.info("agent.online", {
111
+ agentName: name,
112
+ agentPubkey: agent.pubkey ?? "",
113
+ standingReceiver: receiverReady ? "ready" : "starting",
114
+ ...(startingCause !== undefined ? { standingReceiverCause: startingCause } : {}),
115
+ });
116
+ // MCP-002: Broadcast agent_state_changed to ALL connections
117
+ getNotificationDispatcher().dispatchAgentStateChanged(name, "online", "started");
118
+ if (receiverReady)
119
+ return { ok: true, standing_receiver: "ready" };
120
+ return {
121
+ ok: true,
122
+ standing_receiver: "starting",
123
+ standing_receiver_cause: startingCause,
124
+ // Invariant: an agent-facing response carries an affordance. Naming the refusal text is the
125
+ // load-bearing half — an operator who hits it in the next second can otherwise only conclude
126
+ // the other side is broken.
127
+ guidance: `'${name}' is online and its standing receiver is still being built. Outbound sends and ` +
128
+ `cello_initiate_session ensure it on demand, so ordinary use is fine. A session arriving in ` +
129
+ `the next moment can be refused with 'standing_receiver_unavailable' — that is this daemon ` +
130
+ `not being ready yet, NOT the counterparty being unreachable. It clears on its own; ` +
131
+ `cello_status reports the receiver once it is up.`,
132
+ };
133
+ }
134
+ return { startAgentInternal };
135
+ }
136
+ //# sourceMappingURL=start-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-agent.js","sourceRoot":"","sources":["../src/start-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `cello_status` — what ONE CONNECTION can see of this daemon, from its own perspective.
3
+ *
4
+ * The widest read in the daemon and one of the narrowest dependency lists: nine values, every one a
5
+ * reader, nothing written. It reports the agents this connection may act as, its directory
6
+ * signaling, where the consortium manifest came from, unresolved directory nodes, interrupted
7
+ * sessions and live ones.
8
+ *
9
+ * ⚠️ `unresolvedNodesForStatus` DID NOT COME WITH IT, and that is deliberate. The daemon-wide
10
+ * `getStatus()` — what `cello status` at a terminal renders — calls the same helper, and it is the
11
+ * surface that was silent on 2026-07-31 while every session failed. A helper with two consumers
12
+ * moves only when both move; here it is injected instead.
13
+ */
14
+ import { type ManifestOrigin } from "./manifest-validity.js";
15
+ import type { IpcHandler } from "./ipc-server.js";
16
+ import type { AgentInfo, ActiveSessionInfo, DirectorySignalingState, InterruptedSessionInfo } from "./types.js";
17
+ import type { IDirectoryChallengeVerifier } from "@cello-protocol/transport";
18
+ import type { ConsortiumManifest } from "@cello-protocol/protocol-types";
19
+ export interface StatusHandlerDeps {
20
+ handlers: Map<string, IpcHandler>;
21
+ /** Every agent this CONNECTION may act as — not every agent the daemon holds. */
22
+ getAgentsForConnection: (connectionId: string) => AgentInfo[];
23
+ directorySignalingStatus: () => DirectorySignalingState;
24
+ /** Where the verified manifest came from, for a reader deciding how much the rest is worth. */
25
+ manifestOrigin: ManifestOrigin;
26
+ manifestProvider: {
27
+ getCurrentManifest: () => Pick<ConsortiumManifest, "not_before" | "expires"> | null;
28
+ } | undefined;
29
+ /** The configured directory URL, or undefined when nothing was configured. */
30
+ directoryHttpUrl: string | undefined;
31
+ /**
32
+ * The directory challenge verifier, or undefined when this daemon holds none. TYPED, not
33
+ * `unknown`: the posture line an operator reads is derived from `!== undefined`, so a dep loose
34
+ * enough to accept `null` or the wrong variable would report `directory_authentication: enforced`
35
+ * on a daemon that enforces nothing — the failure `DOD-M15-DIRAUTH-1` exists to prevent.
36
+ */
37
+ challengeVerifier: IDirectoryChallengeVerifier | undefined;
38
+ /** Emits ONLY when something is wrong or nothing has looked recently enough to say. */
39
+ unresolvedNodesForStatus: () => {
40
+ directory_endpoints_unresolved: unknown;
41
+ } | undefined;
42
+ buildInterruptedSessions: () => InterruptedSessionInfo[];
43
+ buildActiveSessions: () => ActiveSessionInfo[];
44
+ }
45
+ export declare function registerStatusHandler(deps: StatusHandlerDeps): void;
46
+ //# sourceMappingURL=status-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-handler.d.ts","sourceRoot":"","sources":["../src/status-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAsD,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGjH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAChH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,iFAAiF;IACjF,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAC9D,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;IACxD,+FAA+F;IAC/F,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE;QAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAAG,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;IACtH,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;;;;OAKG;IACH,iBAAiB,EAAE,2BAA2B,GAAG,SAAS,CAAC;IAC3D,uFAAuF;IACvF,wBAAwB,EAAE,MAAM;QAAE,8BAA8B,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACxF,wBAAwB,EAAE,MAAM,sBAAsB,EAAE,CAAC;IACzD,mBAAmB,EAAE,MAAM,iBAAiB,EAAE,CAAC;CAChD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA+CnE"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `cello_status` — what ONE CONNECTION can see of this daemon, from its own perspective.
3
+ *
4
+ * The widest read in the daemon and one of the narrowest dependency lists: nine values, every one a
5
+ * reader, nothing written. It reports the agents this connection may act as, its directory
6
+ * signaling, where the consortium manifest came from, unresolved directory nodes, interrupted
7
+ * sessions and live ones.
8
+ *
9
+ * ⚠️ `unresolvedNodesForStatus` DID NOT COME WITH IT, and that is deliberate. The daemon-wide
10
+ * `getStatus()` — what `cello status` at a terminal renders — calls the same helper, and it is the
11
+ * surface that was silent on 2026-07-31 while every session failed. A helper with two consumers
12
+ * moves only when both move; here it is injected instead.
13
+ */
14
+ import { classifyManifestValidity, describeManifestValidity } from "./manifest-validity.js";
15
+ import { describeDirectoryAuth } from "./directory-auth-posture.js";
16
+ import { resolveDirectoryUrl } from "./directory-bootstrap.js";
17
+ export function registerStatusHandler(deps) {
18
+ const { handlers, getAgentsForConnection, directorySignalingStatus, manifestOrigin, manifestProvider, directoryHttpUrl, challengeVerifier, unresolvedNodesForStatus, buildInterruptedSessions, buildActiveSessions, } = deps;
19
+ handlers.set("cello_status", async (_params, connectionId) => {
20
+ return {
21
+ daemon: "running",
22
+ directory_signaling: directorySignalingStatus(),
23
+ // CAN I ACTUALLY REACH THE DIRECTORY — not just "is my socket up?".
24
+ //
25
+ // These are different facts and they diverged for an hour on 2026-07-31. libp2p signaling
26
+ // dials multiaddrs from the bundled manifest, so it stayed connected and every agent reported
27
+ // online, while a cached NXDOMAIN meant nothing that needed the HTTP endpoint resolved. The
28
+ // roster came back empty, so every threshold ceremony failed — surfacing to the operator as
29
+ // counterparty_offline, then directory_below_threshold, then ceremony_exhausted. Three errors,
30
+ // none of them naming DNS, while the reason sat in the log 26 times per node.
31
+ //
32
+ // Omitted entirely when nothing is failing, so a healthy status stays quiet.
33
+ ...(unresolvedNodesForStatus() ?? {}),
34
+ // DOD-M15-MANIFEST-EXPIRY-LIVE-1: contributes NOTHING while the manifest is comfortably in
35
+ // window. A field present on every status read for the years a manifest is valid is furniture,
36
+ // not a warning, and it teaches the reader to skip the block that matters.
37
+ ...(describeManifestValidity(classifyManifestValidity(manifestProvider?.getCurrentManifest() ?? null, Date.now()), manifestOrigin) ?? {}),
38
+ // DOD-M15-DIRAUTH-1: the posture is STATED, in both directions. Unlike every other field in
39
+ // this milestone the healthy case is reported too — the defect is precisely that "enforced"
40
+ // and "skipped" differ only by the absence of a log line, so an operator must be able to
41
+ // confirm it is on, not merely fail to find evidence that it is off.
42
+ ...describeDirectoryAuth({
43
+ verifierPresent: challengeVerifier !== undefined,
44
+ directoryUrl: directoryHttpUrl ?? resolveDirectoryUrl(process.env),
45
+ // Review F5: with neither set, `resolveDirectoryUrl` re-picks a RANDOM bundled endpoint on
46
+ // every call, so there is no configured URL to quote or to blame.
47
+ urlExplicitlyConfigured: directoryHttpUrl !== undefined || process.env["CELLO_DIRECTORY_URL"] !== undefined,
48
+ }),
49
+ agents: getAgentsForConnection(connectionId),
50
+ // M-1 PULL: live MCP clients must see interrupted sessions too, exactly as
51
+ // the daemon-wide getStatus() surfaces them.
52
+ interrupted_sessions: buildInterruptedSessions(),
53
+ // M8B F16: per-session liveness on the MCP surface too.
54
+ active_sessions: buildActiveSessions(),
55
+ };
56
+ });
57
+ }
58
+ //# sourceMappingURL=status-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-handler.js","sourceRoot":"","sources":["../src/status-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAuB,MAAM,wBAAwB,CAAC;AACjH,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AA6B/D,MAAM,UAAU,qBAAqB,CAAC,IAAuB;IAC3D,MAAM,EACJ,QAAQ,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,cAAc,EAAE,gBAAgB,EAC5F,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,mBAAmB,GAC7G,GAAG,IAAI,CAAC;IAET,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE;QAC3D,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,mBAAmB,EAAE,wBAAwB,EAAE;YAC/C,oEAAoE;YACpE,EAAE;YACF,0FAA0F;YAC1F,8FAA8F;YAC9F,4FAA4F;YAC5F,4FAA4F;YAC5F,+FAA+F;YAC/F,8EAA8E;YAC9E,EAAE;YACF,6EAA6E;YAC7E,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,CAAC;YACrC,2FAA2F;YAC3F,+FAA+F;YAC/F,2EAA2E;YAC3E,GAAG,CAAC,wBAAwB,CAC1B,wBAAwB,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,IAAI,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,EACpF,cAAc,CACf,IAAI,EAAE,CAAC;YACR,4FAA4F;YAC5F,4FAA4F;YAC5F,yFAAyF;YACzF,qEAAqE;YACrE,GAAG,qBAAqB,CAAC;gBACvB,eAAe,EAAE,iBAAiB,KAAK,SAAS;gBAChD,YAAY,EAAE,gBAAgB,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC;gBAClE,2FAA2F;gBAC3F,kEAAkE;gBAClE,uBAAuB,EAAE,gBAAgB,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,KAAK,SAAS;aAC5G,CAAC;YACF,MAAM,EAAE,sBAAsB,CAAC,YAAY,CAAC;YAC5C,2EAA2E;YAC3E,6CAA6C;YAC7C,oBAAoB,EAAE,wBAAwB,EAAE;YAChD,wDAAwD;YACxD,eAAe,EAAE,mBAAmB,EAAE;SACvC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The verbs that exist for TESTS, and nothing else.
3
+ *
4
+ * Two groups with different guards, and the difference is why this file has a header. The seven
5
+ * `__test_*` verbs sit inside `CELLO_ENV === "test"` and cannot be reached in production. The six
6
+ * above them — `queue_failed_send`, `debug_inject_park_fault`, `enqueue_awaiting_content`,
7
+ * `mark_content_acked`, `check_nonce`, `drain_session` — are NOT gated, and FOUR of them write state.
8
+ * `check_nonce` is the one to notice: it does not merely read, it `checkAndAdd`s, which INSERTs into
9
+ * `session_seen_nonces` and survives a restart — so pre-registering a nonce makes the real message
10
+ * carrying it arrive and be discarded as a duplicate, logged at debug and nowhere else. Their only
11
+ * callers are tests (measured: nothing in the CLI, nothing in the MCP shim), so a production daemon
12
+ * answers six verbs nobody outside a test has a use for.
13
+ *
14
+ * ⚠️ THE ASYMMETRY IS RECORDED, NOT FIXED HERE. Gating them changes behaviour and this is a movement
15
+ * order; the guard structure moved exactly as it was. It is written into the order's *Newly
16
+ * discovered* so it can be ranked — rather than inherited by the next reader, who would see the file
17
+ * name and assume the whole thing is unreachable in production.
18
+ *
19
+ * ⚠️ TWO PRODUCTION REGISTRATIONS DID NOT COME WITH IT. `contentPark.registerHandlers(handlers)` and
20
+ * `registerInboundSessionHandlers(handlers)` sit between the two groups in the original file and are
21
+ * real surfaces. They stay in the composition root; only the test verbs on either side moved. That
22
+ * DOES change registration order — those two now run after all thirteen instead of between them —
23
+ * and it is inert: dispatch resolves against the live map on each request rather than snapshotting
24
+ * it, the IPC server is not created until every registration has run, and none of these verb names
25
+ * collides. Written down because "do not reorder registration" is a rule of this order, and the
26
+ * next reader deserves the measurement rather than the worry.
27
+ */
28
+ import type { IpcHandler } from "./ipc-server.js";
29
+ import type { SessionNodeManager } from "./session-node-manager.js";
30
+ import type { Logger } from "./types.js";
31
+ import type { RetryQueue } from "./retry-queue.js";
32
+ import type { NonceDedupStore } from "./nonce-dedup.js";
33
+ import { type AnyRefusalReason } from "./refusal-reasons.js";
34
+ import type { InboundSessionEvent } from "./inbound-sessions.js";
35
+ /** The per-connection agent selection, as these verbs need to read it. */
36
+ export interface TestConnState {
37
+ currentAgent: string | null;
38
+ }
39
+ export interface TestHandlerDeps {
40
+ handlers: Map<string, IpcHandler>;
41
+ logger: Logger;
42
+ sessionNodeManager: SessionNodeManager;
43
+ retryQueue: RetryQueue;
44
+ nonceDedupStore: NonceDedupStore;
45
+ /** Opens a delivery window and hands back the release. */
46
+ deliveryOpens: {
47
+ begin: (openerPubkey: string, targetPubkey: string) => () => void;
48
+ };
49
+ /** Name → pubkey, empty string when this daemon holds no such agent. */
50
+ pubkeyOfAgent: (name: string) => string;
51
+ /** The one dispatch path that also reaches Telegram — tests drive it to assert both halves. */
52
+ dispatchSessionStateChangedWithTelegram: (agentName: string, sessionId: string, state: string, counterpartyPubkey: string | null) => void;
53
+ /** The inbound-session queue machinery these verbs seed, injected rather than reached for. */
54
+ enqueueInboundSession: (agentName: string, event: InboundSessionEvent) => void;
55
+ recordRefusal: (agentName: string, sessionIdHex: string, counterpartyPubkeyHex: string, reason: AnyRefusalReason) => void;
56
+ /** The queue itself — one verb backdates the entry it just enqueued, which needs the container. */
57
+ inboundSessionQueues: Map<string, InboundSessionEvent[]>;
58
+ /** Read this connection's agent selection. The READ, not the container. */
59
+ getConnState: (connectionId: string) => TestConnState | undefined;
60
+ }
61
+ export declare function registerTestHandlers(deps: TestHandlerDeps): void;
62
+ //# sourceMappingURL=test-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-handlers.d.ts","sourceRoot":"","sources":["../src/test-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAqC,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAAG,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAAE;AAE/D,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,0DAA0D;IAC1D,aAAa,EAAE;QAAE,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,IAAI,CAAA;KAAE,CAAC;IACrF,wEAAwE;IACxE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,+FAA+F;IAC/F,uCAAuC,EAAE,CACvC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,MAAM,GAAG,IAAI,KAC9B,IAAI,CAAC;IACV,8FAA8F;IAC9F,qBAAqB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/E,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,qBAAqB,EAAE,MAAM,EAC7B,MAAM,EAAE,gBAAgB,KACrB,IAAI,CAAC;IACV,mGAAmG;IACnG,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACzD,2EAA2E;IAC3E,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;CACnE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAqQhE"}