@moxt-ai/mobius 0.0.26 → 0.0.27
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/agent-catalog/publish-agent-catalog.js +3 -3
- package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
- package/dist/cli.js +750 -54
- package/dist/cli.js.map +4 -4
- package/dist/index.js +742 -53
- package/dist/index.js.map +4 -4
- package/dist/prompt-artifact-resolver.d.ts.map +1 -1
- package/dist/prompt-artifact-resolver.js +7 -4
- package/dist/prompt-artifact-resolver.js.map +1 -1
- package/dist/relay-connection/connect.d.ts.map +1 -1
- package/dist/relay-connection/connect.js +3 -6
- package/dist/relay-connection/connect.js.map +1 -1
- package/dist/relay-connection/runtime-authentication.d.ts +3 -0
- package/dist/relay-connection/runtime-authentication.d.ts.map +1 -0
- package/dist/relay-connection/runtime-authentication.js +14 -0
- package/dist/relay-connection/runtime-authentication.js.map +1 -0
- package/dist/relay-connection/session-event-outbox.d.ts +32 -2
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +362 -11
- package/dist/relay-connection/session-event-outbox.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +272 -22
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +742 -53
- package/dist/runtime.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19340,6 +19340,9 @@ var SESSION_CANCEL_KIND = "session.cancel";
|
|
|
19340
19340
|
var RUNTIME_LIVENESS_READY_KIND = "runtime.liveness.ready";
|
|
19341
19341
|
var RUNTIME_HEARTBEAT_KIND = "runtime.heartbeat";
|
|
19342
19342
|
var RUNTIME_HEARTBEAT_ACK_KIND = "runtime.heartbeat.ack";
|
|
19343
|
+
var RUNTIME_DELIVERY_KIND = "runtime.delivery";
|
|
19344
|
+
var RUNTIME_DELIVERY_RECEIVED_KIND = "runtime.delivery.received";
|
|
19345
|
+
var RUNTIME_DELIVERY_COMMITTED_KIND = "runtime.delivery.committed";
|
|
19343
19346
|
var SESSION_STARTED_KIND = "session.started";
|
|
19344
19347
|
var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
|
|
19345
19348
|
var AGENT_ACTIVITY_KIND = "agent.activity";
|
|
@@ -19362,6 +19365,7 @@ var DIRECTORY_IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
|
|
|
19362
19365
|
var MAX_PROMPT_LENGTH = 1e4;
|
|
19363
19366
|
var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
|
|
19364
19367
|
var MAX_EVENT_TEXT_LENGTH = 1e5;
|
|
19368
|
+
var MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH = 8 * 1024 * 1024;
|
|
19365
19369
|
var ACTIVITY_TYPES = /* @__PURE__ */ new Set(["plan", "progress", "reasoning", "tool"]);
|
|
19366
19370
|
var ACTIVITY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "completed", "failed"]);
|
|
19367
19371
|
var TOOL_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -19640,6 +19644,37 @@ function decodeRuntimeHeartbeatAckEvent(encoded) {
|
|
|
19640
19644
|
kind: RUNTIME_HEARTBEAT_ACK_KIND
|
|
19641
19645
|
};
|
|
19642
19646
|
}
|
|
19647
|
+
function decodeRuntimeDelivery(encoded) {
|
|
19648
|
+
const value = parseJson2(encoded);
|
|
19649
|
+
assertExactKeys(value, ["deliveryId", "kind", "payload", "sessionId"]);
|
|
19650
|
+
assertKind(value, RUNTIME_DELIVERY_KIND);
|
|
19651
|
+
return {
|
|
19652
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
19653
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
19654
|
+
payload: readString(value, "payload", MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH),
|
|
19655
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
19656
|
+
};
|
|
19657
|
+
}
|
|
19658
|
+
function decodeRuntimeDeliveryReceived(encoded) {
|
|
19659
|
+
const value = parseJson2(encoded);
|
|
19660
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
19661
|
+
assertKind(value, RUNTIME_DELIVERY_RECEIVED_KIND);
|
|
19662
|
+
return {
|
|
19663
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
19664
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
19665
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
19666
|
+
};
|
|
19667
|
+
}
|
|
19668
|
+
function decodeRuntimeDeliveryCommitted(encoded) {
|
|
19669
|
+
const value = parseJson2(encoded);
|
|
19670
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
19671
|
+
assertKind(value, RUNTIME_DELIVERY_COMMITTED_KIND);
|
|
19672
|
+
return {
|
|
19673
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
19674
|
+
kind: RUNTIME_DELIVERY_COMMITTED_KIND,
|
|
19675
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
19676
|
+
};
|
|
19677
|
+
}
|
|
19643
19678
|
function decodeSessionStartedEvent(encoded) {
|
|
19644
19679
|
const value = parseJson2(encoded);
|
|
19645
19680
|
assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
|
|
@@ -19727,6 +19762,9 @@ function decodeSessionFailedEvent(encoded) {
|
|
|
19727
19762
|
function encodeRuntimeHeartbeatEvent(message) {
|
|
19728
19763
|
return JSON.stringify(decodeRuntimeHeartbeatEvent(JSON.stringify(message)));
|
|
19729
19764
|
}
|
|
19765
|
+
function encodeRuntimeDeliveryReceived(message) {
|
|
19766
|
+
return JSON.stringify(decodeRuntimeDeliveryReceived(JSON.stringify(message)));
|
|
19767
|
+
}
|
|
19730
19768
|
function encodeSessionStartedEvent(message) {
|
|
19731
19769
|
return JSON.stringify(decodeSessionStartedEvent(JSON.stringify(message)));
|
|
19732
19770
|
}
|
|
@@ -20425,7 +20463,8 @@ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
|
|
|
20425
20463
|
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
20426
20464
|
var SessionEventRejectionCode = {
|
|
20427
20465
|
SessionDeleted: "session_deleted",
|
|
20428
|
-
SessionNotFound: "session_not_found"
|
|
20466
|
+
SessionNotFound: "session_not_found",
|
|
20467
|
+
SessionRejected: "session_rejected"
|
|
20429
20468
|
};
|
|
20430
20469
|
var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
20431
20470
|
var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
|
|
@@ -27468,12 +27507,12 @@ function decodePairingResponse(value, credentialField, expectedKeys) {
|
|
|
27468
27507
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
27469
27508
|
}
|
|
27470
27509
|
const channelId = value["channelId"];
|
|
27471
|
-
const
|
|
27510
|
+
const runtimeCredential2 = value[credentialField];
|
|
27472
27511
|
const runtimeId = value["runtimeId"];
|
|
27473
|
-
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN6.test(channelId) || typeof
|
|
27512
|
+
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN6.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN6.test(runtimeId)) {
|
|
27474
27513
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
27475
27514
|
}
|
|
27476
|
-
return { channelId, runtimeCredential, runtimeId };
|
|
27515
|
+
return { channelId, runtimeCredential: runtimeCredential2, runtimeId };
|
|
27477
27516
|
}
|
|
27478
27517
|
async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
|
|
27479
27518
|
const agents = localAgents.map((agent) => ({
|
|
@@ -27508,7 +27547,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
27508
27547
|
}
|
|
27509
27548
|
return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
|
|
27510
27549
|
}
|
|
27511
|
-
async function persistConnection(channelId, relayOrigin,
|
|
27550
|
+
async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
|
|
27512
27551
|
const connectionsDirectory = join14(readStateDirectory(environment), "connections");
|
|
27513
27552
|
await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
|
|
27514
27553
|
const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
|
|
@@ -27520,7 +27559,7 @@ async function persistConnection(channelId, relayOrigin, runtimeCredential, defa
|
|
|
27520
27559
|
defaultWorkspace,
|
|
27521
27560
|
channelId,
|
|
27522
27561
|
relayOrigin: relayOrigin.toString(),
|
|
27523
|
-
runtimeCredential
|
|
27562
|
+
runtimeCredential: runtimeCredential2
|
|
27524
27563
|
},
|
|
27525
27564
|
null,
|
|
27526
27565
|
2
|
|
@@ -27537,16 +27576,16 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
27537
27576
|
}
|
|
27538
27577
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
27539
27578
|
const channelId = value["channelId"];
|
|
27540
|
-
const
|
|
27579
|
+
const runtimeCredential2 = value["runtimeCredential"] ?? value["daemonToken"];
|
|
27541
27580
|
const relayOrigin = value["relayOrigin"];
|
|
27542
|
-
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN6.test(channelId) || typeof
|
|
27581
|
+
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN6.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
|
|
27543
27582
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
27544
27583
|
}
|
|
27545
27584
|
return {
|
|
27546
27585
|
defaultWorkspace,
|
|
27547
27586
|
channelId,
|
|
27548
27587
|
relayOrigin: parseRelayOrigin(relayOrigin),
|
|
27549
|
-
runtimeCredential
|
|
27588
|
+
runtimeCredential: runtimeCredential2
|
|
27550
27589
|
};
|
|
27551
27590
|
}
|
|
27552
27591
|
async function readSavedConnection(channelId, environment) {
|
|
@@ -27669,6 +27708,23 @@ import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
|
|
|
27669
27708
|
|
|
27670
27709
|
// src/agent-catalog/publish-agent-catalog.ts
|
|
27671
27710
|
import { fetch as fetch4 } from "undici";
|
|
27711
|
+
|
|
27712
|
+
// src/relay-connection/runtime-authentication.ts
|
|
27713
|
+
function runtimeCredential(relayUrl) {
|
|
27714
|
+
return relayUrl.searchParams.get("token") ?? "";
|
|
27715
|
+
}
|
|
27716
|
+
function runtimeAuthorization(relayUrl) {
|
|
27717
|
+
const credential = runtimeCredential(relayUrl);
|
|
27718
|
+
return credential.length === 0 ? {} : { authorization: `Bearer ${credential}` };
|
|
27719
|
+
}
|
|
27720
|
+
function relayHttpEndpoint(relayUrl) {
|
|
27721
|
+
const endpoint = new URL(relayUrl);
|
|
27722
|
+
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
27723
|
+
endpoint.search = "";
|
|
27724
|
+
return endpoint;
|
|
27725
|
+
}
|
|
27726
|
+
|
|
27727
|
+
// src/agent-catalog/publish-agent-catalog.ts
|
|
27672
27728
|
var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
|
|
27673
27729
|
var AgentCatalogPublishError = class extends Error {
|
|
27674
27730
|
code = "agent_catalog_update_failed";
|
|
@@ -27678,8 +27734,7 @@ var AgentCatalogPublishError = class extends Error {
|
|
|
27678
27734
|
}
|
|
27679
27735
|
};
|
|
27680
27736
|
function catalogEndpoint(config2) {
|
|
27681
|
-
const endpoint =
|
|
27682
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
27737
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
27683
27738
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
27684
27739
|
endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/catalog`;
|
|
27685
27740
|
return endpoint;
|
|
@@ -27710,7 +27765,7 @@ async function publishAgentCatalog(config2, signal) {
|
|
|
27710
27765
|
installableAgents: catalog.installableAgents
|
|
27711
27766
|
}),
|
|
27712
27767
|
dispatcher: environmentProxyDispatcher,
|
|
27713
|
-
headers: { "content-type": "application/json" },
|
|
27768
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
27714
27769
|
method: "PUT",
|
|
27715
27770
|
signal: requestSignal
|
|
27716
27771
|
});
|
|
@@ -29066,8 +29121,7 @@ function parseReference(resource) {
|
|
|
29066
29121
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
29067
29122
|
}
|
|
29068
29123
|
function downloadUrl(config2, command, reference) {
|
|
29069
|
-
const url2 =
|
|
29070
|
-
url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
|
|
29124
|
+
const url2 = relayHttpEndpoint(config2.relayUrl);
|
|
29071
29125
|
let channelPath = "";
|
|
29072
29126
|
if (url2.pathname.endsWith("/daemon")) {
|
|
29073
29127
|
channelPath = url2.pathname.slice(0, -"/daemon".length);
|
|
@@ -29079,7 +29133,6 @@ function downloadUrl(config2, command, reference) {
|
|
|
29079
29133
|
channelPath = `${url2.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
29080
29134
|
}
|
|
29081
29135
|
url2.pathname = `${channelPath}/sessions/${encodeURIComponent(command.sessionId)}/commands/${encodeURIComponent(command.commandId)}/artifacts/${encodeURIComponent(reference.artifactId)}/content`;
|
|
29082
|
-
url2.searchParams.delete("liveness");
|
|
29083
29136
|
return url2;
|
|
29084
29137
|
}
|
|
29085
29138
|
async function responseBytes(response, expectedByteLength, signal) {
|
|
@@ -29130,7 +29183,11 @@ async function download(config2, command, reference, signal) {
|
|
|
29130
29183
|
try {
|
|
29131
29184
|
response = await fetch5(downloadUrl(config2, command, reference), {
|
|
29132
29185
|
dispatcher: environmentProxyDispatcher,
|
|
29133
|
-
headers: {
|
|
29186
|
+
headers: {
|
|
29187
|
+
accept: reference.resource.mimeType,
|
|
29188
|
+
"accept-encoding": "identity",
|
|
29189
|
+
...runtimeAuthorization(config2.relayUrl)
|
|
29190
|
+
},
|
|
29134
29191
|
signal: requestSignal
|
|
29135
29192
|
});
|
|
29136
29193
|
if (!response.ok) {
|
|
@@ -29240,12 +29297,8 @@ function connectRelay(url2, signal) {
|
|
|
29240
29297
|
signal.throwIfAborted();
|
|
29241
29298
|
return new Promise((resolve6, reject) => {
|
|
29242
29299
|
const endpoint = new URL(url2);
|
|
29243
|
-
const headers =
|
|
29244
|
-
|
|
29245
|
-
const runtimeCredential = endpoint.searchParams.get("token") ?? "";
|
|
29246
|
-
endpoint.searchParams.delete("token");
|
|
29247
|
-
headers["authorization"] = `Bearer ${runtimeCredential}`;
|
|
29248
|
-
}
|
|
29300
|
+
const headers = runtimeAuthorization(endpoint);
|
|
29301
|
+
endpoint.searchParams.delete("token");
|
|
29249
29302
|
const socket = new WebSocket(endpoint, {
|
|
29250
29303
|
dispatcher: environmentProxyDispatcher,
|
|
29251
29304
|
headers
|
|
@@ -29568,6 +29621,42 @@ var RelayConnectionLiveness = class {
|
|
|
29568
29621
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
29569
29622
|
import { dirname as dirname7 } from "node:path";
|
|
29570
29623
|
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
29624
|
+
var DEFAULT_OUTBOX_LIMITS = {
|
|
29625
|
+
criticalEventBytes: 136 * 1024 * 1024,
|
|
29626
|
+
criticalEventCount: 10128,
|
|
29627
|
+
runtimeDeliveryBytes: 64 * 1024 * 1024,
|
|
29628
|
+
runtimeDeliveryCount: 64,
|
|
29629
|
+
standardEventBytes: 128 * 1024 * 1024,
|
|
29630
|
+
standardEventCount: 1e4
|
|
29631
|
+
};
|
|
29632
|
+
var SessionEventOutboxCapacityError = class extends Error {
|
|
29633
|
+
code = "session_event_outbox_full";
|
|
29634
|
+
constructor() {
|
|
29635
|
+
super("The durable Session event outbox is full");
|
|
29636
|
+
this.name = "SessionEventOutboxCapacityError";
|
|
29637
|
+
}
|
|
29638
|
+
};
|
|
29639
|
+
var RuntimeDeliveryInboxCapacityError = class extends Error {
|
|
29640
|
+
code = "runtime_delivery_inbox_full";
|
|
29641
|
+
constructor() {
|
|
29642
|
+
super("The durable Runtime delivery inbox is full");
|
|
29643
|
+
this.name = "RuntimeDeliveryInboxCapacityError";
|
|
29644
|
+
}
|
|
29645
|
+
};
|
|
29646
|
+
var StoredRuntimeDelivery = class {
|
|
29647
|
+
deliveryId;
|
|
29648
|
+
duplicate;
|
|
29649
|
+
payload;
|
|
29650
|
+
sessionId;
|
|
29651
|
+
state;
|
|
29652
|
+
constructor(deliveryId, sessionId, payload, state, duplicate) {
|
|
29653
|
+
this.deliveryId = deliveryId;
|
|
29654
|
+
this.duplicate = duplicate;
|
|
29655
|
+
this.payload = payload;
|
|
29656
|
+
this.sessionId = sessionId;
|
|
29657
|
+
this.state = state;
|
|
29658
|
+
}
|
|
29659
|
+
};
|
|
29571
29660
|
function readPendingEnvelope(row) {
|
|
29572
29661
|
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
29573
29662
|
throw new Error("SQLite returned an invalid session event outbox row");
|
|
@@ -29578,9 +29667,26 @@ function readPendingEnvelope(row) {
|
|
|
29578
29667
|
}
|
|
29579
29668
|
return envelope2;
|
|
29580
29669
|
}
|
|
29670
|
+
function rowNumber(row, field) {
|
|
29671
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29672
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
29673
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29674
|
+
}
|
|
29675
|
+
return value;
|
|
29676
|
+
}
|
|
29677
|
+
function rowString2(row, field) {
|
|
29678
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29679
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
29680
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29681
|
+
}
|
|
29682
|
+
return value;
|
|
29683
|
+
}
|
|
29581
29684
|
var SessionEventOutbox = class {
|
|
29582
29685
|
#database;
|
|
29583
|
-
|
|
29686
|
+
#limits;
|
|
29687
|
+
constructor(path2, limits = DEFAULT_OUTBOX_LIMITS) {
|
|
29688
|
+
validateLimits(limits);
|
|
29689
|
+
this.#limits = limits;
|
|
29584
29690
|
mkdirSync3(dirname7(path2), { recursive: true });
|
|
29585
29691
|
this.#database = new DatabaseSync4(path2);
|
|
29586
29692
|
this.#database.exec(`
|
|
@@ -29589,6 +29695,7 @@ var SessionEventOutbox = class {
|
|
|
29589
29695
|
event_id TEXT NOT NULL UNIQUE,
|
|
29590
29696
|
session_id TEXT NOT NULL,
|
|
29591
29697
|
source_key TEXT NOT NULL,
|
|
29698
|
+
byte_length INTEGER NOT NULL,
|
|
29592
29699
|
envelope_json TEXT NOT NULL
|
|
29593
29700
|
) STRICT;
|
|
29594
29701
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
@@ -29599,7 +29706,7 @@ var SessionEventOutbox = class {
|
|
|
29599
29706
|
session_id TEXT NOT NULL,
|
|
29600
29707
|
envelope_json TEXT NOT NULL,
|
|
29601
29708
|
rejection_code TEXT NOT NULL CHECK (
|
|
29602
|
-
rejection_code IN ('session_deleted', 'session_not_found')
|
|
29709
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
29603
29710
|
)
|
|
29604
29711
|
) STRICT;
|
|
29605
29712
|
CREATE TABLE IF NOT EXISTS relay_session_event_sources (
|
|
@@ -29615,7 +29722,53 @@ var SessionEventOutbox = class {
|
|
|
29615
29722
|
state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
|
|
29616
29723
|
)
|
|
29617
29724
|
) STRICT;
|
|
29725
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
29726
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
29727
|
+
event_count INTEGER NOT NULL,
|
|
29728
|
+
total_bytes INTEGER NOT NULL
|
|
29729
|
+
) STRICT;
|
|
29730
|
+
INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
29731
|
+
singleton, event_count, total_bytes
|
|
29732
|
+
) VALUES (1, 0, 0);
|
|
29733
|
+
CREATE TABLE IF NOT EXISTS relay_runtime_deliveries (
|
|
29734
|
+
delivery_id TEXT PRIMARY KEY,
|
|
29735
|
+
session_id TEXT NOT NULL,
|
|
29736
|
+
payload_json TEXT NOT NULL,
|
|
29737
|
+
payload_bytes INTEGER NOT NULL,
|
|
29738
|
+
state TEXT NOT NULL CHECK (
|
|
29739
|
+
state IN ('received', 'relay_committed', 'processed')
|
|
29740
|
+
),
|
|
29741
|
+
received_at INTEGER NOT NULL
|
|
29742
|
+
) STRICT;
|
|
29618
29743
|
`);
|
|
29744
|
+
const deadLetterTable = this.#database.prepare(
|
|
29745
|
+
`SELECT sql FROM sqlite_master
|
|
29746
|
+
WHERE type = 'table' AND name = 'relay_session_event_dead_letters'`
|
|
29747
|
+
).get();
|
|
29748
|
+
const deadLetterSql = typeof deadLetterTable === "object" && deadLetterTable !== null ? Reflect.get(deadLetterTable, "sql") : void 0;
|
|
29749
|
+
if (typeof deadLetterSql !== "string" || !deadLetterSql.includes("'session_rejected'")) {
|
|
29750
|
+
this.#database.exec(`
|
|
29751
|
+
BEGIN IMMEDIATE;
|
|
29752
|
+
ALTER TABLE relay_session_event_dead_letters
|
|
29753
|
+
RENAME TO relay_session_event_dead_letters_legacy;
|
|
29754
|
+
CREATE TABLE relay_session_event_dead_letters (
|
|
29755
|
+
ordinal INTEGER PRIMARY KEY,
|
|
29756
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
29757
|
+
session_id TEXT NOT NULL,
|
|
29758
|
+
envelope_json TEXT NOT NULL,
|
|
29759
|
+
rejection_code TEXT NOT NULL CHECK (
|
|
29760
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
29761
|
+
)
|
|
29762
|
+
) STRICT;
|
|
29763
|
+
INSERT INTO relay_session_event_dead_letters (
|
|
29764
|
+
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29765
|
+
)
|
|
29766
|
+
SELECT ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29767
|
+
FROM relay_session_event_dead_letters_legacy;
|
|
29768
|
+
DROP TABLE relay_session_event_dead_letters_legacy;
|
|
29769
|
+
COMMIT;
|
|
29770
|
+
`);
|
|
29771
|
+
}
|
|
29619
29772
|
const outboxColumns = this.#database.prepare("PRAGMA table_info(relay_session_event_outbox)").all();
|
|
29620
29773
|
const hasSourceKey = outboxColumns.some(
|
|
29621
29774
|
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "source_key"
|
|
@@ -29626,6 +29779,15 @@ var SessionEventOutbox = class {
|
|
|
29626
29779
|
ADD COLUMN source_key TEXT NOT NULL DEFAULT '';
|
|
29627
29780
|
`);
|
|
29628
29781
|
}
|
|
29782
|
+
const hasByteLength = outboxColumns.some(
|
|
29783
|
+
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "byte_length"
|
|
29784
|
+
);
|
|
29785
|
+
if (!hasByteLength) {
|
|
29786
|
+
this.#database.exec(`
|
|
29787
|
+
ALTER TABLE relay_session_event_outbox
|
|
29788
|
+
ADD COLUMN byte_length INTEGER NOT NULL DEFAULT 0;
|
|
29789
|
+
`);
|
|
29790
|
+
}
|
|
29629
29791
|
this.#database.exec(`
|
|
29630
29792
|
UPDATE relay_session_event_outbox
|
|
29631
29793
|
SET source_key = CASE json_extract(envelope_json, '$.source.kind')
|
|
@@ -29634,6 +29796,16 @@ var SessionEventOutbox = class {
|
|
|
29634
29796
|
ELSE 'runtime:' || session_id
|
|
29635
29797
|
END
|
|
29636
29798
|
WHERE source_key = '';
|
|
29799
|
+
UPDATE relay_session_event_outbox
|
|
29800
|
+
SET byte_length = length(CAST(envelope_json AS BLOB))
|
|
29801
|
+
WHERE byte_length = 0;
|
|
29802
|
+
UPDATE relay_session_event_outbox_state
|
|
29803
|
+
SET event_count = (SELECT COUNT(*) FROM relay_session_event_outbox),
|
|
29804
|
+
total_bytes = (
|
|
29805
|
+
SELECT COALESCE(SUM(byte_length), 0)
|
|
29806
|
+
FROM relay_session_event_outbox
|
|
29807
|
+
)
|
|
29808
|
+
WHERE singleton = 1;
|
|
29637
29809
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_source_order
|
|
29638
29810
|
ON relay_session_event_outbox(source_key, ordinal);
|
|
29639
29811
|
`);
|
|
@@ -29694,13 +29866,19 @@ var SessionEventOutbox = class {
|
|
|
29694
29866
|
const state = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
|
|
29695
29867
|
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
29696
29868
|
};
|
|
29697
|
-
acknowledge = (acknowledgement) => this.#
|
|
29698
|
-
`DELETE FROM relay_session_event_outbox
|
|
29699
|
-
WHERE event_id = ? AND session_id = ?`
|
|
29700
|
-
).run(acknowledgement.eventId, acknowledgement.sessionId).changes === 1;
|
|
29869
|
+
acknowledge = (acknowledgement) => this.#removeAcknowledgedEvent(acknowledgement.eventId, acknowledgement.sessionId);
|
|
29701
29870
|
quarantine = (rejection) => {
|
|
29702
29871
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
29703
29872
|
try {
|
|
29873
|
+
const stored = this.#database.prepare(
|
|
29874
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
29875
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29876
|
+
).get(rejection.eventId, rejection.sessionId);
|
|
29877
|
+
if (stored === void 0) {
|
|
29878
|
+
this.#database.exec("COMMIT");
|
|
29879
|
+
return false;
|
|
29880
|
+
}
|
|
29881
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
29704
29882
|
const insertion = this.#database.prepare(
|
|
29705
29883
|
`INSERT INTO relay_session_event_dead_letters (
|
|
29706
29884
|
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
@@ -29720,6 +29898,7 @@ var SessionEventOutbox = class {
|
|
|
29720
29898
|
if (deletion.changes !== 1) {
|
|
29721
29899
|
throw new Error("The rejected session event could not be removed from the durable outbox");
|
|
29722
29900
|
}
|
|
29901
|
+
this.#decrementEventState(byteLength);
|
|
29723
29902
|
this.#database.exec("COMMIT");
|
|
29724
29903
|
return true;
|
|
29725
29904
|
} catch (error61) {
|
|
@@ -29731,7 +29910,129 @@ var SessionEventOutbox = class {
|
|
|
29731
29910
|
this.#database.close();
|
|
29732
29911
|
};
|
|
29733
29912
|
enqueue = (sessionId, payload, attemptId = null) => {
|
|
29734
|
-
|
|
29913
|
+
return this.#enqueueBounded(
|
|
29914
|
+
sessionId,
|
|
29915
|
+
payload,
|
|
29916
|
+
attemptId ?? "",
|
|
29917
|
+
this.#limits.standardEventCount,
|
|
29918
|
+
this.#limits.standardEventBytes
|
|
29919
|
+
);
|
|
29920
|
+
};
|
|
29921
|
+
enqueueCritical = (sessionId, payload, attemptId = "") => this.#enqueueBounded(
|
|
29922
|
+
sessionId,
|
|
29923
|
+
payload,
|
|
29924
|
+
attemptId,
|
|
29925
|
+
this.#limits.criticalEventCount,
|
|
29926
|
+
this.#limits.criticalEventBytes
|
|
29927
|
+
);
|
|
29928
|
+
claimRuntimeDelivery = (delivery) => {
|
|
29929
|
+
const payloadBytes = new TextEncoder().encode(delivery.payload).byteLength;
|
|
29930
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29931
|
+
try {
|
|
29932
|
+
const existing = this.#database.prepare(
|
|
29933
|
+
`SELECT session_id, payload_json, state
|
|
29934
|
+
FROM relay_runtime_deliveries
|
|
29935
|
+
WHERE delivery_id = ?`
|
|
29936
|
+
).get(delivery.deliveryId);
|
|
29937
|
+
if (existing !== void 0) {
|
|
29938
|
+
const sessionId = rowString2(existing, "session_id");
|
|
29939
|
+
const payload = rowString2(existing, "payload_json");
|
|
29940
|
+
const state = runtimeDeliveryState(existing);
|
|
29941
|
+
if (sessionId !== delivery.sessionId || payload !== delivery.payload) {
|
|
29942
|
+
throw new Error("The Runtime delivery identity conflicts with its durable receipt");
|
|
29943
|
+
}
|
|
29944
|
+
this.#database.exec("COMMIT");
|
|
29945
|
+
return new StoredRuntimeDelivery(delivery.deliveryId, sessionId, payload, state, true);
|
|
29946
|
+
}
|
|
29947
|
+
const usage = this.#database.prepare(
|
|
29948
|
+
`SELECT COUNT(*) AS delivery_count,
|
|
29949
|
+
COALESCE(SUM(payload_bytes), 0) AS delivery_bytes
|
|
29950
|
+
FROM relay_runtime_deliveries`
|
|
29951
|
+
).get();
|
|
29952
|
+
if (rowNumber(usage, "delivery_count") + 1 > this.#limits.runtimeDeliveryCount || rowNumber(usage, "delivery_bytes") + payloadBytes > this.#limits.runtimeDeliveryBytes) {
|
|
29953
|
+
throw new RuntimeDeliveryInboxCapacityError();
|
|
29954
|
+
}
|
|
29955
|
+
this.#database.prepare(
|
|
29956
|
+
`INSERT INTO relay_runtime_deliveries (
|
|
29957
|
+
delivery_id, session_id, payload_json, payload_bytes, state, received_at
|
|
29958
|
+
) VALUES (?, ?, ?, ?, 'received', ?)`
|
|
29959
|
+
).run(delivery.deliveryId, delivery.sessionId, delivery.payload, payloadBytes, Date.now());
|
|
29960
|
+
this.#database.exec("COMMIT");
|
|
29961
|
+
return new StoredRuntimeDelivery(
|
|
29962
|
+
delivery.deliveryId,
|
|
29963
|
+
delivery.sessionId,
|
|
29964
|
+
delivery.payload,
|
|
29965
|
+
"received",
|
|
29966
|
+
false
|
|
29967
|
+
);
|
|
29968
|
+
} catch (error61) {
|
|
29969
|
+
this.#database.exec("ROLLBACK");
|
|
29970
|
+
throw error61;
|
|
29971
|
+
}
|
|
29972
|
+
};
|
|
29973
|
+
markRuntimeDeliveryCommitted = (deliveryId, sessionId) => {
|
|
29974
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29975
|
+
try {
|
|
29976
|
+
const row = this.#database.prepare(
|
|
29977
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
29978
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
29979
|
+
).get(deliveryId, sessionId);
|
|
29980
|
+
if (row === void 0) {
|
|
29981
|
+
this.#database.exec("COMMIT");
|
|
29982
|
+
return false;
|
|
29983
|
+
}
|
|
29984
|
+
const state = runtimeDeliveryState(row);
|
|
29985
|
+
if (state === "processed") {
|
|
29986
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
29987
|
+
} else if (state === "received") {
|
|
29988
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'relay_committed' WHERE delivery_id = ?`).run(deliveryId);
|
|
29989
|
+
}
|
|
29990
|
+
this.#database.exec("COMMIT");
|
|
29991
|
+
return true;
|
|
29992
|
+
} catch (error61) {
|
|
29993
|
+
this.#database.exec("ROLLBACK");
|
|
29994
|
+
throw error61;
|
|
29995
|
+
}
|
|
29996
|
+
};
|
|
29997
|
+
markRuntimeDeliveryProcessed = (deliveryId, sessionId) => {
|
|
29998
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29999
|
+
try {
|
|
30000
|
+
const row = this.#database.prepare(
|
|
30001
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
30002
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
30003
|
+
).get(deliveryId, sessionId);
|
|
30004
|
+
if (row === void 0) {
|
|
30005
|
+
this.#database.exec("COMMIT");
|
|
30006
|
+
return false;
|
|
30007
|
+
}
|
|
30008
|
+
const state = runtimeDeliveryState(row);
|
|
30009
|
+
if (state === "relay_committed") {
|
|
30010
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
30011
|
+
} else if (state === "received") {
|
|
30012
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'processed' WHERE delivery_id = ?`).run(deliveryId);
|
|
30013
|
+
}
|
|
30014
|
+
this.#database.exec("COMMIT");
|
|
30015
|
+
return true;
|
|
30016
|
+
} catch (error61) {
|
|
30017
|
+
this.#database.exec("ROLLBACK");
|
|
30018
|
+
throw error61;
|
|
30019
|
+
}
|
|
30020
|
+
};
|
|
30021
|
+
runtimeDeliveries = () => this.#database.prepare(
|
|
30022
|
+
`SELECT delivery_id, session_id, payload_json, state
|
|
30023
|
+
FROM relay_runtime_deliveries
|
|
30024
|
+
ORDER BY received_at, delivery_id`
|
|
30025
|
+
).all().map(
|
|
30026
|
+
(row) => new StoredRuntimeDelivery(
|
|
30027
|
+
rowString2(row, "delivery_id"),
|
|
30028
|
+
rowString2(row, "session_id"),
|
|
30029
|
+
rowString2(row, "payload_json"),
|
|
30030
|
+
runtimeDeliveryState(row),
|
|
30031
|
+
true
|
|
30032
|
+
)
|
|
30033
|
+
);
|
|
30034
|
+
#enqueueBounded = (sessionId, payload, attemptId, maximumEventCount, maximumEventBytes) => {
|
|
30035
|
+
const sourceKey = attemptId.length === 0 ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
|
|
29735
30036
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
29736
30037
|
try {
|
|
29737
30038
|
const row = this.#database.prepare(
|
|
@@ -29748,13 +30049,22 @@ var SessionEventOutbox = class {
|
|
|
29748
30049
|
kind: SESSION_EVENT_KIND,
|
|
29749
30050
|
payload,
|
|
29750
30051
|
sessionId,
|
|
29751
|
-
source: attemptId ===
|
|
30052
|
+
source: attemptId.length === 0 ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
|
|
29752
30053
|
attemptId,
|
|
29753
30054
|
kind: "attempt",
|
|
29754
30055
|
sourceSeq: nextSourceSeq.toString()
|
|
29755
30056
|
}
|
|
29756
30057
|
};
|
|
29757
30058
|
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
30059
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
30060
|
+
const state = this.#database.prepare(
|
|
30061
|
+
`SELECT event_count, total_bytes
|
|
30062
|
+
FROM relay_session_event_outbox_state
|
|
30063
|
+
WHERE singleton = 1`
|
|
30064
|
+
).get();
|
|
30065
|
+
if (rowNumber(state, "event_count") + 1 > maximumEventCount || rowNumber(state, "total_bytes") + byteLength > maximumEventBytes) {
|
|
30066
|
+
throw new SessionEventOutboxCapacityError();
|
|
30067
|
+
}
|
|
29758
30068
|
this.#database.prepare(
|
|
29759
30069
|
`INSERT INTO relay_session_event_sources (
|
|
29760
30070
|
source_key, next_source_seq
|
|
@@ -29764,9 +30074,15 @@ var SessionEventOutbox = class {
|
|
|
29764
30074
|
).run(sourceKey, nextSourceSeq + 1);
|
|
29765
30075
|
this.#database.prepare(
|
|
29766
30076
|
`INSERT INTO relay_session_event_outbox (
|
|
29767
|
-
event_id, session_id, source_key, envelope_json
|
|
29768
|
-
) VALUES (?, ?, ?, ?)`
|
|
29769
|
-
).run(envelope2.eventId, envelope2.sessionId, sourceKey, encoded);
|
|
30077
|
+
event_id, session_id, source_key, byte_length, envelope_json
|
|
30078
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
30079
|
+
).run(envelope2.eventId, envelope2.sessionId, sourceKey, byteLength, encoded);
|
|
30080
|
+
this.#database.prepare(
|
|
30081
|
+
`UPDATE relay_session_event_outbox_state
|
|
30082
|
+
SET event_count = event_count + 1,
|
|
30083
|
+
total_bytes = total_bytes + ?
|
|
30084
|
+
WHERE singleton = 1`
|
|
30085
|
+
).run(byteLength);
|
|
29770
30086
|
this.#database.exec("COMMIT");
|
|
29771
30087
|
return encoded;
|
|
29772
30088
|
} catch (error61) {
|
|
@@ -29774,6 +30090,44 @@ var SessionEventOutbox = class {
|
|
|
29774
30090
|
throw error61;
|
|
29775
30091
|
}
|
|
29776
30092
|
};
|
|
30093
|
+
#removeAcknowledgedEvent = (eventId, sessionId) => {
|
|
30094
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
30095
|
+
try {
|
|
30096
|
+
const stored = this.#database.prepare(
|
|
30097
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
30098
|
+
WHERE event_id = ? AND session_id = ?`
|
|
30099
|
+
).get(eventId, sessionId);
|
|
30100
|
+
if (stored === void 0) {
|
|
30101
|
+
this.#database.exec("COMMIT");
|
|
30102
|
+
return false;
|
|
30103
|
+
}
|
|
30104
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
30105
|
+
const deletion = this.#database.prepare(
|
|
30106
|
+
`DELETE FROM relay_session_event_outbox
|
|
30107
|
+
WHERE event_id = ? AND session_id = ?`
|
|
30108
|
+
).run(eventId, sessionId);
|
|
30109
|
+
if (deletion.changes !== 1) {
|
|
30110
|
+
throw new Error("The acknowledged session event could not be removed from the durable outbox");
|
|
30111
|
+
}
|
|
30112
|
+
this.#decrementEventState(byteLength);
|
|
30113
|
+
this.#database.exec("COMMIT");
|
|
30114
|
+
return true;
|
|
30115
|
+
} catch (error61) {
|
|
30116
|
+
this.#database.exec("ROLLBACK");
|
|
30117
|
+
throw error61;
|
|
30118
|
+
}
|
|
30119
|
+
};
|
|
30120
|
+
#decrementEventState = (byteLength) => {
|
|
30121
|
+
const result = this.#database.prepare(
|
|
30122
|
+
`UPDATE relay_session_event_outbox_state
|
|
30123
|
+
SET event_count = event_count - 1,
|
|
30124
|
+
total_bytes = total_bytes - ?
|
|
30125
|
+
WHERE singleton = 1 AND event_count > 0 AND total_bytes >= ?`
|
|
30126
|
+
).run(byteLength, byteLength);
|
|
30127
|
+
if (result.changes !== 1) {
|
|
30128
|
+
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
30129
|
+
}
|
|
30130
|
+
};
|
|
29777
30131
|
pending = () => this.#database.prepare(
|
|
29778
30132
|
`SELECT envelope_json
|
|
29779
30133
|
FROM relay_session_event_outbox
|
|
@@ -29800,7 +30154,68 @@ var SessionEventOutbox = class {
|
|
|
29800
30154
|
LIMIT ?`
|
|
29801
30155
|
).all(limit).map(readPendingEnvelope);
|
|
29802
30156
|
};
|
|
30157
|
+
pendingSourceHeads = (limit, excludedEventIds, excludedSourceKeys) => {
|
|
30158
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
30159
|
+
throw new Error("Session event replay batch limit must be a positive integer");
|
|
30160
|
+
}
|
|
30161
|
+
const exclusions = [];
|
|
30162
|
+
const parameters = [];
|
|
30163
|
+
if (excludedEventIds.length > 0) {
|
|
30164
|
+
exclusions.push(`event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`);
|
|
30165
|
+
parameters.push(...excludedEventIds);
|
|
30166
|
+
}
|
|
30167
|
+
if (excludedSourceKeys.length > 0) {
|
|
30168
|
+
exclusions.push(`source_key NOT IN (${excludedSourceKeys.map(() => "?").join(", ")})`);
|
|
30169
|
+
parameters.push(...excludedSourceKeys);
|
|
30170
|
+
}
|
|
30171
|
+
parameters.push(limit.toString());
|
|
30172
|
+
const where = exclusions.length === 0 ? "" : `WHERE ${exclusions.join(" AND ")}`;
|
|
30173
|
+
return this.#database.prepare(
|
|
30174
|
+
`WITH available_events AS (
|
|
30175
|
+
SELECT ordinal, source_key
|
|
30176
|
+
FROM relay_session_event_outbox
|
|
30177
|
+
${where}
|
|
30178
|
+
), ranked_events AS (
|
|
30179
|
+
SELECT ordinal,
|
|
30180
|
+
ROW_NUMBER() OVER (
|
|
30181
|
+
PARTITION BY source_key
|
|
30182
|
+
ORDER BY ordinal
|
|
30183
|
+
) AS source_position
|
|
30184
|
+
FROM available_events
|
|
30185
|
+
)
|
|
30186
|
+
SELECT outbox.envelope_json
|
|
30187
|
+
FROM ranked_events AS ranked
|
|
30188
|
+
INNER JOIN relay_session_event_outbox AS outbox
|
|
30189
|
+
ON outbox.ordinal = ranked.ordinal
|
|
30190
|
+
WHERE ranked.source_position = 1
|
|
30191
|
+
ORDER BY outbox.ordinal
|
|
30192
|
+
LIMIT ?`
|
|
30193
|
+
).all(...parameters).map(readPendingEnvelope);
|
|
30194
|
+
};
|
|
29803
30195
|
};
|
|
30196
|
+
function validateLimits(limits) {
|
|
30197
|
+
const values = [
|
|
30198
|
+
limits.criticalEventBytes,
|
|
30199
|
+
limits.criticalEventCount,
|
|
30200
|
+
limits.runtimeDeliveryBytes,
|
|
30201
|
+
limits.runtimeDeliveryCount,
|
|
30202
|
+
limits.standardEventBytes,
|
|
30203
|
+
limits.standardEventCount
|
|
30204
|
+
];
|
|
30205
|
+
if (values.some((value) => !Number.isSafeInteger(value) || value < 1)) {
|
|
30206
|
+
throw new Error("Session event outbox limits must be positive integers");
|
|
30207
|
+
}
|
|
30208
|
+
if (limits.criticalEventBytes < limits.standardEventBytes || limits.criticalEventCount < limits.standardEventCount) {
|
|
30209
|
+
throw new Error("Critical Session event capacity must include the standard capacity");
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
30212
|
+
function runtimeDeliveryState(row) {
|
|
30213
|
+
const state = rowString2(row, "state");
|
|
30214
|
+
if (state !== "received" && state !== "relay_committed" && state !== "processed") {
|
|
30215
|
+
throw new Error("SQLite returned an invalid Runtime delivery state");
|
|
30216
|
+
}
|
|
30217
|
+
return state;
|
|
30218
|
+
}
|
|
29804
30219
|
function isDaemonExecutionState(value) {
|
|
29805
30220
|
return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
|
|
29806
30221
|
}
|
|
@@ -30019,8 +30434,7 @@ var ActiveTurnReconciliationError = class extends Error {
|
|
|
30019
30434
|
}
|
|
30020
30435
|
};
|
|
30021
30436
|
function activeTurnReconciliationEndpoint(config2, turn) {
|
|
30022
|
-
const endpoint =
|
|
30023
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
30437
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
30024
30438
|
let channelPath = "";
|
|
30025
30439
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
30026
30440
|
channelPath = endpoint.pathname.slice(0, -"/daemon".length);
|
|
@@ -30032,7 +30446,6 @@ function activeTurnReconciliationEndpoint(config2, turn) {
|
|
|
30032
30446
|
channelPath = `${endpoint.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
30033
30447
|
}
|
|
30034
30448
|
endpoint.pathname = `${channelPath}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
|
|
30035
|
-
endpoint.searchParams.delete("liveness");
|
|
30036
30449
|
return endpoint;
|
|
30037
30450
|
}
|
|
30038
30451
|
async function reconcileActiveTurn(config2, turn, signal) {
|
|
@@ -30044,7 +30457,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
30044
30457
|
response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
|
|
30045
30458
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
30046
30459
|
dispatcher: environmentProxyDispatcher,
|
|
30047
|
-
headers: { "content-type": "application/json" },
|
|
30460
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
30048
30461
|
method: "POST",
|
|
30049
30462
|
signal: requestSignal
|
|
30050
30463
|
});
|
|
@@ -30112,17 +30525,31 @@ var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectio
|
|
|
30112
30525
|
}
|
|
30113
30526
|
};
|
|
30114
30527
|
};
|
|
30115
|
-
var SESSION_EVENT_REPLAY_WINDOW =
|
|
30528
|
+
var SESSION_EVENT_REPLAY_WINDOW = 16;
|
|
30529
|
+
var SESSION_EVENT_SOURCE_REPLAY_WINDOW = 4;
|
|
30530
|
+
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
30531
|
+
var InFlightSessionEvent = class {
|
|
30532
|
+
byteLength;
|
|
30533
|
+
sourceKey;
|
|
30534
|
+
constructor(sourceKey, byteLength) {
|
|
30535
|
+
this.byteLength = byteLength;
|
|
30536
|
+
this.sourceKey = sourceKey;
|
|
30537
|
+
}
|
|
30538
|
+
};
|
|
30539
|
+
function sessionEventSourceKey(envelope2) {
|
|
30540
|
+
return envelope2.source.kind === "attempt" ? `attempt:${envelope2.sessionId}:${envelope2.source.attemptId}` : `runtime:${envelope2.sessionId}`;
|
|
30541
|
+
}
|
|
30116
30542
|
var DaemonSessionEventPublisher = class {
|
|
30117
30543
|
#outbox;
|
|
30118
|
-
#
|
|
30544
|
+
#inFlightEvents = /* @__PURE__ */ new Map();
|
|
30545
|
+
#inFlightBytes = 0;
|
|
30119
30546
|
#connection = new DisconnectedDaemonSessionEventState();
|
|
30120
30547
|
constructor(outbox) {
|
|
30121
30548
|
this.#outbox = outbox;
|
|
30122
30549
|
}
|
|
30123
30550
|
connect = (socket) => {
|
|
30124
30551
|
this.#connection = new ConnectedDaemonSessionEventState(socket);
|
|
30125
|
-
this.#
|
|
30552
|
+
this.#clearInFlight();
|
|
30126
30553
|
this.#publishNextBatch();
|
|
30127
30554
|
};
|
|
30128
30555
|
disconnect = (socket) => {
|
|
@@ -30130,10 +30557,15 @@ var DaemonSessionEventPublisher = class {
|
|
|
30130
30557
|
return;
|
|
30131
30558
|
}
|
|
30132
30559
|
this.#connection = this.#connection.disconnect(socket);
|
|
30133
|
-
this.#
|
|
30560
|
+
this.#clearInFlight();
|
|
30134
30561
|
};
|
|
30135
30562
|
recordAttempt = (sessionId, payload, attemptId) => {
|
|
30136
|
-
|
|
30563
|
+
const kind = decodeMessageKind(payload);
|
|
30564
|
+
if (kind === SESSION_COMPLETED_KIND || kind === SESSION_FAILED_KIND) {
|
|
30565
|
+
this.#outbox.enqueueCritical(sessionId, payload, attemptId);
|
|
30566
|
+
} else {
|
|
30567
|
+
this.#outbox.enqueue(sessionId, payload, attemptId);
|
|
30568
|
+
}
|
|
30137
30569
|
this.#publishNextBatch();
|
|
30138
30570
|
};
|
|
30139
30571
|
recordRuntime = (sessionId, payload) => {
|
|
@@ -30144,7 +30576,7 @@ var DaemonSessionEventPublisher = class {
|
|
|
30144
30576
|
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
30145
30577
|
return;
|
|
30146
30578
|
}
|
|
30147
|
-
this.#
|
|
30579
|
+
this.#removeInFlight(acknowledgement.eventId);
|
|
30148
30580
|
this.#publishNextBatch();
|
|
30149
30581
|
};
|
|
30150
30582
|
quarantine = (rejection) => {
|
|
@@ -30152,24 +30584,60 @@ var DaemonSessionEventPublisher = class {
|
|
|
30152
30584
|
if (!quarantined) {
|
|
30153
30585
|
return false;
|
|
30154
30586
|
}
|
|
30155
|
-
this.#
|
|
30587
|
+
this.#removeInFlight(rejection.eventId);
|
|
30156
30588
|
this.#publishNextBatch();
|
|
30157
30589
|
return true;
|
|
30158
30590
|
};
|
|
30159
30591
|
#publishNextBatch = () => {
|
|
30160
|
-
|
|
30161
|
-
|
|
30162
|
-
|
|
30163
|
-
|
|
30164
|
-
|
|
30165
|
-
const
|
|
30166
|
-
|
|
30167
|
-
this.#
|
|
30592
|
+
while (this.#inFlightEvents.size < SESSION_EVENT_REPLAY_WINDOW) {
|
|
30593
|
+
const sourceCounts = /* @__PURE__ */ new Map();
|
|
30594
|
+
for (const inFlight of this.#inFlightEvents.values()) {
|
|
30595
|
+
sourceCounts.set(inFlight.sourceKey, (sourceCounts.get(inFlight.sourceKey) ?? 0) + 1);
|
|
30596
|
+
}
|
|
30597
|
+
const saturatedSources = [...sourceCounts.entries()].filter(([, count]) => count >= SESSION_EVENT_SOURCE_REPLAY_WINDOW).map(([sourceKey]) => sourceKey);
|
|
30598
|
+
const batch = this.#outbox.pendingSourceHeads(
|
|
30599
|
+
SESSION_EVENT_REPLAY_WINDOW - this.#inFlightEvents.size,
|
|
30600
|
+
[...this.#inFlightEvents.keys()],
|
|
30601
|
+
saturatedSources
|
|
30602
|
+
);
|
|
30603
|
+
let sent = 0;
|
|
30604
|
+
for (const encoded of batch) {
|
|
30605
|
+
const envelope2 = decodeSessionEventEnvelope(encoded);
|
|
30606
|
+
const sourceKey = sessionEventSourceKey(envelope2);
|
|
30607
|
+
const sourceCount = sourceCounts.get(sourceKey) ?? 0;
|
|
30608
|
+
if (sourceCount >= SESSION_EVENT_SOURCE_REPLAY_WINDOW) {
|
|
30609
|
+
continue;
|
|
30610
|
+
}
|
|
30611
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
30612
|
+
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
30613
|
+
continue;
|
|
30614
|
+
}
|
|
30615
|
+
if (!this.#connection.send(encoded)) {
|
|
30616
|
+
this.#clearInFlight();
|
|
30617
|
+
return;
|
|
30618
|
+
}
|
|
30619
|
+
this.#inFlightEvents.set(envelope2.eventId, new InFlightSessionEvent(sourceKey, byteLength));
|
|
30620
|
+
this.#inFlightBytes += byteLength;
|
|
30621
|
+
sourceCounts.set(sourceKey, sourceCount + 1);
|
|
30622
|
+
sent += 1;
|
|
30623
|
+
}
|
|
30624
|
+
if (sent === 0) {
|
|
30168
30625
|
return;
|
|
30169
30626
|
}
|
|
30170
|
-
this.#inFlightEventIds.add(envelope2.eventId);
|
|
30171
30627
|
}
|
|
30172
30628
|
};
|
|
30629
|
+
#removeInFlight = (eventId) => {
|
|
30630
|
+
const inFlight = this.#inFlightEvents.get(eventId);
|
|
30631
|
+
if (inFlight === void 0) {
|
|
30632
|
+
return;
|
|
30633
|
+
}
|
|
30634
|
+
this.#inFlightEvents.delete(eventId);
|
|
30635
|
+
this.#inFlightBytes -= inFlight.byteLength;
|
|
30636
|
+
};
|
|
30637
|
+
#clearInFlight = () => {
|
|
30638
|
+
this.#inFlightEvents.clear();
|
|
30639
|
+
this.#inFlightBytes = 0;
|
|
30640
|
+
};
|
|
30173
30641
|
};
|
|
30174
30642
|
var CoalescingDaemonActivityPublisher = class {
|
|
30175
30643
|
#pending = /* @__PURE__ */ new Map();
|
|
@@ -30421,6 +30889,9 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
|
|
|
30421
30889
|
})
|
|
30422
30890
|
);
|
|
30423
30891
|
} catch (error61) {
|
|
30892
|
+
if (signal.aborted) {
|
|
30893
|
+
signal.throwIfAborted();
|
|
30894
|
+
}
|
|
30424
30895
|
reportOperationFailure(socket, command.requestId, command.sessionId, error61);
|
|
30425
30896
|
}
|
|
30426
30897
|
}
|
|
@@ -30760,6 +31231,7 @@ async function publishAgentCatalogUntilAvailable(config2, diagnostics, signal, t
|
|
|
30760
31231
|
}
|
|
30761
31232
|
async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, connectionEpoch, diagnostics, onConnected, signal, timer) {
|
|
30762
31233
|
const relayUrl = new URL(config2.relayUrl);
|
|
31234
|
+
relayUrl.searchParams.set("deliveryReceipts", "1");
|
|
30763
31235
|
relayUrl.searchParams.set("liveness", "1");
|
|
30764
31236
|
const socket = await connectRelay(relayUrl, signal);
|
|
30765
31237
|
const reconnectingTurns = [...activeTurns.values()];
|
|
@@ -30808,6 +31280,207 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30808
31280
|
closeRelaySocket(socket, code, reason);
|
|
30809
31281
|
rejectConnection(failure);
|
|
30810
31282
|
};
|
|
31283
|
+
const processingDeliveryIds = /* @__PURE__ */ new Set();
|
|
31284
|
+
const processDeliveredPrompt = async (delivery) => {
|
|
31285
|
+
const command = decodeSessionPromptCommand(delivery.payload);
|
|
31286
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31287
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31288
|
+
}
|
|
31289
|
+
const active = activeTurns.get(command.commandId);
|
|
31290
|
+
if (active !== void 0) {
|
|
31291
|
+
await active.completion;
|
|
31292
|
+
return;
|
|
31293
|
+
}
|
|
31294
|
+
const receipt = outbox.claimExecution(command.commandId, command.sessionId, delivery.payload);
|
|
31295
|
+
if (receipt.kind === "duplicate") {
|
|
31296
|
+
if (receipt.state === "running") {
|
|
31297
|
+
reportFailure(
|
|
31298
|
+
publisher,
|
|
31299
|
+
command,
|
|
31300
|
+
"agent_execution_interrupted",
|
|
31301
|
+
"The local Agent execution was interrupted before it completed",
|
|
31302
|
+
receipt.attemptId
|
|
31303
|
+
);
|
|
31304
|
+
outbox.transitionExecution(command.commandId, "failed");
|
|
31305
|
+
return;
|
|
31306
|
+
}
|
|
31307
|
+
if (receipt.state !== "dispatching") {
|
|
31308
|
+
return;
|
|
31309
|
+
}
|
|
31310
|
+
}
|
|
31311
|
+
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
31312
|
+
activeTurns.set(command.commandId, turn);
|
|
31313
|
+
if (command.disposition !== SessionPromptDisposition.Steer) {
|
|
31314
|
+
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
31315
|
+
}
|
|
31316
|
+
try {
|
|
31317
|
+
await executePrompt(
|
|
31318
|
+
outbox,
|
|
31319
|
+
publisher,
|
|
31320
|
+
command,
|
|
31321
|
+
config2,
|
|
31322
|
+
directories,
|
|
31323
|
+
audit,
|
|
31324
|
+
sessions,
|
|
31325
|
+
receipt.attemptId,
|
|
31326
|
+
timer,
|
|
31327
|
+
turn.signal
|
|
31328
|
+
);
|
|
31329
|
+
} finally {
|
|
31330
|
+
activeTurns.delete(command.commandId);
|
|
31331
|
+
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
31332
|
+
activeAttemptIds.delete(command.sessionId);
|
|
31333
|
+
}
|
|
31334
|
+
turn.finish();
|
|
31335
|
+
}
|
|
31336
|
+
};
|
|
31337
|
+
const processDeliveredPayload = async (delivery) => {
|
|
31338
|
+
const kind = decodeMessageKind(delivery.payload);
|
|
31339
|
+
if (kind === SESSION_CANCEL_KIND) {
|
|
31340
|
+
const cancellation = decodeSessionCancelCommand(delivery.payload);
|
|
31341
|
+
if (cancellation.sessionId !== delivery.sessionId) {
|
|
31342
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31343
|
+
}
|
|
31344
|
+
const turn = activeTurns.get(cancellation.commandId);
|
|
31345
|
+
if (turn === void 0 || !turn.matches(cancellation) || !turn.requestCancellation()) {
|
|
31346
|
+
return;
|
|
31347
|
+
}
|
|
31348
|
+
audit.record({
|
|
31349
|
+
commandId: cancellation.commandId,
|
|
31350
|
+
event: "session_cancellation_requested",
|
|
31351
|
+
sessionId: cancellation.sessionId
|
|
31352
|
+
});
|
|
31353
|
+
await sessions.cancelPrompt(cancellation.sessionId);
|
|
31354
|
+
return;
|
|
31355
|
+
}
|
|
31356
|
+
if (kind === SESSION_CONFIGURE_KIND) {
|
|
31357
|
+
const command = decodeSessionConfigureCommand(delivery.payload);
|
|
31358
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31359
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31360
|
+
}
|
|
31361
|
+
await executeSessionConfigure(
|
|
31362
|
+
publisher,
|
|
31363
|
+
socket,
|
|
31364
|
+
command,
|
|
31365
|
+
config2,
|
|
31366
|
+
directories,
|
|
31367
|
+
audit,
|
|
31368
|
+
sessions,
|
|
31369
|
+
connectionController.signal
|
|
31370
|
+
);
|
|
31371
|
+
return;
|
|
31372
|
+
}
|
|
31373
|
+
if (kind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
31374
|
+
const command = decodeSessionPermissionRespondCommand(delivery.payload);
|
|
31375
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31376
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31377
|
+
}
|
|
31378
|
+
try {
|
|
31379
|
+
await sessions.respondPermission(command);
|
|
31380
|
+
audit.record({
|
|
31381
|
+
commandId: command.interactionId,
|
|
31382
|
+
event: "session_permission_resolved",
|
|
31383
|
+
sessionId: command.sessionId
|
|
31384
|
+
});
|
|
31385
|
+
} catch (error61) {
|
|
31386
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
31387
|
+
}
|
|
31388
|
+
return;
|
|
31389
|
+
}
|
|
31390
|
+
if (kind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
31391
|
+
const command = decodeSessionElicitationRespondCommand(delivery.payload);
|
|
31392
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31393
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31394
|
+
}
|
|
31395
|
+
try {
|
|
31396
|
+
await sessions.respondElicitation(command);
|
|
31397
|
+
audit.record({
|
|
31398
|
+
commandId: command.interactionId,
|
|
31399
|
+
event: "session_elicitation_resolved",
|
|
31400
|
+
sessionId: command.sessionId
|
|
31401
|
+
});
|
|
31402
|
+
} catch (error61) {
|
|
31403
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
31404
|
+
}
|
|
31405
|
+
return;
|
|
31406
|
+
}
|
|
31407
|
+
if (kind === SESSION_PROMPT_KIND) {
|
|
31408
|
+
await processDeliveredPrompt(delivery);
|
|
31409
|
+
return;
|
|
31410
|
+
}
|
|
31411
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31412
|
+
};
|
|
31413
|
+
const processRuntimeDelivery = (delivery, state) => {
|
|
31414
|
+
if (state === "processed" || processingDeliveryIds.has(delivery.deliveryId)) {
|
|
31415
|
+
return;
|
|
31416
|
+
}
|
|
31417
|
+
processingDeliveryIds.add(delivery.deliveryId);
|
|
31418
|
+
void processDeliveredPayload(delivery).then(() => {
|
|
31419
|
+
outbox.markRuntimeDeliveryProcessed(delivery.deliveryId, delivery.sessionId);
|
|
31420
|
+
}).catch((error61) => {
|
|
31421
|
+
if (connectionController.signal.aborted) {
|
|
31422
|
+
return;
|
|
31423
|
+
}
|
|
31424
|
+
console.error("Mobius daemon could not process a durable Runtime delivery", error61);
|
|
31425
|
+
failAndClose(
|
|
31426
|
+
new Error("Runtime delivery processing failed", { cause: error61 }),
|
|
31427
|
+
4008,
|
|
31428
|
+
"Invalid Runtime delivery",
|
|
31429
|
+
"delivery"
|
|
31430
|
+
);
|
|
31431
|
+
}).finally(() => processingDeliveryIds.delete(delivery.deliveryId));
|
|
31432
|
+
};
|
|
31433
|
+
const receiveRuntimeDelivery = (delivery) => {
|
|
31434
|
+
const payloadKind = decodeMessageKind(delivery.payload);
|
|
31435
|
+
let payloadSessionId = "";
|
|
31436
|
+
if (payloadKind === SESSION_CANCEL_KIND) {
|
|
31437
|
+
payloadSessionId = decodeSessionCancelCommand(delivery.payload).sessionId;
|
|
31438
|
+
} else if (payloadKind === SESSION_CONFIGURE_KIND) {
|
|
31439
|
+
payloadSessionId = decodeSessionConfigureCommand(delivery.payload).sessionId;
|
|
31440
|
+
} else if (payloadKind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
31441
|
+
payloadSessionId = decodeSessionPermissionRespondCommand(delivery.payload).sessionId;
|
|
31442
|
+
} else if (payloadKind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
31443
|
+
payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
|
|
31444
|
+
} else if (payloadKind === SESSION_PROMPT_KIND) {
|
|
31445
|
+
payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
|
|
31446
|
+
} else {
|
|
31447
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31448
|
+
}
|
|
31449
|
+
if (payloadSessionId !== delivery.sessionId) {
|
|
31450
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31451
|
+
}
|
|
31452
|
+
const stored = outbox.claimRuntimeDelivery(delivery);
|
|
31453
|
+
send(
|
|
31454
|
+
socket,
|
|
31455
|
+
encodeRuntimeDeliveryReceived({
|
|
31456
|
+
deliveryId: delivery.deliveryId,
|
|
31457
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
31458
|
+
sessionId: delivery.sessionId
|
|
31459
|
+
})
|
|
31460
|
+
);
|
|
31461
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
31462
|
+
};
|
|
31463
|
+
const resumeRuntimeDeliveries = () => {
|
|
31464
|
+
for (const stored of outbox.runtimeDeliveries()) {
|
|
31465
|
+
const delivery = {
|
|
31466
|
+
deliveryId: stored.deliveryId,
|
|
31467
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
31468
|
+
payload: stored.payload,
|
|
31469
|
+
sessionId: stored.sessionId
|
|
31470
|
+
};
|
|
31471
|
+
if (stored.state !== "relay_committed") {
|
|
31472
|
+
send(
|
|
31473
|
+
socket,
|
|
31474
|
+
encodeRuntimeDeliveryReceived({
|
|
31475
|
+
deliveryId: stored.deliveryId,
|
|
31476
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
31477
|
+
sessionId: stored.sessionId
|
|
31478
|
+
})
|
|
31479
|
+
);
|
|
31480
|
+
}
|
|
31481
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
31482
|
+
}
|
|
31483
|
+
};
|
|
30811
31484
|
const connectionLiveness = new RelayConnectionLiveness(timer, {
|
|
30812
31485
|
send: (message) => send(socket, message),
|
|
30813
31486
|
unresponsive: (heartbeatId, timeoutMilliseconds) => {
|
|
@@ -30846,6 +31519,17 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30846
31519
|
}
|
|
30847
31520
|
try {
|
|
30848
31521
|
const kind = decodeMessageKind(encoded);
|
|
31522
|
+
if (kind === RUNTIME_DELIVERY_COMMITTED_KIND) {
|
|
31523
|
+
const committed = decodeRuntimeDeliveryCommitted(encoded);
|
|
31524
|
+
if (!outbox.markRuntimeDeliveryCommitted(committed.deliveryId, committed.sessionId)) {
|
|
31525
|
+
console.warn("Mobius daemon ignored confirmation for an unknown Runtime delivery");
|
|
31526
|
+
}
|
|
31527
|
+
return;
|
|
31528
|
+
}
|
|
31529
|
+
if (kind === RUNTIME_DELIVERY_KIND) {
|
|
31530
|
+
receiveRuntimeDelivery(decodeRuntimeDelivery(encoded));
|
|
31531
|
+
return;
|
|
31532
|
+
}
|
|
30849
31533
|
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
30850
31534
|
publisher.acknowledge(decodeSessionEventAcknowledgement(encoded));
|
|
30851
31535
|
return;
|
|
@@ -31282,6 +31966,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31282
31966
|
});
|
|
31283
31967
|
} catch (error61) {
|
|
31284
31968
|
console.error("Mobius daemon rejected a message", error61);
|
|
31969
|
+
if (error61 instanceof RuntimeDeliveryInboxCapacityError) {
|
|
31970
|
+
failAndClose(error61, 4013, "Runtime delivery queue full", "delivery_backpressure");
|
|
31971
|
+
return;
|
|
31972
|
+
}
|
|
31285
31973
|
failAndClose(
|
|
31286
31974
|
new Error("Relay sent an invalid protocol message", { cause: error61 }),
|
|
31287
31975
|
4008,
|
|
@@ -31299,6 +31987,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31299
31987
|
return;
|
|
31300
31988
|
}
|
|
31301
31989
|
publisher.connect(socket);
|
|
31990
|
+
resumeRuntimeDeliveries();
|
|
31302
31991
|
},
|
|
31303
31992
|
(error61) => {
|
|
31304
31993
|
if (finished) {
|