@cello-protocol/daemon 0.0.19 → 0.0.20
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/daemon.d.ts.map +1 -1
- package/dist/daemon.js +68 -20
- package/dist/daemon.js.map +1 -1
- package/dist/session-ceremony.d.ts +26 -13
- package/dist/session-ceremony.d.ts.map +1 -1
- package/dist/session-ceremony.js +36 -18
- package/dist/session-ceremony.js.map +1 -1
- package/dist/session-node-manager.d.ts +14 -0
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +47 -0
- package/dist/session-node-manager.js.map +1 -1
- package/package.json +3 -3
package/dist/daemon.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAQrB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAqB7G,OAAO,KAAK,EAAE,kBAAkB,EAA+C,MAAM,yBAAyB,CAAC;AAM/G,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAqInF,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,oBAAoB,CAAC;IAClC;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,CAAC;IAC5C;;;;;;;;OAQG;IACH,gBAAgB,IAAI,SAAS,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,oBAAoB,IAAI,kBAAkB,CAAC;IAC3C;;;OAGG;IACH,iBAAiB,IAAI,eAAe,CAAC;CACtC;AAyCD,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EAQrB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAqB7G,OAAO,KAAK,EAAE,kBAAkB,EAA+C,MAAM,yBAAyB,CAAC;AAM/G,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAqInF,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,oBAAoB,CAAC;IAClC;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,CAAC;IAC5C;;;;;;;;OAQG;IACH,gBAAgB,IAAI,SAAS,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,oBAAoB,IAAI,kBAAkB,CAAC;IAC3C;;;OAGG;IACH,iBAAiB,IAAI,eAAe,CAAC;CACtC;AAyCD,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAi9H7E"}
|
package/dist/daemon.js
CHANGED
|
@@ -1576,7 +1576,14 @@ export async function startDaemon(config) {
|
|
|
1576
1576
|
logger.error("session.sealed.signature.invalid", { sessionId: sidHex, reason: verdict.reason });
|
|
1577
1577
|
return;
|
|
1578
1578
|
}
|
|
1579
|
-
|
|
1579
|
+
// F2-a: on verified:false, surface WHY (signer_key_not_held / no_frost_share / …) so this
|
|
1580
|
+
// event can never be mistaken for a tolerated failed check. A real failure took the early
|
|
1581
|
+
// return above (session.sealed.signature.invalid) and never reaches here.
|
|
1582
|
+
logger.info("session.sealed.signature.checked", {
|
|
1583
|
+
sessionId: sidHex,
|
|
1584
|
+
verified: verdict.verified,
|
|
1585
|
+
...(verdict.verified ? {} : { reason: verdict.reason }),
|
|
1586
|
+
});
|
|
1580
1587
|
}
|
|
1581
1588
|
// M7-SESSION-004 (AC-005): normalise the wire legibility (Uint8Array pubkeys → hex) into a
|
|
1582
1589
|
// JSON-safe certificate and persist it with the sealed record so it survives a restart and
|
|
@@ -1878,9 +1885,10 @@ export async function startDaemon(config) {
|
|
|
1878
1885
|
// NOTE: cello_await_session is NOT in this stub list — Seam 2 registers a real
|
|
1879
1886
|
// handler for it below (inbound session establishment), with its own inline
|
|
1880
1887
|
// no_current_agent guard.
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1888
|
+
// F1-a2: cello_receive_session is NO LONGER stubbed here — it is registered below as a true
|
|
1889
|
+
// alias of the real (blocking) cello_receive handler. Kept as an (empty) extension point for
|
|
1890
|
+
// future tools that need the plain no_current_agent guard without their own handler.
|
|
1891
|
+
const SESSION_TOOLS_REQUIRING_AGENT = [];
|
|
1884
1892
|
const NO_CURRENT_AGENT_RESPONSE = {
|
|
1885
1893
|
ok: false,
|
|
1886
1894
|
reason: "no_current_agent",
|
|
@@ -3671,35 +3679,75 @@ export async function startDaemon(config) {
|
|
|
3671
3679
|
void newRootHex;
|
|
3672
3680
|
return { ok: true, sequence_number: leafIndex };
|
|
3673
3681
|
});
|
|
3674
|
-
// ─── CELLO-M7-DAEMON-004: cello_receive (
|
|
3675
|
-
|
|
3682
|
+
// ─── CELLO-M7-DAEMON-004 / F1-a: cello_receive (BLOCKING, session-scoped) ────────
|
|
3683
|
+
// F1-a fix: the daemon port had dropped the blocking receive (the handler was a
|
|
3684
|
+
// non-blocking buf.shift and cello_receive_session was a not_implemented stub). It now
|
|
3685
|
+
// BLOCKS up to timeout_ms, polling the received-content buffer — resolved by the next
|
|
3686
|
+
// arrival, a terminal seal answer (F1-b), or timeout. This is the "blocking receive
|
|
3687
|
+
// variant" the guidance names. Registered under both cello_receive and cello_receive_session
|
|
3688
|
+
// (F1-a2: one implementation, both names — the redundant tools are collapsed).
|
|
3689
|
+
const RECEIVE_DEFAULT_TIMEOUT_MS = 30000; // matches the cello-mcp shim's documented default
|
|
3690
|
+
const handleReceive = async (params, connectionId) => {
|
|
3676
3691
|
const connState = perConnectionState.get(connectionId);
|
|
3677
3692
|
if (!connState || !connState.currentAgent)
|
|
3678
3693
|
return NO_CURRENT_AGENT_RESPONSE;
|
|
3679
|
-
|
|
3694
|
+
const agentName = connState.currentAgent;
|
|
3695
|
+
// Read the snake_case public field cello-mcp.ts actually sends.
|
|
3680
3696
|
const sessionId = params?.session_id;
|
|
3681
3697
|
if (!sessionId) {
|
|
3682
3698
|
return { ok: false, reason: "missing_params", guidance: "Provide 'session_id' (hex) to receive content for a specific session." };
|
|
3683
3699
|
}
|
|
3684
|
-
const record = sessionNodeManager.getSessionRecord(
|
|
3700
|
+
const record = sessionNodeManager.getSessionRecord(agentName, sessionId);
|
|
3685
3701
|
if (!record) {
|
|
3686
3702
|
return { ok: false, reason: "session_not_found", guidance: "No session found with this ID. Check cello_list_sessions." };
|
|
3687
3703
|
}
|
|
3688
|
-
if (record.agent_name !==
|
|
3704
|
+
if (record.agent_name !== agentName) {
|
|
3689
3705
|
return { ok: false, reason: "session_not_owned", guidance: "This session belongs to a different agent. Call cello_use_agent to switch to the agent that owns it, then retry." };
|
|
3690
3706
|
}
|
|
3691
|
-
const
|
|
3692
|
-
|
|
3693
|
-
|
|
3707
|
+
const rawTimeout = params?.timeout_ms;
|
|
3708
|
+
const timeoutMs = typeof rawTimeout === "number" && Number.isFinite(rawTimeout) && rawTimeout >= 0
|
|
3709
|
+
? rawTimeout
|
|
3710
|
+
: RECEIVE_DEFAULT_TIMEOUT_MS;
|
|
3711
|
+
const deadline = Date.now() + timeoutMs;
|
|
3712
|
+
for (;;) {
|
|
3713
|
+
// 1) Deliverable content wins — drain one buffered message per call (FIFO).
|
|
3714
|
+
const entry = sessionNodeManager.takeReceivedContent(agentName, sessionId);
|
|
3715
|
+
if (entry) {
|
|
3716
|
+
return {
|
|
3717
|
+
ok: true,
|
|
3718
|
+
content: Buffer.from(entry.contentHex, "hex").toString("utf8"),
|
|
3719
|
+
sessionId,
|
|
3720
|
+
sequence_number: entry.sequenceNumber,
|
|
3721
|
+
senderPubkey: entry.senderPubkey,
|
|
3722
|
+
};
|
|
3723
|
+
}
|
|
3724
|
+
// 2) F1-b: the session sealed while we were (or before we started) waiting — return the
|
|
3725
|
+
// terminal answer instead of hanging to timeout. unread_count reports messages that
|
|
3726
|
+
// were evicted unread (still durable — recoverable via cello_get_transcript).
|
|
3727
|
+
const terminal = sessionNodeManager.peekTerminalMarker(agentName, sessionId);
|
|
3728
|
+
if (terminal) {
|
|
3729
|
+
const sealedRoot = sessionNodeManager.getSealedRootHex(agentName, sessionId);
|
|
3730
|
+
return {
|
|
3731
|
+
ok: true,
|
|
3732
|
+
type: "session_sealed",
|
|
3733
|
+
session_id: sessionId,
|
|
3734
|
+
...(sealedRoot ? { sealed_root: sealedRoot } : {}),
|
|
3735
|
+
unread_count: terminal.unreadCount,
|
|
3736
|
+
guidance: terminal.unreadCount > 0
|
|
3737
|
+
? `The session has been sealed by both parties. ${terminal.unreadCount} message(s) arrived that were not read live — call cello_get_transcript to retrieve the full sealed history. No further actions are required on this session.`
|
|
3738
|
+
: "The session has been sealed by both parties. The full history is available via cello_get_transcript. No further actions are required on this session.",
|
|
3739
|
+
};
|
|
3740
|
+
}
|
|
3741
|
+
// 3) Out of time — non-blocking-equivalent empty answer.
|
|
3742
|
+
const remaining = deadline - Date.now();
|
|
3743
|
+
if (remaining <= 0) {
|
|
3744
|
+
return { ok: true, content: null, guidance: "No content arrived within timeout_ms. Call cello_receive again to keep waiting, or read cello_get_transcript for the full session history." };
|
|
3745
|
+
}
|
|
3746
|
+
await new Promise((r) => setTimeout(r, Math.min(20, remaining)));
|
|
3694
3747
|
}
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
sessionId,
|
|
3699
|
-
sequence_number: entry.sequenceNumber,
|
|
3700
|
-
senderPubkey: entry.senderPubkey,
|
|
3701
|
-
};
|
|
3702
|
-
});
|
|
3748
|
+
};
|
|
3749
|
+
handlers.set("cello_receive", handleReceive);
|
|
3750
|
+
handlers.set("cello_receive_session", handleReceive);
|
|
3703
3751
|
let shutdownPromise = null;
|
|
3704
3752
|
handlers.set("shutdown", async (_params, _connectionId) => {
|
|
3705
3753
|
if (!shutdownPromise) {
|