@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/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { mkdir as mkdir5 } from "node:fs/promises";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@moxt-ai/mobius",
|
|
14
|
-
version: "0.0.
|
|
14
|
+
version: "0.0.27",
|
|
15
15
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
16
16
|
type: "module",
|
|
17
17
|
bin: {
|
|
@@ -22094,6 +22094,9 @@ var SESSION_CANCEL_KIND = "session.cancel";
|
|
|
22094
22094
|
var RUNTIME_LIVENESS_READY_KIND = "runtime.liveness.ready";
|
|
22095
22095
|
var RUNTIME_HEARTBEAT_KIND = "runtime.heartbeat";
|
|
22096
22096
|
var RUNTIME_HEARTBEAT_ACK_KIND = "runtime.heartbeat.ack";
|
|
22097
|
+
var RUNTIME_DELIVERY_KIND = "runtime.delivery";
|
|
22098
|
+
var RUNTIME_DELIVERY_RECEIVED_KIND = "runtime.delivery.received";
|
|
22099
|
+
var RUNTIME_DELIVERY_COMMITTED_KIND = "runtime.delivery.committed";
|
|
22097
22100
|
var SESSION_STARTED_KIND = "session.started";
|
|
22098
22101
|
var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
|
|
22099
22102
|
var AGENT_ACTIVITY_KIND = "agent.activity";
|
|
@@ -22116,6 +22119,7 @@ var DIRECTORY_IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
|
|
|
22116
22119
|
var MAX_PROMPT_LENGTH = 1e4;
|
|
22117
22120
|
var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
|
|
22118
22121
|
var MAX_EVENT_TEXT_LENGTH = 1e5;
|
|
22122
|
+
var MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH = 8 * 1024 * 1024;
|
|
22119
22123
|
var ACTIVITY_TYPES = /* @__PURE__ */ new Set(["plan", "progress", "reasoning", "tool"]);
|
|
22120
22124
|
var ACTIVITY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "completed", "failed"]);
|
|
22121
22125
|
var TOOL_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -22394,6 +22398,37 @@ function decodeRuntimeHeartbeatAckEvent(encoded) {
|
|
|
22394
22398
|
kind: RUNTIME_HEARTBEAT_ACK_KIND
|
|
22395
22399
|
};
|
|
22396
22400
|
}
|
|
22401
|
+
function decodeRuntimeDelivery(encoded) {
|
|
22402
|
+
const value = parseJson2(encoded);
|
|
22403
|
+
assertExactKeys(value, ["deliveryId", "kind", "payload", "sessionId"]);
|
|
22404
|
+
assertKind(value, RUNTIME_DELIVERY_KIND);
|
|
22405
|
+
return {
|
|
22406
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22407
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
22408
|
+
payload: readString(value, "payload", MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH),
|
|
22409
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22410
|
+
};
|
|
22411
|
+
}
|
|
22412
|
+
function decodeRuntimeDeliveryReceived(encoded) {
|
|
22413
|
+
const value = parseJson2(encoded);
|
|
22414
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
22415
|
+
assertKind(value, RUNTIME_DELIVERY_RECEIVED_KIND);
|
|
22416
|
+
return {
|
|
22417
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22418
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
22419
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22420
|
+
};
|
|
22421
|
+
}
|
|
22422
|
+
function decodeRuntimeDeliveryCommitted(encoded) {
|
|
22423
|
+
const value = parseJson2(encoded);
|
|
22424
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
22425
|
+
assertKind(value, RUNTIME_DELIVERY_COMMITTED_KIND);
|
|
22426
|
+
return {
|
|
22427
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22428
|
+
kind: RUNTIME_DELIVERY_COMMITTED_KIND,
|
|
22429
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22430
|
+
};
|
|
22431
|
+
}
|
|
22397
22432
|
function decodeSessionStartedEvent(encoded) {
|
|
22398
22433
|
const value = parseJson2(encoded);
|
|
22399
22434
|
assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
|
|
@@ -22481,6 +22516,9 @@ function decodeSessionFailedEvent(encoded) {
|
|
|
22481
22516
|
function encodeRuntimeHeartbeatEvent(message) {
|
|
22482
22517
|
return JSON.stringify(decodeRuntimeHeartbeatEvent(JSON.stringify(message)));
|
|
22483
22518
|
}
|
|
22519
|
+
function encodeRuntimeDeliveryReceived(message) {
|
|
22520
|
+
return JSON.stringify(decodeRuntimeDeliveryReceived(JSON.stringify(message)));
|
|
22521
|
+
}
|
|
22484
22522
|
function encodeSessionStartedEvent(message) {
|
|
22485
22523
|
return JSON.stringify(decodeSessionStartedEvent(JSON.stringify(message)));
|
|
22486
22524
|
}
|
|
@@ -23179,7 +23217,8 @@ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
|
|
|
23179
23217
|
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
23180
23218
|
var SessionEventRejectionCode = {
|
|
23181
23219
|
SessionDeleted: "session_deleted",
|
|
23182
|
-
SessionNotFound: "session_not_found"
|
|
23220
|
+
SessionNotFound: "session_not_found",
|
|
23221
|
+
SessionRejected: "session_rejected"
|
|
23183
23222
|
};
|
|
23184
23223
|
var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
23185
23224
|
var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
|
|
@@ -23437,12 +23476,12 @@ function decodePairingResponse(value, credentialField, expectedKeys) {
|
|
|
23437
23476
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
23438
23477
|
}
|
|
23439
23478
|
const channelId = value["channelId"];
|
|
23440
|
-
const
|
|
23479
|
+
const runtimeCredential2 = value[credentialField];
|
|
23441
23480
|
const runtimeId = value["runtimeId"];
|
|
23442
|
-
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof
|
|
23481
|
+
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN5.test(runtimeId)) {
|
|
23443
23482
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
23444
23483
|
}
|
|
23445
|
-
return { channelId, runtimeCredential, runtimeId };
|
|
23484
|
+
return { channelId, runtimeCredential: runtimeCredential2, runtimeId };
|
|
23446
23485
|
}
|
|
23447
23486
|
async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
|
|
23448
23487
|
const agents = localAgents.map((agent) => ({
|
|
@@ -23477,7 +23516,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
23477
23516
|
}
|
|
23478
23517
|
return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
|
|
23479
23518
|
}
|
|
23480
|
-
async function persistConnection(channelId, relayOrigin,
|
|
23519
|
+
async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
|
|
23481
23520
|
const connectionsDirectory = join14(readStateDirectory(environment), "connections");
|
|
23482
23521
|
await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
|
|
23483
23522
|
const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
|
|
@@ -23489,7 +23528,7 @@ async function persistConnection(channelId, relayOrigin, runtimeCredential, defa
|
|
|
23489
23528
|
defaultWorkspace,
|
|
23490
23529
|
channelId,
|
|
23491
23530
|
relayOrigin: relayOrigin.toString(),
|
|
23492
|
-
runtimeCredential
|
|
23531
|
+
runtimeCredential: runtimeCredential2
|
|
23493
23532
|
},
|
|
23494
23533
|
null,
|
|
23495
23534
|
2
|
|
@@ -23506,16 +23545,16 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
23506
23545
|
}
|
|
23507
23546
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
23508
23547
|
const channelId = value["channelId"];
|
|
23509
|
-
const
|
|
23548
|
+
const runtimeCredential2 = value["runtimeCredential"] ?? value["daemonToken"];
|
|
23510
23549
|
const relayOrigin = value["relayOrigin"];
|
|
23511
|
-
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof
|
|
23550
|
+
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
|
|
23512
23551
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
23513
23552
|
}
|
|
23514
23553
|
return {
|
|
23515
23554
|
defaultWorkspace,
|
|
23516
23555
|
channelId,
|
|
23517
23556
|
relayOrigin: parseRelayOrigin(relayOrigin),
|
|
23518
|
-
runtimeCredential
|
|
23557
|
+
runtimeCredential: runtimeCredential2
|
|
23519
23558
|
};
|
|
23520
23559
|
}
|
|
23521
23560
|
async function readSavedConnection(channelId, environment) {
|
|
@@ -27048,6 +27087,23 @@ var AcpSessionManager = class {
|
|
|
27048
27087
|
|
|
27049
27088
|
// src/agent-catalog/publish-agent-catalog.ts
|
|
27050
27089
|
import { fetch as fetch3 } from "undici";
|
|
27090
|
+
|
|
27091
|
+
// src/relay-connection/runtime-authentication.ts
|
|
27092
|
+
function runtimeCredential(relayUrl) {
|
|
27093
|
+
return relayUrl.searchParams.get("token") ?? "";
|
|
27094
|
+
}
|
|
27095
|
+
function runtimeAuthorization(relayUrl) {
|
|
27096
|
+
const credential = runtimeCredential(relayUrl);
|
|
27097
|
+
return credential.length === 0 ? {} : { authorization: `Bearer ${credential}` };
|
|
27098
|
+
}
|
|
27099
|
+
function relayHttpEndpoint(relayUrl) {
|
|
27100
|
+
const endpoint = new URL(relayUrl);
|
|
27101
|
+
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
27102
|
+
endpoint.search = "";
|
|
27103
|
+
return endpoint;
|
|
27104
|
+
}
|
|
27105
|
+
|
|
27106
|
+
// src/agent-catalog/publish-agent-catalog.ts
|
|
27051
27107
|
var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
|
|
27052
27108
|
var AgentCatalogPublishError = class extends Error {
|
|
27053
27109
|
code = "agent_catalog_update_failed";
|
|
@@ -27057,8 +27113,7 @@ var AgentCatalogPublishError = class extends Error {
|
|
|
27057
27113
|
}
|
|
27058
27114
|
};
|
|
27059
27115
|
function catalogEndpoint(config2) {
|
|
27060
|
-
const endpoint =
|
|
27061
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
27116
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
27062
27117
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
27063
27118
|
endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/catalog`;
|
|
27064
27119
|
return endpoint;
|
|
@@ -27089,7 +27144,7 @@ async function publishAgentCatalog(config2, signal) {
|
|
|
27089
27144
|
installableAgents: catalog.installableAgents
|
|
27090
27145
|
}),
|
|
27091
27146
|
dispatcher: environmentProxyDispatcher,
|
|
27092
|
-
headers: { "content-type": "application/json" },
|
|
27147
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
27093
27148
|
method: "PUT",
|
|
27094
27149
|
signal: requestSignal
|
|
27095
27150
|
});
|
|
@@ -29131,8 +29186,7 @@ function parseReference(resource) {
|
|
|
29131
29186
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
29132
29187
|
}
|
|
29133
29188
|
function downloadUrl(config2, command, reference) {
|
|
29134
|
-
const url2 =
|
|
29135
|
-
url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
|
|
29189
|
+
const url2 = relayHttpEndpoint(config2.relayUrl);
|
|
29136
29190
|
let channelPath = "";
|
|
29137
29191
|
if (url2.pathname.endsWith("/daemon")) {
|
|
29138
29192
|
channelPath = url2.pathname.slice(0, -"/daemon".length);
|
|
@@ -29144,7 +29198,6 @@ function downloadUrl(config2, command, reference) {
|
|
|
29144
29198
|
channelPath = `${url2.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
29145
29199
|
}
|
|
29146
29200
|
url2.pathname = `${channelPath}/sessions/${encodeURIComponent(command.sessionId)}/commands/${encodeURIComponent(command.commandId)}/artifacts/${encodeURIComponent(reference.artifactId)}/content`;
|
|
29147
|
-
url2.searchParams.delete("liveness");
|
|
29148
29201
|
return url2;
|
|
29149
29202
|
}
|
|
29150
29203
|
async function responseBytes(response, expectedByteLength, signal) {
|
|
@@ -29195,7 +29248,11 @@ async function download(config2, command, reference, signal) {
|
|
|
29195
29248
|
try {
|
|
29196
29249
|
response = await fetch5(downloadUrl(config2, command, reference), {
|
|
29197
29250
|
dispatcher: environmentProxyDispatcher,
|
|
29198
|
-
headers: {
|
|
29251
|
+
headers: {
|
|
29252
|
+
accept: reference.resource.mimeType,
|
|
29253
|
+
"accept-encoding": "identity",
|
|
29254
|
+
...runtimeAuthorization(config2.relayUrl)
|
|
29255
|
+
},
|
|
29199
29256
|
signal: requestSignal
|
|
29200
29257
|
});
|
|
29201
29258
|
if (!response.ok) {
|
|
@@ -29305,12 +29362,8 @@ function connectRelay(url2, signal) {
|
|
|
29305
29362
|
signal.throwIfAborted();
|
|
29306
29363
|
return new Promise((resolve5, reject) => {
|
|
29307
29364
|
const endpoint = new URL(url2);
|
|
29308
|
-
const headers =
|
|
29309
|
-
|
|
29310
|
-
const runtimeCredential = endpoint.searchParams.get("token") ?? "";
|
|
29311
|
-
endpoint.searchParams.delete("token");
|
|
29312
|
-
headers["authorization"] = `Bearer ${runtimeCredential}`;
|
|
29313
|
-
}
|
|
29365
|
+
const headers = runtimeAuthorization(endpoint);
|
|
29366
|
+
endpoint.searchParams.delete("token");
|
|
29314
29367
|
const socket = new WebSocket(endpoint, {
|
|
29315
29368
|
dispatcher: environmentProxyDispatcher,
|
|
29316
29369
|
headers
|
|
@@ -29633,6 +29686,42 @@ var RelayConnectionLiveness = class {
|
|
|
29633
29686
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
29634
29687
|
import { dirname as dirname7 } from "node:path";
|
|
29635
29688
|
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
29689
|
+
var DEFAULT_OUTBOX_LIMITS = {
|
|
29690
|
+
criticalEventBytes: 136 * 1024 * 1024,
|
|
29691
|
+
criticalEventCount: 10128,
|
|
29692
|
+
runtimeDeliveryBytes: 64 * 1024 * 1024,
|
|
29693
|
+
runtimeDeliveryCount: 64,
|
|
29694
|
+
standardEventBytes: 128 * 1024 * 1024,
|
|
29695
|
+
standardEventCount: 1e4
|
|
29696
|
+
};
|
|
29697
|
+
var SessionEventOutboxCapacityError = class extends Error {
|
|
29698
|
+
code = "session_event_outbox_full";
|
|
29699
|
+
constructor() {
|
|
29700
|
+
super("The durable Session event outbox is full");
|
|
29701
|
+
this.name = "SessionEventOutboxCapacityError";
|
|
29702
|
+
}
|
|
29703
|
+
};
|
|
29704
|
+
var RuntimeDeliveryInboxCapacityError = class extends Error {
|
|
29705
|
+
code = "runtime_delivery_inbox_full";
|
|
29706
|
+
constructor() {
|
|
29707
|
+
super("The durable Runtime delivery inbox is full");
|
|
29708
|
+
this.name = "RuntimeDeliveryInboxCapacityError";
|
|
29709
|
+
}
|
|
29710
|
+
};
|
|
29711
|
+
var StoredRuntimeDelivery = class {
|
|
29712
|
+
deliveryId;
|
|
29713
|
+
duplicate;
|
|
29714
|
+
payload;
|
|
29715
|
+
sessionId;
|
|
29716
|
+
state;
|
|
29717
|
+
constructor(deliveryId, sessionId, payload, state, duplicate) {
|
|
29718
|
+
this.deliveryId = deliveryId;
|
|
29719
|
+
this.duplicate = duplicate;
|
|
29720
|
+
this.payload = payload;
|
|
29721
|
+
this.sessionId = sessionId;
|
|
29722
|
+
this.state = state;
|
|
29723
|
+
}
|
|
29724
|
+
};
|
|
29636
29725
|
function readPendingEnvelope(row) {
|
|
29637
29726
|
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
29638
29727
|
throw new Error("SQLite returned an invalid session event outbox row");
|
|
@@ -29643,9 +29732,26 @@ function readPendingEnvelope(row) {
|
|
|
29643
29732
|
}
|
|
29644
29733
|
return envelope2;
|
|
29645
29734
|
}
|
|
29735
|
+
function rowNumber(row, field) {
|
|
29736
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29737
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
29738
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29739
|
+
}
|
|
29740
|
+
return value;
|
|
29741
|
+
}
|
|
29742
|
+
function rowString2(row, field) {
|
|
29743
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29744
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
29745
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29746
|
+
}
|
|
29747
|
+
return value;
|
|
29748
|
+
}
|
|
29646
29749
|
var SessionEventOutbox = class {
|
|
29647
29750
|
#database;
|
|
29648
|
-
|
|
29751
|
+
#limits;
|
|
29752
|
+
constructor(path2, limits = DEFAULT_OUTBOX_LIMITS) {
|
|
29753
|
+
validateLimits(limits);
|
|
29754
|
+
this.#limits = limits;
|
|
29649
29755
|
mkdirSync3(dirname7(path2), { recursive: true });
|
|
29650
29756
|
this.#database = new DatabaseSync4(path2);
|
|
29651
29757
|
this.#database.exec(`
|
|
@@ -29654,6 +29760,7 @@ var SessionEventOutbox = class {
|
|
|
29654
29760
|
event_id TEXT NOT NULL UNIQUE,
|
|
29655
29761
|
session_id TEXT NOT NULL,
|
|
29656
29762
|
source_key TEXT NOT NULL,
|
|
29763
|
+
byte_length INTEGER NOT NULL,
|
|
29657
29764
|
envelope_json TEXT NOT NULL
|
|
29658
29765
|
) STRICT;
|
|
29659
29766
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
@@ -29664,7 +29771,7 @@ var SessionEventOutbox = class {
|
|
|
29664
29771
|
session_id TEXT NOT NULL,
|
|
29665
29772
|
envelope_json TEXT NOT NULL,
|
|
29666
29773
|
rejection_code TEXT NOT NULL CHECK (
|
|
29667
|
-
rejection_code IN ('session_deleted', 'session_not_found')
|
|
29774
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
29668
29775
|
)
|
|
29669
29776
|
) STRICT;
|
|
29670
29777
|
CREATE TABLE IF NOT EXISTS relay_session_event_sources (
|
|
@@ -29680,7 +29787,53 @@ var SessionEventOutbox = class {
|
|
|
29680
29787
|
state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
|
|
29681
29788
|
)
|
|
29682
29789
|
) STRICT;
|
|
29790
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
29791
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
29792
|
+
event_count INTEGER NOT NULL,
|
|
29793
|
+
total_bytes INTEGER NOT NULL
|
|
29794
|
+
) STRICT;
|
|
29795
|
+
INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
29796
|
+
singleton, event_count, total_bytes
|
|
29797
|
+
) VALUES (1, 0, 0);
|
|
29798
|
+
CREATE TABLE IF NOT EXISTS relay_runtime_deliveries (
|
|
29799
|
+
delivery_id TEXT PRIMARY KEY,
|
|
29800
|
+
session_id TEXT NOT NULL,
|
|
29801
|
+
payload_json TEXT NOT NULL,
|
|
29802
|
+
payload_bytes INTEGER NOT NULL,
|
|
29803
|
+
state TEXT NOT NULL CHECK (
|
|
29804
|
+
state IN ('received', 'relay_committed', 'processed')
|
|
29805
|
+
),
|
|
29806
|
+
received_at INTEGER NOT NULL
|
|
29807
|
+
) STRICT;
|
|
29683
29808
|
`);
|
|
29809
|
+
const deadLetterTable = this.#database.prepare(
|
|
29810
|
+
`SELECT sql FROM sqlite_master
|
|
29811
|
+
WHERE type = 'table' AND name = 'relay_session_event_dead_letters'`
|
|
29812
|
+
).get();
|
|
29813
|
+
const deadLetterSql = typeof deadLetterTable === "object" && deadLetterTable !== null ? Reflect.get(deadLetterTable, "sql") : void 0;
|
|
29814
|
+
if (typeof deadLetterSql !== "string" || !deadLetterSql.includes("'session_rejected'")) {
|
|
29815
|
+
this.#database.exec(`
|
|
29816
|
+
BEGIN IMMEDIATE;
|
|
29817
|
+
ALTER TABLE relay_session_event_dead_letters
|
|
29818
|
+
RENAME TO relay_session_event_dead_letters_legacy;
|
|
29819
|
+
CREATE TABLE relay_session_event_dead_letters (
|
|
29820
|
+
ordinal INTEGER PRIMARY KEY,
|
|
29821
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
29822
|
+
session_id TEXT NOT NULL,
|
|
29823
|
+
envelope_json TEXT NOT NULL,
|
|
29824
|
+
rejection_code TEXT NOT NULL CHECK (
|
|
29825
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
29826
|
+
)
|
|
29827
|
+
) STRICT;
|
|
29828
|
+
INSERT INTO relay_session_event_dead_letters (
|
|
29829
|
+
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29830
|
+
)
|
|
29831
|
+
SELECT ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29832
|
+
FROM relay_session_event_dead_letters_legacy;
|
|
29833
|
+
DROP TABLE relay_session_event_dead_letters_legacy;
|
|
29834
|
+
COMMIT;
|
|
29835
|
+
`);
|
|
29836
|
+
}
|
|
29684
29837
|
const outboxColumns = this.#database.prepare("PRAGMA table_info(relay_session_event_outbox)").all();
|
|
29685
29838
|
const hasSourceKey = outboxColumns.some(
|
|
29686
29839
|
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "source_key"
|
|
@@ -29691,6 +29844,15 @@ var SessionEventOutbox = class {
|
|
|
29691
29844
|
ADD COLUMN source_key TEXT NOT NULL DEFAULT '';
|
|
29692
29845
|
`);
|
|
29693
29846
|
}
|
|
29847
|
+
const hasByteLength = outboxColumns.some(
|
|
29848
|
+
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "byte_length"
|
|
29849
|
+
);
|
|
29850
|
+
if (!hasByteLength) {
|
|
29851
|
+
this.#database.exec(`
|
|
29852
|
+
ALTER TABLE relay_session_event_outbox
|
|
29853
|
+
ADD COLUMN byte_length INTEGER NOT NULL DEFAULT 0;
|
|
29854
|
+
`);
|
|
29855
|
+
}
|
|
29694
29856
|
this.#database.exec(`
|
|
29695
29857
|
UPDATE relay_session_event_outbox
|
|
29696
29858
|
SET source_key = CASE json_extract(envelope_json, '$.source.kind')
|
|
@@ -29699,6 +29861,16 @@ var SessionEventOutbox = class {
|
|
|
29699
29861
|
ELSE 'runtime:' || session_id
|
|
29700
29862
|
END
|
|
29701
29863
|
WHERE source_key = '';
|
|
29864
|
+
UPDATE relay_session_event_outbox
|
|
29865
|
+
SET byte_length = length(CAST(envelope_json AS BLOB))
|
|
29866
|
+
WHERE byte_length = 0;
|
|
29867
|
+
UPDATE relay_session_event_outbox_state
|
|
29868
|
+
SET event_count = (SELECT COUNT(*) FROM relay_session_event_outbox),
|
|
29869
|
+
total_bytes = (
|
|
29870
|
+
SELECT COALESCE(SUM(byte_length), 0)
|
|
29871
|
+
FROM relay_session_event_outbox
|
|
29872
|
+
)
|
|
29873
|
+
WHERE singleton = 1;
|
|
29702
29874
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_source_order
|
|
29703
29875
|
ON relay_session_event_outbox(source_key, ordinal);
|
|
29704
29876
|
`);
|
|
@@ -29759,13 +29931,19 @@ var SessionEventOutbox = class {
|
|
|
29759
29931
|
const state = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
|
|
29760
29932
|
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
29761
29933
|
};
|
|
29762
|
-
acknowledge = (acknowledgement) => this.#
|
|
29763
|
-
`DELETE FROM relay_session_event_outbox
|
|
29764
|
-
WHERE event_id = ? AND session_id = ?`
|
|
29765
|
-
).run(acknowledgement.eventId, acknowledgement.sessionId).changes === 1;
|
|
29934
|
+
acknowledge = (acknowledgement) => this.#removeAcknowledgedEvent(acknowledgement.eventId, acknowledgement.sessionId);
|
|
29766
29935
|
quarantine = (rejection) => {
|
|
29767
29936
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
29768
29937
|
try {
|
|
29938
|
+
const stored = this.#database.prepare(
|
|
29939
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
29940
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29941
|
+
).get(rejection.eventId, rejection.sessionId);
|
|
29942
|
+
if (stored === void 0) {
|
|
29943
|
+
this.#database.exec("COMMIT");
|
|
29944
|
+
return false;
|
|
29945
|
+
}
|
|
29946
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
29769
29947
|
const insertion = this.#database.prepare(
|
|
29770
29948
|
`INSERT INTO relay_session_event_dead_letters (
|
|
29771
29949
|
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
@@ -29785,6 +29963,7 @@ var SessionEventOutbox = class {
|
|
|
29785
29963
|
if (deletion.changes !== 1) {
|
|
29786
29964
|
throw new Error("The rejected session event could not be removed from the durable outbox");
|
|
29787
29965
|
}
|
|
29966
|
+
this.#decrementEventState(byteLength);
|
|
29788
29967
|
this.#database.exec("COMMIT");
|
|
29789
29968
|
return true;
|
|
29790
29969
|
} catch (error61) {
|
|
@@ -29796,7 +29975,129 @@ var SessionEventOutbox = class {
|
|
|
29796
29975
|
this.#database.close();
|
|
29797
29976
|
};
|
|
29798
29977
|
enqueue = (sessionId, payload, attemptId = null) => {
|
|
29799
|
-
|
|
29978
|
+
return this.#enqueueBounded(
|
|
29979
|
+
sessionId,
|
|
29980
|
+
payload,
|
|
29981
|
+
attemptId ?? "",
|
|
29982
|
+
this.#limits.standardEventCount,
|
|
29983
|
+
this.#limits.standardEventBytes
|
|
29984
|
+
);
|
|
29985
|
+
};
|
|
29986
|
+
enqueueCritical = (sessionId, payload, attemptId = "") => this.#enqueueBounded(
|
|
29987
|
+
sessionId,
|
|
29988
|
+
payload,
|
|
29989
|
+
attemptId,
|
|
29990
|
+
this.#limits.criticalEventCount,
|
|
29991
|
+
this.#limits.criticalEventBytes
|
|
29992
|
+
);
|
|
29993
|
+
claimRuntimeDelivery = (delivery) => {
|
|
29994
|
+
const payloadBytes = new TextEncoder().encode(delivery.payload).byteLength;
|
|
29995
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29996
|
+
try {
|
|
29997
|
+
const existing = this.#database.prepare(
|
|
29998
|
+
`SELECT session_id, payload_json, state
|
|
29999
|
+
FROM relay_runtime_deliveries
|
|
30000
|
+
WHERE delivery_id = ?`
|
|
30001
|
+
).get(delivery.deliveryId);
|
|
30002
|
+
if (existing !== void 0) {
|
|
30003
|
+
const sessionId = rowString2(existing, "session_id");
|
|
30004
|
+
const payload = rowString2(existing, "payload_json");
|
|
30005
|
+
const state = runtimeDeliveryState(existing);
|
|
30006
|
+
if (sessionId !== delivery.sessionId || payload !== delivery.payload) {
|
|
30007
|
+
throw new Error("The Runtime delivery identity conflicts with its durable receipt");
|
|
30008
|
+
}
|
|
30009
|
+
this.#database.exec("COMMIT");
|
|
30010
|
+
return new StoredRuntimeDelivery(delivery.deliveryId, sessionId, payload, state, true);
|
|
30011
|
+
}
|
|
30012
|
+
const usage = this.#database.prepare(
|
|
30013
|
+
`SELECT COUNT(*) AS delivery_count,
|
|
30014
|
+
COALESCE(SUM(payload_bytes), 0) AS delivery_bytes
|
|
30015
|
+
FROM relay_runtime_deliveries`
|
|
30016
|
+
).get();
|
|
30017
|
+
if (rowNumber(usage, "delivery_count") + 1 > this.#limits.runtimeDeliveryCount || rowNumber(usage, "delivery_bytes") + payloadBytes > this.#limits.runtimeDeliveryBytes) {
|
|
30018
|
+
throw new RuntimeDeliveryInboxCapacityError();
|
|
30019
|
+
}
|
|
30020
|
+
this.#database.prepare(
|
|
30021
|
+
`INSERT INTO relay_runtime_deliveries (
|
|
30022
|
+
delivery_id, session_id, payload_json, payload_bytes, state, received_at
|
|
30023
|
+
) VALUES (?, ?, ?, ?, 'received', ?)`
|
|
30024
|
+
).run(delivery.deliveryId, delivery.sessionId, delivery.payload, payloadBytes, Date.now());
|
|
30025
|
+
this.#database.exec("COMMIT");
|
|
30026
|
+
return new StoredRuntimeDelivery(
|
|
30027
|
+
delivery.deliveryId,
|
|
30028
|
+
delivery.sessionId,
|
|
30029
|
+
delivery.payload,
|
|
30030
|
+
"received",
|
|
30031
|
+
false
|
|
30032
|
+
);
|
|
30033
|
+
} catch (error61) {
|
|
30034
|
+
this.#database.exec("ROLLBACK");
|
|
30035
|
+
throw error61;
|
|
30036
|
+
}
|
|
30037
|
+
};
|
|
30038
|
+
markRuntimeDeliveryCommitted = (deliveryId, sessionId) => {
|
|
30039
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
30040
|
+
try {
|
|
30041
|
+
const row = this.#database.prepare(
|
|
30042
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
30043
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
30044
|
+
).get(deliveryId, sessionId);
|
|
30045
|
+
if (row === void 0) {
|
|
30046
|
+
this.#database.exec("COMMIT");
|
|
30047
|
+
return false;
|
|
30048
|
+
}
|
|
30049
|
+
const state = runtimeDeliveryState(row);
|
|
30050
|
+
if (state === "processed") {
|
|
30051
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
30052
|
+
} else if (state === "received") {
|
|
30053
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'relay_committed' WHERE delivery_id = ?`).run(deliveryId);
|
|
30054
|
+
}
|
|
30055
|
+
this.#database.exec("COMMIT");
|
|
30056
|
+
return true;
|
|
30057
|
+
} catch (error61) {
|
|
30058
|
+
this.#database.exec("ROLLBACK");
|
|
30059
|
+
throw error61;
|
|
30060
|
+
}
|
|
30061
|
+
};
|
|
30062
|
+
markRuntimeDeliveryProcessed = (deliveryId, sessionId) => {
|
|
30063
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
30064
|
+
try {
|
|
30065
|
+
const row = this.#database.prepare(
|
|
30066
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
30067
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
30068
|
+
).get(deliveryId, sessionId);
|
|
30069
|
+
if (row === void 0) {
|
|
30070
|
+
this.#database.exec("COMMIT");
|
|
30071
|
+
return false;
|
|
30072
|
+
}
|
|
30073
|
+
const state = runtimeDeliveryState(row);
|
|
30074
|
+
if (state === "relay_committed") {
|
|
30075
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
30076
|
+
} else if (state === "received") {
|
|
30077
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'processed' WHERE delivery_id = ?`).run(deliveryId);
|
|
30078
|
+
}
|
|
30079
|
+
this.#database.exec("COMMIT");
|
|
30080
|
+
return true;
|
|
30081
|
+
} catch (error61) {
|
|
30082
|
+
this.#database.exec("ROLLBACK");
|
|
30083
|
+
throw error61;
|
|
30084
|
+
}
|
|
30085
|
+
};
|
|
30086
|
+
runtimeDeliveries = () => this.#database.prepare(
|
|
30087
|
+
`SELECT delivery_id, session_id, payload_json, state
|
|
30088
|
+
FROM relay_runtime_deliveries
|
|
30089
|
+
ORDER BY received_at, delivery_id`
|
|
30090
|
+
).all().map(
|
|
30091
|
+
(row) => new StoredRuntimeDelivery(
|
|
30092
|
+
rowString2(row, "delivery_id"),
|
|
30093
|
+
rowString2(row, "session_id"),
|
|
30094
|
+
rowString2(row, "payload_json"),
|
|
30095
|
+
runtimeDeliveryState(row),
|
|
30096
|
+
true
|
|
30097
|
+
)
|
|
30098
|
+
);
|
|
30099
|
+
#enqueueBounded = (sessionId, payload, attemptId, maximumEventCount, maximumEventBytes) => {
|
|
30100
|
+
const sourceKey = attemptId.length === 0 ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
|
|
29800
30101
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
29801
30102
|
try {
|
|
29802
30103
|
const row = this.#database.prepare(
|
|
@@ -29813,13 +30114,22 @@ var SessionEventOutbox = class {
|
|
|
29813
30114
|
kind: SESSION_EVENT_KIND,
|
|
29814
30115
|
payload,
|
|
29815
30116
|
sessionId,
|
|
29816
|
-
source: attemptId ===
|
|
30117
|
+
source: attemptId.length === 0 ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
|
|
29817
30118
|
attemptId,
|
|
29818
30119
|
kind: "attempt",
|
|
29819
30120
|
sourceSeq: nextSourceSeq.toString()
|
|
29820
30121
|
}
|
|
29821
30122
|
};
|
|
29822
30123
|
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
30124
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
30125
|
+
const state = this.#database.prepare(
|
|
30126
|
+
`SELECT event_count, total_bytes
|
|
30127
|
+
FROM relay_session_event_outbox_state
|
|
30128
|
+
WHERE singleton = 1`
|
|
30129
|
+
).get();
|
|
30130
|
+
if (rowNumber(state, "event_count") + 1 > maximumEventCount || rowNumber(state, "total_bytes") + byteLength > maximumEventBytes) {
|
|
30131
|
+
throw new SessionEventOutboxCapacityError();
|
|
30132
|
+
}
|
|
29823
30133
|
this.#database.prepare(
|
|
29824
30134
|
`INSERT INTO relay_session_event_sources (
|
|
29825
30135
|
source_key, next_source_seq
|
|
@@ -29829,9 +30139,15 @@ var SessionEventOutbox = class {
|
|
|
29829
30139
|
).run(sourceKey, nextSourceSeq + 1);
|
|
29830
30140
|
this.#database.prepare(
|
|
29831
30141
|
`INSERT INTO relay_session_event_outbox (
|
|
29832
|
-
event_id, session_id, source_key, envelope_json
|
|
29833
|
-
) VALUES (?, ?, ?, ?)`
|
|
29834
|
-
).run(envelope2.eventId, envelope2.sessionId, sourceKey, encoded);
|
|
30142
|
+
event_id, session_id, source_key, byte_length, envelope_json
|
|
30143
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
30144
|
+
).run(envelope2.eventId, envelope2.sessionId, sourceKey, byteLength, encoded);
|
|
30145
|
+
this.#database.prepare(
|
|
30146
|
+
`UPDATE relay_session_event_outbox_state
|
|
30147
|
+
SET event_count = event_count + 1,
|
|
30148
|
+
total_bytes = total_bytes + ?
|
|
30149
|
+
WHERE singleton = 1`
|
|
30150
|
+
).run(byteLength);
|
|
29835
30151
|
this.#database.exec("COMMIT");
|
|
29836
30152
|
return encoded;
|
|
29837
30153
|
} catch (error61) {
|
|
@@ -29839,6 +30155,44 @@ var SessionEventOutbox = class {
|
|
|
29839
30155
|
throw error61;
|
|
29840
30156
|
}
|
|
29841
30157
|
};
|
|
30158
|
+
#removeAcknowledgedEvent = (eventId, sessionId) => {
|
|
30159
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
30160
|
+
try {
|
|
30161
|
+
const stored = this.#database.prepare(
|
|
30162
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
30163
|
+
WHERE event_id = ? AND session_id = ?`
|
|
30164
|
+
).get(eventId, sessionId);
|
|
30165
|
+
if (stored === void 0) {
|
|
30166
|
+
this.#database.exec("COMMIT");
|
|
30167
|
+
return false;
|
|
30168
|
+
}
|
|
30169
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
30170
|
+
const deletion = this.#database.prepare(
|
|
30171
|
+
`DELETE FROM relay_session_event_outbox
|
|
30172
|
+
WHERE event_id = ? AND session_id = ?`
|
|
30173
|
+
).run(eventId, sessionId);
|
|
30174
|
+
if (deletion.changes !== 1) {
|
|
30175
|
+
throw new Error("The acknowledged session event could not be removed from the durable outbox");
|
|
30176
|
+
}
|
|
30177
|
+
this.#decrementEventState(byteLength);
|
|
30178
|
+
this.#database.exec("COMMIT");
|
|
30179
|
+
return true;
|
|
30180
|
+
} catch (error61) {
|
|
30181
|
+
this.#database.exec("ROLLBACK");
|
|
30182
|
+
throw error61;
|
|
30183
|
+
}
|
|
30184
|
+
};
|
|
30185
|
+
#decrementEventState = (byteLength) => {
|
|
30186
|
+
const result = this.#database.prepare(
|
|
30187
|
+
`UPDATE relay_session_event_outbox_state
|
|
30188
|
+
SET event_count = event_count - 1,
|
|
30189
|
+
total_bytes = total_bytes - ?
|
|
30190
|
+
WHERE singleton = 1 AND event_count > 0 AND total_bytes >= ?`
|
|
30191
|
+
).run(byteLength, byteLength);
|
|
30192
|
+
if (result.changes !== 1) {
|
|
30193
|
+
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
30194
|
+
}
|
|
30195
|
+
};
|
|
29842
30196
|
pending = () => this.#database.prepare(
|
|
29843
30197
|
`SELECT envelope_json
|
|
29844
30198
|
FROM relay_session_event_outbox
|
|
@@ -29865,7 +30219,68 @@ var SessionEventOutbox = class {
|
|
|
29865
30219
|
LIMIT ?`
|
|
29866
30220
|
).all(limit).map(readPendingEnvelope);
|
|
29867
30221
|
};
|
|
30222
|
+
pendingSourceHeads = (limit, excludedEventIds, excludedSourceKeys) => {
|
|
30223
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
30224
|
+
throw new Error("Session event replay batch limit must be a positive integer");
|
|
30225
|
+
}
|
|
30226
|
+
const exclusions = [];
|
|
30227
|
+
const parameters = [];
|
|
30228
|
+
if (excludedEventIds.length > 0) {
|
|
30229
|
+
exclusions.push(`event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`);
|
|
30230
|
+
parameters.push(...excludedEventIds);
|
|
30231
|
+
}
|
|
30232
|
+
if (excludedSourceKeys.length > 0) {
|
|
30233
|
+
exclusions.push(`source_key NOT IN (${excludedSourceKeys.map(() => "?").join(", ")})`);
|
|
30234
|
+
parameters.push(...excludedSourceKeys);
|
|
30235
|
+
}
|
|
30236
|
+
parameters.push(limit.toString());
|
|
30237
|
+
const where = exclusions.length === 0 ? "" : `WHERE ${exclusions.join(" AND ")}`;
|
|
30238
|
+
return this.#database.prepare(
|
|
30239
|
+
`WITH available_events AS (
|
|
30240
|
+
SELECT ordinal, source_key
|
|
30241
|
+
FROM relay_session_event_outbox
|
|
30242
|
+
${where}
|
|
30243
|
+
), ranked_events AS (
|
|
30244
|
+
SELECT ordinal,
|
|
30245
|
+
ROW_NUMBER() OVER (
|
|
30246
|
+
PARTITION BY source_key
|
|
30247
|
+
ORDER BY ordinal
|
|
30248
|
+
) AS source_position
|
|
30249
|
+
FROM available_events
|
|
30250
|
+
)
|
|
30251
|
+
SELECT outbox.envelope_json
|
|
30252
|
+
FROM ranked_events AS ranked
|
|
30253
|
+
INNER JOIN relay_session_event_outbox AS outbox
|
|
30254
|
+
ON outbox.ordinal = ranked.ordinal
|
|
30255
|
+
WHERE ranked.source_position = 1
|
|
30256
|
+
ORDER BY outbox.ordinal
|
|
30257
|
+
LIMIT ?`
|
|
30258
|
+
).all(...parameters).map(readPendingEnvelope);
|
|
30259
|
+
};
|
|
29868
30260
|
};
|
|
30261
|
+
function validateLimits(limits) {
|
|
30262
|
+
const values = [
|
|
30263
|
+
limits.criticalEventBytes,
|
|
30264
|
+
limits.criticalEventCount,
|
|
30265
|
+
limits.runtimeDeliveryBytes,
|
|
30266
|
+
limits.runtimeDeliveryCount,
|
|
30267
|
+
limits.standardEventBytes,
|
|
30268
|
+
limits.standardEventCount
|
|
30269
|
+
];
|
|
30270
|
+
if (values.some((value) => !Number.isSafeInteger(value) || value < 1)) {
|
|
30271
|
+
throw new Error("Session event outbox limits must be positive integers");
|
|
30272
|
+
}
|
|
30273
|
+
if (limits.criticalEventBytes < limits.standardEventBytes || limits.criticalEventCount < limits.standardEventCount) {
|
|
30274
|
+
throw new Error("Critical Session event capacity must include the standard capacity");
|
|
30275
|
+
}
|
|
30276
|
+
}
|
|
30277
|
+
function runtimeDeliveryState(row) {
|
|
30278
|
+
const state = rowString2(row, "state");
|
|
30279
|
+
if (state !== "received" && state !== "relay_committed" && state !== "processed") {
|
|
30280
|
+
throw new Error("SQLite returned an invalid Runtime delivery state");
|
|
30281
|
+
}
|
|
30282
|
+
return state;
|
|
30283
|
+
}
|
|
29869
30284
|
function isDaemonExecutionState(value) {
|
|
29870
30285
|
return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
|
|
29871
30286
|
}
|
|
@@ -30084,8 +30499,7 @@ var ActiveTurnReconciliationError = class extends Error {
|
|
|
30084
30499
|
}
|
|
30085
30500
|
};
|
|
30086
30501
|
function activeTurnReconciliationEndpoint(config2, turn) {
|
|
30087
|
-
const endpoint =
|
|
30088
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
30502
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
30089
30503
|
let channelPath = "";
|
|
30090
30504
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
30091
30505
|
channelPath = endpoint.pathname.slice(0, -"/daemon".length);
|
|
@@ -30097,7 +30511,6 @@ function activeTurnReconciliationEndpoint(config2, turn) {
|
|
|
30097
30511
|
channelPath = `${endpoint.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
30098
30512
|
}
|
|
30099
30513
|
endpoint.pathname = `${channelPath}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
|
|
30100
|
-
endpoint.searchParams.delete("liveness");
|
|
30101
30514
|
return endpoint;
|
|
30102
30515
|
}
|
|
30103
30516
|
async function reconcileActiveTurn(config2, turn, signal) {
|
|
@@ -30109,7 +30522,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
30109
30522
|
response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
|
|
30110
30523
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
30111
30524
|
dispatcher: environmentProxyDispatcher,
|
|
30112
|
-
headers: { "content-type": "application/json" },
|
|
30525
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
30113
30526
|
method: "POST",
|
|
30114
30527
|
signal: requestSignal
|
|
30115
30528
|
});
|
|
@@ -30177,17 +30590,31 @@ var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectio
|
|
|
30177
30590
|
}
|
|
30178
30591
|
};
|
|
30179
30592
|
};
|
|
30180
|
-
var SESSION_EVENT_REPLAY_WINDOW =
|
|
30593
|
+
var SESSION_EVENT_REPLAY_WINDOW = 16;
|
|
30594
|
+
var SESSION_EVENT_SOURCE_REPLAY_WINDOW = 4;
|
|
30595
|
+
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
30596
|
+
var InFlightSessionEvent = class {
|
|
30597
|
+
byteLength;
|
|
30598
|
+
sourceKey;
|
|
30599
|
+
constructor(sourceKey, byteLength) {
|
|
30600
|
+
this.byteLength = byteLength;
|
|
30601
|
+
this.sourceKey = sourceKey;
|
|
30602
|
+
}
|
|
30603
|
+
};
|
|
30604
|
+
function sessionEventSourceKey(envelope2) {
|
|
30605
|
+
return envelope2.source.kind === "attempt" ? `attempt:${envelope2.sessionId}:${envelope2.source.attemptId}` : `runtime:${envelope2.sessionId}`;
|
|
30606
|
+
}
|
|
30181
30607
|
var DaemonSessionEventPublisher = class {
|
|
30182
30608
|
#outbox;
|
|
30183
|
-
#
|
|
30609
|
+
#inFlightEvents = /* @__PURE__ */ new Map();
|
|
30610
|
+
#inFlightBytes = 0;
|
|
30184
30611
|
#connection = new DisconnectedDaemonSessionEventState();
|
|
30185
30612
|
constructor(outbox) {
|
|
30186
30613
|
this.#outbox = outbox;
|
|
30187
30614
|
}
|
|
30188
30615
|
connect = (socket) => {
|
|
30189
30616
|
this.#connection = new ConnectedDaemonSessionEventState(socket);
|
|
30190
|
-
this.#
|
|
30617
|
+
this.#clearInFlight();
|
|
30191
30618
|
this.#publishNextBatch();
|
|
30192
30619
|
};
|
|
30193
30620
|
disconnect = (socket) => {
|
|
@@ -30195,10 +30622,15 @@ var DaemonSessionEventPublisher = class {
|
|
|
30195
30622
|
return;
|
|
30196
30623
|
}
|
|
30197
30624
|
this.#connection = this.#connection.disconnect(socket);
|
|
30198
|
-
this.#
|
|
30625
|
+
this.#clearInFlight();
|
|
30199
30626
|
};
|
|
30200
30627
|
recordAttempt = (sessionId, payload, attemptId) => {
|
|
30201
|
-
|
|
30628
|
+
const kind = decodeMessageKind(payload);
|
|
30629
|
+
if (kind === SESSION_COMPLETED_KIND || kind === SESSION_FAILED_KIND) {
|
|
30630
|
+
this.#outbox.enqueueCritical(sessionId, payload, attemptId);
|
|
30631
|
+
} else {
|
|
30632
|
+
this.#outbox.enqueue(sessionId, payload, attemptId);
|
|
30633
|
+
}
|
|
30202
30634
|
this.#publishNextBatch();
|
|
30203
30635
|
};
|
|
30204
30636
|
recordRuntime = (sessionId, payload) => {
|
|
@@ -30209,7 +30641,7 @@ var DaemonSessionEventPublisher = class {
|
|
|
30209
30641
|
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
30210
30642
|
return;
|
|
30211
30643
|
}
|
|
30212
|
-
this.#
|
|
30644
|
+
this.#removeInFlight(acknowledgement.eventId);
|
|
30213
30645
|
this.#publishNextBatch();
|
|
30214
30646
|
};
|
|
30215
30647
|
quarantine = (rejection) => {
|
|
@@ -30217,24 +30649,60 @@ var DaemonSessionEventPublisher = class {
|
|
|
30217
30649
|
if (!quarantined) {
|
|
30218
30650
|
return false;
|
|
30219
30651
|
}
|
|
30220
|
-
this.#
|
|
30652
|
+
this.#removeInFlight(rejection.eventId);
|
|
30221
30653
|
this.#publishNextBatch();
|
|
30222
30654
|
return true;
|
|
30223
30655
|
};
|
|
30224
30656
|
#publishNextBatch = () => {
|
|
30225
|
-
|
|
30226
|
-
|
|
30227
|
-
|
|
30228
|
-
|
|
30229
|
-
|
|
30230
|
-
const
|
|
30231
|
-
|
|
30232
|
-
this.#
|
|
30657
|
+
while (this.#inFlightEvents.size < SESSION_EVENT_REPLAY_WINDOW) {
|
|
30658
|
+
const sourceCounts = /* @__PURE__ */ new Map();
|
|
30659
|
+
for (const inFlight of this.#inFlightEvents.values()) {
|
|
30660
|
+
sourceCounts.set(inFlight.sourceKey, (sourceCounts.get(inFlight.sourceKey) ?? 0) + 1);
|
|
30661
|
+
}
|
|
30662
|
+
const saturatedSources = [...sourceCounts.entries()].filter(([, count]) => count >= SESSION_EVENT_SOURCE_REPLAY_WINDOW).map(([sourceKey]) => sourceKey);
|
|
30663
|
+
const batch = this.#outbox.pendingSourceHeads(
|
|
30664
|
+
SESSION_EVENT_REPLAY_WINDOW - this.#inFlightEvents.size,
|
|
30665
|
+
[...this.#inFlightEvents.keys()],
|
|
30666
|
+
saturatedSources
|
|
30667
|
+
);
|
|
30668
|
+
let sent = 0;
|
|
30669
|
+
for (const encoded of batch) {
|
|
30670
|
+
const envelope2 = decodeSessionEventEnvelope(encoded);
|
|
30671
|
+
const sourceKey = sessionEventSourceKey(envelope2);
|
|
30672
|
+
const sourceCount = sourceCounts.get(sourceKey) ?? 0;
|
|
30673
|
+
if (sourceCount >= SESSION_EVENT_SOURCE_REPLAY_WINDOW) {
|
|
30674
|
+
continue;
|
|
30675
|
+
}
|
|
30676
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
30677
|
+
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
30678
|
+
continue;
|
|
30679
|
+
}
|
|
30680
|
+
if (!this.#connection.send(encoded)) {
|
|
30681
|
+
this.#clearInFlight();
|
|
30682
|
+
return;
|
|
30683
|
+
}
|
|
30684
|
+
this.#inFlightEvents.set(envelope2.eventId, new InFlightSessionEvent(sourceKey, byteLength));
|
|
30685
|
+
this.#inFlightBytes += byteLength;
|
|
30686
|
+
sourceCounts.set(sourceKey, sourceCount + 1);
|
|
30687
|
+
sent += 1;
|
|
30688
|
+
}
|
|
30689
|
+
if (sent === 0) {
|
|
30233
30690
|
return;
|
|
30234
30691
|
}
|
|
30235
|
-
this.#inFlightEventIds.add(envelope2.eventId);
|
|
30236
30692
|
}
|
|
30237
30693
|
};
|
|
30694
|
+
#removeInFlight = (eventId) => {
|
|
30695
|
+
const inFlight = this.#inFlightEvents.get(eventId);
|
|
30696
|
+
if (inFlight === void 0) {
|
|
30697
|
+
return;
|
|
30698
|
+
}
|
|
30699
|
+
this.#inFlightEvents.delete(eventId);
|
|
30700
|
+
this.#inFlightBytes -= inFlight.byteLength;
|
|
30701
|
+
};
|
|
30702
|
+
#clearInFlight = () => {
|
|
30703
|
+
this.#inFlightEvents.clear();
|
|
30704
|
+
this.#inFlightBytes = 0;
|
|
30705
|
+
};
|
|
30238
30706
|
};
|
|
30239
30707
|
var CoalescingDaemonActivityPublisher = class {
|
|
30240
30708
|
#pending = /* @__PURE__ */ new Map();
|
|
@@ -30486,6 +30954,9 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
|
|
|
30486
30954
|
})
|
|
30487
30955
|
);
|
|
30488
30956
|
} catch (error61) {
|
|
30957
|
+
if (signal.aborted) {
|
|
30958
|
+
signal.throwIfAborted();
|
|
30959
|
+
}
|
|
30489
30960
|
reportOperationFailure(socket, command.requestId, command.sessionId, error61);
|
|
30490
30961
|
}
|
|
30491
30962
|
}
|
|
@@ -30825,6 +31296,7 @@ async function publishAgentCatalogUntilAvailable(config2, diagnostics, signal, t
|
|
|
30825
31296
|
}
|
|
30826
31297
|
async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, connectionEpoch, diagnostics, onConnected, signal, timer) {
|
|
30827
31298
|
const relayUrl = new URL(config2.relayUrl);
|
|
31299
|
+
relayUrl.searchParams.set("deliveryReceipts", "1");
|
|
30828
31300
|
relayUrl.searchParams.set("liveness", "1");
|
|
30829
31301
|
const socket = await connectRelay(relayUrl, signal);
|
|
30830
31302
|
const reconnectingTurns = [...activeTurns.values()];
|
|
@@ -30873,6 +31345,207 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30873
31345
|
closeRelaySocket(socket, code, reason);
|
|
30874
31346
|
rejectConnection(failure);
|
|
30875
31347
|
};
|
|
31348
|
+
const processingDeliveryIds = /* @__PURE__ */ new Set();
|
|
31349
|
+
const processDeliveredPrompt = async (delivery) => {
|
|
31350
|
+
const command = decodeSessionPromptCommand(delivery.payload);
|
|
31351
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31352
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31353
|
+
}
|
|
31354
|
+
const active = activeTurns.get(command.commandId);
|
|
31355
|
+
if (active !== void 0) {
|
|
31356
|
+
await active.completion;
|
|
31357
|
+
return;
|
|
31358
|
+
}
|
|
31359
|
+
const receipt = outbox.claimExecution(command.commandId, command.sessionId, delivery.payload);
|
|
31360
|
+
if (receipt.kind === "duplicate") {
|
|
31361
|
+
if (receipt.state === "running") {
|
|
31362
|
+
reportFailure(
|
|
31363
|
+
publisher,
|
|
31364
|
+
command,
|
|
31365
|
+
"agent_execution_interrupted",
|
|
31366
|
+
"The local Agent execution was interrupted before it completed",
|
|
31367
|
+
receipt.attemptId
|
|
31368
|
+
);
|
|
31369
|
+
outbox.transitionExecution(command.commandId, "failed");
|
|
31370
|
+
return;
|
|
31371
|
+
}
|
|
31372
|
+
if (receipt.state !== "dispatching") {
|
|
31373
|
+
return;
|
|
31374
|
+
}
|
|
31375
|
+
}
|
|
31376
|
+
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
31377
|
+
activeTurns.set(command.commandId, turn);
|
|
31378
|
+
if (command.disposition !== SessionPromptDisposition.Steer) {
|
|
31379
|
+
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
31380
|
+
}
|
|
31381
|
+
try {
|
|
31382
|
+
await executePrompt(
|
|
31383
|
+
outbox,
|
|
31384
|
+
publisher,
|
|
31385
|
+
command,
|
|
31386
|
+
config2,
|
|
31387
|
+
directories,
|
|
31388
|
+
audit,
|
|
31389
|
+
sessions,
|
|
31390
|
+
receipt.attemptId,
|
|
31391
|
+
timer,
|
|
31392
|
+
turn.signal
|
|
31393
|
+
);
|
|
31394
|
+
} finally {
|
|
31395
|
+
activeTurns.delete(command.commandId);
|
|
31396
|
+
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
31397
|
+
activeAttemptIds.delete(command.sessionId);
|
|
31398
|
+
}
|
|
31399
|
+
turn.finish();
|
|
31400
|
+
}
|
|
31401
|
+
};
|
|
31402
|
+
const processDeliveredPayload = async (delivery) => {
|
|
31403
|
+
const kind = decodeMessageKind(delivery.payload);
|
|
31404
|
+
if (kind === SESSION_CANCEL_KIND) {
|
|
31405
|
+
const cancellation = decodeSessionCancelCommand(delivery.payload);
|
|
31406
|
+
if (cancellation.sessionId !== delivery.sessionId) {
|
|
31407
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31408
|
+
}
|
|
31409
|
+
const turn = activeTurns.get(cancellation.commandId);
|
|
31410
|
+
if (turn === void 0 || !turn.matches(cancellation) || !turn.requestCancellation()) {
|
|
31411
|
+
return;
|
|
31412
|
+
}
|
|
31413
|
+
audit.record({
|
|
31414
|
+
commandId: cancellation.commandId,
|
|
31415
|
+
event: "session_cancellation_requested",
|
|
31416
|
+
sessionId: cancellation.sessionId
|
|
31417
|
+
});
|
|
31418
|
+
await sessions.cancelPrompt(cancellation.sessionId);
|
|
31419
|
+
return;
|
|
31420
|
+
}
|
|
31421
|
+
if (kind === SESSION_CONFIGURE_KIND) {
|
|
31422
|
+
const command = decodeSessionConfigureCommand(delivery.payload);
|
|
31423
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31424
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31425
|
+
}
|
|
31426
|
+
await executeSessionConfigure(
|
|
31427
|
+
publisher,
|
|
31428
|
+
socket,
|
|
31429
|
+
command,
|
|
31430
|
+
config2,
|
|
31431
|
+
directories,
|
|
31432
|
+
audit,
|
|
31433
|
+
sessions,
|
|
31434
|
+
connectionController.signal
|
|
31435
|
+
);
|
|
31436
|
+
return;
|
|
31437
|
+
}
|
|
31438
|
+
if (kind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
31439
|
+
const command = decodeSessionPermissionRespondCommand(delivery.payload);
|
|
31440
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31441
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31442
|
+
}
|
|
31443
|
+
try {
|
|
31444
|
+
await sessions.respondPermission(command);
|
|
31445
|
+
audit.record({
|
|
31446
|
+
commandId: command.interactionId,
|
|
31447
|
+
event: "session_permission_resolved",
|
|
31448
|
+
sessionId: command.sessionId
|
|
31449
|
+
});
|
|
31450
|
+
} catch (error61) {
|
|
31451
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
31452
|
+
}
|
|
31453
|
+
return;
|
|
31454
|
+
}
|
|
31455
|
+
if (kind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
31456
|
+
const command = decodeSessionElicitationRespondCommand(delivery.payload);
|
|
31457
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
31458
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31459
|
+
}
|
|
31460
|
+
try {
|
|
31461
|
+
await sessions.respondElicitation(command);
|
|
31462
|
+
audit.record({
|
|
31463
|
+
commandId: command.interactionId,
|
|
31464
|
+
event: "session_elicitation_resolved",
|
|
31465
|
+
sessionId: command.sessionId
|
|
31466
|
+
});
|
|
31467
|
+
} catch (error61) {
|
|
31468
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
31469
|
+
}
|
|
31470
|
+
return;
|
|
31471
|
+
}
|
|
31472
|
+
if (kind === SESSION_PROMPT_KIND) {
|
|
31473
|
+
await processDeliveredPrompt(delivery);
|
|
31474
|
+
return;
|
|
31475
|
+
}
|
|
31476
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31477
|
+
};
|
|
31478
|
+
const processRuntimeDelivery = (delivery, state) => {
|
|
31479
|
+
if (state === "processed" || processingDeliveryIds.has(delivery.deliveryId)) {
|
|
31480
|
+
return;
|
|
31481
|
+
}
|
|
31482
|
+
processingDeliveryIds.add(delivery.deliveryId);
|
|
31483
|
+
void processDeliveredPayload(delivery).then(() => {
|
|
31484
|
+
outbox.markRuntimeDeliveryProcessed(delivery.deliveryId, delivery.sessionId);
|
|
31485
|
+
}).catch((error61) => {
|
|
31486
|
+
if (connectionController.signal.aborted) {
|
|
31487
|
+
return;
|
|
31488
|
+
}
|
|
31489
|
+
console.error("Mobius daemon could not process a durable Runtime delivery", error61);
|
|
31490
|
+
failAndClose(
|
|
31491
|
+
new Error("Runtime delivery processing failed", { cause: error61 }),
|
|
31492
|
+
4008,
|
|
31493
|
+
"Invalid Runtime delivery",
|
|
31494
|
+
"delivery"
|
|
31495
|
+
);
|
|
31496
|
+
}).finally(() => processingDeliveryIds.delete(delivery.deliveryId));
|
|
31497
|
+
};
|
|
31498
|
+
const receiveRuntimeDelivery = (delivery) => {
|
|
31499
|
+
const payloadKind = decodeMessageKind(delivery.payload);
|
|
31500
|
+
let payloadSessionId = "";
|
|
31501
|
+
if (payloadKind === SESSION_CANCEL_KIND) {
|
|
31502
|
+
payloadSessionId = decodeSessionCancelCommand(delivery.payload).sessionId;
|
|
31503
|
+
} else if (payloadKind === SESSION_CONFIGURE_KIND) {
|
|
31504
|
+
payloadSessionId = decodeSessionConfigureCommand(delivery.payload).sessionId;
|
|
31505
|
+
} else if (payloadKind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
31506
|
+
payloadSessionId = decodeSessionPermissionRespondCommand(delivery.payload).sessionId;
|
|
31507
|
+
} else if (payloadKind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
31508
|
+
payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
|
|
31509
|
+
} else if (payloadKind === SESSION_PROMPT_KIND) {
|
|
31510
|
+
payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
|
|
31511
|
+
} else {
|
|
31512
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31513
|
+
}
|
|
31514
|
+
if (payloadSessionId !== delivery.sessionId) {
|
|
31515
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31516
|
+
}
|
|
31517
|
+
const stored = outbox.claimRuntimeDelivery(delivery);
|
|
31518
|
+
send(
|
|
31519
|
+
socket,
|
|
31520
|
+
encodeRuntimeDeliveryReceived({
|
|
31521
|
+
deliveryId: delivery.deliveryId,
|
|
31522
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
31523
|
+
sessionId: delivery.sessionId
|
|
31524
|
+
})
|
|
31525
|
+
);
|
|
31526
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
31527
|
+
};
|
|
31528
|
+
const resumeRuntimeDeliveries = () => {
|
|
31529
|
+
for (const stored of outbox.runtimeDeliveries()) {
|
|
31530
|
+
const delivery = {
|
|
31531
|
+
deliveryId: stored.deliveryId,
|
|
31532
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
31533
|
+
payload: stored.payload,
|
|
31534
|
+
sessionId: stored.sessionId
|
|
31535
|
+
};
|
|
31536
|
+
if (stored.state !== "relay_committed") {
|
|
31537
|
+
send(
|
|
31538
|
+
socket,
|
|
31539
|
+
encodeRuntimeDeliveryReceived({
|
|
31540
|
+
deliveryId: stored.deliveryId,
|
|
31541
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
31542
|
+
sessionId: stored.sessionId
|
|
31543
|
+
})
|
|
31544
|
+
);
|
|
31545
|
+
}
|
|
31546
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
31547
|
+
}
|
|
31548
|
+
};
|
|
30876
31549
|
const connectionLiveness = new RelayConnectionLiveness(timer, {
|
|
30877
31550
|
send: (message) => send(socket, message),
|
|
30878
31551
|
unresponsive: (heartbeatId, timeoutMilliseconds) => {
|
|
@@ -30911,6 +31584,17 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30911
31584
|
}
|
|
30912
31585
|
try {
|
|
30913
31586
|
const kind = decodeMessageKind(encoded);
|
|
31587
|
+
if (kind === RUNTIME_DELIVERY_COMMITTED_KIND) {
|
|
31588
|
+
const committed = decodeRuntimeDeliveryCommitted(encoded);
|
|
31589
|
+
if (!outbox.markRuntimeDeliveryCommitted(committed.deliveryId, committed.sessionId)) {
|
|
31590
|
+
console.warn("Mobius daemon ignored confirmation for an unknown Runtime delivery");
|
|
31591
|
+
}
|
|
31592
|
+
return;
|
|
31593
|
+
}
|
|
31594
|
+
if (kind === RUNTIME_DELIVERY_KIND) {
|
|
31595
|
+
receiveRuntimeDelivery(decodeRuntimeDelivery(encoded));
|
|
31596
|
+
return;
|
|
31597
|
+
}
|
|
30914
31598
|
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
30915
31599
|
publisher.acknowledge(decodeSessionEventAcknowledgement(encoded));
|
|
30916
31600
|
return;
|
|
@@ -31347,6 +32031,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31347
32031
|
});
|
|
31348
32032
|
} catch (error61) {
|
|
31349
32033
|
console.error("Mobius daemon rejected a message", error61);
|
|
32034
|
+
if (error61 instanceof RuntimeDeliveryInboxCapacityError) {
|
|
32035
|
+
failAndClose(error61, 4013, "Runtime delivery queue full", "delivery_backpressure");
|
|
32036
|
+
return;
|
|
32037
|
+
}
|
|
31350
32038
|
failAndClose(
|
|
31351
32039
|
new Error("Relay sent an invalid protocol message", { cause: error61 }),
|
|
31352
32040
|
4008,
|
|
@@ -31364,6 +32052,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31364
32052
|
return;
|
|
31365
32053
|
}
|
|
31366
32054
|
publisher.connect(socket);
|
|
32055
|
+
resumeRuntimeDeliveries();
|
|
31367
32056
|
},
|
|
31368
32057
|
(error61) => {
|
|
31369
32058
|
if (finished) {
|
|
@@ -31583,12 +32272,14 @@ process.once("SIGTERM", () => shutdown.abort());
|
|
|
31583
32272
|
var USAGE = `Mobius CLI
|
|
31584
32273
|
|
|
31585
32274
|
Usage:
|
|
32275
|
+
mobius --version
|
|
31586
32276
|
mobius pair --url <relay-url> --pairing <runtime-pairing-id> --code <pairing-code> [--workspace <directory>]
|
|
31587
32277
|
mobius start --channel <channel-id>
|
|
31588
32278
|
mobius agents [--json]
|
|
31589
32279
|
mobius bot message send --target <current|alias> --text <message>
|
|
31590
32280
|
|
|
31591
32281
|
Commands:
|
|
32282
|
+
--version Print the installed Mobius CLI version
|
|
31592
32283
|
pair Pair this machine and start its local daemon
|
|
31593
32284
|
start Start the local daemon for a saved channel
|
|
31594
32285
|
agents Show detected, missing, and integration-ready Agents
|
|
@@ -31603,6 +32294,11 @@ async function main() {
|
|
|
31603
32294
|
process.stdout.write(USAGE);
|
|
31604
32295
|
return;
|
|
31605
32296
|
}
|
|
32297
|
+
if (command === "--version" || command === "-v" || command === "version") {
|
|
32298
|
+
process.stdout.write(`${package_default.version}
|
|
32299
|
+
`);
|
|
32300
|
+
return;
|
|
32301
|
+
}
|
|
31606
32302
|
if (command === "agents") {
|
|
31607
32303
|
const arguments_ = process.argv.slice(3);
|
|
31608
32304
|
if (arguments_.length > 1 || arguments_.length === 1 && arguments_[0] !== "--json") {
|