@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
|
@@ -20,19 +20,6 @@ export declare class DaemonTurnRegistry {
|
|
|
20
20
|
epoch: string;
|
|
21
21
|
hasOlder: boolean;
|
|
22
22
|
interaction: Readonly<{
|
|
23
|
-
commandId: string;
|
|
24
|
-
interactionId: string;
|
|
25
|
-
kind: "session.permission.requested";
|
|
26
|
-
options: readonly Readonly<{
|
|
27
|
-
kind: "allow_always" | "allow_once" | "reject_always" | "reject_once";
|
|
28
|
-
name: string;
|
|
29
|
-
optionId: string;
|
|
30
|
-
}>[];
|
|
31
|
-
sessionId: string;
|
|
32
|
-
title: string;
|
|
33
|
-
toolCallId: string;
|
|
34
|
-
toolKind: string;
|
|
35
|
-
}> | Readonly<{
|
|
36
23
|
accepted: boolean;
|
|
37
24
|
commandId: string;
|
|
38
25
|
elicitationId: string;
|
|
@@ -64,6 +51,19 @@ export declare class DaemonTurnRegistry {
|
|
|
64
51
|
mode: "form" | "url";
|
|
65
52
|
sessionId: string;
|
|
66
53
|
url: string;
|
|
54
|
+
}> | Readonly<{
|
|
55
|
+
commandId: string;
|
|
56
|
+
interactionId: string;
|
|
57
|
+
kind: "session.permission.requested";
|
|
58
|
+
options: readonly Readonly<{
|
|
59
|
+
kind: "allow_always" | "allow_once" | "reject_always" | "reject_once";
|
|
60
|
+
name: string;
|
|
61
|
+
optionId: string;
|
|
62
|
+
}>[];
|
|
63
|
+
sessionId: string;
|
|
64
|
+
title: string;
|
|
65
|
+
toolCallId: string;
|
|
66
|
+
toolKind: string;
|
|
67
67
|
}> | null;
|
|
68
68
|
messages: readonly (Readonly<{
|
|
69
69
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -20767,16 +20767,8 @@ function decodeSessionQueuedEvent(encoded) {
|
|
|
20767
20767
|
function decodeRuntimeLivenessReadyEvent(encoded) {
|
|
20768
20768
|
const value = parseJson2(encoded);
|
|
20769
20769
|
assertKind(value, RUNTIME_LIVENESS_READY_KIND);
|
|
20770
|
-
|
|
20771
|
-
|
|
20772
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
20773
|
-
}
|
|
20774
|
-
assertExactKeys(value, ["kind", "sessionEventDelivery"]);
|
|
20775
|
-
const sessionEventDelivery = readString(value, "sessionEventDelivery", 32);
|
|
20776
|
-
if (sessionEventDelivery !== "reliable-v1") {
|
|
20777
|
-
throw new ProtocolMessageError("Unsupported Session event delivery mode");
|
|
20778
|
-
}
|
|
20779
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND, sessionEventDelivery };
|
|
20770
|
+
assertExactKeys(value, ["kind"]);
|
|
20771
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
20780
20772
|
}
|
|
20781
20773
|
function decodeRuntimeHeartbeatEvent(encoded) {
|
|
20782
20774
|
const value = parseJson2(encoded);
|
|
@@ -21243,60 +21235,13 @@ var encodeNativeSessionCancel = (value) => JSON.stringify(nativeSessionCancelSch
|
|
|
21243
21235
|
|
|
21244
21236
|
// ../protocol/src/session-events.ts
|
|
21245
21237
|
var SESSION_EVENT_KIND = "session.event";
|
|
21246
|
-
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
21247
|
-
var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
|
|
21248
|
-
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
21249
21238
|
var SESSION_FORKED_KIND = "session.forked";
|
|
21250
|
-
var SessionEventRejectionCode = {
|
|
21251
|
-
IdempotencyConflict: "idempotency_conflict",
|
|
21252
|
-
InvalidEvent: "invalid_event",
|
|
21253
|
-
RecordingRejected: "recording_rejected"
|
|
21254
|
-
};
|
|
21255
21239
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
21256
|
-
var
|
|
21257
|
-
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21258
|
-
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21259
|
-
sessionId: identifierStringSchema
|
|
21260
|
-
}).readonly();
|
|
21261
|
-
var reliableDeliverySchema = external_exports.strictObject({
|
|
21262
|
-
eventId: identifierStringSchema,
|
|
21263
|
-
kind: external_exports.literal("reliable"),
|
|
21264
|
-
sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
|
|
21265
|
-
streamId: identifierStringSchema
|
|
21266
|
-
}).readonly();
|
|
21267
|
-
var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
|
|
21268
|
-
delivery: reliableDeliverySchema,
|
|
21240
|
+
var sessionEventEnvelopeSchema = external_exports.strictObject({
|
|
21269
21241
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21270
21242
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21271
21243
|
sessionId: identifierStringSchema
|
|
21272
21244
|
}).readonly();
|
|
21273
|
-
var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
|
|
21274
|
-
var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
21275
|
-
external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
|
|
21276
|
-
external_exports.strictObject({
|
|
21277
|
-
kind: external_exports.literal("recorded"),
|
|
21278
|
-
providerId: identifierStringSchema,
|
|
21279
|
-
recordingEpoch: identifierStringSchema
|
|
21280
|
-
}).readonly()
|
|
21281
|
-
]);
|
|
21282
|
-
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
21283
|
-
eventId: identifierStringSchema,
|
|
21284
|
-
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
21285
|
-
outcome: acknowledgementOutcomeSchema,
|
|
21286
|
-
sessionId: identifierStringSchema
|
|
21287
|
-
}).readonly();
|
|
21288
|
-
var eventDeferredSchema = external_exports.strictObject({
|
|
21289
|
-
eventId: identifierStringSchema,
|
|
21290
|
-
kind: external_exports.literal(SESSION_EVENT_DEFERRED_KIND),
|
|
21291
|
-
retryAfterMilliseconds: external_exports.number().int().min(100).max(6e4),
|
|
21292
|
-
sessionId: identifierStringSchema
|
|
21293
|
-
}).readonly();
|
|
21294
|
-
var eventRejectedSchema = external_exports.strictObject({
|
|
21295
|
-
code: external_exports.enum(SessionEventRejectionCode),
|
|
21296
|
-
eventId: identifierStringSchema,
|
|
21297
|
-
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
21298
|
-
sessionId: identifierStringSchema
|
|
21299
|
-
}).readonly();
|
|
21300
21245
|
var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
|
|
21301
21246
|
var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
|
|
21302
21247
|
var sessionForkedSchema = external_exports.strictObject({
|
|
@@ -21329,14 +21274,8 @@ var encode4 = (message, schema) => {
|
|
|
21329
21274
|
}
|
|
21330
21275
|
return JSON.stringify(decoded.data);
|
|
21331
21276
|
};
|
|
21332
|
-
var decodeSessionEventEnvelope = (encoded) => decode5(encoded,
|
|
21333
|
-
var encodeSessionEventEnvelope = (message) => encode4(message,
|
|
21334
|
-
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
21335
|
-
var encodeSessionEventAcknowledgement = (message) => encode4(message, eventAcknowledgementSchema);
|
|
21336
|
-
var decodeSessionEventDeferred = (encoded) => decode5(encoded, eventDeferredSchema);
|
|
21337
|
-
var encodeSessionEventDeferred = (message) => encode4(message, eventDeferredSchema);
|
|
21338
|
-
var decodeSessionEventRejected = (encoded) => decode5(encoded, eventRejectedSchema);
|
|
21339
|
-
var encodeSessionEventRejected = (message) => encode4(message, eventRejectedSchema);
|
|
21277
|
+
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, sessionEventEnvelopeSchema);
|
|
21278
|
+
var encodeSessionEventEnvelope = (message) => encode4(message, sessionEventEnvelopeSchema);
|
|
21340
21279
|
function decodeRecordedSessionEvent(encoded) {
|
|
21341
21280
|
const kind = decodeMessageKind(encoded);
|
|
21342
21281
|
switch (kind) {
|
|
@@ -21510,21 +21449,6 @@ var serviceToDaemonSignatures = {
|
|
|
21510
21449
|
encodeSessionElicitationRespondCommand,
|
|
21511
21450
|
decodeSessionElicitationRespondCommand
|
|
21512
21451
|
),
|
|
21513
|
-
[SESSION_EVENT_ACK_KIND]: defineMessageSignature(
|
|
21514
|
-
SESSION_EVENT_ACK_KIND,
|
|
21515
|
-
encodeSessionEventAcknowledgement,
|
|
21516
|
-
decodeSessionEventAcknowledgement
|
|
21517
|
-
),
|
|
21518
|
-
[SESSION_EVENT_DEFERRED_KIND]: defineMessageSignature(
|
|
21519
|
-
SESSION_EVENT_DEFERRED_KIND,
|
|
21520
|
-
encodeSessionEventDeferred,
|
|
21521
|
-
decodeSessionEventDeferred
|
|
21522
|
-
),
|
|
21523
|
-
[SESSION_EVENT_REJECTED_KIND]: defineMessageSignature(
|
|
21524
|
-
SESSION_EVENT_REJECTED_KIND,
|
|
21525
|
-
encodeSessionEventRejected,
|
|
21526
|
-
decodeSessionEventRejected
|
|
21527
|
-
),
|
|
21528
21452
|
[SESSION_LIVE_HISTORY_LOAD_KIND]: defineMessageSignature(
|
|
21529
21453
|
SESSION_LIVE_HISTORY_LOAD_KIND,
|
|
21530
21454
|
encodeSessionLiveHistoryLoad,
|
|
@@ -37660,7 +37584,7 @@ function isRuntimeRelayRevocation(closeCode, closeReason) {
|
|
|
37660
37584
|
}
|
|
37661
37585
|
|
|
37662
37586
|
// src/run-daemon.ts
|
|
37663
|
-
import { createHash as createHash6, randomUUID as
|
|
37587
|
+
import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
|
|
37664
37588
|
import { join as join18 } from "node:path";
|
|
37665
37589
|
import { styleText } from "node:util";
|
|
37666
37590
|
|
|
@@ -43337,7 +43261,6 @@ async function runRelayConnection({
|
|
|
43337
43261
|
}) {
|
|
43338
43262
|
const relayUrl = new URL(config2.relayUrl);
|
|
43339
43263
|
relayUrl.searchParams.set("liveness", "1");
|
|
43340
|
-
relayUrl.searchParams.set("sessionEventDelivery", "reliable-v1");
|
|
43341
43264
|
const socket = await connectRelay(relayUrl, signal);
|
|
43342
43265
|
diagnostics.connectionOpened(connectionEpoch);
|
|
43343
43266
|
const connectionController = new AbortController();
|
|
@@ -43457,10 +43380,7 @@ async function runRelayConnection({
|
|
|
43457
43380
|
const message = decodeServiceToDaemonMessage(encoded);
|
|
43458
43381
|
const kind = message.kind;
|
|
43459
43382
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
43460
|
-
publisher.connect(
|
|
43461
|
-
socket,
|
|
43462
|
-
message.sessionEventDelivery === "reliable-v1" ? "reliable" : "ephemeral"
|
|
43463
|
-
);
|
|
43383
|
+
publisher.connect(socket);
|
|
43464
43384
|
connectionLiveness.start();
|
|
43465
43385
|
return;
|
|
43466
43386
|
}
|
|
@@ -43468,18 +43388,6 @@ async function runRelayConnection({
|
|
|
43468
43388
|
connectionLiveness.acknowledge(message);
|
|
43469
43389
|
return;
|
|
43470
43390
|
}
|
|
43471
|
-
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
43472
|
-
publisher.acknowledge(message);
|
|
43473
|
-
return;
|
|
43474
|
-
}
|
|
43475
|
-
if (kind === SESSION_EVENT_DEFERRED_KIND) {
|
|
43476
|
-
publisher.defer(message);
|
|
43477
|
-
return;
|
|
43478
|
-
}
|
|
43479
|
-
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
43480
|
-
publisher.quarantine(message);
|
|
43481
|
-
return;
|
|
43482
|
-
}
|
|
43483
43391
|
commands.handle(message);
|
|
43484
43392
|
} catch (error62) {
|
|
43485
43393
|
console.error("Mobius daemon rejected a message", error62);
|
|
@@ -43504,404 +43412,44 @@ async function runRelayConnection({
|
|
|
43504
43412
|
}
|
|
43505
43413
|
}
|
|
43506
43414
|
|
|
43507
|
-
// src/relay-connection/session-event-outbox.ts
|
|
43508
|
-
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
43509
|
-
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
43510
|
-
import { dirname as dirname6 } from "node:path";
|
|
43511
|
-
import { DatabaseSync } from "node:sqlite";
|
|
43512
|
-
var DEFAULT_STANDARD_EVENT_BYTES = 96 * 1024 * 1024;
|
|
43513
|
-
var DEFAULT_CRITICAL_EVENT_BYTES = 128 * 1024 * 1024;
|
|
43514
|
-
var MAX_DEAD_LETTERS = 1024;
|
|
43515
|
-
var DEFAULT_LIMITS = {
|
|
43516
|
-
criticalEventBytes: DEFAULT_CRITICAL_EVENT_BYTES,
|
|
43517
|
-
standardEventBytes: DEFAULT_STANDARD_EVENT_BYTES
|
|
43518
|
-
};
|
|
43519
|
-
var SessionEventOutboxCapacityError = class extends Error {
|
|
43520
|
-
code = "session_event_outbox_full";
|
|
43521
|
-
constructor() {
|
|
43522
|
-
super("The persistent Session event outbox is full");
|
|
43523
|
-
this.name = "SessionEventOutboxCapacityError";
|
|
43524
|
-
}
|
|
43525
|
-
};
|
|
43526
|
-
function rowNumber(row, field) {
|
|
43527
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
43528
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
43529
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
43530
|
-
}
|
|
43531
|
-
return value;
|
|
43532
|
-
}
|
|
43533
|
-
function rowString(row, field) {
|
|
43534
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
43535
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
43536
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
43537
|
-
}
|
|
43538
|
-
return value;
|
|
43539
|
-
}
|
|
43540
|
-
function validateLimits(limits) {
|
|
43541
|
-
if (!Number.isSafeInteger(limits.standardEventBytes) || limits.standardEventBytes < 1 || !Number.isSafeInteger(limits.criticalEventBytes) || limits.criticalEventBytes < limits.standardEventBytes) {
|
|
43542
|
-
throw new Error("Session event outbox limits are invalid");
|
|
43543
|
-
}
|
|
43544
|
-
}
|
|
43545
|
-
var SessionEventOutbox = class {
|
|
43546
|
-
#database;
|
|
43547
|
-
#limits;
|
|
43548
|
-
constructor(path2, limits = DEFAULT_LIMITS) {
|
|
43549
|
-
validateLimits(limits);
|
|
43550
|
-
mkdirSync3(dirname6(path2), { mode: 448, recursive: true });
|
|
43551
|
-
this.#limits = limits;
|
|
43552
|
-
this.#database = new DatabaseSync(path2);
|
|
43553
|
-
this.#database.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; PRAGMA busy_timeout = 5000;");
|
|
43554
|
-
this.#database.exec(`
|
|
43555
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
43556
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43557
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
43558
|
-
session_id TEXT NOT NULL,
|
|
43559
|
-
source_seq INTEGER NOT NULL UNIQUE,
|
|
43560
|
-
byte_length INTEGER NOT NULL,
|
|
43561
|
-
envelope_json TEXT NOT NULL
|
|
43562
|
-
) STRICT;
|
|
43563
|
-
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
43564
|
-
ON relay_session_event_outbox(source_seq);
|
|
43565
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
43566
|
-
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
43567
|
-
stream_id TEXT NOT NULL,
|
|
43568
|
-
next_source_seq INTEGER NOT NULL,
|
|
43569
|
-
total_bytes INTEGER NOT NULL
|
|
43570
|
-
) STRICT;
|
|
43571
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
43572
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43573
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
43574
|
-
session_id TEXT NOT NULL,
|
|
43575
|
-
rejection_code TEXT NOT NULL,
|
|
43576
|
-
envelope_json TEXT NOT NULL
|
|
43577
|
-
) STRICT;
|
|
43578
|
-
`);
|
|
43579
|
-
this.#database.prepare(
|
|
43580
|
-
`INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
43581
|
-
singleton, stream_id, next_source_seq, total_bytes
|
|
43582
|
-
) VALUES (1, ?, 1, 0)`
|
|
43583
|
-
).run(randomUUID7());
|
|
43584
|
-
}
|
|
43585
|
-
acknowledge = (acknowledgement) => this.#remove(acknowledgement.eventId, acknowledgement.sessionId);
|
|
43586
|
-
close = () => {
|
|
43587
|
-
this.#database.close();
|
|
43588
|
-
};
|
|
43589
|
-
enqueue = (sessionId, payload, critical) => {
|
|
43590
|
-
const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
|
|
43591
|
-
if (envelope2 === void 0) {
|
|
43592
|
-
throw new Error("The Session event outbox did not enqueue the event");
|
|
43593
|
-
}
|
|
43594
|
-
return envelope2;
|
|
43595
|
-
};
|
|
43596
|
-
enqueueBatch = (sessionId, payloads, critical) => {
|
|
43597
|
-
if (payloads.length < 1 || payloads.length > 32) {
|
|
43598
|
-
throw new Error("A Session event batch must contain between 1 and 32 events");
|
|
43599
|
-
}
|
|
43600
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
43601
|
-
try {
|
|
43602
|
-
const state = this.#database.prepare(
|
|
43603
|
-
`SELECT stream_id, next_source_seq, total_bytes
|
|
43604
|
-
FROM relay_session_event_outbox_state
|
|
43605
|
-
WHERE singleton = 1`
|
|
43606
|
-
).get();
|
|
43607
|
-
const sourceSeq = rowNumber(state, "next_source_seq");
|
|
43608
|
-
if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
|
|
43609
|
-
throw new Error("The Session event source sequence is exhausted");
|
|
43610
|
-
}
|
|
43611
|
-
const streamId = rowString(state, "stream_id");
|
|
43612
|
-
const stored = payloads.map((payload, index) => {
|
|
43613
|
-
const envelope2 = {
|
|
43614
|
-
delivery: {
|
|
43615
|
-
eventId: randomUUID7(),
|
|
43616
|
-
kind: "reliable",
|
|
43617
|
-
sourceSeq: (sourceSeq + index).toString(),
|
|
43618
|
-
streamId
|
|
43619
|
-
},
|
|
43620
|
-
kind: SESSION_EVENT_KIND,
|
|
43621
|
-
payload,
|
|
43622
|
-
sessionId
|
|
43623
|
-
};
|
|
43624
|
-
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
43625
|
-
return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
|
|
43626
|
-
});
|
|
43627
|
-
const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
|
|
43628
|
-
const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
|
|
43629
|
-
if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
|
|
43630
|
-
throw new SessionEventOutboxCapacityError();
|
|
43631
|
-
}
|
|
43632
|
-
const insert = this.#database.prepare(
|
|
43633
|
-
`INSERT INTO relay_session_event_outbox (
|
|
43634
|
-
event_id, session_id, source_seq, byte_length, envelope_json
|
|
43635
|
-
) VALUES (?, ?, ?, ?, ?)`
|
|
43636
|
-
);
|
|
43637
|
-
for (const entry of stored) {
|
|
43638
|
-
insert.run(
|
|
43639
|
-
entry.envelope.delivery.eventId,
|
|
43640
|
-
sessionId,
|
|
43641
|
-
Number(entry.envelope.delivery.sourceSeq),
|
|
43642
|
-
entry.byteLength,
|
|
43643
|
-
entry.encoded
|
|
43644
|
-
);
|
|
43645
|
-
}
|
|
43646
|
-
this.#database.prepare(
|
|
43647
|
-
`UPDATE relay_session_event_outbox_state
|
|
43648
|
-
SET next_source_seq = next_source_seq + ?,
|
|
43649
|
-
total_bytes = total_bytes + ?
|
|
43650
|
-
WHERE singleton = 1`
|
|
43651
|
-
).run(stored.length, byteLength);
|
|
43652
|
-
this.#database.exec("COMMIT");
|
|
43653
|
-
return stored.map((entry) => entry.envelope);
|
|
43654
|
-
} catch (error62) {
|
|
43655
|
-
this.#database.exec("ROLLBACK");
|
|
43656
|
-
throw error62;
|
|
43657
|
-
}
|
|
43658
|
-
};
|
|
43659
|
-
pending = (limit, excludedEventIds) => {
|
|
43660
|
-
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
43661
|
-
throw new Error("Session event replay limit must be a positive integer");
|
|
43662
|
-
}
|
|
43663
|
-
const exclusion = excludedEventIds.length === 0 ? "" : `WHERE event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`;
|
|
43664
|
-
return this.#database.prepare(
|
|
43665
|
-
`SELECT envelope_json
|
|
43666
|
-
FROM relay_session_event_outbox
|
|
43667
|
-
${exclusion}
|
|
43668
|
-
ORDER BY source_seq
|
|
43669
|
-
LIMIT ?`
|
|
43670
|
-
).all(...excludedEventIds, limit).map((row) => {
|
|
43671
|
-
const envelope2 = decodeSessionEventEnvelope(rowString(row, "envelope_json"));
|
|
43672
|
-
if (!("delivery" in envelope2)) {
|
|
43673
|
-
throw new Error("SQLite returned an invalid reliable Session event envelope");
|
|
43674
|
-
}
|
|
43675
|
-
return envelope2;
|
|
43676
|
-
});
|
|
43677
|
-
};
|
|
43678
|
-
quarantine = (rejection) => {
|
|
43679
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
43680
|
-
try {
|
|
43681
|
-
const stored = this.#database.prepare(
|
|
43682
|
-
`SELECT byte_length, envelope_json
|
|
43683
|
-
FROM relay_session_event_outbox
|
|
43684
|
-
WHERE event_id = ? AND session_id = ?`
|
|
43685
|
-
).get(rejection.eventId, rejection.sessionId);
|
|
43686
|
-
if (stored === void 0) {
|
|
43687
|
-
this.#database.exec("COMMIT");
|
|
43688
|
-
return false;
|
|
43689
|
-
}
|
|
43690
|
-
this.#database.prepare(
|
|
43691
|
-
`INSERT INTO relay_session_event_dead_letters (
|
|
43692
|
-
event_id, session_id, rejection_code, envelope_json
|
|
43693
|
-
) VALUES (?, ?, ?, ?)`
|
|
43694
|
-
).run(rejection.eventId, rejection.sessionId, rejection.code, rowString(stored, "envelope_json"));
|
|
43695
|
-
this.#deleteStored(rejection.eventId, rejection.sessionId, rowNumber(stored, "byte_length"));
|
|
43696
|
-
this.#database.prepare(
|
|
43697
|
-
`DELETE FROM relay_session_event_dead_letters
|
|
43698
|
-
WHERE ordinal NOT IN (
|
|
43699
|
-
SELECT ordinal FROM relay_session_event_dead_letters
|
|
43700
|
-
ORDER BY ordinal DESC LIMIT ?
|
|
43701
|
-
)`
|
|
43702
|
-
).run(MAX_DEAD_LETTERS);
|
|
43703
|
-
this.#database.exec("COMMIT");
|
|
43704
|
-
return true;
|
|
43705
|
-
} catch (error62) {
|
|
43706
|
-
this.#database.exec("ROLLBACK");
|
|
43707
|
-
throw error62;
|
|
43708
|
-
}
|
|
43709
|
-
};
|
|
43710
|
-
#deleteStored = (eventId, sessionId, byteLength) => {
|
|
43711
|
-
const deletion = this.#database.prepare(
|
|
43712
|
-
`DELETE FROM relay_session_event_outbox
|
|
43713
|
-
WHERE event_id = ? AND session_id = ?`
|
|
43714
|
-
).run(eventId, sessionId);
|
|
43715
|
-
if (deletion.changes !== 1) {
|
|
43716
|
-
throw new Error("The Session event could not be removed from the outbox");
|
|
43717
|
-
}
|
|
43718
|
-
const state = this.#database.prepare(
|
|
43719
|
-
`UPDATE relay_session_event_outbox_state
|
|
43720
|
-
SET total_bytes = total_bytes - ?
|
|
43721
|
-
WHERE singleton = 1 AND total_bytes >= ?`
|
|
43722
|
-
).run(byteLength, byteLength);
|
|
43723
|
-
if (state.changes !== 1) {
|
|
43724
|
-
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
43725
|
-
}
|
|
43726
|
-
};
|
|
43727
|
-
#remove = (eventId, sessionId) => {
|
|
43728
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
43729
|
-
try {
|
|
43730
|
-
const stored = this.#database.prepare(
|
|
43731
|
-
`SELECT byte_length
|
|
43732
|
-
FROM relay_session_event_outbox
|
|
43733
|
-
WHERE event_id = ? AND session_id = ?`
|
|
43734
|
-
).get(eventId, sessionId);
|
|
43735
|
-
if (stored === void 0) {
|
|
43736
|
-
this.#database.exec("COMMIT");
|
|
43737
|
-
return false;
|
|
43738
|
-
}
|
|
43739
|
-
this.#deleteStored(eventId, sessionId, rowNumber(stored, "byte_length"));
|
|
43740
|
-
this.#database.exec("COMMIT");
|
|
43741
|
-
return true;
|
|
43742
|
-
} catch (error62) {
|
|
43743
|
-
this.#database.exec("ROLLBACK");
|
|
43744
|
-
throw error62;
|
|
43745
|
-
}
|
|
43746
|
-
};
|
|
43747
|
-
};
|
|
43748
|
-
|
|
43749
43415
|
// src/relay-connection/session-event-publisher.ts
|
|
43750
43416
|
import { WebSocket as WebSocket9 } from "undici";
|
|
43751
|
-
var
|
|
43752
|
-
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
43753
|
-
function reservesSessionEventCapacity(event) {
|
|
43754
|
-
if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
|
|
43755
|
-
return true;
|
|
43756
|
-
}
|
|
43757
|
-
return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
|
|
43758
|
-
}
|
|
43417
|
+
var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
|
|
43759
43418
|
var DaemonSessionEventPublisher = class {
|
|
43760
|
-
#
|
|
43761
|
-
|
|
43762
|
-
|
|
43763
|
-
#timer;
|
|
43764
|
-
#connection = { kind: "disconnected" };
|
|
43765
|
-
#deferredReplay = null;
|
|
43766
|
-
#inFlightBytes = 0;
|
|
43767
|
-
constructor(outbox, timer) {
|
|
43768
|
-
this.#outbox = outbox;
|
|
43769
|
-
this.#timer = timer;
|
|
43770
|
-
}
|
|
43771
|
-
acknowledge = (acknowledgement) => {
|
|
43772
|
-
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
43773
|
-
return;
|
|
43774
|
-
}
|
|
43775
|
-
this.#removeInFlight(acknowledgement.eventId);
|
|
43776
|
-
this.#publishNextBatch();
|
|
43777
|
-
};
|
|
43778
|
-
close = () => {
|
|
43779
|
-
this.#deferredReplay?.cancel();
|
|
43780
|
-
this.#deferredReplay = null;
|
|
43781
|
-
this.#connection = { kind: "disconnected" };
|
|
43782
|
-
this.#clearInFlight();
|
|
43783
|
-
this.#outbox.close();
|
|
43784
|
-
};
|
|
43785
|
-
connect = (socket, delivery) => {
|
|
43786
|
-
this.#connection = { delivery, kind: "connected", socket };
|
|
43787
|
-
this.#clearInFlight();
|
|
43788
|
-
this.#publishNextBatch();
|
|
43789
|
-
};
|
|
43790
|
-
defer = (deferred) => {
|
|
43791
|
-
if (!this.#inFlight.has(deferred.eventId)) {
|
|
43792
|
-
return;
|
|
43793
|
-
}
|
|
43794
|
-
this.#clearInFlight();
|
|
43795
|
-
if (this.#deferredReplay !== null) {
|
|
43796
|
-
return;
|
|
43797
|
-
}
|
|
43798
|
-
this.#deferredReplay = this.#timer.schedule(() => {
|
|
43799
|
-
this.#deferredReplay = null;
|
|
43800
|
-
this.#publishNextBatch();
|
|
43801
|
-
}, deferred.retryAfterMilliseconds);
|
|
43419
|
+
#socket = null;
|
|
43420
|
+
connect = (socket) => {
|
|
43421
|
+
this.#socket = socket;
|
|
43802
43422
|
};
|
|
43803
43423
|
disconnect = (socket) => {
|
|
43804
|
-
if (this.#
|
|
43805
|
-
|
|
43806
|
-
}
|
|
43807
|
-
this.#connection = { kind: "disconnected" };
|
|
43808
|
-
this.#clearInFlight();
|
|
43809
|
-
};
|
|
43810
|
-
publish = (sessionId, event) => {
|
|
43811
|
-
try {
|
|
43812
|
-
this.#outbox.enqueue(sessionId, encodeRecordedSessionEvent(event), reservesSessionEventCapacity(event));
|
|
43813
|
-
} catch (error62) {
|
|
43814
|
-
if (!(error62 instanceof SessionEventOutboxCapacityError)) {
|
|
43815
|
-
throw error62;
|
|
43816
|
-
}
|
|
43817
|
-
if (!this.#reportedCapacityKinds.has(event.kind)) {
|
|
43818
|
-
this.#reportedCapacityKinds.add(event.kind);
|
|
43819
|
-
console.warn(
|
|
43820
|
-
`Mobius daemon could not persist "${event.kind}" because the Session event outbox is full`
|
|
43821
|
-
);
|
|
43822
|
-
}
|
|
43823
|
-
return;
|
|
43824
|
-
}
|
|
43825
|
-
this.#publishNextBatch();
|
|
43826
|
-
};
|
|
43827
|
-
publishBatch = (sessionId, events) => {
|
|
43828
|
-
const critical = events.some(reservesSessionEventCapacity);
|
|
43829
|
-
this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
|
|
43830
|
-
this.#publishNextBatch();
|
|
43831
|
-
};
|
|
43832
|
-
quarantine = (rejection) => {
|
|
43833
|
-
if (!this.#outbox.quarantine(rejection)) {
|
|
43834
|
-
return;
|
|
43424
|
+
if (this.#socket === socket) {
|
|
43425
|
+
this.#socket = null;
|
|
43835
43426
|
}
|
|
43836
|
-
this.#removeInFlight(rejection.eventId);
|
|
43837
|
-
console.error(`Mobius Relay rejected Session event ${rejection.eventId} with code ${rejection.code}`);
|
|
43838
|
-
this.#publishNextBatch();
|
|
43839
43427
|
};
|
|
43840
|
-
|
|
43841
|
-
this.#
|
|
43842
|
-
this.#inFlightBytes = 0;
|
|
43428
|
+
close = () => {
|
|
43429
|
+
this.#socket = null;
|
|
43843
43430
|
};
|
|
43844
|
-
|
|
43845
|
-
|
|
43431
|
+
publish = (sessionId, event) => {
|
|
43432
|
+
const socket = this.#socket;
|
|
43433
|
+
if (socket === null || socket.readyState !== WebSocket9.OPEN) {
|
|
43846
43434
|
return;
|
|
43847
43435
|
}
|
|
43848
|
-
|
|
43849
|
-
|
|
43850
|
-
|
|
43851
|
-
|
|
43852
|
-
|
|
43853
|
-
|
|
43854
|
-
|
|
43855
|
-
this.#connection.delivery === "reliable" ? envelope2 : {
|
|
43856
|
-
kind: envelope2.kind,
|
|
43857
|
-
payload: envelope2.payload,
|
|
43858
|
-
sessionId: envelope2.sessionId
|
|
43859
|
-
}
|
|
43860
|
-
);
|
|
43861
|
-
const byteLength = Buffer.byteLength(encoded, "utf8");
|
|
43862
|
-
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
43863
|
-
return;
|
|
43864
|
-
}
|
|
43865
|
-
if (!this.#send(encoded)) {
|
|
43866
|
-
this.#clearInFlight();
|
|
43867
|
-
return;
|
|
43868
|
-
}
|
|
43869
|
-
if (this.#connection.delivery === "ephemeral") {
|
|
43870
|
-
this.#outbox.acknowledge({
|
|
43871
|
-
eventId: envelope2.delivery.eventId,
|
|
43872
|
-
kind: "session.event.ack",
|
|
43873
|
-
outcome: { kind: "relayed" },
|
|
43874
|
-
sessionId: envelope2.sessionId
|
|
43875
|
-
});
|
|
43876
|
-
sent += 1;
|
|
43877
|
-
continue;
|
|
43878
|
-
}
|
|
43879
|
-
this.#inFlight.set(envelope2.delivery.eventId, { byteLength });
|
|
43880
|
-
this.#inFlightBytes += byteLength;
|
|
43881
|
-
sent += 1;
|
|
43882
|
-
}
|
|
43883
|
-
if (sent === 0) {
|
|
43884
|
-
return;
|
|
43885
|
-
}
|
|
43886
|
-
}
|
|
43887
|
-
};
|
|
43888
|
-
#removeInFlight = (eventId) => {
|
|
43889
|
-
const inFlight = this.#inFlight.get(eventId);
|
|
43890
|
-
if (inFlight === void 0) {
|
|
43436
|
+
const encoded = encodeDaemonToServiceMessage({
|
|
43437
|
+
kind: SESSION_EVENT_KIND,
|
|
43438
|
+
payload: encodeRecordedSessionEvent(event),
|
|
43439
|
+
sessionId
|
|
43440
|
+
});
|
|
43441
|
+
if (socket.bufferedAmount + Buffer.byteLength(encoded, "utf8") > MAX_BUFFERED_BYTES) {
|
|
43442
|
+
socket.close(1013, "Live event transport overloaded");
|
|
43891
43443
|
return;
|
|
43892
43444
|
}
|
|
43893
|
-
this.#inFlight.delete(eventId);
|
|
43894
|
-
this.#inFlightBytes -= inFlight.byteLength;
|
|
43895
|
-
};
|
|
43896
|
-
#send = (encoded) => {
|
|
43897
|
-
if (this.#connection.kind !== "connected" || this.#connection.socket.readyState !== WebSocket9.OPEN) {
|
|
43898
|
-
return false;
|
|
43899
|
-
}
|
|
43900
43445
|
try {
|
|
43901
|
-
|
|
43902
|
-
return true;
|
|
43446
|
+
socket.send(encoded);
|
|
43903
43447
|
} catch {
|
|
43904
|
-
|
|
43448
|
+
}
|
|
43449
|
+
};
|
|
43450
|
+
publishBatch = (sessionId, events) => {
|
|
43451
|
+
for (const event of events) {
|
|
43452
|
+
this.publish(sessionId, event);
|
|
43905
43453
|
}
|
|
43906
43454
|
};
|
|
43907
43455
|
};
|
|
@@ -43963,7 +43511,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
43963
43511
|
{
|
|
43964
43512
|
agentId: agent.id,
|
|
43965
43513
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
43966
|
-
requestId: `automatic-integration-${
|
|
43514
|
+
requestId: `automatic-integration-${randomUUID7()}`
|
|
43967
43515
|
},
|
|
43968
43516
|
signal
|
|
43969
43517
|
);
|
|
@@ -43985,11 +43533,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43985
43533
|
join18(stateDirectory, "sessions", `${createHash6("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
43986
43534
|
);
|
|
43987
43535
|
const operations = new DaemonOperationState();
|
|
43988
|
-
const
|
|
43989
|
-
const publisher = new DaemonSessionEventPublisher(
|
|
43990
|
-
new SessionEventOutbox(join18(stateDirectory, "events", `${channelHash}.sqlite`)),
|
|
43991
|
-
timer
|
|
43992
|
-
);
|
|
43536
|
+
const publisher = new DaemonSessionEventPublisher();
|
|
43993
43537
|
const activeTurns = new DaemonTurnRegistry(operations);
|
|
43994
43538
|
const recordSessionEvent = (sessionId, event) => {
|
|
43995
43539
|
publisher.publish(sessionId, activeTurns.recordEvent(event));
|