@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/cli.js
CHANGED
|
@@ -3381,7 +3381,7 @@ var program = new Command();
|
|
|
3381
3381
|
// package.json
|
|
3382
3382
|
var package_default = {
|
|
3383
3383
|
name: "@moxt-ai/mobius",
|
|
3384
|
-
version: "0.0.
|
|
3384
|
+
version: "0.0.155",
|
|
3385
3385
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
3386
3386
|
type: "module",
|
|
3387
3387
|
bin: {
|
|
@@ -29338,16 +29338,8 @@ function decodeSessionQueuedEvent(encoded) {
|
|
|
29338
29338
|
function decodeRuntimeLivenessReadyEvent(encoded) {
|
|
29339
29339
|
const value = parseJson2(encoded);
|
|
29340
29340
|
assertKind(value, RUNTIME_LIVENESS_READY_KIND);
|
|
29341
|
-
|
|
29342
|
-
|
|
29343
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
29344
|
-
}
|
|
29345
|
-
assertExactKeys(value, ["kind", "sessionEventDelivery"]);
|
|
29346
|
-
const sessionEventDelivery = readString2(value, "sessionEventDelivery", 32);
|
|
29347
|
-
if (sessionEventDelivery !== "reliable-v1") {
|
|
29348
|
-
throw new ProtocolMessageError("Unsupported Session event delivery mode");
|
|
29349
|
-
}
|
|
29350
|
-
return { kind: RUNTIME_LIVENESS_READY_KIND, sessionEventDelivery };
|
|
29341
|
+
assertExactKeys(value, ["kind"]);
|
|
29342
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
29351
29343
|
}
|
|
29352
29344
|
function decodeRuntimeHeartbeatEvent(encoded) {
|
|
29353
29345
|
const value = parseJson2(encoded);
|
|
@@ -29814,60 +29806,13 @@ var encodeNativeSessionCancel = (value) => JSON.stringify(nativeSessionCancelSch
|
|
|
29814
29806
|
|
|
29815
29807
|
// ../protocol/src/session-events.ts
|
|
29816
29808
|
var SESSION_EVENT_KIND = "session.event";
|
|
29817
|
-
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
29818
|
-
var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
|
|
29819
|
-
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
29820
29809
|
var SESSION_FORKED_KIND = "session.forked";
|
|
29821
|
-
var SessionEventRejectionCode = {
|
|
29822
|
-
IdempotencyConflict: "idempotency_conflict",
|
|
29823
|
-
InvalidEvent: "invalid_event",
|
|
29824
|
-
RecordingRejected: "recording_rejected"
|
|
29825
|
-
};
|
|
29826
29810
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
29827
|
-
var
|
|
29828
|
-
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
29829
|
-
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
29830
|
-
sessionId: identifierStringSchema
|
|
29831
|
-
}).readonly();
|
|
29832
|
-
var reliableDeliverySchema = external_exports.strictObject({
|
|
29833
|
-
eventId: identifierStringSchema,
|
|
29834
|
-
kind: external_exports.literal("reliable"),
|
|
29835
|
-
sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
|
|
29836
|
-
streamId: identifierStringSchema
|
|
29837
|
-
}).readonly();
|
|
29838
|
-
var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
|
|
29839
|
-
delivery: reliableDeliverySchema,
|
|
29811
|
+
var sessionEventEnvelopeSchema = external_exports.strictObject({
|
|
29840
29812
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
29841
29813
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
29842
29814
|
sessionId: identifierStringSchema
|
|
29843
29815
|
}).readonly();
|
|
29844
|
-
var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
|
|
29845
|
-
var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
29846
|
-
external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
|
|
29847
|
-
external_exports.strictObject({
|
|
29848
|
-
kind: external_exports.literal("recorded"),
|
|
29849
|
-
providerId: identifierStringSchema,
|
|
29850
|
-
recordingEpoch: identifierStringSchema
|
|
29851
|
-
}).readonly()
|
|
29852
|
-
]);
|
|
29853
|
-
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
29854
|
-
eventId: identifierStringSchema,
|
|
29855
|
-
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
29856
|
-
outcome: acknowledgementOutcomeSchema,
|
|
29857
|
-
sessionId: identifierStringSchema
|
|
29858
|
-
}).readonly();
|
|
29859
|
-
var eventDeferredSchema = external_exports.strictObject({
|
|
29860
|
-
eventId: identifierStringSchema,
|
|
29861
|
-
kind: external_exports.literal(SESSION_EVENT_DEFERRED_KIND),
|
|
29862
|
-
retryAfterMilliseconds: external_exports.number().int().min(100).max(6e4),
|
|
29863
|
-
sessionId: identifierStringSchema
|
|
29864
|
-
}).readonly();
|
|
29865
|
-
var eventRejectedSchema = external_exports.strictObject({
|
|
29866
|
-
code: external_exports.enum(SessionEventRejectionCode),
|
|
29867
|
-
eventId: identifierStringSchema,
|
|
29868
|
-
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
29869
|
-
sessionId: identifierStringSchema
|
|
29870
|
-
}).readonly();
|
|
29871
29816
|
var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
|
|
29872
29817
|
var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
|
|
29873
29818
|
var sessionForkedSchema = external_exports.strictObject({
|
|
@@ -29900,14 +29845,8 @@ var encode4 = (message, schema) => {
|
|
|
29900
29845
|
}
|
|
29901
29846
|
return JSON.stringify(decoded.data);
|
|
29902
29847
|
};
|
|
29903
|
-
var decodeSessionEventEnvelope = (encoded) => decode5(encoded,
|
|
29904
|
-
var encodeSessionEventEnvelope = (message) => encode4(message,
|
|
29905
|
-
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
29906
|
-
var encodeSessionEventAcknowledgement = (message) => encode4(message, eventAcknowledgementSchema);
|
|
29907
|
-
var decodeSessionEventDeferred = (encoded) => decode5(encoded, eventDeferredSchema);
|
|
29908
|
-
var encodeSessionEventDeferred = (message) => encode4(message, eventDeferredSchema);
|
|
29909
|
-
var decodeSessionEventRejected = (encoded) => decode5(encoded, eventRejectedSchema);
|
|
29910
|
-
var encodeSessionEventRejected = (message) => encode4(message, eventRejectedSchema);
|
|
29848
|
+
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, sessionEventEnvelopeSchema);
|
|
29849
|
+
var encodeSessionEventEnvelope = (message) => encode4(message, sessionEventEnvelopeSchema);
|
|
29911
29850
|
function decodeRecordedSessionEvent(encoded) {
|
|
29912
29851
|
const kind = decodeMessageKind(encoded);
|
|
29913
29852
|
switch (kind) {
|
|
@@ -30081,21 +30020,6 @@ var serviceToDaemonSignatures = {
|
|
|
30081
30020
|
encodeSessionElicitationRespondCommand,
|
|
30082
30021
|
decodeSessionElicitationRespondCommand
|
|
30083
30022
|
),
|
|
30084
|
-
[SESSION_EVENT_ACK_KIND]: defineMessageSignature(
|
|
30085
|
-
SESSION_EVENT_ACK_KIND,
|
|
30086
|
-
encodeSessionEventAcknowledgement,
|
|
30087
|
-
decodeSessionEventAcknowledgement
|
|
30088
|
-
),
|
|
30089
|
-
[SESSION_EVENT_DEFERRED_KIND]: defineMessageSignature(
|
|
30090
|
-
SESSION_EVENT_DEFERRED_KIND,
|
|
30091
|
-
encodeSessionEventDeferred,
|
|
30092
|
-
decodeSessionEventDeferred
|
|
30093
|
-
),
|
|
30094
|
-
[SESSION_EVENT_REJECTED_KIND]: defineMessageSignature(
|
|
30095
|
-
SESSION_EVENT_REJECTED_KIND,
|
|
30096
|
-
encodeSessionEventRejected,
|
|
30097
|
-
decodeSessionEventRejected
|
|
30098
|
-
),
|
|
30099
30023
|
[SESSION_LIVE_HISTORY_LOAD_KIND]: defineMessageSignature(
|
|
30100
30024
|
SESSION_LIVE_HISTORY_LOAD_KIND,
|
|
30101
30025
|
encodeSessionLiveHistoryLoad,
|
|
@@ -31154,7 +31078,7 @@ var AuditStore = class {
|
|
|
31154
31078
|
};
|
|
31155
31079
|
|
|
31156
31080
|
// src/run-daemon.ts
|
|
31157
|
-
import { createHash as createHash6, randomUUID as
|
|
31081
|
+
import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
|
|
31158
31082
|
import { join as join18 } from "node:path";
|
|
31159
31083
|
import { styleText } from "node:util";
|
|
31160
31084
|
|
|
@@ -46840,7 +46764,6 @@ async function runRelayConnection({
|
|
|
46840
46764
|
}) {
|
|
46841
46765
|
const relayUrl = new URL(config2.relayUrl);
|
|
46842
46766
|
relayUrl.searchParams.set("liveness", "1");
|
|
46843
|
-
relayUrl.searchParams.set("sessionEventDelivery", "reliable-v1");
|
|
46844
46767
|
const socket = await connectRelay(relayUrl, signal);
|
|
46845
46768
|
diagnostics.connectionOpened(connectionEpoch);
|
|
46846
46769
|
const connectionController = new AbortController();
|
|
@@ -46960,10 +46883,7 @@ async function runRelayConnection({
|
|
|
46960
46883
|
const message = decodeServiceToDaemonMessage(encoded);
|
|
46961
46884
|
const kind = message.kind;
|
|
46962
46885
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
46963
|
-
publisher.connect(
|
|
46964
|
-
socket,
|
|
46965
|
-
message.sessionEventDelivery === "reliable-v1" ? "reliable" : "ephemeral"
|
|
46966
|
-
);
|
|
46886
|
+
publisher.connect(socket);
|
|
46967
46887
|
connectionLiveness.start();
|
|
46968
46888
|
return;
|
|
46969
46889
|
}
|
|
@@ -46971,18 +46891,6 @@ async function runRelayConnection({
|
|
|
46971
46891
|
connectionLiveness.acknowledge(message);
|
|
46972
46892
|
return;
|
|
46973
46893
|
}
|
|
46974
|
-
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
46975
|
-
publisher.acknowledge(message);
|
|
46976
|
-
return;
|
|
46977
|
-
}
|
|
46978
|
-
if (kind === SESSION_EVENT_DEFERRED_KIND) {
|
|
46979
|
-
publisher.defer(message);
|
|
46980
|
-
return;
|
|
46981
|
-
}
|
|
46982
|
-
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
46983
|
-
publisher.quarantine(message);
|
|
46984
|
-
return;
|
|
46985
|
-
}
|
|
46986
46894
|
commands.handle(message);
|
|
46987
46895
|
} catch (error62) {
|
|
46988
46896
|
console.error("Mobius daemon rejected a message", error62);
|
|
@@ -47007,404 +46915,44 @@ async function runRelayConnection({
|
|
|
47007
46915
|
}
|
|
47008
46916
|
}
|
|
47009
46917
|
|
|
47010
|
-
// src/relay-connection/session-event-outbox.ts
|
|
47011
|
-
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
47012
|
-
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
47013
|
-
import { dirname as dirname6 } from "node:path";
|
|
47014
|
-
import { DatabaseSync } from "node:sqlite";
|
|
47015
|
-
var DEFAULT_STANDARD_EVENT_BYTES = 96 * 1024 * 1024;
|
|
47016
|
-
var DEFAULT_CRITICAL_EVENT_BYTES = 128 * 1024 * 1024;
|
|
47017
|
-
var MAX_DEAD_LETTERS = 1024;
|
|
47018
|
-
var DEFAULT_LIMITS = {
|
|
47019
|
-
criticalEventBytes: DEFAULT_CRITICAL_EVENT_BYTES,
|
|
47020
|
-
standardEventBytes: DEFAULT_STANDARD_EVENT_BYTES
|
|
47021
|
-
};
|
|
47022
|
-
var SessionEventOutboxCapacityError = class extends Error {
|
|
47023
|
-
code = "session_event_outbox_full";
|
|
47024
|
-
constructor() {
|
|
47025
|
-
super("The persistent Session event outbox is full");
|
|
47026
|
-
this.name = "SessionEventOutboxCapacityError";
|
|
47027
|
-
}
|
|
47028
|
-
};
|
|
47029
|
-
function rowNumber(row, field) {
|
|
47030
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
47031
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
47032
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
47033
|
-
}
|
|
47034
|
-
return value;
|
|
47035
|
-
}
|
|
47036
|
-
function rowString(row, field) {
|
|
47037
|
-
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
47038
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
47039
|
-
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
47040
|
-
}
|
|
47041
|
-
return value;
|
|
47042
|
-
}
|
|
47043
|
-
function validateLimits(limits) {
|
|
47044
|
-
if (!Number.isSafeInteger(limits.standardEventBytes) || limits.standardEventBytes < 1 || !Number.isSafeInteger(limits.criticalEventBytes) || limits.criticalEventBytes < limits.standardEventBytes) {
|
|
47045
|
-
throw new Error("Session event outbox limits are invalid");
|
|
47046
|
-
}
|
|
47047
|
-
}
|
|
47048
|
-
var SessionEventOutbox = class {
|
|
47049
|
-
#database;
|
|
47050
|
-
#limits;
|
|
47051
|
-
constructor(path3, limits = DEFAULT_LIMITS) {
|
|
47052
|
-
validateLimits(limits);
|
|
47053
|
-
mkdirSync3(dirname6(path3), { mode: 448, recursive: true });
|
|
47054
|
-
this.#limits = limits;
|
|
47055
|
-
this.#database = new DatabaseSync(path3);
|
|
47056
|
-
this.#database.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; PRAGMA busy_timeout = 5000;");
|
|
47057
|
-
this.#database.exec(`
|
|
47058
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
47059
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47060
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
47061
|
-
session_id TEXT NOT NULL,
|
|
47062
|
-
source_seq INTEGER NOT NULL UNIQUE,
|
|
47063
|
-
byte_length INTEGER NOT NULL,
|
|
47064
|
-
envelope_json TEXT NOT NULL
|
|
47065
|
-
) STRICT;
|
|
47066
|
-
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
47067
|
-
ON relay_session_event_outbox(source_seq);
|
|
47068
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
47069
|
-
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
47070
|
-
stream_id TEXT NOT NULL,
|
|
47071
|
-
next_source_seq INTEGER NOT NULL,
|
|
47072
|
-
total_bytes INTEGER NOT NULL
|
|
47073
|
-
) STRICT;
|
|
47074
|
-
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
47075
|
-
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47076
|
-
event_id TEXT NOT NULL UNIQUE,
|
|
47077
|
-
session_id TEXT NOT NULL,
|
|
47078
|
-
rejection_code TEXT NOT NULL,
|
|
47079
|
-
envelope_json TEXT NOT NULL
|
|
47080
|
-
) STRICT;
|
|
47081
|
-
`);
|
|
47082
|
-
this.#database.prepare(
|
|
47083
|
-
`INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
47084
|
-
singleton, stream_id, next_source_seq, total_bytes
|
|
47085
|
-
) VALUES (1, ?, 1, 0)`
|
|
47086
|
-
).run(randomUUID7());
|
|
47087
|
-
}
|
|
47088
|
-
acknowledge = (acknowledgement) => this.#remove(acknowledgement.eventId, acknowledgement.sessionId);
|
|
47089
|
-
close = () => {
|
|
47090
|
-
this.#database.close();
|
|
47091
|
-
};
|
|
47092
|
-
enqueue = (sessionId, payload, critical) => {
|
|
47093
|
-
const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
|
|
47094
|
-
if (envelope2 === void 0) {
|
|
47095
|
-
throw new Error("The Session event outbox did not enqueue the event");
|
|
47096
|
-
}
|
|
47097
|
-
return envelope2;
|
|
47098
|
-
};
|
|
47099
|
-
enqueueBatch = (sessionId, payloads, critical) => {
|
|
47100
|
-
if (payloads.length < 1 || payloads.length > 32) {
|
|
47101
|
-
throw new Error("A Session event batch must contain between 1 and 32 events");
|
|
47102
|
-
}
|
|
47103
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
47104
|
-
try {
|
|
47105
|
-
const state = this.#database.prepare(
|
|
47106
|
-
`SELECT stream_id, next_source_seq, total_bytes
|
|
47107
|
-
FROM relay_session_event_outbox_state
|
|
47108
|
-
WHERE singleton = 1`
|
|
47109
|
-
).get();
|
|
47110
|
-
const sourceSeq = rowNumber(state, "next_source_seq");
|
|
47111
|
-
if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
|
|
47112
|
-
throw new Error("The Session event source sequence is exhausted");
|
|
47113
|
-
}
|
|
47114
|
-
const streamId = rowString(state, "stream_id");
|
|
47115
|
-
const stored = payloads.map((payload, index) => {
|
|
47116
|
-
const envelope2 = {
|
|
47117
|
-
delivery: {
|
|
47118
|
-
eventId: randomUUID7(),
|
|
47119
|
-
kind: "reliable",
|
|
47120
|
-
sourceSeq: (sourceSeq + index).toString(),
|
|
47121
|
-
streamId
|
|
47122
|
-
},
|
|
47123
|
-
kind: SESSION_EVENT_KIND,
|
|
47124
|
-
payload,
|
|
47125
|
-
sessionId
|
|
47126
|
-
};
|
|
47127
|
-
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
47128
|
-
return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
|
|
47129
|
-
});
|
|
47130
|
-
const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
|
|
47131
|
-
const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
|
|
47132
|
-
if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
|
|
47133
|
-
throw new SessionEventOutboxCapacityError();
|
|
47134
|
-
}
|
|
47135
|
-
const insert = this.#database.prepare(
|
|
47136
|
-
`INSERT INTO relay_session_event_outbox (
|
|
47137
|
-
event_id, session_id, source_seq, byte_length, envelope_json
|
|
47138
|
-
) VALUES (?, ?, ?, ?, ?)`
|
|
47139
|
-
);
|
|
47140
|
-
for (const entry of stored) {
|
|
47141
|
-
insert.run(
|
|
47142
|
-
entry.envelope.delivery.eventId,
|
|
47143
|
-
sessionId,
|
|
47144
|
-
Number(entry.envelope.delivery.sourceSeq),
|
|
47145
|
-
entry.byteLength,
|
|
47146
|
-
entry.encoded
|
|
47147
|
-
);
|
|
47148
|
-
}
|
|
47149
|
-
this.#database.prepare(
|
|
47150
|
-
`UPDATE relay_session_event_outbox_state
|
|
47151
|
-
SET next_source_seq = next_source_seq + ?,
|
|
47152
|
-
total_bytes = total_bytes + ?
|
|
47153
|
-
WHERE singleton = 1`
|
|
47154
|
-
).run(stored.length, byteLength);
|
|
47155
|
-
this.#database.exec("COMMIT");
|
|
47156
|
-
return stored.map((entry) => entry.envelope);
|
|
47157
|
-
} catch (error62) {
|
|
47158
|
-
this.#database.exec("ROLLBACK");
|
|
47159
|
-
throw error62;
|
|
47160
|
-
}
|
|
47161
|
-
};
|
|
47162
|
-
pending = (limit, excludedEventIds) => {
|
|
47163
|
-
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
47164
|
-
throw new Error("Session event replay limit must be a positive integer");
|
|
47165
|
-
}
|
|
47166
|
-
const exclusion = excludedEventIds.length === 0 ? "" : `WHERE event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`;
|
|
47167
|
-
return this.#database.prepare(
|
|
47168
|
-
`SELECT envelope_json
|
|
47169
|
-
FROM relay_session_event_outbox
|
|
47170
|
-
${exclusion}
|
|
47171
|
-
ORDER BY source_seq
|
|
47172
|
-
LIMIT ?`
|
|
47173
|
-
).all(...excludedEventIds, limit).map((row) => {
|
|
47174
|
-
const envelope2 = decodeSessionEventEnvelope(rowString(row, "envelope_json"));
|
|
47175
|
-
if (!("delivery" in envelope2)) {
|
|
47176
|
-
throw new Error("SQLite returned an invalid reliable Session event envelope");
|
|
47177
|
-
}
|
|
47178
|
-
return envelope2;
|
|
47179
|
-
});
|
|
47180
|
-
};
|
|
47181
|
-
quarantine = (rejection) => {
|
|
47182
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
47183
|
-
try {
|
|
47184
|
-
const stored = this.#database.prepare(
|
|
47185
|
-
`SELECT byte_length, envelope_json
|
|
47186
|
-
FROM relay_session_event_outbox
|
|
47187
|
-
WHERE event_id = ? AND session_id = ?`
|
|
47188
|
-
).get(rejection.eventId, rejection.sessionId);
|
|
47189
|
-
if (stored === void 0) {
|
|
47190
|
-
this.#database.exec("COMMIT");
|
|
47191
|
-
return false;
|
|
47192
|
-
}
|
|
47193
|
-
this.#database.prepare(
|
|
47194
|
-
`INSERT INTO relay_session_event_dead_letters (
|
|
47195
|
-
event_id, session_id, rejection_code, envelope_json
|
|
47196
|
-
) VALUES (?, ?, ?, ?)`
|
|
47197
|
-
).run(rejection.eventId, rejection.sessionId, rejection.code, rowString(stored, "envelope_json"));
|
|
47198
|
-
this.#deleteStored(rejection.eventId, rejection.sessionId, rowNumber(stored, "byte_length"));
|
|
47199
|
-
this.#database.prepare(
|
|
47200
|
-
`DELETE FROM relay_session_event_dead_letters
|
|
47201
|
-
WHERE ordinal NOT IN (
|
|
47202
|
-
SELECT ordinal FROM relay_session_event_dead_letters
|
|
47203
|
-
ORDER BY ordinal DESC LIMIT ?
|
|
47204
|
-
)`
|
|
47205
|
-
).run(MAX_DEAD_LETTERS);
|
|
47206
|
-
this.#database.exec("COMMIT");
|
|
47207
|
-
return true;
|
|
47208
|
-
} catch (error62) {
|
|
47209
|
-
this.#database.exec("ROLLBACK");
|
|
47210
|
-
throw error62;
|
|
47211
|
-
}
|
|
47212
|
-
};
|
|
47213
|
-
#deleteStored = (eventId, sessionId, byteLength) => {
|
|
47214
|
-
const deletion = this.#database.prepare(
|
|
47215
|
-
`DELETE FROM relay_session_event_outbox
|
|
47216
|
-
WHERE event_id = ? AND session_id = ?`
|
|
47217
|
-
).run(eventId, sessionId);
|
|
47218
|
-
if (deletion.changes !== 1) {
|
|
47219
|
-
throw new Error("The Session event could not be removed from the outbox");
|
|
47220
|
-
}
|
|
47221
|
-
const state = this.#database.prepare(
|
|
47222
|
-
`UPDATE relay_session_event_outbox_state
|
|
47223
|
-
SET total_bytes = total_bytes - ?
|
|
47224
|
-
WHERE singleton = 1 AND total_bytes >= ?`
|
|
47225
|
-
).run(byteLength, byteLength);
|
|
47226
|
-
if (state.changes !== 1) {
|
|
47227
|
-
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
47228
|
-
}
|
|
47229
|
-
};
|
|
47230
|
-
#remove = (eventId, sessionId) => {
|
|
47231
|
-
this.#database.exec("BEGIN IMMEDIATE");
|
|
47232
|
-
try {
|
|
47233
|
-
const stored = this.#database.prepare(
|
|
47234
|
-
`SELECT byte_length
|
|
47235
|
-
FROM relay_session_event_outbox
|
|
47236
|
-
WHERE event_id = ? AND session_id = ?`
|
|
47237
|
-
).get(eventId, sessionId);
|
|
47238
|
-
if (stored === void 0) {
|
|
47239
|
-
this.#database.exec("COMMIT");
|
|
47240
|
-
return false;
|
|
47241
|
-
}
|
|
47242
|
-
this.#deleteStored(eventId, sessionId, rowNumber(stored, "byte_length"));
|
|
47243
|
-
this.#database.exec("COMMIT");
|
|
47244
|
-
return true;
|
|
47245
|
-
} catch (error62) {
|
|
47246
|
-
this.#database.exec("ROLLBACK");
|
|
47247
|
-
throw error62;
|
|
47248
|
-
}
|
|
47249
|
-
};
|
|
47250
|
-
};
|
|
47251
|
-
|
|
47252
46918
|
// src/relay-connection/session-event-publisher.ts
|
|
47253
46919
|
import { WebSocket as WebSocket9 } from "undici";
|
|
47254
|
-
var
|
|
47255
|
-
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
47256
|
-
function reservesSessionEventCapacity(event) {
|
|
47257
|
-
if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
|
|
47258
|
-
return true;
|
|
47259
|
-
}
|
|
47260
|
-
return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
|
|
47261
|
-
}
|
|
46920
|
+
var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
|
|
47262
46921
|
var DaemonSessionEventPublisher = class {
|
|
47263
|
-
#
|
|
47264
|
-
|
|
47265
|
-
|
|
47266
|
-
#timer;
|
|
47267
|
-
#connection = { kind: "disconnected" };
|
|
47268
|
-
#deferredReplay = null;
|
|
47269
|
-
#inFlightBytes = 0;
|
|
47270
|
-
constructor(outbox, timer) {
|
|
47271
|
-
this.#outbox = outbox;
|
|
47272
|
-
this.#timer = timer;
|
|
47273
|
-
}
|
|
47274
|
-
acknowledge = (acknowledgement) => {
|
|
47275
|
-
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
47276
|
-
return;
|
|
47277
|
-
}
|
|
47278
|
-
this.#removeInFlight(acknowledgement.eventId);
|
|
47279
|
-
this.#publishNextBatch();
|
|
47280
|
-
};
|
|
47281
|
-
close = () => {
|
|
47282
|
-
this.#deferredReplay?.cancel();
|
|
47283
|
-
this.#deferredReplay = null;
|
|
47284
|
-
this.#connection = { kind: "disconnected" };
|
|
47285
|
-
this.#clearInFlight();
|
|
47286
|
-
this.#outbox.close();
|
|
47287
|
-
};
|
|
47288
|
-
connect = (socket, delivery) => {
|
|
47289
|
-
this.#connection = { delivery, kind: "connected", socket };
|
|
47290
|
-
this.#clearInFlight();
|
|
47291
|
-
this.#publishNextBatch();
|
|
47292
|
-
};
|
|
47293
|
-
defer = (deferred) => {
|
|
47294
|
-
if (!this.#inFlight.has(deferred.eventId)) {
|
|
47295
|
-
return;
|
|
47296
|
-
}
|
|
47297
|
-
this.#clearInFlight();
|
|
47298
|
-
if (this.#deferredReplay !== null) {
|
|
47299
|
-
return;
|
|
47300
|
-
}
|
|
47301
|
-
this.#deferredReplay = this.#timer.schedule(() => {
|
|
47302
|
-
this.#deferredReplay = null;
|
|
47303
|
-
this.#publishNextBatch();
|
|
47304
|
-
}, deferred.retryAfterMilliseconds);
|
|
46922
|
+
#socket = null;
|
|
46923
|
+
connect = (socket) => {
|
|
46924
|
+
this.#socket = socket;
|
|
47305
46925
|
};
|
|
47306
46926
|
disconnect = (socket) => {
|
|
47307
|
-
if (this.#
|
|
47308
|
-
|
|
47309
|
-
}
|
|
47310
|
-
this.#connection = { kind: "disconnected" };
|
|
47311
|
-
this.#clearInFlight();
|
|
47312
|
-
};
|
|
47313
|
-
publish = (sessionId, event) => {
|
|
47314
|
-
try {
|
|
47315
|
-
this.#outbox.enqueue(sessionId, encodeRecordedSessionEvent(event), reservesSessionEventCapacity(event));
|
|
47316
|
-
} catch (error62) {
|
|
47317
|
-
if (!(error62 instanceof SessionEventOutboxCapacityError)) {
|
|
47318
|
-
throw error62;
|
|
47319
|
-
}
|
|
47320
|
-
if (!this.#reportedCapacityKinds.has(event.kind)) {
|
|
47321
|
-
this.#reportedCapacityKinds.add(event.kind);
|
|
47322
|
-
console.warn(
|
|
47323
|
-
`Mobius daemon could not persist "${event.kind}" because the Session event outbox is full`
|
|
47324
|
-
);
|
|
47325
|
-
}
|
|
47326
|
-
return;
|
|
47327
|
-
}
|
|
47328
|
-
this.#publishNextBatch();
|
|
47329
|
-
};
|
|
47330
|
-
publishBatch = (sessionId, events) => {
|
|
47331
|
-
const critical = events.some(reservesSessionEventCapacity);
|
|
47332
|
-
this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
|
|
47333
|
-
this.#publishNextBatch();
|
|
47334
|
-
};
|
|
47335
|
-
quarantine = (rejection) => {
|
|
47336
|
-
if (!this.#outbox.quarantine(rejection)) {
|
|
47337
|
-
return;
|
|
46927
|
+
if (this.#socket === socket) {
|
|
46928
|
+
this.#socket = null;
|
|
47338
46929
|
}
|
|
47339
|
-
this.#removeInFlight(rejection.eventId);
|
|
47340
|
-
console.error(`Mobius Relay rejected Session event ${rejection.eventId} with code ${rejection.code}`);
|
|
47341
|
-
this.#publishNextBatch();
|
|
47342
46930
|
};
|
|
47343
|
-
|
|
47344
|
-
this.#
|
|
47345
|
-
this.#inFlightBytes = 0;
|
|
46931
|
+
close = () => {
|
|
46932
|
+
this.#socket = null;
|
|
47346
46933
|
};
|
|
47347
|
-
|
|
47348
|
-
|
|
46934
|
+
publish = (sessionId, event) => {
|
|
46935
|
+
const socket = this.#socket;
|
|
46936
|
+
if (socket === null || socket.readyState !== WebSocket9.OPEN) {
|
|
47349
46937
|
return;
|
|
47350
46938
|
}
|
|
47351
|
-
|
|
47352
|
-
|
|
47353
|
-
|
|
47354
|
-
|
|
47355
|
-
|
|
47356
|
-
|
|
47357
|
-
|
|
47358
|
-
this.#connection.delivery === "reliable" ? envelope2 : {
|
|
47359
|
-
kind: envelope2.kind,
|
|
47360
|
-
payload: envelope2.payload,
|
|
47361
|
-
sessionId: envelope2.sessionId
|
|
47362
|
-
}
|
|
47363
|
-
);
|
|
47364
|
-
const byteLength = Buffer.byteLength(encoded, "utf8");
|
|
47365
|
-
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
47366
|
-
return;
|
|
47367
|
-
}
|
|
47368
|
-
if (!this.#send(encoded)) {
|
|
47369
|
-
this.#clearInFlight();
|
|
47370
|
-
return;
|
|
47371
|
-
}
|
|
47372
|
-
if (this.#connection.delivery === "ephemeral") {
|
|
47373
|
-
this.#outbox.acknowledge({
|
|
47374
|
-
eventId: envelope2.delivery.eventId,
|
|
47375
|
-
kind: "session.event.ack",
|
|
47376
|
-
outcome: { kind: "relayed" },
|
|
47377
|
-
sessionId: envelope2.sessionId
|
|
47378
|
-
});
|
|
47379
|
-
sent += 1;
|
|
47380
|
-
continue;
|
|
47381
|
-
}
|
|
47382
|
-
this.#inFlight.set(envelope2.delivery.eventId, { byteLength });
|
|
47383
|
-
this.#inFlightBytes += byteLength;
|
|
47384
|
-
sent += 1;
|
|
47385
|
-
}
|
|
47386
|
-
if (sent === 0) {
|
|
47387
|
-
return;
|
|
47388
|
-
}
|
|
47389
|
-
}
|
|
47390
|
-
};
|
|
47391
|
-
#removeInFlight = (eventId) => {
|
|
47392
|
-
const inFlight = this.#inFlight.get(eventId);
|
|
47393
|
-
if (inFlight === void 0) {
|
|
46939
|
+
const encoded = encodeDaemonToServiceMessage({
|
|
46940
|
+
kind: SESSION_EVENT_KIND,
|
|
46941
|
+
payload: encodeRecordedSessionEvent(event),
|
|
46942
|
+
sessionId
|
|
46943
|
+
});
|
|
46944
|
+
if (socket.bufferedAmount + Buffer.byteLength(encoded, "utf8") > MAX_BUFFERED_BYTES) {
|
|
46945
|
+
socket.close(1013, "Live event transport overloaded");
|
|
47394
46946
|
return;
|
|
47395
46947
|
}
|
|
47396
|
-
this.#inFlight.delete(eventId);
|
|
47397
|
-
this.#inFlightBytes -= inFlight.byteLength;
|
|
47398
|
-
};
|
|
47399
|
-
#send = (encoded) => {
|
|
47400
|
-
if (this.#connection.kind !== "connected" || this.#connection.socket.readyState !== WebSocket9.OPEN) {
|
|
47401
|
-
return false;
|
|
47402
|
-
}
|
|
47403
46948
|
try {
|
|
47404
|
-
|
|
47405
|
-
return true;
|
|
46949
|
+
socket.send(encoded);
|
|
47406
46950
|
} catch {
|
|
47407
|
-
|
|
46951
|
+
}
|
|
46952
|
+
};
|
|
46953
|
+
publishBatch = (sessionId, events) => {
|
|
46954
|
+
for (const event of events) {
|
|
46955
|
+
this.publish(sessionId, event);
|
|
47408
46956
|
}
|
|
47409
46957
|
};
|
|
47410
46958
|
};
|
|
@@ -47466,7 +47014,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
47466
47014
|
{
|
|
47467
47015
|
agentId: agent.id,
|
|
47468
47016
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
47469
|
-
requestId: `automatic-integration-${
|
|
47017
|
+
requestId: `automatic-integration-${randomUUID7()}`
|
|
47470
47018
|
},
|
|
47471
47019
|
signal
|
|
47472
47020
|
);
|
|
@@ -47488,11 +47036,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
47488
47036
|
join18(stateDirectory, "sessions", `${createHash6("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
47489
47037
|
);
|
|
47490
47038
|
const operations = new DaemonOperationState();
|
|
47491
|
-
const
|
|
47492
|
-
const publisher = new DaemonSessionEventPublisher(
|
|
47493
|
-
new SessionEventOutbox(join18(stateDirectory, "events", `${channelHash}.sqlite`)),
|
|
47494
|
-
timer
|
|
47495
|
-
);
|
|
47039
|
+
const publisher = new DaemonSessionEventPublisher();
|
|
47496
47040
|
const activeTurns = new DaemonTurnRegistry(operations);
|
|
47497
47041
|
const recordSessionEvent = (sessionId, event) => {
|
|
47498
47042
|
publisher.publish(sessionId, activeTurns.recordEvent(event));
|