@moxt-ai/mobius 0.0.153 → 0.0.155
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/cli.js +34 -490
- package/dist/cli.js.map +4 -4
- package/dist/daemon-turn-registry.d.ts +13 -13
- package/dist/index.js +33 -489
- package/dist/index.js.map +4 -4
- package/dist/relay-connection/run-relay-connection.d.ts.map +1 -1
- package/dist/relay-connection/run-relay-connection.js +2 -15
- package/dist/relay-connection/run-relay-connection.js.map +1 -1
- package/dist/relay-connection/session-event-publisher.d.ts +4 -10
- package/dist/relay-connection/session-event-publisher.d.ts.map +1 -1
- package/dist/relay-connection/session-event-publisher.js +26 -148
- package/dist/relay-connection/session-event-publisher.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +1 -3
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +39 -495
- package/dist/runtime.js.map +4 -4
- package/package.json +1 -1
- package/dist/relay-connection/session-event-outbox.d.ts +0 -20
- package/dist/relay-connection/session-event-outbox.d.ts.map +0 -1
- package/dist/relay-connection/session-event-outbox.js +0 -243
- package/dist/relay-connection/session-event-outbox.js.map +0 -1
package/dist/runtime.js
CHANGED
|
@@ -20741,16 +20741,8 @@ function decodeSessionQueuedEvent(encoded) {
|
|
|
20741
20741
|
function decodeRuntimeLivenessReadyEvent(encoded) {
|
|
20742
20742
|
const value = parseJson2(encoded);
|
|
20743
20743
|
assertKind(value, RUNTIME_LIVENESS_READY_KIND);
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
20747
|
-
}
|
|
20748
|
-
assertExactKeys(value, ["kind", "sessionEventDelivery"]);
|
|
20749
|
-
const sessionEventDelivery = readString(value, "sessionEventDelivery", 32);
|
|
20750
|
-
if (sessionEventDelivery !== "reliable-v1") {
|
|
20751
|
-
throw new ProtocolMessageError("Unsupported Session event delivery mode");
|
|
20752
|
-
}
|
|
20753
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND, sessionEventDelivery };
|
|
20744
|
+
assertExactKeys(value, ["kind"]);
|
|
20745
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
20754
20746
|
}
|
|
20755
20747
|
function decodeRuntimeHeartbeatEvent(encoded) {
|
|
20756
20748
|
const value = parseJson2(encoded);
|
|
@@ -21217,60 +21209,13 @@ var encodeNativeSessionCancel = (value) => JSON.stringify(nativeSessionCancelSch
|
|
|
21217
21209
|
|
|
21218
21210
|
// ../protocol/src/session-events.ts
|
|
21219
21211
|
var SESSION_EVENT_KIND = "session.event";
|
|
21220
|
-
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
21221
|
-
var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
|
|
21222
|
-
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
21223
21212
|
var SESSION_FORKED_KIND = "session.forked";
|
|
21224
|
-
var SessionEventRejectionCode = {
|
|
21225
|
-
IdempotencyConflict: "idempotency_conflict",
|
|
21226
|
-
InvalidEvent: "invalid_event",
|
|
21227
|
-
RecordingRejected: "recording_rejected"
|
|
21228
|
-
};
|
|
21229
21213
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
21230
|
-
var
|
|
21231
|
-
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21232
|
-
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21233
|
-
sessionId: identifierStringSchema
|
|
21234
|
-
}).readonly();
|
|
21235
|
-
var reliableDeliverySchema = external_exports.strictObject({
|
|
21236
|
-
eventId: identifierStringSchema,
|
|
21237
|
-
kind: external_exports.literal("reliable"),
|
|
21238
|
-
sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
|
|
21239
|
-
streamId: identifierStringSchema
|
|
21240
|
-
}).readonly();
|
|
21241
|
-
var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
|
|
21242
|
-
delivery: reliableDeliverySchema,
|
|
21214
|
+
var sessionEventEnvelopeSchema = external_exports.strictObject({
|
|
21243
21215
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21244
21216
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21245
21217
|
sessionId: identifierStringSchema
|
|
21246
21218
|
}).readonly();
|
|
21247
|
-
var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
|
|
21248
|
-
var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
21249
|
-
external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
|
|
21250
|
-
external_exports.strictObject({
|
|
21251
|
-
kind: external_exports.literal("recorded"),
|
|
21252
|
-
providerId: identifierStringSchema,
|
|
21253
|
-
recordingEpoch: identifierStringSchema
|
|
21254
|
-
}).readonly()
|
|
21255
|
-
]);
|
|
21256
|
-
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
21257
|
-
eventId: identifierStringSchema,
|
|
21258
|
-
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
21259
|
-
outcome: acknowledgementOutcomeSchema,
|
|
21260
|
-
sessionId: identifierStringSchema
|
|
21261
|
-
}).readonly();
|
|
21262
|
-
var eventDeferredSchema = external_exports.strictObject({
|
|
21263
|
-
eventId: identifierStringSchema,
|
|
21264
|
-
kind: external_exports.literal(SESSION_EVENT_DEFERRED_KIND),
|
|
21265
|
-
retryAfterMilliseconds: external_exports.number().int().min(100).max(6e4),
|
|
21266
|
-
sessionId: identifierStringSchema
|
|
21267
|
-
}).readonly();
|
|
21268
|
-
var eventRejectedSchema = external_exports.strictObject({
|
|
21269
|
-
code: external_exports.enum(SessionEventRejectionCode),
|
|
21270
|
-
eventId: identifierStringSchema,
|
|
21271
|
-
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
21272
|
-
sessionId: identifierStringSchema
|
|
21273
|
-
}).readonly();
|
|
21274
21219
|
var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
|
|
21275
21220
|
var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
|
|
21276
21221
|
var sessionForkedSchema = external_exports.strictObject({
|
|
@@ -21303,14 +21248,8 @@ var encode4 = (message, schema) => {
|
|
|
21303
21248
|
}
|
|
21304
21249
|
return JSON.stringify(decoded.data);
|
|
21305
21250
|
};
|
|
21306
|
-
var decodeSessionEventEnvelope = (encoded) => decode5(encoded,
|
|
21307
|
-
var encodeSessionEventEnvelope = (message) => encode4(message,
|
|
21308
|
-
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
21309
|
-
var encodeSessionEventAcknowledgement = (message) => encode4(message, eventAcknowledgementSchema);
|
|
21310
|
-
var decodeSessionEventDeferred = (encoded) => decode5(encoded, eventDeferredSchema);
|
|
21311
|
-
var encodeSessionEventDeferred = (message) => encode4(message, eventDeferredSchema);
|
|
21312
|
-
var decodeSessionEventRejected = (encoded) => decode5(encoded, eventRejectedSchema);
|
|
21313
|
-
var encodeSessionEventRejected = (message) => encode4(message, eventRejectedSchema);
|
|
21251
|
+
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, sessionEventEnvelopeSchema);
|
|
21252
|
+
var encodeSessionEventEnvelope = (message) => encode4(message, sessionEventEnvelopeSchema);
|
|
21314
21253
|
function decodeRecordedSessionEvent(encoded) {
|
|
21315
21254
|
const kind = decodeMessageKind(encoded);
|
|
21316
21255
|
switch (kind) {
|
|
@@ -21484,21 +21423,6 @@ var serviceToDaemonSignatures = {
|
|
|
21484
21423
|
encodeSessionElicitationRespondCommand,
|
|
21485
21424
|
decodeSessionElicitationRespondCommand
|
|
21486
21425
|
),
|
|
21487
|
-
[SESSION_EVENT_ACK_KIND]: defineMessageSignature(
|
|
21488
|
-
SESSION_EVENT_ACK_KIND,
|
|
21489
|
-
encodeSessionEventAcknowledgement,
|
|
21490
|
-
decodeSessionEventAcknowledgement
|
|
21491
|
-
),
|
|
21492
|
-
[SESSION_EVENT_DEFERRED_KIND]: defineMessageSignature(
|
|
21493
|
-
SESSION_EVENT_DEFERRED_KIND,
|
|
21494
|
-
encodeSessionEventDeferred,
|
|
21495
|
-
decodeSessionEventDeferred
|
|
21496
|
-
),
|
|
21497
|
-
[SESSION_EVENT_REJECTED_KIND]: defineMessageSignature(
|
|
21498
|
-
SESSION_EVENT_REJECTED_KIND,
|
|
21499
|
-
encodeSessionEventRejected,
|
|
21500
|
-
decodeSessionEventRejected
|
|
21501
|
-
),
|
|
21502
21426
|
[SESSION_LIVE_HISTORY_LOAD_KIND]: defineMessageSignature(
|
|
21503
21427
|
SESSION_LIVE_HISTORY_LOAD_KIND,
|
|
21504
21428
|
encodeSessionLiveHistoryLoad,
|
|
@@ -26793,7 +26717,7 @@ function createDaemonConfig(connection, agents = [], installableAgents = [], loc
|
|
|
26793
26717
|
}
|
|
26794
26718
|
|
|
26795
26719
|
// src/run-daemon.ts
|
|
26796
|
-
import { createHash as createHash5, randomUUID as
|
|
26720
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "node:crypto";
|
|
26797
26721
|
import { join as join17 } from "node:path";
|
|
26798
26722
|
import { styleText } from "node:util";
|
|
26799
26723
|
|
|
@@ -42479,7 +42403,6 @@ async function runRelayConnection({
|
|
|
42479
42403
|
}) {
|
|
42480
42404
|
const relayUrl = new URL(config2.relayUrl);
|
|
42481
42405
|
relayUrl.searchParams.set("liveness", "1");
|
|
42482
|
-
relayUrl.searchParams.set("sessionEventDelivery", "reliable-v1");
|
|
42483
42406
|
const socket = await connectRelay(relayUrl, signal);
|
|
42484
42407
|
diagnostics.connectionOpened(connectionEpoch);
|
|
42485
42408
|
const connectionController = new AbortController();
|
|
@@ -42599,10 +42522,7 @@ async function runRelayConnection({
|
|
|
42599
42522
|
const message = decodeServiceToDaemonMessage(encoded);
|
|
42600
42523
|
const kind = message.kind;
|
|
42601
42524
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
42602
|
-
publisher.connect(
|
|
42603
|
-
socket,
|
|
42604
|
-
message.sessionEventDelivery === "reliable-v1" ? "reliable" : "ephemeral"
|
|
42605
|
-
);
|
|
42525
|
+
publisher.connect(socket);
|
|
42606
42526
|
connectionLiveness.start();
|
|
42607
42527
|
return;
|
|
42608
42528
|
}
|
|
@@ -42610,18 +42530,6 @@ async function runRelayConnection({
|
|
|
42610
42530
|
connectionLiveness.acknowledge(message);
|
|
42611
42531
|
return;
|
|
42612
42532
|
}
|
|
42613
|
-
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
42614
|
-
publisher.acknowledge(message);
|
|
42615
|
-
return;
|
|
42616
|
-
}
|
|
42617
|
-
if (kind === SESSION_EVENT_DEFERRED_KIND) {
|
|
42618
|
-
publisher.defer(message);
|
|
42619
|
-
return;
|
|
42620
|
-
}
|
|
42621
|
-
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
42622
|
-
publisher.quarantine(message);
|
|
42623
|
-
return;
|
|
42624
|
-
}
|
|
42625
42533
|
commands.handle(message);
|
|
42626
42534
|
} catch (error62) {
|
|
42627
42535
|
console.error("Mobius daemon rejected a message", error62);
|
|
@@ -42646,404 +42554,44 @@ async function runRelayConnection({
|
|
|
42646
42554
|
}
|
|
42647
42555
|
}
|
|
42648
42556
|
|
|
42649
|
-
// src/relay-connection/session-event-outbox.ts
|
|
42650
|
-
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
42651
|
-
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
42652
|
-
import { dirname as dirname5 } from "node:path";
|
|
42653
|
-
import { DatabaseSync } from "node:sqlite";
|
|
42654
|
-
var DEFAULT_STANDARD_EVENT_BYTES = 96 * 1024 * 1024;
|
|
42655
|
-
var DEFAULT_CRITICAL_EVENT_BYTES = 128 * 1024 * 1024;
|
|
42656
|
-
var MAX_DEAD_LETTERS = 1024;
|
|
42657
|
-
var DEFAULT_LIMITS = {
|
|
42658
|
-
criticalEventBytes: DEFAULT_CRITICAL_EVENT_BYTES,
|
|
42659
|
-
standardEventBytes: DEFAULT_STANDARD_EVENT_BYTES
|
|
42660
|
-
};
|
|
42661
|
-
var SessionEventOutboxCapacityError = class extends Error {
|
|
42662
|
-
code = "session_event_outbox_full";
|
|
42663
|
-
constructor() {
|
|
42664
|
-
super("The persistent Session event outbox is full");
|
|
42665
|
-
this.name = "SessionEventOutboxCapacityError";
|
|
42666
|
-
}
|
|
42667
|
-
};
|
|
42668
|
-
function rowNumber(row, field) {
|
|
42669
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
42670
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
42671
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
42672
|
-
}
|
|
42673
|
-
return value;
|
|
42674
|
-
}
|
|
42675
|
-
function rowString(row, field) {
|
|
42676
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
42677
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
42678
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
42679
|
-
}
|
|
42680
|
-
return value;
|
|
42681
|
-
}
|
|
42682
|
-
function validateLimits(limits) {
|
|
42683
|
-
if (!Number.isSafeInteger(limits.standardEventBytes) || limits.standardEventBytes < 1 || !Number.isSafeInteger(limits.criticalEventBytes) || limits.criticalEventBytes < limits.standardEventBytes) {
|
|
42684
|
-
throw new Error("Session event outbox limits are invalid");
|
|
42685
|
-
}
|
|
42686
|
-
}
|
|
42687
|
-
var SessionEventOutbox = class {
|
|
42688
|
-
#database;
|
|
42689
|
-
#limits;
|
|
42690
|
-
constructor(path2, limits = DEFAULT_LIMITS) {
|
|
42691
|
-
validateLimits(limits);
|
|
42692
|
-
mkdirSync3(dirname5(path2), { mode: 448, recursive: true });
|
|
42693
|
-
this.#limits = limits;
|
|
42694
|
-
this.#database = new DatabaseSync(path2);
|
|
42695
|
-
this.#database.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; PRAGMA busy_timeout = 5000;");
|
|
42696
|
-
this.#database.exec(`
|
|
42697
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
42698
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
42699
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
42700
|
-
session_id TEXT NOT NULL,
|
|
42701
|
-
source_seq INTEGER NOT NULL UNIQUE,
|
|
42702
|
-
byte_length INTEGER NOT NULL,
|
|
42703
|
-
envelope_json TEXT NOT NULL
|
|
42704
|
-
) STRICT;
|
|
42705
|
-
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
42706
|
-
ON relay_session_event_outbox(source_seq);
|
|
42707
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
42708
|
-
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
42709
|
-
stream_id TEXT NOT NULL,
|
|
42710
|
-
next_source_seq INTEGER NOT NULL,
|
|
42711
|
-
total_bytes INTEGER NOT NULL
|
|
42712
|
-
) STRICT;
|
|
42713
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
42714
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
42715
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
42716
|
-
session_id TEXT NOT NULL,
|
|
42717
|
-
rejection_code TEXT NOT NULL,
|
|
42718
|
-
envelope_json TEXT NOT NULL
|
|
42719
|
-
) STRICT;
|
|
42720
|
-
`);
|
|
42721
|
-
this.#database.prepare(
|
|
42722
|
-
`INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
42723
|
-
singleton, stream_id, next_source_seq, total_bytes
|
|
42724
|
-
) VALUES (1, ?, 1, 0)`
|
|
42725
|
-
).run(randomUUID6());
|
|
42726
|
-
}
|
|
42727
|
-
acknowledge = (acknowledgement) => this.#remove(acknowledgement.eventId, acknowledgement.sessionId);
|
|
42728
|
-
close = () => {
|
|
42729
|
-
this.#database.close();
|
|
42730
|
-
};
|
|
42731
|
-
enqueue = (sessionId, payload, critical) => {
|
|
42732
|
-
const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
|
|
42733
|
-
if (envelope2 === void 0) {
|
|
42734
|
-
throw new Error("The Session event outbox did not enqueue the event");
|
|
42735
|
-
}
|
|
42736
|
-
return envelope2;
|
|
42737
|
-
};
|
|
42738
|
-
enqueueBatch = (sessionId, payloads, critical) => {
|
|
42739
|
-
if (payloads.length < 1 || payloads.length > 32) {
|
|
42740
|
-
throw new Error("A Session event batch must contain between 1 and 32 events");
|
|
42741
|
-
}
|
|
42742
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
42743
|
-
try {
|
|
42744
|
-
const state = this.#database.prepare(
|
|
42745
|
-
`SELECT stream_id, next_source_seq, total_bytes
|
|
42746
|
-
FROM relay_session_event_outbox_state
|
|
42747
|
-
WHERE singleton = 1`
|
|
42748
|
-
).get();
|
|
42749
|
-
const sourceSeq = rowNumber(state, "next_source_seq");
|
|
42750
|
-
if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
|
|
42751
|
-
throw new Error("The Session event source sequence is exhausted");
|
|
42752
|
-
}
|
|
42753
|
-
const streamId = rowString(state, "stream_id");
|
|
42754
|
-
const stored = payloads.map((payload, index) => {
|
|
42755
|
-
const envelope2 = {
|
|
42756
|
-
delivery: {
|
|
42757
|
-
eventId: randomUUID6(),
|
|
42758
|
-
kind: "reliable",
|
|
42759
|
-
sourceSeq: (sourceSeq + index).toString(),
|
|
42760
|
-
streamId
|
|
42761
|
-
},
|
|
42762
|
-
kind: SESSION_EVENT_KIND,
|
|
42763
|
-
payload,
|
|
42764
|
-
sessionId
|
|
42765
|
-
};
|
|
42766
|
-
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
42767
|
-
return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
|
|
42768
|
-
});
|
|
42769
|
-
const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
|
|
42770
|
-
const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
|
|
42771
|
-
if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
|
|
42772
|
-
throw new SessionEventOutboxCapacityError();
|
|
42773
|
-
}
|
|
42774
|
-
const insert = this.#database.prepare(
|
|
42775
|
-
`INSERT INTO relay_session_event_outbox (
|
|
42776
|
-
event_id, session_id, source_seq, byte_length, envelope_json
|
|
42777
|
-
) VALUES (?, ?, ?, ?, ?)`
|
|
42778
|
-
);
|
|
42779
|
-
for (const entry of stored) {
|
|
42780
|
-
insert.run(
|
|
42781
|
-
entry.envelope.delivery.eventId,
|
|
42782
|
-
sessionId,
|
|
42783
|
-
Number(entry.envelope.delivery.sourceSeq),
|
|
42784
|
-
entry.byteLength,
|
|
42785
|
-
entry.encoded
|
|
42786
|
-
);
|
|
42787
|
-
}
|
|
42788
|
-
this.#database.prepare(
|
|
42789
|
-
`UPDATE relay_session_event_outbox_state
|
|
42790
|
-
SET next_source_seq = next_source_seq + ?,
|
|
42791
|
-
total_bytes = total_bytes + ?
|
|
42792
|
-
WHERE singleton = 1`
|
|
42793
|
-
).run(stored.length, byteLength);
|
|
42794
|
-
this.#database.exec("COMMIT");
|
|
42795
|
-
return stored.map((entry) => entry.envelope);
|
|
42796
|
-
} catch (error62) {
|
|
42797
|
-
this.#database.exec("ROLLBACK");
|
|
42798
|
-
throw error62;
|
|
42799
|
-
}
|
|
42800
|
-
};
|
|
42801
|
-
pending = (limit, excludedEventIds) => {
|
|
42802
|
-
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
42803
|
-
throw new Error("Session event replay limit must be a positive integer");
|
|
42804
|
-
}
|
|
42805
|
-
const exclusion = excludedEventIds.length === 0 ? "" : `WHERE event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`;
|
|
42806
|
-
return this.#database.prepare(
|
|
42807
|
-
`SELECT envelope_json
|
|
42808
|
-
FROM relay_session_event_outbox
|
|
42809
|
-
${exclusion}
|
|
42810
|
-
ORDER BY source_seq
|
|
42811
|
-
LIMIT ?`
|
|
42812
|
-
).all(...excludedEventIds, limit).map((row) => {
|
|
42813
|
-
const envelope2 = decodeSessionEventEnvelope(rowString(row, "envelope_json"));
|
|
42814
|
-
if (!("delivery" in envelope2)) {
|
|
42815
|
-
throw new Error("SQLite returned an invalid reliable Session event envelope");
|
|
42816
|
-
}
|
|
42817
|
-
return envelope2;
|
|
42818
|
-
});
|
|
42819
|
-
};
|
|
42820
|
-
quarantine = (rejection) => {
|
|
42821
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
42822
|
-
try {
|
|
42823
|
-
const stored = this.#database.prepare(
|
|
42824
|
-
`SELECT byte_length, envelope_json
|
|
42825
|
-
FROM relay_session_event_outbox
|
|
42826
|
-
WHERE event_id = ? AND session_id = ?`
|
|
42827
|
-
).get(rejection.eventId, rejection.sessionId);
|
|
42828
|
-
if (stored === void 0) {
|
|
42829
|
-
this.#database.exec("COMMIT");
|
|
42830
|
-
return false;
|
|
42831
|
-
}
|
|
42832
|
-
this.#database.prepare(
|
|
42833
|
-
`INSERT INTO relay_session_event_dead_letters (
|
|
42834
|
-
event_id, session_id, rejection_code, envelope_json
|
|
42835
|
-
) VALUES (?, ?, ?, ?)`
|
|
42836
|
-
).run(rejection.eventId, rejection.sessionId, rejection.code, rowString(stored, "envelope_json"));
|
|
42837
|
-
this.#deleteStored(rejection.eventId, rejection.sessionId, rowNumber(stored, "byte_length"));
|
|
42838
|
-
this.#database.prepare(
|
|
42839
|
-
`DELETE FROM relay_session_event_dead_letters
|
|
42840
|
-
WHERE ordinal NOT IN (
|
|
42841
|
-
SELECT ordinal FROM relay_session_event_dead_letters
|
|
42842
|
-
ORDER BY ordinal DESC LIMIT ?
|
|
42843
|
-
)`
|
|
42844
|
-
).run(MAX_DEAD_LETTERS);
|
|
42845
|
-
this.#database.exec("COMMIT");
|
|
42846
|
-
return true;
|
|
42847
|
-
} catch (error62) {
|
|
42848
|
-
this.#database.exec("ROLLBACK");
|
|
42849
|
-
throw error62;
|
|
42850
|
-
}
|
|
42851
|
-
};
|
|
42852
|
-
#deleteStored = (eventId, sessionId, byteLength) => {
|
|
42853
|
-
const deletion = this.#database.prepare(
|
|
42854
|
-
`DELETE FROM relay_session_event_outbox
|
|
42855
|
-
WHERE event_id = ? AND session_id = ?`
|
|
42856
|
-
).run(eventId, sessionId);
|
|
42857
|
-
if (deletion.changes !== 1) {
|
|
42858
|
-
throw new Error("The Session event could not be removed from the outbox");
|
|
42859
|
-
}
|
|
42860
|
-
const state = this.#database.prepare(
|
|
42861
|
-
`UPDATE relay_session_event_outbox_state
|
|
42862
|
-
SET total_bytes = total_bytes - ?
|
|
42863
|
-
WHERE singleton = 1 AND total_bytes >= ?`
|
|
42864
|
-
).run(byteLength, byteLength);
|
|
42865
|
-
if (state.changes !== 1) {
|
|
42866
|
-
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
42867
|
-
}
|
|
42868
|
-
};
|
|
42869
|
-
#remove = (eventId, sessionId) => {
|
|
42870
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
42871
|
-
try {
|
|
42872
|
-
const stored = this.#database.prepare(
|
|
42873
|
-
`SELECT byte_length
|
|
42874
|
-
FROM relay_session_event_outbox
|
|
42875
|
-
WHERE event_id = ? AND session_id = ?`
|
|
42876
|
-
).get(eventId, sessionId);
|
|
42877
|
-
if (stored === void 0) {
|
|
42878
|
-
this.#database.exec("COMMIT");
|
|
42879
|
-
return false;
|
|
42880
|
-
}
|
|
42881
|
-
this.#deleteStored(eventId, sessionId, rowNumber(stored, "byte_length"));
|
|
42882
|
-
this.#database.exec("COMMIT");
|
|
42883
|
-
return true;
|
|
42884
|
-
} catch (error62) {
|
|
42885
|
-
this.#database.exec("ROLLBACK");
|
|
42886
|
-
throw error62;
|
|
42887
|
-
}
|
|
42888
|
-
};
|
|
42889
|
-
};
|
|
42890
|
-
|
|
42891
42557
|
// src/relay-connection/session-event-publisher.ts
|
|
42892
42558
|
import { WebSocket as WebSocket9 } from "undici";
|
|
42893
|
-
var
|
|
42894
|
-
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
42895
|
-
function reservesSessionEventCapacity(event) {
|
|
42896
|
-
if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
|
|
42897
|
-
return true;
|
|
42898
|
-
}
|
|
42899
|
-
return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
|
|
42900
|
-
}
|
|
42559
|
+
var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
|
|
42901
42560
|
var DaemonSessionEventPublisher = class {
|
|
42902
|
-
#
|
|
42903
|
-
|
|
42904
|
-
|
|
42905
|
-
#timer;
|
|
42906
|
-
#connection = { kind: "disconnected" };
|
|
42907
|
-
#deferredReplay = null;
|
|
42908
|
-
#inFlightBytes = 0;
|
|
42909
|
-
constructor(outbox, timer) {
|
|
42910
|
-
this.#outbox = outbox;
|
|
42911
|
-
this.#timer = timer;
|
|
42912
|
-
}
|
|
42913
|
-
acknowledge = (acknowledgement) => {
|
|
42914
|
-
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
42915
|
-
return;
|
|
42916
|
-
}
|
|
42917
|
-
this.#removeInFlight(acknowledgement.eventId);
|
|
42918
|
-
this.#publishNextBatch();
|
|
42919
|
-
};
|
|
42920
|
-
close = () => {
|
|
42921
|
-
this.#deferredReplay?.cancel();
|
|
42922
|
-
this.#deferredReplay = null;
|
|
42923
|
-
this.#connection = { kind: "disconnected" };
|
|
42924
|
-
this.#clearInFlight();
|
|
42925
|
-
this.#outbox.close();
|
|
42926
|
-
};
|
|
42927
|
-
connect = (socket, delivery) => {
|
|
42928
|
-
this.#connection = { delivery, kind: "connected", socket };
|
|
42929
|
-
this.#clearInFlight();
|
|
42930
|
-
this.#publishNextBatch();
|
|
42931
|
-
};
|
|
42932
|
-
defer = (deferred) => {
|
|
42933
|
-
if (!this.#inFlight.has(deferred.eventId)) {
|
|
42934
|
-
return;
|
|
42935
|
-
}
|
|
42936
|
-
this.#clearInFlight();
|
|
42937
|
-
if (this.#deferredReplay !== null) {
|
|
42938
|
-
return;
|
|
42939
|
-
}
|
|
42940
|
-
this.#deferredReplay = this.#timer.schedule(() => {
|
|
42941
|
-
this.#deferredReplay = null;
|
|
42942
|
-
this.#publishNextBatch();
|
|
42943
|
-
}, deferred.retryAfterMilliseconds);
|
|
42561
|
+
#socket = null;
|
|
42562
|
+
connect = (socket) => {
|
|
42563
|
+
this.#socket = socket;
|
|
42944
42564
|
};
|
|
42945
42565
|
disconnect = (socket) => {
|
|
42946
|
-
if (this.#
|
|
42947
|
-
|
|
42948
|
-
}
|
|
42949
|
-
this.#connection = { kind: "disconnected" };
|
|
42950
|
-
this.#clearInFlight();
|
|
42951
|
-
};
|
|
42952
|
-
publish = (sessionId, event) => {
|
|
42953
|
-
try {
|
|
42954
|
-
this.#outbox.enqueue(sessionId, encodeRecordedSessionEvent(event), reservesSessionEventCapacity(event));
|
|
42955
|
-
} catch (error62) {
|
|
42956
|
-
if (!(error62 instanceof SessionEventOutboxCapacityError)) {
|
|
42957
|
-
throw error62;
|
|
42958
|
-
}
|
|
42959
|
-
if (!this.#reportedCapacityKinds.has(event.kind)) {
|
|
42960
|
-
this.#reportedCapacityKinds.add(event.kind);
|
|
42961
|
-
console.warn(
|
|
42962
|
-
`Mobius daemon could not persist "${event.kind}" because the Session event outbox is full`
|
|
42963
|
-
);
|
|
42964
|
-
}
|
|
42965
|
-
return;
|
|
42966
|
-
}
|
|
42967
|
-
this.#publishNextBatch();
|
|
42968
|
-
};
|
|
42969
|
-
publishBatch = (sessionId, events) => {
|
|
42970
|
-
const critical = events.some(reservesSessionEventCapacity);
|
|
42971
|
-
this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
|
|
42972
|
-
this.#publishNextBatch();
|
|
42973
|
-
};
|
|
42974
|
-
quarantine = (rejection) => {
|
|
42975
|
-
if (!this.#outbox.quarantine(rejection)) {
|
|
42976
|
-
return;
|
|
42566
|
+
if (this.#socket === socket) {
|
|
42567
|
+
this.#socket = null;
|
|
42977
42568
|
}
|
|
42978
|
-
this.#removeInFlight(rejection.eventId);
|
|
42979
|
-
console.error(`Mobius Relay rejected Session event ${rejection.eventId} with code ${rejection.code}`);
|
|
42980
|
-
this.#publishNextBatch();
|
|
42981
42569
|
};
|
|
42982
|
-
|
|
42983
|
-
this.#
|
|
42984
|
-
this.#inFlightBytes = 0;
|
|
42570
|
+
close = () => {
|
|
42571
|
+
this.#socket = null;
|
|
42985
42572
|
};
|
|
42986
|
-
|
|
42987
|
-
|
|
42573
|
+
publish = (sessionId, event) => {
|
|
42574
|
+
const socket = this.#socket;
|
|
42575
|
+
if (socket === null || socket.readyState !== WebSocket9.OPEN) {
|
|
42988
42576
|
return;
|
|
42989
42577
|
}
|
|
42990
|
-
|
|
42991
|
-
|
|
42992
|
-
|
|
42993
|
-
|
|
42994
|
-
|
|
42995
|
-
|
|
42996
|
-
|
|
42997
|
-
this.#connection.delivery === "reliable" ? envelope2 : {
|
|
42998
|
-
kind: envelope2.kind,
|
|
42999
|
-
payload: envelope2.payload,
|
|
43000
|
-
sessionId: envelope2.sessionId
|
|
43001
|
-
}
|
|
43002
|
-
);
|
|
43003
|
-
const byteLength = Buffer.byteLength(encoded, "utf8");
|
|
43004
|
-
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
43005
|
-
return;
|
|
43006
|
-
}
|
|
43007
|
-
if (!this.#send(encoded)) {
|
|
43008
|
-
this.#clearInFlight();
|
|
43009
|
-
return;
|
|
43010
|
-
}
|
|
43011
|
-
if (this.#connection.delivery === "ephemeral") {
|
|
43012
|
-
this.#outbox.acknowledge({
|
|
43013
|
-
eventId: envelope2.delivery.eventId,
|
|
43014
|
-
kind: "session.event.ack",
|
|
43015
|
-
outcome: { kind: "relayed" },
|
|
43016
|
-
sessionId: envelope2.sessionId
|
|
43017
|
-
});
|
|
43018
|
-
sent += 1;
|
|
43019
|
-
continue;
|
|
43020
|
-
}
|
|
43021
|
-
this.#inFlight.set(envelope2.delivery.eventId, { byteLength });
|
|
43022
|
-
this.#inFlightBytes += byteLength;
|
|
43023
|
-
sent += 1;
|
|
43024
|
-
}
|
|
43025
|
-
if (sent === 0) {
|
|
43026
|
-
return;
|
|
43027
|
-
}
|
|
43028
|
-
}
|
|
43029
|
-
};
|
|
43030
|
-
#removeInFlight = (eventId) => {
|
|
43031
|
-
const inFlight = this.#inFlight.get(eventId);
|
|
43032
|
-
if (inFlight === void 0) {
|
|
42578
|
+
const encoded = encodeDaemonToServiceMessage({
|
|
42579
|
+
kind: SESSION_EVENT_KIND,
|
|
42580
|
+
payload: encodeRecordedSessionEvent(event),
|
|
42581
|
+
sessionId
|
|
42582
|
+
});
|
|
42583
|
+
if (socket.bufferedAmount + Buffer.byteLength(encoded, "utf8") > MAX_BUFFERED_BYTES) {
|
|
42584
|
+
socket.close(1013, "Live event transport overloaded");
|
|
43033
42585
|
return;
|
|
43034
42586
|
}
|
|
43035
|
-
this.#inFlight.delete(eventId);
|
|
43036
|
-
this.#inFlightBytes -= inFlight.byteLength;
|
|
43037
|
-
};
|
|
43038
|
-
#send = (encoded) => {
|
|
43039
|
-
if (this.#connection.kind !== "connected" || this.#connection.socket.readyState !== WebSocket9.OPEN) {
|
|
43040
|
-
return false;
|
|
43041
|
-
}
|
|
43042
42587
|
try {
|
|
43043
|
-
|
|
43044
|
-
return true;
|
|
42588
|
+
socket.send(encoded);
|
|
43045
42589
|
} catch {
|
|
43046
|
-
|
|
42590
|
+
}
|
|
42591
|
+
};
|
|
42592
|
+
publishBatch = (sessionId, events) => {
|
|
42593
|
+
for (const event of events) {
|
|
42594
|
+
this.publish(sessionId, event);
|
|
43047
42595
|
}
|
|
43048
42596
|
};
|
|
43049
42597
|
};
|
|
@@ -43105,7 +42653,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
43105
42653
|
{
|
|
43106
42654
|
agentId: agent.id,
|
|
43107
42655
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
43108
|
-
requestId: `automatic-integration-${
|
|
42656
|
+
requestId: `automatic-integration-${randomUUID6()}`
|
|
43109
42657
|
},
|
|
43110
42658
|
signal
|
|
43111
42659
|
);
|
|
@@ -43127,11 +42675,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43127
42675
|
join17(stateDirectory, "sessions", `${createHash5("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
43128
42676
|
);
|
|
43129
42677
|
const operations = new DaemonOperationState();
|
|
43130
|
-
const
|
|
43131
|
-
const publisher = new DaemonSessionEventPublisher(
|
|
43132
|
-
new SessionEventOutbox(join17(stateDirectory, "events", `${channelHash}.sqlite`)),
|
|
43133
|
-
timer
|
|
43134
|
-
);
|
|
42678
|
+
const publisher = new DaemonSessionEventPublisher();
|
|
43135
42679
|
const activeTurns = new DaemonTurnRegistry(operations);
|
|
43136
42680
|
const recordSessionEvent = (sessionId, event) => {
|
|
43137
42681
|
publisher.publish(sessionId, activeTurns.recordEvent(event));
|
|
@@ -43323,9 +42867,9 @@ import { basename as basename7, resolve as resolve7 } from "node:path";
|
|
|
43323
42867
|
import { fetch as fetch4 } from "undici";
|
|
43324
42868
|
|
|
43325
42869
|
// src/storage/runtime-installation-store.ts
|
|
43326
|
-
import { createHash as createHash6, randomUUID as
|
|
42870
|
+
import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
|
|
43327
42871
|
import { mkdir as mkdir4, open as open5, readdir as readdir3, rename as rename3, unlink, writeFile as writeFile3 } from "node:fs/promises";
|
|
43328
|
-
import { dirname as
|
|
42872
|
+
import { dirname as dirname5, join as join18, resolve as resolve6 } from "node:path";
|
|
43329
42873
|
var APPLICATION_ID_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){1,31}$/;
|
|
43330
42874
|
var CONNECTION_ID_PATTERN = /^mcn_[a-f0-9]{32}$/;
|
|
43331
42875
|
var INSTALLATION_ID_PATTERN = /^min_[a-f0-9]{32}$/;
|
|
@@ -43453,10 +42997,10 @@ function parseRelayOrigin(value) {
|
|
|
43453
42997
|
return origin;
|
|
43454
42998
|
}
|
|
43455
42999
|
function connectionId() {
|
|
43456
|
-
return `mcn_${
|
|
43000
|
+
return `mcn_${randomUUID7().replaceAll("-", "")}`;
|
|
43457
43001
|
}
|
|
43458
43002
|
function installationId() {
|
|
43459
|
-
return `min_${
|
|
43003
|
+
return `min_${randomUUID7().replaceAll("-", "")}`;
|
|
43460
43004
|
}
|
|
43461
43005
|
function channelIndexFileName(channelId) {
|
|
43462
43006
|
return `mci_${createHash6("sha256").update(channelId).digest("hex")}.json`;
|
|
@@ -43567,8 +43111,8 @@ async function readJsonFile(path2, signal, missingCode) {
|
|
|
43567
43111
|
}
|
|
43568
43112
|
async function writeJsonAtomically(path2, value, signal) {
|
|
43569
43113
|
signal.throwIfAborted();
|
|
43570
|
-
const directory =
|
|
43571
|
-
const temporaryPath = join18(directory, `.${
|
|
43114
|
+
const directory = dirname5(path2);
|
|
43115
|
+
const temporaryPath = join18(directory, `.${randomUUID7()}.tmp`);
|
|
43572
43116
|
try {
|
|
43573
43117
|
await mkdir4(directory, { mode: 448, recursive: true });
|
|
43574
43118
|
signal.throwIfAborted();
|