@cello-protocol/daemon 0.0.40 → 0.0.42
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 +45 -5
- package/dist/daemon.js.map +1 -1
- package/dist/session-ceremony.d.ts.map +1 -1
- package/dist/session-ceremony.js +56 -5
- package/dist/session-ceremony.js.map +1 -1
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +76 -13
- package/dist/session-node-manager.js.map +1 -1
- package/package.json +2 -2
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;AAQ/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsB7G,OAAO,KAAK,EAAE,kBAAkB,EAA+C,MAAM,yBAAyB,CAAC;AAQ/G,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AA0InF,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;AA2CD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAE1D,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;AAQ/D,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsB7G,OAAO,KAAK,EAAE,kBAAkB,EAA+C,MAAM,yBAAyB,CAAC;AAQ/G,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AA0InF,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;AA2CD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAE1D,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAktL7E"}
|
package/dist/daemon.js
CHANGED
|
@@ -4117,6 +4117,7 @@ export async function startDaemon(config) {
|
|
|
4117
4117
|
participantAPubkeyHex,
|
|
4118
4118
|
participantBPubkeyHex,
|
|
4119
4119
|
initiatorPeerId: typeof a["initiator_session_peer_id"] === "string" ? a["initiator_session_peer_id"] : "",
|
|
4120
|
+
counterpartySessionPeerId: typeof a["counterparty_session_peer_id"] === "string" ? a["counterparty_session_peer_id"] : null,
|
|
4120
4121
|
sessionTimestamp: typeof a["session_timestamp"] === "number" ? a["session_timestamp"] : 0,
|
|
4121
4122
|
signatureType: typeof a["signature_type"] === "string" ? a["signature_type"] : null,
|
|
4122
4123
|
// M7 legibility-TBS-binding (responder verify): the FROST-signed assignment embeds the
|
|
@@ -4321,6 +4322,22 @@ export async function startDaemon(config) {
|
|
|
4321
4322
|
});
|
|
4322
4323
|
return;
|
|
4323
4324
|
}
|
|
4325
|
+
// DOD-INBOUND-GUARD-1 (D3): the receive-side mirror of the initiator's F13 guard (~3189).
|
|
4326
|
+
// An empty counterparty endpoint means the offer-accept never happened (this agent's standing
|
|
4327
|
+
// receiver was not up when the directory's session_offer arrived) and the directory signed the
|
|
4328
|
+
// assignment anyway, with "empty defaults". The initiator refuses that assignment and creates
|
|
4329
|
+
// NO session — accepting it here builds a phantom session whose away-reply lands in the
|
|
4330
|
+
// initiator's transcript with no session row: permanently unread AND unreadable. Refuse it
|
|
4331
|
+
// loudly, before any session state exists. Nothing legitimate is lost — a session whose
|
|
4332
|
+
// initiator has no address to dial is unusable by construction.
|
|
4333
|
+
if (!parsed.counterpartySessionPeerId) {
|
|
4334
|
+
logger.warn("session.inbound.assignment.incomplete", {
|
|
4335
|
+
agentName: localAgent.name,
|
|
4336
|
+
sessionId: parsed.sessionIdHex,
|
|
4337
|
+
correlationId,
|
|
4338
|
+
});
|
|
4339
|
+
return;
|
|
4340
|
+
}
|
|
4324
4341
|
// M1: idempotency — a retransmitted assignment for an already-known session (persisted
|
|
4325
4342
|
// row OR currently in flight) must not double-accept (orphaned node) or double-enqueue.
|
|
4326
4343
|
if (inboundInFlight.has(parsed.sessionIdHex) || sessionNodeManager.getSessionRecord(localAgent.name, parsed.sessionIdHex)) {
|
|
@@ -5151,12 +5168,22 @@ export async function startDaemon(config) {
|
|
|
5151
5168
|
return { ok: false, reason: "missing_params", guidance: "Provide 'session_id' (hex) to receive content for a specific session." };
|
|
5152
5169
|
}
|
|
5153
5170
|
const record = sessionNodeManager.getSessionRecord(agentName, sessionId);
|
|
5171
|
+
// DOD-UNREAD-1 D4b: a TRANSCRIPT-ONLY session — received rows exist but no sessions row (the
|
|
5172
|
+
// pre-D3/D4a phantom residue: the counterparty's reply landed while this side refused the
|
|
5173
|
+
// session). Those rows are counted unread by getUnreadSummary, so cello_receive MUST be able
|
|
5174
|
+
// to read them or the badge can never clear. Reading is a transcript operation: the since_seq
|
|
5175
|
+
// catch-up below works from the durable transcript alone. Only a session with NEITHER a row
|
|
5176
|
+
// NOR transcript rows is truly not found.
|
|
5177
|
+
let transcriptOnly = false;
|
|
5154
5178
|
if (!record) {
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5179
|
+
if (sessionNodeManager.readTranscript(agentName, sessionId).messages.length === 0) {
|
|
5180
|
+
return { ok: false, reason: "session_not_found", guidance: "No session found with this ID. Check cello_list_sessions." };
|
|
5181
|
+
}
|
|
5182
|
+
transcriptOnly = true;
|
|
5159
5183
|
}
|
|
5184
|
+
// (D4 review F3: the old `record.agent_name !== agentName` → session_not_owned branch was dead
|
|
5185
|
+
// code — getSessionRecord is keyed by (agent_name, session_id), so a record can never belong to
|
|
5186
|
+
// a different agent. A cross-agent session id simply has no record under this agent.)
|
|
5160
5187
|
// M8C-SINCESEQ-1: stateless catch-up. When since_seq is provided, return a BATCH of received
|
|
5161
5188
|
// transcript messages with sequence > since_seq (durable transcript, not the ephemeral buffer —
|
|
5162
5189
|
// so concurrent arrivals don't shift what a given since_seq returns; no replay race). Replaces
|
|
@@ -5166,7 +5193,9 @@ export async function startDaemon(config) {
|
|
|
5166
5193
|
const rawSince = params?.since_seq;
|
|
5167
5194
|
if (typeof rawSince === "number" && Number.isFinite(rawSince)) {
|
|
5168
5195
|
const sinceSeq = rawSince;
|
|
5169
|
-
|
|
5196
|
+
// D4b AC2: a transcript-only session has no record to attribute from — `from` is null,
|
|
5197
|
+
// NEVER the string "unknown" (the transcript stores no counterparty; don't invent one).
|
|
5198
|
+
const from = record ? record.counterparty_pubkey : null;
|
|
5170
5199
|
const { messages } = sessionNodeManager.readTranscript(agentName, sessionId);
|
|
5171
5200
|
const received = messages.filter((m) => m.direction === "received" && m.sequence > sinceSeq);
|
|
5172
5201
|
if (received.length > 0) {
|
|
@@ -5187,6 +5216,17 @@ export async function startDaemon(config) {
|
|
|
5187
5216
|
messages: received.map((m) => ({ sequence: m.sequence, content: m.text, from })),
|
|
5188
5217
|
};
|
|
5189
5218
|
}
|
|
5219
|
+
// D4b AC3: the plain (blocking) receive waits on a LIVE session's buffer — a transcript-only
|
|
5220
|
+
// session has no live node and nothing will ever arrive. Waiting to a null timeout would be
|
|
5221
|
+
// misleading and session_not_found would be a lie (the transcript exists). A distinct reason
|
|
5222
|
+
// points the caller at the read that works.
|
|
5223
|
+
if (transcriptOnly) {
|
|
5224
|
+
return {
|
|
5225
|
+
ok: false,
|
|
5226
|
+
reason: "session_not_live",
|
|
5227
|
+
guidance: "This session exists only as a durable transcript (no live session — it was never established or predates this daemon). Read it with cello_receive { since_seq } (e.g. since_seq: -1 for everything) or cello_get_transcript.",
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5190
5230
|
const rawTimeout = params?.timeout_ms;
|
|
5191
5231
|
const timeoutMs = typeof rawTimeout === "number" && Number.isFinite(rawTimeout) && rawTimeout >= 0
|
|
5192
5232
|
? rawTimeout
|