@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.
- package/dist/agent-admin-handlers.d.ts +56 -0
- package/dist/agent-admin-handlers.d.ts.map +1 -0
- package/dist/agent-admin-handlers.js +70 -0
- package/dist/agent-admin-handlers.js.map +1 -0
- package/dist/agent-handlers.d.ts +8 -7
- package/dist/agent-handlers.d.ts.map +1 -1
- package/dist/agent-handlers.js.map +1 -1
- package/dist/agent-selection-root.d.ts +29 -0
- package/dist/agent-selection-root.d.ts.map +1 -0
- package/dist/agent-selection-root.js +126 -0
- package/dist/agent-selection-root.js.map +1 -0
- package/dist/attendance-wiring.d.ts +44 -0
- package/dist/attendance-wiring.d.ts.map +1 -0
- package/dist/attendance-wiring.js +432 -0
- package/dist/attendance-wiring.js.map +1 -0
- package/dist/backup-restore-handlers.d.ts +10 -0
- package/dist/backup-restore-handlers.d.ts.map +1 -0
- package/dist/backup-restore-handlers.js +82 -0
- package/dist/backup-restore-handlers.js.map +1 -0
- package/dist/boot-agents.d.ts +64 -0
- package/dist/boot-agents.d.ts.map +1 -0
- package/dist/boot-agents.js +241 -0
- package/dist/boot-agents.js.map +1 -0
- package/dist/boot-connection-state.d.ts +40 -0
- package/dist/boot-connection-state.d.ts.map +1 -0
- package/dist/boot-connection-state.js +136 -0
- package/dist/boot-connection-state.js.map +1 -0
- package/dist/boot-core.d.ts +36 -0
- package/dist/boot-core.d.ts.map +1 -0
- package/dist/boot-core.js +292 -0
- package/dist/boot-core.js.map +1 -0
- package/dist/boot-parked-content.d.ts +34 -0
- package/dist/boot-parked-content.d.ts.map +1 -0
- package/dist/boot-parked-content.js +527 -0
- package/dist/boot-parked-content.js.map +1 -0
- package/dist/boot-sweeps.d.ts +22 -0
- package/dist/boot-sweeps.d.ts.map +1 -0
- package/dist/boot-sweeps.js +50 -0
- package/dist/boot-sweeps.js.map +1 -0
- package/dist/connection-agents.d.ts +16 -0
- package/dist/connection-agents.d.ts.map +1 -0
- package/dist/connection-agents.js +68 -0
- package/dist/connection-agents.js.map +1 -0
- package/dist/content-park.d.ts.map +1 -1
- package/dist/content-park.js +274 -25
- package/dist/content-park.js.map +1 -1
- package/dist/daemon-handle.d.ts +57 -0
- package/dist/daemon-handle.d.ts.map +1 -0
- package/dist/daemon-handle.js +2 -0
- package/dist/daemon-handle.js.map +1 -0
- package/dist/daemon-status-report.d.ts +40 -0
- package/dist/daemon-status-report.d.ts.map +1 -0
- package/dist/daemon-status-report.js +78 -0
- package/dist/daemon-status-report.js.map +1 -0
- package/dist/daemon.d.ts +5 -66
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +332 -4894
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-open-registry.d.ts +1 -1
- package/dist/delivery-open-registry.js +1 -1
- package/dist/directory-connect.d.ts +27 -0
- package/dist/directory-connect.d.ts.map +1 -0
- package/dist/directory-connect.js +98 -0
- package/dist/directory-connect.js.map +1 -0
- package/dist/disconnect-cleanup.d.ts +45 -0
- package/dist/disconnect-cleanup.d.ts.map +1 -0
- package/dist/disconnect-cleanup.js +65 -0
- package/dist/disconnect-cleanup.js.map +1 -0
- package/dist/document-surface.d.ts +32 -0
- package/dist/document-surface.d.ts.map +1 -0
- package/dist/document-surface.js +150 -0
- package/dist/document-surface.js.map +1 -0
- package/dist/document-wiring.d.ts +53 -0
- package/dist/document-wiring.d.ts.map +1 -0
- package/dist/document-wiring.js +323 -0
- package/dist/document-wiring.js.map +1 -0
- package/dist/held-content.d.ts +7 -3
- package/dist/held-content.d.ts.map +1 -1
- package/dist/held-content.js.map +1 -1
- package/dist/inbound-sessions.d.ts +9 -1
- package/dist/inbound-sessions.d.ts.map +1 -1
- package/dist/inbound-sessions.js +9 -1
- package/dist/inbound-sessions.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/ipc-surface.d.ts +44 -0
- package/dist/ipc-surface.d.ts.map +1 -0
- package/dist/ipc-surface.js +106 -0
- package/dist/ipc-surface.js.map +1 -0
- package/dist/network-directory-node.d.ts +0 -18
- package/dist/network-directory-node.d.ts.map +1 -1
- package/dist/network-directory-node.js +1 -38
- package/dist/network-directory-node.js.map +1 -1
- package/dist/notification-handlers.d.ts.map +1 -1
- package/dist/notification-handlers.js +2 -0
- package/dist/notification-handlers.js.map +1 -1
- package/dist/operator-guidance.d.ts +25 -0
- package/dist/operator-guidance.d.ts.map +1 -0
- package/dist/operator-guidance.js +50 -0
- package/dist/operator-guidance.js.map +1 -0
- package/dist/park-recovery.d.ts +22 -1
- package/dist/park-recovery.d.ts.map +1 -1
- package/dist/park-recovery.js.map +1 -1
- package/dist/park-refusals.d.ts +147 -0
- package/dist/park-refusals.d.ts.map +1 -0
- package/dist/park-refusals.js +331 -0
- package/dist/park-refusals.js.map +1 -0
- package/dist/refusal-notices.d.ts.map +1 -1
- package/dist/refusal-notices.js +22 -2
- package/dist/refusal-notices.js.map +1 -1
- package/dist/refusal-reasons.d.ts +13 -0
- package/dist/refusal-reasons.d.ts.map +1 -1
- package/dist/refusal-reasons.js +19 -0
- package/dist/refusal-reasons.js.map +1 -1
- package/dist/register-handler.d.ts +8 -7
- package/dist/register-handler.d.ts.map +1 -1
- package/dist/register-handler.js.map +1 -1
- package/dist/session-content-context.d.ts +144 -0
- package/dist/session-content-context.d.ts.map +1 -0
- package/dist/session-content-context.js +2 -0
- package/dist/session-content-context.js.map +1 -0
- package/dist/session-content-handlers.d.ts.map +1 -1
- package/dist/session-content-handlers.js +2 -0
- package/dist/session-content-handlers.js.map +1 -1
- package/dist/session-content-ingest.d.ts +209 -0
- package/dist/session-content-ingest.d.ts.map +1 -0
- package/dist/session-content-ingest.js +2216 -0
- package/dist/session-content-ingest.js.map +1 -0
- package/dist/session-content-send.d.ts +184 -0
- package/dist/session-content-send.d.ts.map +1 -0
- package/dist/session-content-send.js +1300 -0
- package/dist/session-content-send.js.map +1 -0
- package/dist/session-lifecycle.d.ts +303 -0
- package/dist/session-lifecycle.d.ts.map +1 -0
- package/dist/session-lifecycle.js +1643 -0
- package/dist/session-lifecycle.js.map +1 -0
- package/dist/session-node-factory.d.ts +18 -0
- package/dist/session-node-factory.d.ts.map +1 -0
- package/dist/session-node-factory.js +182 -0
- package/dist/session-node-factory.js.map +1 -0
- package/dist/session-node-manager.d.ts +68 -766
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +966 -7940
- package/dist/session-node-manager.js.map +1 -1
- package/dist/session-node-types.d.ts +30 -0
- package/dist/session-node-types.d.ts.map +1 -1
- package/dist/session-node-types.js.map +1 -1
- package/dist/session-notify.d.ts +46 -0
- package/dist/session-notify.d.ts.map +1 -0
- package/dist/session-notify.js +115 -0
- package/dist/session-notify.js.map +1 -0
- package/dist/session-read-handlers.d.ts.map +1 -1
- package/dist/session-read-handlers.js +0 -1
- package/dist/session-read-handlers.js.map +1 -1
- package/dist/session-relay.d.ts +361 -0
- package/dist/session-relay.d.ts.map +1 -0
- package/dist/session-relay.js +1471 -0
- package/dist/session-relay.js.map +1 -0
- package/dist/session-salt-agreement.d.ts +0 -7
- package/dist/session-salt-agreement.d.ts.map +1 -1
- package/dist/session-salt-agreement.js +0 -7
- package/dist/session-salt-agreement.js.map +1 -1
- package/dist/session-salts.d.ts +13 -0
- package/dist/session-salts.d.ts.map +1 -1
- package/dist/session-salts.js +13 -0
- package/dist/session-salts.js.map +1 -1
- package/dist/session-seal.d.ts +336 -0
- package/dist/session-seal.d.ts.map +1 -0
- package/dist/session-seal.js +948 -0
- package/dist/session-seal.js.map +1 -0
- package/dist/session-views.d.ts +46 -0
- package/dist/session-views.d.ts.map +1 -0
- package/dist/session-views.js +197 -0
- package/dist/session-views.js.map +1 -0
- package/dist/signal-handlers.d.ts +66 -0
- package/dist/signal-handlers.d.ts.map +1 -0
- package/dist/signal-handlers.js +975 -0
- package/dist/signal-handlers.js.map +1 -0
- package/dist/signaling-wiring.d.ts +100 -0
- package/dist/signaling-wiring.d.ts.map +1 -0
- package/dist/signaling-wiring.js +392 -0
- package/dist/signaling-wiring.js.map +1 -0
- package/dist/start-agent.d.ts +64 -0
- package/dist/start-agent.d.ts.map +1 -0
- package/dist/start-agent.js +136 -0
- package/dist/start-agent.js.map +1 -0
- package/dist/status-handler.d.ts +46 -0
- package/dist/status-handler.d.ts.map +1 -0
- package/dist/status-handler.js +58 -0
- package/dist/status-handler.js.map +1 -0
- package/dist/test-handlers.d.ts +62 -0
- package/dist/test-handlers.d.ts.map +1 -0
- package/dist/test-handlers.js +239 -0
- package/dist/test-handlers.js.map +1 -0
- package/dist/types.d.ts +0 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +1 -1
- package/dist/unresolved-nodes-report.d.ts +14 -0
- package/dist/unresolved-nodes-report.d.ts.map +1 -0
- package/dist/unresolved-nodes-report.js +96 -0
- package/dist/unresolved-nodes-report.js.map +1 -0
- package/dist/who-resolver.d.ts +15 -0
- package/dist/who-resolver.d.ts.map +1 -0
- package/dist/who-resolver.js +46 -0
- package/dist/who-resolver.js.map +1 -0
- package/dist/wire-content-hash.d.ts +0 -2
- package/dist/wire-content-hash.d.ts.map +1 -1
- package/dist/wire-content-hash.js +0 -4
- package/dist/wire-content-hash.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the daemon forgets, and what it says, when an IPC connection closes.
|
|
3
|
+
*
|
|
4
|
+
* Why the close is reported at all — `DOD-M15-IPCVISIBLE-1` — is written below, at the code that
|
|
5
|
+
* builds the report. It is not repeated here: a paragraph kept in two places is one someone corrects
|
|
6
|
+
* in one of them.
|
|
7
|
+
*
|
|
8
|
+
* The three per-connection maps are released by the module that owns them; this is the reporting
|
|
9
|
+
* half, and it returns its context rather than logging its own line, because the IPC server merges
|
|
10
|
+
* it into the single `daemon.ipc.disconnected` entry. A second line under the same name left
|
|
11
|
+
* neither carrying the whole picture and doubled every count.
|
|
12
|
+
*/
|
|
13
|
+
import type { IpcServer } from "./ipc-server.js";
|
|
14
|
+
import type { NotificationDispatcher } from "./notification-dispatcher.js";
|
|
15
|
+
import type { InboundSessionWaiter } from "./inbound-sessions.js";
|
|
16
|
+
export interface DisconnectCleanupDeps {
|
|
17
|
+
ipcServer: IpcServer;
|
|
18
|
+
/** Read this connection's selection before it is forgotten — the log needs what it was attending. */
|
|
19
|
+
getConnState: (connectionId: string) => {
|
|
20
|
+
currentAgent: string | null;
|
|
21
|
+
clientType?: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
/** How many connections still attend an agent, after this one goes. */
|
|
24
|
+
countAttendanceFor: (agentName: string) => number;
|
|
25
|
+
/** Releases the three per-connection maps. Lives with the maps, not here. */
|
|
26
|
+
forgetConnection: (connectionId: string) => void;
|
|
27
|
+
forgetTakeLedger: (connectionId: string) => void;
|
|
28
|
+
/** Callers blocked in `cello_await_session` for an agent, so a dying connection releases them. */
|
|
29
|
+
inboundSessionWaiters: Map<string, InboundSessionWaiter[]>;
|
|
30
|
+
/**
|
|
31
|
+
* ⚠️ A GETTER, AND THE REASON IS NOT THE OBVIOUS ONE. The dispatcher is a `const` 82 lines ABOVE
|
|
32
|
+
* this wiring, so passing it by value would work today. The getter is there so that moving the
|
|
33
|
+
* construction below cannot break the disconnect path silently — the same shape as `getStop` in
|
|
34
|
+
* `ipc-surface.ts`.
|
|
35
|
+
*
|
|
36
|
+
* An earlier version of this comment said the dispatcher was constructed BELOW. It was not, and a
|
|
37
|
+
* false worked example of late binding is worse than none: the rule this order paid for is that a
|
|
38
|
+
* value assigned below a call site must be read through a getter, and the silent shape is a `let`
|
|
39
|
+
* (a `const` crashes loudly on TDZ). Teaching "getter because it is below" from a value that is
|
|
40
|
+
* above hands the next reader the wrong discriminator.
|
|
41
|
+
*/
|
|
42
|
+
getNotificationDispatcher: () => NotificationDispatcher;
|
|
43
|
+
}
|
|
44
|
+
export declare function wireDisconnectCleanup(deps: DisconnectCleanupDeps): void;
|
|
45
|
+
//# sourceMappingURL=disconnect-cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disconnect-cleanup.d.ts","sourceRoot":"","sources":["../src/disconnect-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,qGAAqG;IACrG,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACzG,uEAAuE;IACvE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,6EAA6E;IAC7E,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,kGAAkG;IAClG,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC3D;;;;;;;;;;;OAWG;IACH,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;CACzD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAiEvE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export function wireDisconnectCleanup(deps) {
|
|
2
|
+
const { ipcServer, getConnState, countAttendanceFor, forgetConnection, forgetTakeLedger, inboundSessionWaiters, getNotificationDispatcher, } = deps;
|
|
3
|
+
// MCP-001: Clean up per-connection state when a connection disconnects
|
|
4
|
+
// MCP-002: Also unregister from notification dispatcher
|
|
5
|
+
ipcServer.onDisconnect((connectionId) => {
|
|
6
|
+
/**
|
|
7
|
+
* DOD-M15-IPCVISIBLE-1: SAY THAT IT CLOSED, and say what it was attending.
|
|
8
|
+
*
|
|
9
|
+
* `daemon.ipc.connected` fired on every open and nothing on close, so a live client and a dead
|
|
10
|
+
* one that was never cleaned up looked identical in the log. The attended agent is the field
|
|
11
|
+
* that matters: attendance dropping was silent, and an agent losing its last attendee changes
|
|
12
|
+
* whether away-messages fire and who receives doorbells — so a session that stopped waking is
|
|
13
|
+
* diagnosable from the log rather than by guesswork.
|
|
14
|
+
*/
|
|
15
|
+
const closing = getConnState(connectionId);
|
|
16
|
+
const stillAttending = closing?.currentAgent
|
|
17
|
+
? countAttendanceFor(closing.currentAgent) - 1
|
|
18
|
+
: null;
|
|
19
|
+
// RETURNED, not logged here — `ipcServer` merges this into its single
|
|
20
|
+
// `daemon.ipc.disconnected` line. A second line under the same name left neither carrying the
|
|
21
|
+
// whole picture and doubled every count (review F8).
|
|
22
|
+
const disconnectContext = {
|
|
23
|
+
clientType: closing?.clientType ?? "unknown",
|
|
24
|
+
attendedAgent: closing?.currentAgent ?? null,
|
|
25
|
+
...(stillAttending !== null ? { remainingAttendance: stillAttending } : {}),
|
|
26
|
+
...(stillAttending === 0
|
|
27
|
+
? {
|
|
28
|
+
impact: "that agent has no attending session left — inbound sessions are now answered with " +
|
|
29
|
+
"its away message rather than a live reply, and its doorbells reach nobody",
|
|
30
|
+
}
|
|
31
|
+
: {}),
|
|
32
|
+
};
|
|
33
|
+
// The three per-connection maps are released by the module that owns them; the reasons each
|
|
34
|
+
// must die with its connection live there, beside the containers.
|
|
35
|
+
forgetConnection(connectionId);
|
|
36
|
+
// DOD-COATTEND-VISIBLE-1 (review HIGH): the take ledger is connection-scoped for the SAME
|
|
37
|
+
// reason and must die with the connection too. Leaving it behind made every reconnect look
|
|
38
|
+
// like a theft: a fresh connection starts at cursor -1, so every take a now-dead connection
|
|
39
|
+
// ever recorded sits above that bar and was reported as "another session took it" — on the
|
|
40
|
+
// `cello` CLI, which opens a fresh connection per command, that fired on ordinary use, forever,
|
|
41
|
+
// with no live sibling anywhere. A signal that fires on the normal case is not a signal, and
|
|
42
|
+
// this one would have taught the operator to disbelieve the real theft it exists to announce.
|
|
43
|
+
forgetTakeLedger(connectionId);
|
|
44
|
+
getNotificationDispatcher().unregisterConnection(connectionId);
|
|
45
|
+
// Seam 2 (review H2): evict any cello_await_session waiters owned by this connection.
|
|
46
|
+
// Otherwise enqueueInboundSession would hand the next inbound session to a closed
|
|
47
|
+
// connection's waiter and the event would be lost. deliver(null) clears the waiter's
|
|
48
|
+
// timer and resolves its (now-orphaned) promise as a timeout.
|
|
49
|
+
for (const [agentName, waiters] of inboundSessionWaiters) {
|
|
50
|
+
const survivors = [];
|
|
51
|
+
for (const w of waiters) {
|
|
52
|
+
if (w.connectionId === connectionId)
|
|
53
|
+
w.deliver(null);
|
|
54
|
+
else
|
|
55
|
+
survivors.push(w);
|
|
56
|
+
}
|
|
57
|
+
if (survivors.length > 0)
|
|
58
|
+
inboundSessionWaiters.set(agentName, survivors);
|
|
59
|
+
else
|
|
60
|
+
inboundSessionWaiters.delete(agentName);
|
|
61
|
+
}
|
|
62
|
+
return disconnectContext;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=disconnect-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disconnect-cleanup.js","sourceRoot":"","sources":["../src/disconnect-cleanup.ts"],"names":[],"mappings":"AA0CA,MAAM,UAAU,qBAAqB,CAAC,IAA2B;IAC/D,MAAM,EACJ,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,gBAAgB,EAC/E,qBAAqB,EACrB,yBAAyB,GAC1B,GAAG,IAAI,CAAC;IAET,uEAAuE;IACvE,wDAAwD;IACxD,SAAS,CAAC,YAAY,CAAC,CAAC,YAAY,EAAE,EAAE;QACtC;;;;;;;;WAQG;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,cAAc,GAAG,OAAO,EAAE,YAAY;YAC1C,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC;YAC9C,CAAC,CAAC,IAAI,CAAC;QACT,sEAAsE;QACtE,8FAA8F;QAC9F,qDAAqD;QACrD,MAAM,iBAAiB,GAA4B;YACjD,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,SAAS;YAC5C,aAAa,EAAE,OAAO,EAAE,YAAY,IAAI,IAAI;YAC5C,GAAG,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,cAAc,KAAK,CAAC;gBACtB,CAAC,CAAC;oBACE,MAAM,EACJ,oFAAoF;wBACpF,2EAA2E;iBAC9E;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,4FAA4F;QAC5F,kEAAkE;QAClE,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC/B,0FAA0F;QAC1F,2FAA2F;QAC3F,4FAA4F;QAC5F,2FAA2F;QAC3F,gGAAgG;QAChG,6FAA6F;QAC7F,8FAA8F;QAC9F,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC/B,yBAAyB,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;QAC/D,sFAAsF;QACtF,kFAAkF;QAClF,qFAAqF;QACrF,8DAA8D;QAC9D,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,qBAAqB,EAAE,CAAC;YACzD,MAAM,SAAS,GAAmB,EAAE,CAAC;YACrC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY;oBAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;;oBAChD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,qBAAqB,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;;gBACrE,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,iBAAiB,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReconcileScheduler } from "./document-reconcile-scheduler.js";
|
|
2
|
+
import type { IpcHandler } from "./ipc-server.js";
|
|
3
|
+
import type { Logger } from "./types.js";
|
|
4
|
+
import type { KeyProvider } from "@cello-protocol/crypto";
|
|
5
|
+
import type { SignalingManager } from "@cello-protocol/transport";
|
|
6
|
+
export interface DocumentSurfaceDeps {
|
|
7
|
+
logger: Logger;
|
|
8
|
+
handlers: Map<string, IpcHandler>;
|
|
9
|
+
loadedAgents: ReadonlyArray<{
|
|
10
|
+
name: string;
|
|
11
|
+
pubkey: string;
|
|
12
|
+
keyProvider: KeyProvider;
|
|
13
|
+
}>;
|
|
14
|
+
keyProviders: Map<string, KeyProvider>;
|
|
15
|
+
perConnectionState: ReadonlyMap<string, {
|
|
16
|
+
currentAgent: string | null;
|
|
17
|
+
}>;
|
|
18
|
+
perAgentSignaling: ReadonlyMap<string, {
|
|
19
|
+
signaling: SignalingManager;
|
|
20
|
+
}>;
|
|
21
|
+
resolveCurrentAgent: (connState: {
|
|
22
|
+
currentAgent: string | null;
|
|
23
|
+
} | undefined, explicitAgent?: string) => string | null;
|
|
24
|
+
documentLayer: ReturnType<typeof import("./document-layer.js").createDocumentLayer>;
|
|
25
|
+
documentOwnerKeyFor: (agentName: string) => string | null;
|
|
26
|
+
documentTransportFor: (agentName: string) => ReturnType<typeof import("./document-delivery-transport.js").createDocumentDeliveryTransport>;
|
|
27
|
+
}
|
|
28
|
+
export declare function createDocumentSurface(deps: DocumentSurfaceDeps): {
|
|
29
|
+
reconcileSweepTimer: NodeJS.Timeout;
|
|
30
|
+
reconcileScheduler: ReconcileScheduler;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=document-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-surface.d.ts","sourceRoot":"","sources":["../src/document-surface.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,YAAY,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACxF,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACzE,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IACxE,mBAAmB,EAAE,CAAC,SAAS,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACvH,aAAa,EAAE,UAAU,CAAC,cAAc,qBAAqB,EAAE,mBAAmB,CAAC,CAAC;IACpF,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1D,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,CAAC,cAAc,kCAAkC,EAAE,+BAA+B,CAAC,CAAC;CAC5I;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB;;;EA+I9D"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The document OPERATOR surface, and the sweep that keeps shared documents converging.
|
|
3
|
+
*
|
|
4
|
+
* Registered last of the document wiring, deliberately: this is the only part that can CREATE a
|
|
5
|
+
* document, and everything it creates has to have somewhere to go. Without the inbound path a peer's
|
|
6
|
+
* answer is unroutable; without the delivery worker a published update never leaves.
|
|
7
|
+
*
|
|
8
|
+
* The reconcile sweep travels with it because it is what makes the surface's promise true over time
|
|
9
|
+
* — a document published to a peer who was unreachable is not lost, it is retried on a bound.
|
|
10
|
+
*/
|
|
11
|
+
import { DocumentPublish } from "./document-publish.js";
|
|
12
|
+
import { ReconcileScheduler } from "./document-reconcile-scheduler.js";
|
|
13
|
+
import { registerDocumentHandlers } from "./document-handlers.js";
|
|
14
|
+
export function createDocumentSurface(deps) {
|
|
15
|
+
const { logger, handlers, loadedAgents, keyProviders, perConnectionState, perAgentSignaling, resolveCurrentAgent, documentLayer, documentOwnerKeyFor, documentTransportFor, } = deps;
|
|
16
|
+
// ⚠️ ASSIGNED HERE AND READ ELSEWHERE. Two modules built EARLIER hold getters over the root's
|
|
17
|
+
// `let` for this scheduler; the value is produced below and handed back so the root can set it.
|
|
18
|
+
// Returning it is what keeps those getters correct — they resolve at call time, which is always
|
|
19
|
+
// after this runs.
|
|
20
|
+
let reconcileScheduler;
|
|
21
|
+
// M14 / DOD-DOC-TOOLS-1 — the OPERATOR SURFACE. Registered last of the document wiring, because
|
|
22
|
+
// it is the only part that can create a document, and everything it creates has to have somewhere
|
|
23
|
+
// to go: without the inbound path a peer's answer is unroutable, and without the delivery worker a
|
|
24
|
+
// published update never leaves.
|
|
25
|
+
const documentPublish = new DocumentPublish({
|
|
26
|
+
holdersFor: (ownerAgentId, documentId) => documentLayer.holdersFor(ownerAgentId, documentId),
|
|
27
|
+
governanceFrontierFor: (ownerAgentId, documentId) => documentLayer.governanceFrontierFor(ownerAgentId, documentId),
|
|
28
|
+
store: documentLayer.store,
|
|
29
|
+
engine: documentLayer.engine,
|
|
30
|
+
logger,
|
|
31
|
+
sign: async (ownerAgentId, tbs) => {
|
|
32
|
+
// `ownerAgentId` is the owner KEY here, and keyProviders is keyed by NAME — so it is resolved
|
|
33
|
+
// back through the same map the owner key came from rather than guessed. A miss throws: an
|
|
34
|
+
// unsigned envelope in an append-only log is worse than a failed publish.
|
|
35
|
+
const agentName = loadedAgents.find((a) => a.pubkey?.toLowerCase() === ownerAgentId)?.name;
|
|
36
|
+
const provider = agentName ? keyProviders.get(agentName) : undefined;
|
|
37
|
+
if (!provider) {
|
|
38
|
+
throw new Error(`document_publish_unsigned: no key provider for owner ${ownerAgentId.slice(0, 16)}…, ` +
|
|
39
|
+
`so this update cannot be signed`);
|
|
40
|
+
}
|
|
41
|
+
return provider.sign(tbs);
|
|
42
|
+
},
|
|
43
|
+
// M14-D5: our wire sender id IS the owner key. Kept as its own callback because they are
|
|
44
|
+
// different facts that happen to coincide — see DocumentStore.pendingDeliveries.
|
|
45
|
+
senderIdFor: (ownerAgentId) => ownerAgentId,
|
|
46
|
+
canPublish: (ownerAgentId, documentId) => documentLayer.lifecycle.canPublish(ownerAgentId, documentId),
|
|
47
|
+
// SYNC-P4 (R39's first trigger): each seat gets an initiated reconcile exchange — the
|
|
48
|
+
// envelope rides the exchange's own difference computation. Fire-and-forget by contract.
|
|
49
|
+
nudgeSeats: (ownerAgentId, documentId, seats) => {
|
|
50
|
+
for (const seat of seats) {
|
|
51
|
+
void documentLayer
|
|
52
|
+
.initiateReconcile(ownerAgentId, seat, [documentId])
|
|
53
|
+
.then((sent) => {
|
|
54
|
+
if (!sent.ok) {
|
|
55
|
+
// NOT SILENT (review F3): a lost nudge is legal for correctness (any later
|
|
56
|
+
// exchange recomputes the difference — R40), but until P5's sweeps exist this
|
|
57
|
+
// line is the only trace an operator has for "my edit never arrived".
|
|
58
|
+
logger.warn("document.reconcile.nudge_failed", {
|
|
59
|
+
documentId, peerAgentId: seat, reason: sent.reason,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
.catch((err) => {
|
|
64
|
+
logger.warn("document.reconcile.nudge_failed", {
|
|
65
|
+
documentId, peerAgentId: seat,
|
|
66
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
registerDocumentHandlers({
|
|
73
|
+
handlers,
|
|
74
|
+
logger,
|
|
75
|
+
layer: documentLayer,
|
|
76
|
+
publish: documentPublish,
|
|
77
|
+
transportFor: documentTransportFor,
|
|
78
|
+
resolveAgent: (connectionId, explicit) => resolveCurrentAgent(perConnectionState.get(connectionId), explicit),
|
|
79
|
+
ownerKeyFor: documentOwnerKeyFor,
|
|
80
|
+
sign: async (agentName, tbs) => {
|
|
81
|
+
const provider = keyProviders.get(agentName);
|
|
82
|
+
if (!provider)
|
|
83
|
+
throw new Error(`document_proposal_unsigned: no key provider for ${agentName}`);
|
|
84
|
+
return provider.sign(tbs);
|
|
85
|
+
},
|
|
86
|
+
now: () => Date.now(),
|
|
87
|
+
});
|
|
88
|
+
// SYNC-P5 (R39–R43) — WHEN reconciling is attempted: the periodic sweep and the party-became-
|
|
89
|
+
// reachable trigger. All state volatile (R41); a lost tick costs latency, never correctness.
|
|
90
|
+
reconcileScheduler = new ReconcileScheduler({
|
|
91
|
+
now: () => Date.now(),
|
|
92
|
+
logger,
|
|
93
|
+
sweepTargets: (ownerAgentId) => documentLayer.sweepTargets(ownerAgentId),
|
|
94
|
+
pendingFor: (ownerAgentId, documentId, partyAgentId) => documentLayer.pendingFor(ownerAgentId, documentId, partyAgentId),
|
|
95
|
+
initiateReconcile: (ownerAgentId, peerAgentId, documentIds) => documentLayer.initiateReconcile(ownerAgentId, peerAgentId, documentIds),
|
|
96
|
+
...(Number.isFinite(Number(process.env["CELLO_DOCUMENT_RECONCILE_BACKOFF_MS"])) &&
|
|
97
|
+
Number(process.env["CELLO_DOCUMENT_RECONCILE_BACKOFF_MS"]) >= 250
|
|
98
|
+
? { backoffBaseMs: Number(process.env["CELLO_DOCUMENT_RECONCILE_BACKOFF_MS"]) }
|
|
99
|
+
: {}),
|
|
100
|
+
});
|
|
101
|
+
// Overridable for tests (the delivery tick precedent); floored so a misread env cannot busy-loop.
|
|
102
|
+
const reconcileTickOverride = Number(process.env["CELLO_DOCUMENT_RECONCILE_SWEEP_MS"]);
|
|
103
|
+
const RECONCILE_SWEEP_MS = Number.isFinite(reconcileTickOverride) && reconcileTickOverride >= 250
|
|
104
|
+
? reconcileTickOverride
|
|
105
|
+
: 120_000;
|
|
106
|
+
// Review F2: the guard is TIME-STAMPED, not a bare boolean — a pass that never settles (a
|
|
107
|
+
// dial with no timeout) would otherwise end the sweep silently for the daemon's lifetime,
|
|
108
|
+
// the exact R42 stall one level above the module that fixed it. Past the bound the wedge is
|
|
109
|
+
// WARNED and the guard force-released; the abandoned pass's own scheduler marks are
|
|
110
|
+
// themselves time-bounded, so double-attempts are latency, never correctness.
|
|
111
|
+
const RECONCILE_PASS_BOUND_MS = 5 * 60_000;
|
|
112
|
+
let reconcileSweepStartedAt = null;
|
|
113
|
+
const reconcileSweepTimer = setInterval(() => {
|
|
114
|
+
if (reconcileSweepStartedAt !== null) {
|
|
115
|
+
if (Date.now() - reconcileSweepStartedAt < RECONCILE_PASS_BOUND_MS)
|
|
116
|
+
return;
|
|
117
|
+
logger.warn("document.reconcile.sweep_wedged", {
|
|
118
|
+
heldMs: Date.now() - reconcileSweepStartedAt,
|
|
119
|
+
impact: "a sweep pass never settled; the guard is force-released so sweeping continues",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
reconcileSweepStartedAt = Date.now();
|
|
123
|
+
void (async () => {
|
|
124
|
+
try {
|
|
125
|
+
for (const agentName of perAgentSignaling.keys()) {
|
|
126
|
+
const ownerAgentId = documentOwnerKeyFor(agentName);
|
|
127
|
+
if (ownerAgentId === null)
|
|
128
|
+
continue;
|
|
129
|
+
const result = await reconcileScheduler.sweep(ownerAgentId);
|
|
130
|
+
if (result.attempted > 0 || result.failed > 0) {
|
|
131
|
+
logger.debug("document.reconcile.sweep", { agentName, ...result });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
logger.warn("document.reconcile.sweep_threw", {
|
|
137
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
reconcileSweepStartedAt = null;
|
|
142
|
+
}
|
|
143
|
+
})();
|
|
144
|
+
}, RECONCILE_SWEEP_MS);
|
|
145
|
+
reconcileSweepTimer.unref?.();
|
|
146
|
+
// `documentPublish` is NOT returned: its only consumer is the handler registration inside this
|
|
147
|
+
// module. Returning it would widen the surface for no caller.
|
|
148
|
+
return { reconcileSweepTimer, reconcileScheduler };
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=document-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-surface.js","sourceRoot":"","sources":["../src/document-surface.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type SecurityGatewayClient } from "@cello-protocol/gateway";
|
|
2
|
+
import type { IpcHandler } from "./ipc-server.js";
|
|
3
|
+
import type { SessionNodeManager } from "./session-node-manager.js";
|
|
4
|
+
import type { Logger } from "./types.js";
|
|
5
|
+
import type { LoadedAgent } from "./agent-loader.js";
|
|
6
|
+
import type { KeyProvider } from "@cello-protocol/crypto";
|
|
7
|
+
import type { SignalingManager } from "@cello-protocol/transport";
|
|
8
|
+
import type { NotificationDispatcher } from "./notification-dispatcher.js";
|
|
9
|
+
import type { DiscoveryOutcome } from "./cross-node-negotiation.js";
|
|
10
|
+
export interface DocumentWiringDeps {
|
|
11
|
+
logger: Logger;
|
|
12
|
+
sessionNodeManager: SessionNodeManager;
|
|
13
|
+
/** The LIVE registry — `cello_create_agent` pushes into it, so a new agent works without a restart. */
|
|
14
|
+
loadedAgents: ReadonlyArray<LoadedAgent>;
|
|
15
|
+
keyProviders: Map<string, KeyProvider>;
|
|
16
|
+
/** The gateway itself, not the config that holds it. */
|
|
17
|
+
securityGateway: SecurityGatewayClient;
|
|
18
|
+
/** Where the daemon keeps its data; documents live under it. */
|
|
19
|
+
celloDir: string;
|
|
20
|
+
deliveryOpens: {
|
|
21
|
+
begin: (openerPubkey: string, targetPubkey: string) => () => void;
|
|
22
|
+
};
|
|
23
|
+
pubkeyOfAgent: (name: string) => string;
|
|
24
|
+
openSessionFor: (agentName: string, opts: {
|
|
25
|
+
targetPubkey: string;
|
|
26
|
+
}) => Promise<unknown>;
|
|
27
|
+
perAgentSignaling: Map<string, {
|
|
28
|
+
signaling: SignalingManager;
|
|
29
|
+
}>;
|
|
30
|
+
runDiscoveryLookup: (signaling: SignalingManager, targetHex: string, timeoutMs: number, correlationId: string) => Promise<DiscoveryOutcome>;
|
|
31
|
+
/**
|
|
32
|
+
* ⚠️ A GETTER, NOT THE VALUE. The scheduler is constructed AFTER this wiring — it consumes the
|
|
33
|
+
* layer's sweep targets — so at the moment this module is built the binding is `undefined`.
|
|
34
|
+
* Passing the value captures that `undefined` for the life of the process and
|
|
35
|
+
* `reconcileScheduler?.noteRefusal(...)` becomes a permanent no-op: refusals still log, backoff
|
|
36
|
+
* never applies, and the sweep re-asks immediately. Measured cost of that state, from the
|
|
37
|
+
* scheduler's own notes: 321 attempts against two documents in 85 minutes, refused every time.
|
|
38
|
+
* Optional chaining makes it silent and the `| undefined` in the type makes it legal, so nothing
|
|
39
|
+
* but this comment and the test beside it stands between here and that behaviour.
|
|
40
|
+
*/
|
|
41
|
+
getReconcileScheduler: () => {
|
|
42
|
+
noteRefusal: (ownerAgentId: string, peerAgentId: string, terminal: boolean) => void;
|
|
43
|
+
} | undefined;
|
|
44
|
+
notificationDispatcher: NotificationDispatcher;
|
|
45
|
+
/** ONE other handler, not the map it lives in. */
|
|
46
|
+
getCloseSessionHandler: () => IpcHandler | undefined;
|
|
47
|
+
}
|
|
48
|
+
export declare function createDocumentWiring(deps: DocumentWiringDeps): {
|
|
49
|
+
documentLayer: import("./document-layer.js").DocumentLayer;
|
|
50
|
+
documentOwnerKeyFor: (agentName: string) => string | null;
|
|
51
|
+
documentTransportFor: (agentName: string) => import("./document-delivery-transport.js").DocumentDeliveryTransport;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=document-wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-wiring.d.ts","sourceRoot":"","sources":["../src/document-wiring.ts"],"names":[],"mappings":"AAyBA,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChG,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,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,uGAAuG;IACvG,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACzC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC,wDAAwD;IACxD,eAAe,EAAE,qBAAqB,CAAC;IACvC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE;QAAE,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,IAAI,CAAA;KAAE,CAAC;IACrF,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxF,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAChE,kBAAkB,EAAE,CAClB,SAAS,EAAE,gBAAgB,EAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,KAClB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B;;;;;;;;;OASG;IACH,qBAAqB,EAAE,MAAM;QAAE,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;IACjI,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,kDAAkD;IAClD,sBAAsB,EAAE,MAAM,UAAU,GAAG,SAAS,CAAC;CACtD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB;;qCAuBnB,MAAM,KAAG,MAAM,GAAG,IAAI;sCAgJrB,MAAM;EAqJhD"}
|