@moxt-ai/mobius 0.0.25 → 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 +1194 -205
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1186 -204
- package/dist/index.js.map +4 -4
- package/dist/network/environment-proxy.d.ts +1 -0
- package/dist/network/environment-proxy.d.ts.map +1 -1
- package/dist/network/environment-proxy.js +47 -0
- package/dist/network/environment-proxy.js.map +1 -1
- 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 +19 -14
- package/dist/relay-connection/connect.js.map +1 -1
- package/dist/relay-connection/diagnostics.d.ts +11 -0
- package/dist/relay-connection/diagnostics.d.ts.map +1 -0
- package/dist/relay-connection/diagnostics.js +122 -0
- package/dist/relay-connection/diagnostics.js.map +1 -0
- package/dist/relay-connection/liveness.d.ts +1 -1
- package/dist/relay-connection/liveness.d.ts.map +1 -1
- package/dist/relay-connection/liveness.js +2 -1
- package/dist/relay-connection/liveness.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 +34 -3
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +404 -13
- 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 +437 -151
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +1186 -204
- package/dist/runtime.js.map +4 -4
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -1450,7 +1450,53 @@ import { fetch } from "undici";
|
|
|
1450
1450
|
|
|
1451
1451
|
// src/network/environment-proxy.ts
|
|
1452
1452
|
import { EnvHttpProxyAgent } from "undici";
|
|
1453
|
+
var configuredHttpProxy = process.env["http_proxy"] ?? process.env["HTTP_PROXY"] ?? "";
|
|
1454
|
+
var configuredHttpsProxy = process.env["https_proxy"] ?? process.env["HTTPS_PROXY"] ?? configuredHttpProxy;
|
|
1453
1455
|
var environmentProxyDispatcher = new EnvHttpProxyAgent();
|
|
1456
|
+
function bypassesProxy(target) {
|
|
1457
|
+
const noProxy = process.env["no_proxy"] ?? process.env["NO_PROXY"] ?? "";
|
|
1458
|
+
if (noProxy === "*") {
|
|
1459
|
+
return true;
|
|
1460
|
+
}
|
|
1461
|
+
const hostname4 = target.hostname.replace(/^\[|\]$/gu, "").toLowerCase();
|
|
1462
|
+
const defaultPort = target.protocol === "wss:" || target.protocol === "https:" ? 443 : 80;
|
|
1463
|
+
const port = Number.parseInt(target.port, 10) || defaultPort;
|
|
1464
|
+
for (const rawEntry of noProxy.split(/[,\s]/u)) {
|
|
1465
|
+
if (rawEntry.length === 0) {
|
|
1466
|
+
continue;
|
|
1467
|
+
}
|
|
1468
|
+
const parsed = rawEntry.match(/^(.+):(\d+)$/u);
|
|
1469
|
+
const entryHostname = (parsed?.[1] ?? rawEntry).replace(/^\*?\./u, "").toLowerCase();
|
|
1470
|
+
const entryPort = parsed?.[2] === void 0 ? 0 : Number.parseInt(parsed[2], 10);
|
|
1471
|
+
if (entryPort !== 0 && entryPort !== port) {
|
|
1472
|
+
continue;
|
|
1473
|
+
}
|
|
1474
|
+
if (hostname4 === entryHostname || hostname4.endsWith(`.${entryHostname}`)) {
|
|
1475
|
+
return true;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return false;
|
|
1479
|
+
}
|
|
1480
|
+
function sanitizedProxyOrigin(proxyUrl) {
|
|
1481
|
+
try {
|
|
1482
|
+
return new URL(proxyUrl).origin;
|
|
1483
|
+
} catch {
|
|
1484
|
+
return "configured-invalid-url";
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
function describeEnvironmentProxyRoute(target) {
|
|
1488
|
+
if (bypassesProxy(target)) {
|
|
1489
|
+
return { proxyRoute: "direct" };
|
|
1490
|
+
}
|
|
1491
|
+
const proxyUrl = target.protocol === "wss:" || target.protocol === "https:" ? configuredHttpsProxy : configuredHttpProxy;
|
|
1492
|
+
if (proxyUrl.length === 0) {
|
|
1493
|
+
return { proxyRoute: "direct" };
|
|
1494
|
+
}
|
|
1495
|
+
return {
|
|
1496
|
+
proxyOrigin: sanitizedProxyOrigin(proxyUrl),
|
|
1497
|
+
proxyRoute: "proxy"
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1454
1500
|
|
|
1455
1501
|
// src/agent-installation/managed-agent-archive.ts
|
|
1456
1502
|
var ARCHIVE_DOWNLOAD_LIMIT_BYTES = 128 * 1024 * 1024;
|
|
@@ -21810,6 +21856,9 @@ var SESSION_CANCEL_KIND = "session.cancel";
|
|
|
21810
21856
|
var RUNTIME_LIVENESS_READY_KIND = "runtime.liveness.ready";
|
|
21811
21857
|
var RUNTIME_HEARTBEAT_KIND = "runtime.heartbeat";
|
|
21812
21858
|
var RUNTIME_HEARTBEAT_ACK_KIND = "runtime.heartbeat.ack";
|
|
21859
|
+
var RUNTIME_DELIVERY_KIND = "runtime.delivery";
|
|
21860
|
+
var RUNTIME_DELIVERY_RECEIVED_KIND = "runtime.delivery.received";
|
|
21861
|
+
var RUNTIME_DELIVERY_COMMITTED_KIND = "runtime.delivery.committed";
|
|
21813
21862
|
var SESSION_STARTED_KIND = "session.started";
|
|
21814
21863
|
var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
|
|
21815
21864
|
var AGENT_ACTIVITY_KIND = "agent.activity";
|
|
@@ -21832,6 +21881,7 @@ var DIRECTORY_IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
|
|
|
21832
21881
|
var MAX_PROMPT_LENGTH = 1e4;
|
|
21833
21882
|
var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
|
|
21834
21883
|
var MAX_EVENT_TEXT_LENGTH = 1e5;
|
|
21884
|
+
var MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH = 8 * 1024 * 1024;
|
|
21835
21885
|
var ACTIVITY_TYPES = /* @__PURE__ */ new Set(["plan", "progress", "reasoning", "tool"]);
|
|
21836
21886
|
var ACTIVITY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "completed", "failed"]);
|
|
21837
21887
|
var TOOL_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -22110,6 +22160,37 @@ function decodeRuntimeHeartbeatAckEvent(encoded) {
|
|
|
22110
22160
|
kind: RUNTIME_HEARTBEAT_ACK_KIND
|
|
22111
22161
|
};
|
|
22112
22162
|
}
|
|
22163
|
+
function decodeRuntimeDelivery(encoded) {
|
|
22164
|
+
const value = parseJson2(encoded);
|
|
22165
|
+
assertExactKeys(value, ["deliveryId", "kind", "payload", "sessionId"]);
|
|
22166
|
+
assertKind(value, RUNTIME_DELIVERY_KIND);
|
|
22167
|
+
return {
|
|
22168
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22169
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
22170
|
+
payload: readString(value, "payload", MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH),
|
|
22171
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22172
|
+
};
|
|
22173
|
+
}
|
|
22174
|
+
function decodeRuntimeDeliveryReceived(encoded) {
|
|
22175
|
+
const value = parseJson2(encoded);
|
|
22176
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
22177
|
+
assertKind(value, RUNTIME_DELIVERY_RECEIVED_KIND);
|
|
22178
|
+
return {
|
|
22179
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22180
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
22181
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22182
|
+
};
|
|
22183
|
+
}
|
|
22184
|
+
function decodeRuntimeDeliveryCommitted(encoded) {
|
|
22185
|
+
const value = parseJson2(encoded);
|
|
22186
|
+
assertExactKeys(value, ["deliveryId", "kind", "sessionId"]);
|
|
22187
|
+
assertKind(value, RUNTIME_DELIVERY_COMMITTED_KIND);
|
|
22188
|
+
return {
|
|
22189
|
+
deliveryId: readIdentifier(value, "deliveryId"),
|
|
22190
|
+
kind: RUNTIME_DELIVERY_COMMITTED_KIND,
|
|
22191
|
+
sessionId: readIdentifier(value, "sessionId")
|
|
22192
|
+
};
|
|
22193
|
+
}
|
|
22113
22194
|
function decodeSessionStartedEvent(encoded) {
|
|
22114
22195
|
const value = parseJson2(encoded);
|
|
22115
22196
|
assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
|
|
@@ -22197,6 +22278,9 @@ function decodeSessionFailedEvent(encoded) {
|
|
|
22197
22278
|
function encodeRuntimeHeartbeatEvent(message) {
|
|
22198
22279
|
return JSON.stringify(decodeRuntimeHeartbeatEvent(JSON.stringify(message)));
|
|
22199
22280
|
}
|
|
22281
|
+
function encodeRuntimeDeliveryReceived(message) {
|
|
22282
|
+
return JSON.stringify(decodeRuntimeDeliveryReceived(JSON.stringify(message)));
|
|
22283
|
+
}
|
|
22200
22284
|
function encodeSessionStartedEvent(message) {
|
|
22201
22285
|
return JSON.stringify(decodeSessionStartedEvent(JSON.stringify(message)));
|
|
22202
22286
|
}
|
|
@@ -22895,7 +22979,8 @@ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
|
|
|
22895
22979
|
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
22896
22980
|
var SessionEventRejectionCode = {
|
|
22897
22981
|
SessionDeleted: "session_deleted",
|
|
22898
|
-
SessionNotFound: "session_not_found"
|
|
22982
|
+
SessionNotFound: "session_not_found",
|
|
22983
|
+
SessionRejected: "session_rejected"
|
|
22899
22984
|
};
|
|
22900
22985
|
var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
22901
22986
|
var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
|
|
@@ -22967,6 +23052,7 @@ var encode4 = (message, schema) => {
|
|
|
22967
23052
|
}
|
|
22968
23053
|
return JSON.stringify(decoded.data);
|
|
22969
23054
|
};
|
|
23055
|
+
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, eventEnvelopeSchema);
|
|
22970
23056
|
var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
|
|
22971
23057
|
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
22972
23058
|
var decodeSessionEventRejection = (encoded) => decode5(encoded, eventRejectionSchema);
|
|
@@ -26371,6 +26457,23 @@ var AcpSessionManager = class {
|
|
|
26371
26457
|
|
|
26372
26458
|
// src/agent-catalog/publish-agent-catalog.ts
|
|
26373
26459
|
import { fetch as fetch2 } from "undici";
|
|
26460
|
+
|
|
26461
|
+
// src/relay-connection/runtime-authentication.ts
|
|
26462
|
+
function runtimeCredential(relayUrl) {
|
|
26463
|
+
return relayUrl.searchParams.get("token") ?? "";
|
|
26464
|
+
}
|
|
26465
|
+
function runtimeAuthorization(relayUrl) {
|
|
26466
|
+
const credential = runtimeCredential(relayUrl);
|
|
26467
|
+
return credential.length === 0 ? {} : { authorization: `Bearer ${credential}` };
|
|
26468
|
+
}
|
|
26469
|
+
function relayHttpEndpoint(relayUrl) {
|
|
26470
|
+
const endpoint = new URL(relayUrl);
|
|
26471
|
+
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
26472
|
+
endpoint.search = "";
|
|
26473
|
+
return endpoint;
|
|
26474
|
+
}
|
|
26475
|
+
|
|
26476
|
+
// src/agent-catalog/publish-agent-catalog.ts
|
|
26374
26477
|
var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
|
|
26375
26478
|
var AgentCatalogPublishError = class extends Error {
|
|
26376
26479
|
code = "agent_catalog_update_failed";
|
|
@@ -26380,8 +26483,7 @@ var AgentCatalogPublishError = class extends Error {
|
|
|
26380
26483
|
}
|
|
26381
26484
|
};
|
|
26382
26485
|
function catalogEndpoint(config2) {
|
|
26383
|
-
const endpoint =
|
|
26384
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
26486
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
26385
26487
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
26386
26488
|
endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/catalog`;
|
|
26387
26489
|
return endpoint;
|
|
@@ -26412,7 +26514,7 @@ async function publishAgentCatalog(config2, signal) {
|
|
|
26412
26514
|
installableAgents: catalog.installableAgents
|
|
26413
26515
|
}),
|
|
26414
26516
|
dispatcher: environmentProxyDispatcher,
|
|
26415
|
-
headers: { "content-type": "application/json" },
|
|
26517
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
26416
26518
|
method: "PUT",
|
|
26417
26519
|
signal: requestSignal
|
|
26418
26520
|
});
|
|
@@ -28454,8 +28556,7 @@ function parseReference(resource) {
|
|
|
28454
28556
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
28455
28557
|
}
|
|
28456
28558
|
function downloadUrl(config2, command, reference) {
|
|
28457
|
-
const url2 =
|
|
28458
|
-
url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
|
|
28559
|
+
const url2 = relayHttpEndpoint(config2.relayUrl);
|
|
28459
28560
|
let channelPath = "";
|
|
28460
28561
|
if (url2.pathname.endsWith("/daemon")) {
|
|
28461
28562
|
channelPath = url2.pathname.slice(0, -"/daemon".length);
|
|
@@ -28467,7 +28568,6 @@ function downloadUrl(config2, command, reference) {
|
|
|
28467
28568
|
channelPath = `${url2.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
28468
28569
|
}
|
|
28469
28570
|
url2.pathname = `${channelPath}/sessions/${encodeURIComponent(command.sessionId)}/commands/${encodeURIComponent(command.commandId)}/artifacts/${encodeURIComponent(reference.artifactId)}/content`;
|
|
28470
|
-
url2.searchParams.delete("liveness");
|
|
28471
28571
|
return url2;
|
|
28472
28572
|
}
|
|
28473
28573
|
async function responseBytes(response, expectedByteLength, signal) {
|
|
@@ -28518,7 +28618,11 @@ async function download(config2, command, reference, signal) {
|
|
|
28518
28618
|
try {
|
|
28519
28619
|
response = await fetch4(downloadUrl(config2, command, reference), {
|
|
28520
28620
|
dispatcher: environmentProxyDispatcher,
|
|
28521
|
-
headers: {
|
|
28621
|
+
headers: {
|
|
28622
|
+
accept: reference.resource.mimeType,
|
|
28623
|
+
"accept-encoding": "identity",
|
|
28624
|
+
...runtimeAuthorization(config2.relayUrl)
|
|
28625
|
+
},
|
|
28522
28626
|
signal: requestSignal
|
|
28523
28627
|
});
|
|
28524
28628
|
if (!response.ok) {
|
|
@@ -28616,9 +28720,11 @@ import { WebSocket } from "undici";
|
|
|
28616
28720
|
var CONNECTION_TIMEOUT_MILLISECONDS = 15e3;
|
|
28617
28721
|
var RelayConnectionError = class extends Error {
|
|
28618
28722
|
code;
|
|
28619
|
-
|
|
28723
|
+
diagnosticDetails;
|
|
28724
|
+
constructor(code, message, diagnosticDetails = {}, options = {}) {
|
|
28620
28725
|
super(message, options);
|
|
28621
28726
|
this.code = code;
|
|
28727
|
+
this.diagnosticDetails = diagnosticDetails;
|
|
28622
28728
|
this.name = "RelayConnectionError";
|
|
28623
28729
|
}
|
|
28624
28730
|
};
|
|
@@ -28626,12 +28732,8 @@ function connectRelay(url2, signal) {
|
|
|
28626
28732
|
signal.throwIfAborted();
|
|
28627
28733
|
return new Promise((resolve6, reject) => {
|
|
28628
28734
|
const endpoint = new URL(url2);
|
|
28629
|
-
const headers =
|
|
28630
|
-
|
|
28631
|
-
const runtimeCredential = endpoint.searchParams.get("token") ?? "";
|
|
28632
|
-
endpoint.searchParams.delete("token");
|
|
28633
|
-
headers["authorization"] = `Bearer ${runtimeCredential}`;
|
|
28634
|
-
}
|
|
28735
|
+
const headers = runtimeAuthorization(endpoint);
|
|
28736
|
+
endpoint.searchParams.delete("token");
|
|
28635
28737
|
const socket = new WebSocket(endpoint, {
|
|
28636
28738
|
dispatcher: environmentProxyDispatcher,
|
|
28637
28739
|
headers
|
|
@@ -28656,16 +28758,34 @@ function connectRelay(url2, signal) {
|
|
|
28656
28758
|
};
|
|
28657
28759
|
const onAbort = () => {
|
|
28658
28760
|
fail(
|
|
28659
|
-
new RelayConnectionError(
|
|
28660
|
-
|
|
28661
|
-
|
|
28761
|
+
new RelayConnectionError(
|
|
28762
|
+
"relay_connection_cancelled",
|
|
28763
|
+
"Relay connection was cancelled",
|
|
28764
|
+
{
|
|
28765
|
+
cancellation: "requested"
|
|
28766
|
+
},
|
|
28767
|
+
{ cause: signal.reason }
|
|
28768
|
+
)
|
|
28662
28769
|
);
|
|
28663
28770
|
};
|
|
28664
|
-
const onClose = () => {
|
|
28665
|
-
fail(
|
|
28771
|
+
const onClose = (event) => {
|
|
28772
|
+
fail(
|
|
28773
|
+
new RelayConnectionError("relay_connection_closed", "Relay connection closed before it was ready", {
|
|
28774
|
+
closeCode: event.code.toString(),
|
|
28775
|
+
closeReason: event.reason
|
|
28776
|
+
})
|
|
28777
|
+
);
|
|
28666
28778
|
};
|
|
28667
|
-
const onError = () => {
|
|
28668
|
-
|
|
28779
|
+
const onError = (event) => {
|
|
28780
|
+
const cause = Reflect.get(event, "error");
|
|
28781
|
+
fail(
|
|
28782
|
+
new RelayConnectionError(
|
|
28783
|
+
"relay_connection_failed",
|
|
28784
|
+
"Relay connection failed",
|
|
28785
|
+
{},
|
|
28786
|
+
{ cause: cause ?? event }
|
|
28787
|
+
)
|
|
28788
|
+
);
|
|
28669
28789
|
};
|
|
28670
28790
|
const onOpen = () => {
|
|
28671
28791
|
if (finished) {
|
|
@@ -28676,7 +28796,11 @@ function connectRelay(url2, signal) {
|
|
|
28676
28796
|
resolve6(socket);
|
|
28677
28797
|
};
|
|
28678
28798
|
function onTimeout() {
|
|
28679
|
-
fail(
|
|
28799
|
+
fail(
|
|
28800
|
+
new RelayConnectionError("relay_connection_timeout", "Relay connection timed out", {
|
|
28801
|
+
timeoutMilliseconds: CONNECTION_TIMEOUT_MILLISECONDS.toString()
|
|
28802
|
+
})
|
|
28803
|
+
);
|
|
28680
28804
|
}
|
|
28681
28805
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
28682
28806
|
socket.addEventListener("close", onClose, { once: true });
|
|
@@ -28688,6 +28812,142 @@ function connectRelay(url2, signal) {
|
|
|
28688
28812
|
});
|
|
28689
28813
|
}
|
|
28690
28814
|
|
|
28815
|
+
// src/relay-connection/diagnostics.ts
|
|
28816
|
+
var MAX_DIAGNOSTIC_TEXT_LENGTH = 256;
|
|
28817
|
+
function sanitizeDiagnosticText(value) {
|
|
28818
|
+
const printable = Array.from(value, (character) => {
|
|
28819
|
+
const code = character.charCodeAt(0);
|
|
28820
|
+
return code < 32 || code === 127 ? " " : character;
|
|
28821
|
+
}).join("");
|
|
28822
|
+
const withoutSecrets = printable.replace(/([?&](?:access_token|authorization|credential|key|secret|token)=)[^&\s]*/giu, "$1[redacted]").replace(/(?:https?|wss?):\/\/[^\s)]+/giu, (encodedUrl) => {
|
|
28823
|
+
try {
|
|
28824
|
+
return new URL(encodedUrl).origin;
|
|
28825
|
+
} catch {
|
|
28826
|
+
return "[redacted-url]";
|
|
28827
|
+
}
|
|
28828
|
+
});
|
|
28829
|
+
return withoutSecrets.slice(0, MAX_DIAGNOSTIC_TEXT_LENGTH);
|
|
28830
|
+
}
|
|
28831
|
+
function addFailureDetails(details, failure) {
|
|
28832
|
+
let current = failure;
|
|
28833
|
+
for (let depth = 0; depth < 3 && current instanceof Error; depth += 1) {
|
|
28834
|
+
const prefix = depth === 0 ? "failure" : `cause${depth.toString()}`;
|
|
28835
|
+
details[`${prefix}Name`] = current.name;
|
|
28836
|
+
details[`${prefix}Message`] = sanitizeDiagnosticText(current.message);
|
|
28837
|
+
const code = Reflect.get(current, "code");
|
|
28838
|
+
if (typeof code === "string" || typeof code === "number") {
|
|
28839
|
+
details[`${prefix}Code`] = String(code);
|
|
28840
|
+
}
|
|
28841
|
+
const statusCode = Reflect.get(current, "statusCode");
|
|
28842
|
+
if (typeof statusCode === "string" || typeof statusCode === "number") {
|
|
28843
|
+
details[`${prefix}StatusCode`] = String(statusCode);
|
|
28844
|
+
}
|
|
28845
|
+
const diagnosticDetails = Reflect.get(current, "diagnosticDetails");
|
|
28846
|
+
if (typeof diagnosticDetails === "object" && diagnosticDetails !== null) {
|
|
28847
|
+
for (const [key, value] of Object.entries(diagnosticDetails)) {
|
|
28848
|
+
if (typeof value === "string") {
|
|
28849
|
+
details[key] = sanitizeDiagnosticText(value);
|
|
28850
|
+
}
|
|
28851
|
+
}
|
|
28852
|
+
}
|
|
28853
|
+
current = current.cause;
|
|
28854
|
+
}
|
|
28855
|
+
}
|
|
28856
|
+
var RelayConnectionDiagnostics = class {
|
|
28857
|
+
#audit;
|
|
28858
|
+
#channelId;
|
|
28859
|
+
#lastClosedEpoch = 0;
|
|
28860
|
+
#lastFailedEpoch = 0;
|
|
28861
|
+
#relayOrigin;
|
|
28862
|
+
#route;
|
|
28863
|
+
constructor(audit, channelId, relayUrl) {
|
|
28864
|
+
this.#audit = audit;
|
|
28865
|
+
this.#channelId = channelId;
|
|
28866
|
+
this.#relayOrigin = relayUrl.origin;
|
|
28867
|
+
this.#route = describeEnvironmentProxyRoute(relayUrl);
|
|
28868
|
+
}
|
|
28869
|
+
catalogFailed = (failure) => {
|
|
28870
|
+
const details = { ...this.#route, relayOrigin: this.#relayOrigin };
|
|
28871
|
+
addFailureDetails(details, failure);
|
|
28872
|
+
this.#record("agent_catalog_publish_failed", "catalog", details, true);
|
|
28873
|
+
};
|
|
28874
|
+
connectionClosed = (connectionEpoch, code, reason, source) => {
|
|
28875
|
+
if (this.#lastClosedEpoch === connectionEpoch) {
|
|
28876
|
+
return;
|
|
28877
|
+
}
|
|
28878
|
+
this.#lastClosedEpoch = connectionEpoch;
|
|
28879
|
+
this.#record(
|
|
28880
|
+
"relay_connection_closed",
|
|
28881
|
+
connectionEpoch.toString(),
|
|
28882
|
+
{
|
|
28883
|
+
closeCode: code.toString(),
|
|
28884
|
+
closeReason: sanitizeDiagnosticText(reason),
|
|
28885
|
+
connectionEpoch: connectionEpoch.toString(),
|
|
28886
|
+
relayOrigin: this.#relayOrigin,
|
|
28887
|
+
source,
|
|
28888
|
+
...this.#route
|
|
28889
|
+
},
|
|
28890
|
+
true
|
|
28891
|
+
);
|
|
28892
|
+
};
|
|
28893
|
+
connectionFailed = (connectionEpoch, failure, source) => {
|
|
28894
|
+
if (this.#lastFailedEpoch === connectionEpoch) {
|
|
28895
|
+
return;
|
|
28896
|
+
}
|
|
28897
|
+
this.#lastFailedEpoch = connectionEpoch;
|
|
28898
|
+
const details = {
|
|
28899
|
+
connectionEpoch: connectionEpoch.toString(),
|
|
28900
|
+
relayOrigin: this.#relayOrigin,
|
|
28901
|
+
source,
|
|
28902
|
+
...this.#route
|
|
28903
|
+
};
|
|
28904
|
+
addFailureDetails(details, failure);
|
|
28905
|
+
this.#record("relay_connection_failed", connectionEpoch.toString(), details, true);
|
|
28906
|
+
};
|
|
28907
|
+
connectionOpened = (connectionEpoch) => {
|
|
28908
|
+
this.#record(
|
|
28909
|
+
"relay_connection_opened",
|
|
28910
|
+
connectionEpoch.toString(),
|
|
28911
|
+
{
|
|
28912
|
+
connectionEpoch: connectionEpoch.toString(),
|
|
28913
|
+
relayOrigin: this.#relayOrigin,
|
|
28914
|
+
...this.#route
|
|
28915
|
+
},
|
|
28916
|
+
false
|
|
28917
|
+
);
|
|
28918
|
+
};
|
|
28919
|
+
heartbeatTimedOut = (connectionEpoch, heartbeatId, timeoutMilliseconds) => {
|
|
28920
|
+
this.#record(
|
|
28921
|
+
"relay_heartbeat_timed_out",
|
|
28922
|
+
connectionEpoch.toString(),
|
|
28923
|
+
{
|
|
28924
|
+
connectionEpoch: connectionEpoch.toString(),
|
|
28925
|
+
heartbeatId,
|
|
28926
|
+
relayOrigin: this.#relayOrigin,
|
|
28927
|
+
timeoutMilliseconds: timeoutMilliseconds.toString(),
|
|
28928
|
+
...this.#route
|
|
28929
|
+
},
|
|
28930
|
+
true
|
|
28931
|
+
);
|
|
28932
|
+
};
|
|
28933
|
+
#record = (event, commandId, details, warning) => {
|
|
28934
|
+
this.#audit.record({
|
|
28935
|
+
commandId,
|
|
28936
|
+
details,
|
|
28937
|
+
event,
|
|
28938
|
+
sessionId: this.#channelId
|
|
28939
|
+
});
|
|
28940
|
+
const encoded = JSON.stringify({ channelId: this.#channelId, event, ...details });
|
|
28941
|
+
if (warning) {
|
|
28942
|
+
process.stderr.write(`Mobius relay diagnostic ${encoded}
|
|
28943
|
+
`);
|
|
28944
|
+
return;
|
|
28945
|
+
}
|
|
28946
|
+
process.stdout.write(`Mobius relay diagnostic ${encoded}
|
|
28947
|
+
`);
|
|
28948
|
+
};
|
|
28949
|
+
};
|
|
28950
|
+
|
|
28691
28951
|
// src/relay-connection/liveness.ts
|
|
28692
28952
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
28693
28953
|
var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
|
|
@@ -28764,9 +29024,10 @@ var RelayConnectionLiveness = class {
|
|
|
28764
29024
|
if (!(this.#state instanceof AwaitingHeartbeatAckState)) {
|
|
28765
29025
|
throw new Error("Heartbeat timeout occurred in an invalid state");
|
|
28766
29026
|
}
|
|
29027
|
+
const heartbeatId = this.#state.heartbeatId;
|
|
28767
29028
|
this.#state.timeout.cancel();
|
|
28768
29029
|
this.#state = new FinishedRelayLivenessState();
|
|
28769
|
-
this.#transport.unresponsive();
|
|
29030
|
+
this.#transport.unresponsive(heartbeatId, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS);
|
|
28770
29031
|
};
|
|
28771
29032
|
#sendHeartbeat = () => {
|
|
28772
29033
|
if (this.#state instanceof WaitingForHeartbeatState) {
|
|
@@ -28795,6 +29056,42 @@ var RelayConnectionLiveness = class {
|
|
|
28795
29056
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
28796
29057
|
import { dirname as dirname7 } from "node:path";
|
|
28797
29058
|
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
29059
|
+
var DEFAULT_OUTBOX_LIMITS = {
|
|
29060
|
+
criticalEventBytes: 136 * 1024 * 1024,
|
|
29061
|
+
criticalEventCount: 10128,
|
|
29062
|
+
runtimeDeliveryBytes: 64 * 1024 * 1024,
|
|
29063
|
+
runtimeDeliveryCount: 64,
|
|
29064
|
+
standardEventBytes: 128 * 1024 * 1024,
|
|
29065
|
+
standardEventCount: 1e4
|
|
29066
|
+
};
|
|
29067
|
+
var SessionEventOutboxCapacityError = class extends Error {
|
|
29068
|
+
code = "session_event_outbox_full";
|
|
29069
|
+
constructor() {
|
|
29070
|
+
super("The durable Session event outbox is full");
|
|
29071
|
+
this.name = "SessionEventOutboxCapacityError";
|
|
29072
|
+
}
|
|
29073
|
+
};
|
|
29074
|
+
var RuntimeDeliveryInboxCapacityError = class extends Error {
|
|
29075
|
+
code = "runtime_delivery_inbox_full";
|
|
29076
|
+
constructor() {
|
|
29077
|
+
super("The durable Runtime delivery inbox is full");
|
|
29078
|
+
this.name = "RuntimeDeliveryInboxCapacityError";
|
|
29079
|
+
}
|
|
29080
|
+
};
|
|
29081
|
+
var StoredRuntimeDelivery = class {
|
|
29082
|
+
deliveryId;
|
|
29083
|
+
duplicate;
|
|
29084
|
+
payload;
|
|
29085
|
+
sessionId;
|
|
29086
|
+
state;
|
|
29087
|
+
constructor(deliveryId, sessionId, payload, state, duplicate) {
|
|
29088
|
+
this.deliveryId = deliveryId;
|
|
29089
|
+
this.duplicate = duplicate;
|
|
29090
|
+
this.payload = payload;
|
|
29091
|
+
this.sessionId = sessionId;
|
|
29092
|
+
this.state = state;
|
|
29093
|
+
}
|
|
29094
|
+
};
|
|
28798
29095
|
function readPendingEnvelope(row) {
|
|
28799
29096
|
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
28800
29097
|
throw new Error("SQLite returned an invalid session event outbox row");
|
|
@@ -28805,9 +29102,26 @@ function readPendingEnvelope(row) {
|
|
|
28805
29102
|
}
|
|
28806
29103
|
return envelope2;
|
|
28807
29104
|
}
|
|
29105
|
+
function rowNumber(row, field) {
|
|
29106
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29107
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
29108
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29109
|
+
}
|
|
29110
|
+
return value;
|
|
29111
|
+
}
|
|
29112
|
+
function rowString2(row, field) {
|
|
29113
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
29114
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
29115
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
29116
|
+
}
|
|
29117
|
+
return value;
|
|
29118
|
+
}
|
|
28808
29119
|
var SessionEventOutbox = class {
|
|
28809
29120
|
#database;
|
|
28810
|
-
|
|
29121
|
+
#limits;
|
|
29122
|
+
constructor(path2, limits = DEFAULT_OUTBOX_LIMITS) {
|
|
29123
|
+
validateLimits(limits);
|
|
29124
|
+
this.#limits = limits;
|
|
28811
29125
|
mkdirSync3(dirname7(path2), { recursive: true });
|
|
28812
29126
|
this.#database = new DatabaseSync4(path2);
|
|
28813
29127
|
this.#database.exec(`
|
|
@@ -28815,6 +29129,8 @@ var SessionEventOutbox = class {
|
|
|
28815
29129
|
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
28816
29130
|
event_id TEXT NOT NULL UNIQUE,
|
|
28817
29131
|
session_id TEXT NOT NULL,
|
|
29132
|
+
source_key TEXT NOT NULL,
|
|
29133
|
+
byte_length INTEGER NOT NULL,
|
|
28818
29134
|
envelope_json TEXT NOT NULL
|
|
28819
29135
|
) STRICT;
|
|
28820
29136
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
@@ -28825,7 +29141,7 @@ var SessionEventOutbox = class {
|
|
|
28825
29141
|
session_id TEXT NOT NULL,
|
|
28826
29142
|
envelope_json TEXT NOT NULL,
|
|
28827
29143
|
rejection_code TEXT NOT NULL CHECK (
|
|
28828
|
-
rejection_code IN ('session_deleted', 'session_not_found')
|
|
29144
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
28829
29145
|
)
|
|
28830
29146
|
) STRICT;
|
|
28831
29147
|
CREATE TABLE IF NOT EXISTS relay_session_event_sources (
|
|
@@ -28841,6 +29157,92 @@ var SessionEventOutbox = class {
|
|
|
28841
29157
|
state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
|
|
28842
29158
|
)
|
|
28843
29159
|
) STRICT;
|
|
29160
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
29161
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
29162
|
+
event_count INTEGER NOT NULL,
|
|
29163
|
+
total_bytes INTEGER NOT NULL
|
|
29164
|
+
) STRICT;
|
|
29165
|
+
INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
29166
|
+
singleton, event_count, total_bytes
|
|
29167
|
+
) VALUES (1, 0, 0);
|
|
29168
|
+
CREATE TABLE IF NOT EXISTS relay_runtime_deliveries (
|
|
29169
|
+
delivery_id TEXT PRIMARY KEY,
|
|
29170
|
+
session_id TEXT NOT NULL,
|
|
29171
|
+
payload_json TEXT NOT NULL,
|
|
29172
|
+
payload_bytes INTEGER NOT NULL,
|
|
29173
|
+
state TEXT NOT NULL CHECK (
|
|
29174
|
+
state IN ('received', 'relay_committed', 'processed')
|
|
29175
|
+
),
|
|
29176
|
+
received_at INTEGER NOT NULL
|
|
29177
|
+
) STRICT;
|
|
29178
|
+
`);
|
|
29179
|
+
const deadLetterTable = this.#database.prepare(
|
|
29180
|
+
`SELECT sql FROM sqlite_master
|
|
29181
|
+
WHERE type = 'table' AND name = 'relay_session_event_dead_letters'`
|
|
29182
|
+
).get();
|
|
29183
|
+
const deadLetterSql = typeof deadLetterTable === "object" && deadLetterTable !== null ? Reflect.get(deadLetterTable, "sql") : void 0;
|
|
29184
|
+
if (typeof deadLetterSql !== "string" || !deadLetterSql.includes("'session_rejected'")) {
|
|
29185
|
+
this.#database.exec(`
|
|
29186
|
+
BEGIN IMMEDIATE;
|
|
29187
|
+
ALTER TABLE relay_session_event_dead_letters
|
|
29188
|
+
RENAME TO relay_session_event_dead_letters_legacy;
|
|
29189
|
+
CREATE TABLE relay_session_event_dead_letters (
|
|
29190
|
+
ordinal INTEGER PRIMARY KEY,
|
|
29191
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
29192
|
+
session_id TEXT NOT NULL,
|
|
29193
|
+
envelope_json TEXT NOT NULL,
|
|
29194
|
+
rejection_code TEXT NOT NULL CHECK (
|
|
29195
|
+
rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
|
|
29196
|
+
)
|
|
29197
|
+
) STRICT;
|
|
29198
|
+
INSERT INTO relay_session_event_dead_letters (
|
|
29199
|
+
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29200
|
+
)
|
|
29201
|
+
SELECT ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29202
|
+
FROM relay_session_event_dead_letters_legacy;
|
|
29203
|
+
DROP TABLE relay_session_event_dead_letters_legacy;
|
|
29204
|
+
COMMIT;
|
|
29205
|
+
`);
|
|
29206
|
+
}
|
|
29207
|
+
const outboxColumns = this.#database.prepare("PRAGMA table_info(relay_session_event_outbox)").all();
|
|
29208
|
+
const hasSourceKey = outboxColumns.some(
|
|
29209
|
+
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "source_key"
|
|
29210
|
+
);
|
|
29211
|
+
if (!hasSourceKey) {
|
|
29212
|
+
this.#database.exec(`
|
|
29213
|
+
ALTER TABLE relay_session_event_outbox
|
|
29214
|
+
ADD COLUMN source_key TEXT NOT NULL DEFAULT '';
|
|
29215
|
+
`);
|
|
29216
|
+
}
|
|
29217
|
+
const hasByteLength = outboxColumns.some(
|
|
29218
|
+
(column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "byte_length"
|
|
29219
|
+
);
|
|
29220
|
+
if (!hasByteLength) {
|
|
29221
|
+
this.#database.exec(`
|
|
29222
|
+
ALTER TABLE relay_session_event_outbox
|
|
29223
|
+
ADD COLUMN byte_length INTEGER NOT NULL DEFAULT 0;
|
|
29224
|
+
`);
|
|
29225
|
+
}
|
|
29226
|
+
this.#database.exec(`
|
|
29227
|
+
UPDATE relay_session_event_outbox
|
|
29228
|
+
SET source_key = CASE json_extract(envelope_json, '$.source.kind')
|
|
29229
|
+
WHEN 'attempt' THEN
|
|
29230
|
+
'attempt:' || session_id || ':' || json_extract(envelope_json, '$.source.attemptId')
|
|
29231
|
+
ELSE 'runtime:' || session_id
|
|
29232
|
+
END
|
|
29233
|
+
WHERE source_key = '';
|
|
29234
|
+
UPDATE relay_session_event_outbox
|
|
29235
|
+
SET byte_length = length(CAST(envelope_json AS BLOB))
|
|
29236
|
+
WHERE byte_length = 0;
|
|
29237
|
+
UPDATE relay_session_event_outbox_state
|
|
29238
|
+
SET event_count = (SELECT COUNT(*) FROM relay_session_event_outbox),
|
|
29239
|
+
total_bytes = (
|
|
29240
|
+
SELECT COALESCE(SUM(byte_length), 0)
|
|
29241
|
+
FROM relay_session_event_outbox
|
|
29242
|
+
)
|
|
29243
|
+
WHERE singleton = 1;
|
|
29244
|
+
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_source_order
|
|
29245
|
+
ON relay_session_event_outbox(source_key, ordinal);
|
|
28844
29246
|
`);
|
|
28845
29247
|
}
|
|
28846
29248
|
claimExecution = (commandId, sessionId, commandJson) => {
|
|
@@ -28899,15 +29301,19 @@ var SessionEventOutbox = class {
|
|
|
28899
29301
|
const state = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
|
|
28900
29302
|
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
28901
29303
|
};
|
|
28902
|
-
acknowledge = (acknowledgement) =>
|
|
28903
|
-
this.#database.prepare(
|
|
28904
|
-
`DELETE FROM relay_session_event_outbox
|
|
28905
|
-
WHERE event_id = ? AND session_id = ?`
|
|
28906
|
-
).run(acknowledgement.eventId, acknowledgement.sessionId);
|
|
28907
|
-
};
|
|
29304
|
+
acknowledge = (acknowledgement) => this.#removeAcknowledgedEvent(acknowledgement.eventId, acknowledgement.sessionId);
|
|
28908
29305
|
quarantine = (rejection) => {
|
|
28909
29306
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
28910
29307
|
try {
|
|
29308
|
+
const stored = this.#database.prepare(
|
|
29309
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
29310
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29311
|
+
).get(rejection.eventId, rejection.sessionId);
|
|
29312
|
+
if (stored === void 0) {
|
|
29313
|
+
this.#database.exec("COMMIT");
|
|
29314
|
+
return false;
|
|
29315
|
+
}
|
|
29316
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
28911
29317
|
const insertion = this.#database.prepare(
|
|
28912
29318
|
`INSERT INTO relay_session_event_dead_letters (
|
|
28913
29319
|
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
@@ -28927,6 +29333,7 @@ var SessionEventOutbox = class {
|
|
|
28927
29333
|
if (deletion.changes !== 1) {
|
|
28928
29334
|
throw new Error("The rejected session event could not be removed from the durable outbox");
|
|
28929
29335
|
}
|
|
29336
|
+
this.#decrementEventState(byteLength);
|
|
28930
29337
|
this.#database.exec("COMMIT");
|
|
28931
29338
|
return true;
|
|
28932
29339
|
} catch (error61) {
|
|
@@ -28938,7 +29345,129 @@ var SessionEventOutbox = class {
|
|
|
28938
29345
|
this.#database.close();
|
|
28939
29346
|
};
|
|
28940
29347
|
enqueue = (sessionId, payload, attemptId = null) => {
|
|
28941
|
-
|
|
29348
|
+
return this.#enqueueBounded(
|
|
29349
|
+
sessionId,
|
|
29350
|
+
payload,
|
|
29351
|
+
attemptId ?? "",
|
|
29352
|
+
this.#limits.standardEventCount,
|
|
29353
|
+
this.#limits.standardEventBytes
|
|
29354
|
+
);
|
|
29355
|
+
};
|
|
29356
|
+
enqueueCritical = (sessionId, payload, attemptId = "") => this.#enqueueBounded(
|
|
29357
|
+
sessionId,
|
|
29358
|
+
payload,
|
|
29359
|
+
attemptId,
|
|
29360
|
+
this.#limits.criticalEventCount,
|
|
29361
|
+
this.#limits.criticalEventBytes
|
|
29362
|
+
);
|
|
29363
|
+
claimRuntimeDelivery = (delivery) => {
|
|
29364
|
+
const payloadBytes = new TextEncoder().encode(delivery.payload).byteLength;
|
|
29365
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29366
|
+
try {
|
|
29367
|
+
const existing = this.#database.prepare(
|
|
29368
|
+
`SELECT session_id, payload_json, state
|
|
29369
|
+
FROM relay_runtime_deliveries
|
|
29370
|
+
WHERE delivery_id = ?`
|
|
29371
|
+
).get(delivery.deliveryId);
|
|
29372
|
+
if (existing !== void 0) {
|
|
29373
|
+
const sessionId = rowString2(existing, "session_id");
|
|
29374
|
+
const payload = rowString2(existing, "payload_json");
|
|
29375
|
+
const state = runtimeDeliveryState(existing);
|
|
29376
|
+
if (sessionId !== delivery.sessionId || payload !== delivery.payload) {
|
|
29377
|
+
throw new Error("The Runtime delivery identity conflicts with its durable receipt");
|
|
29378
|
+
}
|
|
29379
|
+
this.#database.exec("COMMIT");
|
|
29380
|
+
return new StoredRuntimeDelivery(delivery.deliveryId, sessionId, payload, state, true);
|
|
29381
|
+
}
|
|
29382
|
+
const usage = this.#database.prepare(
|
|
29383
|
+
`SELECT COUNT(*) AS delivery_count,
|
|
29384
|
+
COALESCE(SUM(payload_bytes), 0) AS delivery_bytes
|
|
29385
|
+
FROM relay_runtime_deliveries`
|
|
29386
|
+
).get();
|
|
29387
|
+
if (rowNumber(usage, "delivery_count") + 1 > this.#limits.runtimeDeliveryCount || rowNumber(usage, "delivery_bytes") + payloadBytes > this.#limits.runtimeDeliveryBytes) {
|
|
29388
|
+
throw new RuntimeDeliveryInboxCapacityError();
|
|
29389
|
+
}
|
|
29390
|
+
this.#database.prepare(
|
|
29391
|
+
`INSERT INTO relay_runtime_deliveries (
|
|
29392
|
+
delivery_id, session_id, payload_json, payload_bytes, state, received_at
|
|
29393
|
+
) VALUES (?, ?, ?, ?, 'received', ?)`
|
|
29394
|
+
).run(delivery.deliveryId, delivery.sessionId, delivery.payload, payloadBytes, Date.now());
|
|
29395
|
+
this.#database.exec("COMMIT");
|
|
29396
|
+
return new StoredRuntimeDelivery(
|
|
29397
|
+
delivery.deliveryId,
|
|
29398
|
+
delivery.sessionId,
|
|
29399
|
+
delivery.payload,
|
|
29400
|
+
"received",
|
|
29401
|
+
false
|
|
29402
|
+
);
|
|
29403
|
+
} catch (error61) {
|
|
29404
|
+
this.#database.exec("ROLLBACK");
|
|
29405
|
+
throw error61;
|
|
29406
|
+
}
|
|
29407
|
+
};
|
|
29408
|
+
markRuntimeDeliveryCommitted = (deliveryId, sessionId) => {
|
|
29409
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29410
|
+
try {
|
|
29411
|
+
const row = this.#database.prepare(
|
|
29412
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
29413
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
29414
|
+
).get(deliveryId, sessionId);
|
|
29415
|
+
if (row === void 0) {
|
|
29416
|
+
this.#database.exec("COMMIT");
|
|
29417
|
+
return false;
|
|
29418
|
+
}
|
|
29419
|
+
const state = runtimeDeliveryState(row);
|
|
29420
|
+
if (state === "processed") {
|
|
29421
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
29422
|
+
} else if (state === "received") {
|
|
29423
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'relay_committed' WHERE delivery_id = ?`).run(deliveryId);
|
|
29424
|
+
}
|
|
29425
|
+
this.#database.exec("COMMIT");
|
|
29426
|
+
return true;
|
|
29427
|
+
} catch (error61) {
|
|
29428
|
+
this.#database.exec("ROLLBACK");
|
|
29429
|
+
throw error61;
|
|
29430
|
+
}
|
|
29431
|
+
};
|
|
29432
|
+
markRuntimeDeliveryProcessed = (deliveryId, sessionId) => {
|
|
29433
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29434
|
+
try {
|
|
29435
|
+
const row = this.#database.prepare(
|
|
29436
|
+
`SELECT state FROM relay_runtime_deliveries
|
|
29437
|
+
WHERE delivery_id = ? AND session_id = ?`
|
|
29438
|
+
).get(deliveryId, sessionId);
|
|
29439
|
+
if (row === void 0) {
|
|
29440
|
+
this.#database.exec("COMMIT");
|
|
29441
|
+
return false;
|
|
29442
|
+
}
|
|
29443
|
+
const state = runtimeDeliveryState(row);
|
|
29444
|
+
if (state === "relay_committed") {
|
|
29445
|
+
this.#database.prepare(`DELETE FROM relay_runtime_deliveries WHERE delivery_id = ?`).run(deliveryId);
|
|
29446
|
+
} else if (state === "received") {
|
|
29447
|
+
this.#database.prepare(`UPDATE relay_runtime_deliveries SET state = 'processed' WHERE delivery_id = ?`).run(deliveryId);
|
|
29448
|
+
}
|
|
29449
|
+
this.#database.exec("COMMIT");
|
|
29450
|
+
return true;
|
|
29451
|
+
} catch (error61) {
|
|
29452
|
+
this.#database.exec("ROLLBACK");
|
|
29453
|
+
throw error61;
|
|
29454
|
+
}
|
|
29455
|
+
};
|
|
29456
|
+
runtimeDeliveries = () => this.#database.prepare(
|
|
29457
|
+
`SELECT delivery_id, session_id, payload_json, state
|
|
29458
|
+
FROM relay_runtime_deliveries
|
|
29459
|
+
ORDER BY received_at, delivery_id`
|
|
29460
|
+
).all().map(
|
|
29461
|
+
(row) => new StoredRuntimeDelivery(
|
|
29462
|
+
rowString2(row, "delivery_id"),
|
|
29463
|
+
rowString2(row, "session_id"),
|
|
29464
|
+
rowString2(row, "payload_json"),
|
|
29465
|
+
runtimeDeliveryState(row),
|
|
29466
|
+
true
|
|
29467
|
+
)
|
|
29468
|
+
);
|
|
29469
|
+
#enqueueBounded = (sessionId, payload, attemptId, maximumEventCount, maximumEventBytes) => {
|
|
29470
|
+
const sourceKey = attemptId.length === 0 ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
|
|
28942
29471
|
this.#database.exec("BEGIN IMMEDIATE");
|
|
28943
29472
|
try {
|
|
28944
29473
|
const row = this.#database.prepare(
|
|
@@ -28955,13 +29484,22 @@ var SessionEventOutbox = class {
|
|
|
28955
29484
|
kind: SESSION_EVENT_KIND,
|
|
28956
29485
|
payload,
|
|
28957
29486
|
sessionId,
|
|
28958
|
-
source: attemptId ===
|
|
29487
|
+
source: attemptId.length === 0 ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
|
|
28959
29488
|
attemptId,
|
|
28960
29489
|
kind: "attempt",
|
|
28961
29490
|
sourceSeq: nextSourceSeq.toString()
|
|
28962
29491
|
}
|
|
28963
29492
|
};
|
|
28964
29493
|
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
29494
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
29495
|
+
const state = this.#database.prepare(
|
|
29496
|
+
`SELECT event_count, total_bytes
|
|
29497
|
+
FROM relay_session_event_outbox_state
|
|
29498
|
+
WHERE singleton = 1`
|
|
29499
|
+
).get();
|
|
29500
|
+
if (rowNumber(state, "event_count") + 1 > maximumEventCount || rowNumber(state, "total_bytes") + byteLength > maximumEventBytes) {
|
|
29501
|
+
throw new SessionEventOutboxCapacityError();
|
|
29502
|
+
}
|
|
28965
29503
|
this.#database.prepare(
|
|
28966
29504
|
`INSERT INTO relay_session_event_sources (
|
|
28967
29505
|
source_key, next_source_seq
|
|
@@ -28971,9 +29509,15 @@ var SessionEventOutbox = class {
|
|
|
28971
29509
|
).run(sourceKey, nextSourceSeq + 1);
|
|
28972
29510
|
this.#database.prepare(
|
|
28973
29511
|
`INSERT INTO relay_session_event_outbox (
|
|
28974
|
-
event_id, session_id, envelope_json
|
|
28975
|
-
) VALUES (?, ?, ?)`
|
|
28976
|
-
).run(envelope2.eventId, envelope2.sessionId, encoded);
|
|
29512
|
+
event_id, session_id, source_key, byte_length, envelope_json
|
|
29513
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
29514
|
+
).run(envelope2.eventId, envelope2.sessionId, sourceKey, byteLength, encoded);
|
|
29515
|
+
this.#database.prepare(
|
|
29516
|
+
`UPDATE relay_session_event_outbox_state
|
|
29517
|
+
SET event_count = event_count + 1,
|
|
29518
|
+
total_bytes = total_bytes + ?
|
|
29519
|
+
WHERE singleton = 1`
|
|
29520
|
+
).run(byteLength);
|
|
28977
29521
|
this.#database.exec("COMMIT");
|
|
28978
29522
|
return encoded;
|
|
28979
29523
|
} catch (error61) {
|
|
@@ -28981,12 +29525,132 @@ var SessionEventOutbox = class {
|
|
|
28981
29525
|
throw error61;
|
|
28982
29526
|
}
|
|
28983
29527
|
};
|
|
29528
|
+
#removeAcknowledgedEvent = (eventId, sessionId) => {
|
|
29529
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29530
|
+
try {
|
|
29531
|
+
const stored = this.#database.prepare(
|
|
29532
|
+
`SELECT byte_length FROM relay_session_event_outbox
|
|
29533
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29534
|
+
).get(eventId, sessionId);
|
|
29535
|
+
if (stored === void 0) {
|
|
29536
|
+
this.#database.exec("COMMIT");
|
|
29537
|
+
return false;
|
|
29538
|
+
}
|
|
29539
|
+
const byteLength = rowNumber(stored, "byte_length");
|
|
29540
|
+
const deletion = this.#database.prepare(
|
|
29541
|
+
`DELETE FROM relay_session_event_outbox
|
|
29542
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29543
|
+
).run(eventId, sessionId);
|
|
29544
|
+
if (deletion.changes !== 1) {
|
|
29545
|
+
throw new Error("The acknowledged session event could not be removed from the durable outbox");
|
|
29546
|
+
}
|
|
29547
|
+
this.#decrementEventState(byteLength);
|
|
29548
|
+
this.#database.exec("COMMIT");
|
|
29549
|
+
return true;
|
|
29550
|
+
} catch (error61) {
|
|
29551
|
+
this.#database.exec("ROLLBACK");
|
|
29552
|
+
throw error61;
|
|
29553
|
+
}
|
|
29554
|
+
};
|
|
29555
|
+
#decrementEventState = (byteLength) => {
|
|
29556
|
+
const result = this.#database.prepare(
|
|
29557
|
+
`UPDATE relay_session_event_outbox_state
|
|
29558
|
+
SET event_count = event_count - 1,
|
|
29559
|
+
total_bytes = total_bytes - ?
|
|
29560
|
+
WHERE singleton = 1 AND event_count > 0 AND total_bytes >= ?`
|
|
29561
|
+
).run(byteLength, byteLength);
|
|
29562
|
+
if (result.changes !== 1) {
|
|
29563
|
+
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
29564
|
+
}
|
|
29565
|
+
};
|
|
28984
29566
|
pending = () => this.#database.prepare(
|
|
28985
29567
|
`SELECT envelope_json
|
|
28986
29568
|
FROM relay_session_event_outbox
|
|
28987
29569
|
ORDER BY ordinal`
|
|
28988
29570
|
).all().map(readPendingEnvelope);
|
|
28989
|
-
|
|
29571
|
+
pendingBatch = (limit) => {
|
|
29572
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
29573
|
+
throw new Error("Session event replay batch limit must be a positive integer");
|
|
29574
|
+
}
|
|
29575
|
+
return this.#database.prepare(
|
|
29576
|
+
`WITH ranked_events AS (
|
|
29577
|
+
SELECT ordinal,
|
|
29578
|
+
ROW_NUMBER() OVER (
|
|
29579
|
+
PARTITION BY source_key
|
|
29580
|
+
ORDER BY ordinal
|
|
29581
|
+
) AS source_position
|
|
29582
|
+
FROM relay_session_event_outbox
|
|
29583
|
+
)
|
|
29584
|
+
SELECT outbox.envelope_json
|
|
29585
|
+
FROM ranked_events AS ranked
|
|
29586
|
+
INNER JOIN relay_session_event_outbox AS outbox
|
|
29587
|
+
ON outbox.ordinal = ranked.ordinal
|
|
29588
|
+
ORDER BY ranked.source_position, outbox.ordinal
|
|
29589
|
+
LIMIT ?`
|
|
29590
|
+
).all(limit).map(readPendingEnvelope);
|
|
29591
|
+
};
|
|
29592
|
+
pendingSourceHeads = (limit, excludedEventIds, excludedSourceKeys) => {
|
|
29593
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
29594
|
+
throw new Error("Session event replay batch limit must be a positive integer");
|
|
29595
|
+
}
|
|
29596
|
+
const exclusions = [];
|
|
29597
|
+
const parameters = [];
|
|
29598
|
+
if (excludedEventIds.length > 0) {
|
|
29599
|
+
exclusions.push(`event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`);
|
|
29600
|
+
parameters.push(...excludedEventIds);
|
|
29601
|
+
}
|
|
29602
|
+
if (excludedSourceKeys.length > 0) {
|
|
29603
|
+
exclusions.push(`source_key NOT IN (${excludedSourceKeys.map(() => "?").join(", ")})`);
|
|
29604
|
+
parameters.push(...excludedSourceKeys);
|
|
29605
|
+
}
|
|
29606
|
+
parameters.push(limit.toString());
|
|
29607
|
+
const where = exclusions.length === 0 ? "" : `WHERE ${exclusions.join(" AND ")}`;
|
|
29608
|
+
return this.#database.prepare(
|
|
29609
|
+
`WITH available_events AS (
|
|
29610
|
+
SELECT ordinal, source_key
|
|
29611
|
+
FROM relay_session_event_outbox
|
|
29612
|
+
${where}
|
|
29613
|
+
), ranked_events AS (
|
|
29614
|
+
SELECT ordinal,
|
|
29615
|
+
ROW_NUMBER() OVER (
|
|
29616
|
+
PARTITION BY source_key
|
|
29617
|
+
ORDER BY ordinal
|
|
29618
|
+
) AS source_position
|
|
29619
|
+
FROM available_events
|
|
29620
|
+
)
|
|
29621
|
+
SELECT outbox.envelope_json
|
|
29622
|
+
FROM ranked_events AS ranked
|
|
29623
|
+
INNER JOIN relay_session_event_outbox AS outbox
|
|
29624
|
+
ON outbox.ordinal = ranked.ordinal
|
|
29625
|
+
WHERE ranked.source_position = 1
|
|
29626
|
+
ORDER BY outbox.ordinal
|
|
29627
|
+
LIMIT ?`
|
|
29628
|
+
).all(...parameters).map(readPendingEnvelope);
|
|
29629
|
+
};
|
|
29630
|
+
};
|
|
29631
|
+
function validateLimits(limits) {
|
|
29632
|
+
const values = [
|
|
29633
|
+
limits.criticalEventBytes,
|
|
29634
|
+
limits.criticalEventCount,
|
|
29635
|
+
limits.runtimeDeliveryBytes,
|
|
29636
|
+
limits.runtimeDeliveryCount,
|
|
29637
|
+
limits.standardEventBytes,
|
|
29638
|
+
limits.standardEventCount
|
|
29639
|
+
];
|
|
29640
|
+
if (values.some((value) => !Number.isSafeInteger(value) || value < 1)) {
|
|
29641
|
+
throw new Error("Session event outbox limits must be positive integers");
|
|
29642
|
+
}
|
|
29643
|
+
if (limits.criticalEventBytes < limits.standardEventBytes || limits.criticalEventCount < limits.standardEventCount) {
|
|
29644
|
+
throw new Error("Critical Session event capacity must include the standard capacity");
|
|
29645
|
+
}
|
|
29646
|
+
}
|
|
29647
|
+
function runtimeDeliveryState(row) {
|
|
29648
|
+
const state = rowString2(row, "state");
|
|
29649
|
+
if (state !== "received" && state !== "relay_committed" && state !== "processed") {
|
|
29650
|
+
throw new Error("SQLite returned an invalid Runtime delivery state");
|
|
29651
|
+
}
|
|
29652
|
+
return state;
|
|
29653
|
+
}
|
|
28990
29654
|
function isDaemonExecutionState(value) {
|
|
28991
29655
|
return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
|
|
28992
29656
|
}
|
|
@@ -29002,7 +29666,7 @@ var systemDaemonTimer = new SystemDaemonTimer();
|
|
|
29002
29666
|
|
|
29003
29667
|
// src/run-daemon.ts
|
|
29004
29668
|
var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
|
|
29005
|
-
var
|
|
29669
|
+
var AGENT_ACTIVITY_COALESCING_MILLISECONDS = 100;
|
|
29006
29670
|
var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
|
|
29007
29671
|
var ACTIVE_TURN_RECONCILIATION_CLOSE_CODE = 4009;
|
|
29008
29672
|
function botIpcSocketPath() {
|
|
@@ -29011,54 +29675,6 @@ function botIpcSocketPath() {
|
|
|
29011
29675
|
}
|
|
29012
29676
|
return join15("/tmp", `mobius-bot-${randomUUID4()}.sock`);
|
|
29013
29677
|
}
|
|
29014
|
-
var RelayConnectionRefreshState = class {
|
|
29015
|
-
};
|
|
29016
|
-
var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
|
|
29017
|
-
};
|
|
29018
|
-
var DueRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
|
|
29019
|
-
};
|
|
29020
|
-
var FinishedRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
|
|
29021
|
-
};
|
|
29022
|
-
var RelayConnectionRefresh = class {
|
|
29023
|
-
#isSafe;
|
|
29024
|
-
#refresh;
|
|
29025
|
-
#scheduledTask;
|
|
29026
|
-
#state = new ScheduledRelayConnectionRefreshState();
|
|
29027
|
-
constructor(timer, isSafe, refresh) {
|
|
29028
|
-
this.#isSafe = isSafe;
|
|
29029
|
-
this.#refresh = refresh;
|
|
29030
|
-
this.#scheduledTask = timer.schedule(this.#request, RELAY_CONNECTION_REFRESH_MILLISECONDS);
|
|
29031
|
-
}
|
|
29032
|
-
afterTurnFinished = () => {
|
|
29033
|
-
if (this.#state instanceof DueRelayConnectionRefreshState) {
|
|
29034
|
-
this.#request();
|
|
29035
|
-
return;
|
|
29036
|
-
}
|
|
29037
|
-
if (this.#state instanceof ScheduledRelayConnectionRefreshState || this.#state instanceof FinishedRelayConnectionRefreshState) {
|
|
29038
|
-
return;
|
|
29039
|
-
}
|
|
29040
|
-
throw new Error("Unknown relay connection refresh state");
|
|
29041
|
-
};
|
|
29042
|
-
close = () => {
|
|
29043
|
-
this.#scheduledTask.cancel();
|
|
29044
|
-
this.#state = new FinishedRelayConnectionRefreshState();
|
|
29045
|
-
};
|
|
29046
|
-
#request = () => {
|
|
29047
|
-
if (this.#state instanceof FinishedRelayConnectionRefreshState) {
|
|
29048
|
-
return;
|
|
29049
|
-
}
|
|
29050
|
-
if (!(this.#state instanceof ScheduledRelayConnectionRefreshState) && !(this.#state instanceof DueRelayConnectionRefreshState)) {
|
|
29051
|
-
throw new Error("Unknown relay connection refresh state");
|
|
29052
|
-
}
|
|
29053
|
-
if (!this.#isSafe()) {
|
|
29054
|
-
this.#state = new DueRelayConnectionRefreshState();
|
|
29055
|
-
return;
|
|
29056
|
-
}
|
|
29057
|
-
this.#state = new FinishedRelayConnectionRefreshState();
|
|
29058
|
-
this.#scheduledTask.cancel();
|
|
29059
|
-
this.#refresh();
|
|
29060
|
-
};
|
|
29061
|
-
};
|
|
29062
29678
|
var DaemonAcpObserver = class {
|
|
29063
29679
|
#record;
|
|
29064
29680
|
constructor(record2) {
|
|
@@ -29253,8 +29869,7 @@ var ActiveTurnReconciliationError = class extends Error {
|
|
|
29253
29869
|
}
|
|
29254
29870
|
};
|
|
29255
29871
|
function activeTurnReconciliationEndpoint(config2, turn) {
|
|
29256
|
-
const endpoint =
|
|
29257
|
-
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
29872
|
+
const endpoint = relayHttpEndpoint(config2.relayUrl);
|
|
29258
29873
|
let channelPath = "";
|
|
29259
29874
|
if (endpoint.pathname.endsWith("/daemon")) {
|
|
29260
29875
|
channelPath = endpoint.pathname.slice(0, -"/daemon".length);
|
|
@@ -29266,7 +29881,6 @@ function activeTurnReconciliationEndpoint(config2, turn) {
|
|
|
29266
29881
|
channelPath = `${endpoint.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
29267
29882
|
}
|
|
29268
29883
|
endpoint.pathname = `${channelPath}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
|
|
29269
|
-
endpoint.searchParams.delete("liveness");
|
|
29270
29884
|
return endpoint;
|
|
29271
29885
|
}
|
|
29272
29886
|
async function reconcileActiveTurn(config2, turn, signal) {
|
|
@@ -29278,7 +29892,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
29278
29892
|
response = await fetch5(activeTurnReconciliationEndpoint(config2, turn), {
|
|
29279
29893
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
29280
29894
|
dispatcher: environmentProxyDispatcher,
|
|
29281
|
-
headers: { "content-type": "application/json" },
|
|
29895
|
+
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
29282
29896
|
method: "POST",
|
|
29283
29897
|
signal: requestSignal
|
|
29284
29898
|
});
|
|
@@ -29323,7 +29937,8 @@ var DaemonSessionEventConnectionState = class {
|
|
|
29323
29937
|
};
|
|
29324
29938
|
var DisconnectedDaemonSessionEventState = class extends DaemonSessionEventConnectionState {
|
|
29325
29939
|
disconnect = () => this;
|
|
29326
|
-
|
|
29940
|
+
matches = () => false;
|
|
29941
|
+
send = () => false;
|
|
29327
29942
|
};
|
|
29328
29943
|
var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectionState {
|
|
29329
29944
|
#socket;
|
|
@@ -29332,38 +29947,210 @@ var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectio
|
|
|
29332
29947
|
this.#socket = socket;
|
|
29333
29948
|
}
|
|
29334
29949
|
disconnect = (socket) => socket === this.#socket ? new DisconnectedDaemonSessionEventState() : this;
|
|
29950
|
+
matches = (socket) => socket === this.#socket;
|
|
29335
29951
|
send = (message) => {
|
|
29336
|
-
if (this.#socket.readyState
|
|
29337
|
-
|
|
29338
|
-
|
|
29339
|
-
|
|
29340
|
-
|
|
29952
|
+
if (this.#socket.readyState !== WebSocket2.OPEN) {
|
|
29953
|
+
return false;
|
|
29954
|
+
}
|
|
29955
|
+
try {
|
|
29956
|
+
this.#socket.send(message);
|
|
29957
|
+
return true;
|
|
29958
|
+
} catch {
|
|
29959
|
+
return false;
|
|
29341
29960
|
}
|
|
29342
29961
|
};
|
|
29343
29962
|
};
|
|
29963
|
+
var SESSION_EVENT_REPLAY_WINDOW = 16;
|
|
29964
|
+
var SESSION_EVENT_SOURCE_REPLAY_WINDOW = 4;
|
|
29965
|
+
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
29966
|
+
var InFlightSessionEvent = class {
|
|
29967
|
+
byteLength;
|
|
29968
|
+
sourceKey;
|
|
29969
|
+
constructor(sourceKey, byteLength) {
|
|
29970
|
+
this.byteLength = byteLength;
|
|
29971
|
+
this.sourceKey = sourceKey;
|
|
29972
|
+
}
|
|
29973
|
+
};
|
|
29974
|
+
function sessionEventSourceKey(envelope2) {
|
|
29975
|
+
return envelope2.source.kind === "attempt" ? `attempt:${envelope2.sessionId}:${envelope2.source.attemptId}` : `runtime:${envelope2.sessionId}`;
|
|
29976
|
+
}
|
|
29344
29977
|
var DaemonSessionEventPublisher = class {
|
|
29345
29978
|
#outbox;
|
|
29979
|
+
#inFlightEvents = /* @__PURE__ */ new Map();
|
|
29980
|
+
#inFlightBytes = 0;
|
|
29346
29981
|
#connection = new DisconnectedDaemonSessionEventState();
|
|
29347
29982
|
constructor(outbox) {
|
|
29348
29983
|
this.#outbox = outbox;
|
|
29349
29984
|
}
|
|
29350
29985
|
connect = (socket) => {
|
|
29351
|
-
|
|
29352
|
-
this.#
|
|
29353
|
-
|
|
29354
|
-
connection.send(pending);
|
|
29355
|
-
}
|
|
29986
|
+
this.#connection = new ConnectedDaemonSessionEventState(socket);
|
|
29987
|
+
this.#clearInFlight();
|
|
29988
|
+
this.#publishNextBatch();
|
|
29356
29989
|
};
|
|
29357
29990
|
disconnect = (socket) => {
|
|
29991
|
+
if (!this.#connection.matches(socket)) {
|
|
29992
|
+
return;
|
|
29993
|
+
}
|
|
29358
29994
|
this.#connection = this.#connection.disconnect(socket);
|
|
29995
|
+
this.#clearInFlight();
|
|
29359
29996
|
};
|
|
29360
29997
|
recordAttempt = (sessionId, payload, attemptId) => {
|
|
29361
|
-
|
|
29998
|
+
const kind = decodeMessageKind(payload);
|
|
29999
|
+
if (kind === SESSION_COMPLETED_KIND || kind === SESSION_FAILED_KIND) {
|
|
30000
|
+
this.#outbox.enqueueCritical(sessionId, payload, attemptId);
|
|
30001
|
+
} else {
|
|
30002
|
+
this.#outbox.enqueue(sessionId, payload, attemptId);
|
|
30003
|
+
}
|
|
30004
|
+
this.#publishNextBatch();
|
|
29362
30005
|
};
|
|
29363
30006
|
recordRuntime = (sessionId, payload) => {
|
|
29364
|
-
this.#
|
|
30007
|
+
this.#outbox.enqueue(sessionId, payload);
|
|
30008
|
+
this.#publishNextBatch();
|
|
30009
|
+
};
|
|
30010
|
+
acknowledge = (acknowledgement) => {
|
|
30011
|
+
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
30012
|
+
return;
|
|
30013
|
+
}
|
|
30014
|
+
this.#removeInFlight(acknowledgement.eventId);
|
|
30015
|
+
this.#publishNextBatch();
|
|
30016
|
+
};
|
|
30017
|
+
quarantine = (rejection) => {
|
|
30018
|
+
const quarantined = this.#outbox.quarantine(rejection);
|
|
30019
|
+
if (!quarantined) {
|
|
30020
|
+
return false;
|
|
30021
|
+
}
|
|
30022
|
+
this.#removeInFlight(rejection.eventId);
|
|
30023
|
+
this.#publishNextBatch();
|
|
30024
|
+
return true;
|
|
30025
|
+
};
|
|
30026
|
+
#publishNextBatch = () => {
|
|
30027
|
+
while (this.#inFlightEvents.size < SESSION_EVENT_REPLAY_WINDOW) {
|
|
30028
|
+
const sourceCounts = /* @__PURE__ */ new Map();
|
|
30029
|
+
for (const inFlight of this.#inFlightEvents.values()) {
|
|
30030
|
+
sourceCounts.set(inFlight.sourceKey, (sourceCounts.get(inFlight.sourceKey) ?? 0) + 1);
|
|
30031
|
+
}
|
|
30032
|
+
const saturatedSources = [...sourceCounts.entries()].filter(([, count]) => count >= SESSION_EVENT_SOURCE_REPLAY_WINDOW).map(([sourceKey]) => sourceKey);
|
|
30033
|
+
const batch = this.#outbox.pendingSourceHeads(
|
|
30034
|
+
SESSION_EVENT_REPLAY_WINDOW - this.#inFlightEvents.size,
|
|
30035
|
+
[...this.#inFlightEvents.keys()],
|
|
30036
|
+
saturatedSources
|
|
30037
|
+
);
|
|
30038
|
+
let sent = 0;
|
|
30039
|
+
for (const encoded of batch) {
|
|
30040
|
+
const envelope2 = decodeSessionEventEnvelope(encoded);
|
|
30041
|
+
const sourceKey = sessionEventSourceKey(envelope2);
|
|
30042
|
+
const sourceCount = sourceCounts.get(sourceKey) ?? 0;
|
|
30043
|
+
if (sourceCount >= SESSION_EVENT_SOURCE_REPLAY_WINDOW) {
|
|
30044
|
+
continue;
|
|
30045
|
+
}
|
|
30046
|
+
const byteLength = new TextEncoder().encode(encoded).byteLength;
|
|
30047
|
+
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
30048
|
+
continue;
|
|
30049
|
+
}
|
|
30050
|
+
if (!this.#connection.send(encoded)) {
|
|
30051
|
+
this.#clearInFlight();
|
|
30052
|
+
return;
|
|
30053
|
+
}
|
|
30054
|
+
this.#inFlightEvents.set(envelope2.eventId, new InFlightSessionEvent(sourceKey, byteLength));
|
|
30055
|
+
this.#inFlightBytes += byteLength;
|
|
30056
|
+
sourceCounts.set(sourceKey, sourceCount + 1);
|
|
30057
|
+
sent += 1;
|
|
30058
|
+
}
|
|
30059
|
+
if (sent === 0) {
|
|
30060
|
+
return;
|
|
30061
|
+
}
|
|
30062
|
+
}
|
|
30063
|
+
};
|
|
30064
|
+
#removeInFlight = (eventId) => {
|
|
30065
|
+
const inFlight = this.#inFlightEvents.get(eventId);
|
|
30066
|
+
if (inFlight === void 0) {
|
|
30067
|
+
return;
|
|
30068
|
+
}
|
|
30069
|
+
this.#inFlightEvents.delete(eventId);
|
|
30070
|
+
this.#inFlightBytes -= inFlight.byteLength;
|
|
30071
|
+
};
|
|
30072
|
+
#clearInFlight = () => {
|
|
30073
|
+
this.#inFlightEvents.clear();
|
|
30074
|
+
this.#inFlightBytes = 0;
|
|
29365
30075
|
};
|
|
29366
30076
|
};
|
|
30077
|
+
var CoalescingDaemonActivityPublisher = class {
|
|
30078
|
+
#pending = /* @__PURE__ */ new Map();
|
|
30079
|
+
#publish;
|
|
30080
|
+
#publishedActivityIds = /* @__PURE__ */ new Set();
|
|
30081
|
+
#scheduled = /* @__PURE__ */ new Map();
|
|
30082
|
+
#timer;
|
|
30083
|
+
constructor(timer, publish) {
|
|
30084
|
+
this.#publish = publish;
|
|
30085
|
+
this.#timer = timer;
|
|
30086
|
+
}
|
|
30087
|
+
flush = () => {
|
|
30088
|
+
const activities = [...this.#pending.values()].sort((left, right) => left.sequence - right.sequence);
|
|
30089
|
+
for (const task of this.#scheduled.values()) {
|
|
30090
|
+
task.cancel();
|
|
30091
|
+
}
|
|
30092
|
+
this.#pending.clear();
|
|
30093
|
+
this.#scheduled.clear();
|
|
30094
|
+
for (const activity of activities) {
|
|
30095
|
+
this.#publish(activity);
|
|
30096
|
+
}
|
|
30097
|
+
};
|
|
30098
|
+
record = (activity) => {
|
|
30099
|
+
if (activity.status !== "pending" && activity.status !== "running") {
|
|
30100
|
+
this.#discardPending(activity.activityId);
|
|
30101
|
+
this.#publishedActivityIds.add(activity.activityId);
|
|
30102
|
+
this.#publish(activity);
|
|
30103
|
+
return Promise.resolve();
|
|
30104
|
+
}
|
|
30105
|
+
if (!this.#publishedActivityIds.has(activity.activityId)) {
|
|
30106
|
+
this.#publishedActivityIds.add(activity.activityId);
|
|
30107
|
+
this.#publish(activity);
|
|
30108
|
+
return Promise.resolve();
|
|
30109
|
+
}
|
|
30110
|
+
this.#pending.set(activity.activityId, activity);
|
|
30111
|
+
if (!this.#scheduled.has(activity.activityId)) {
|
|
30112
|
+
this.#scheduled.set(
|
|
30113
|
+
activity.activityId,
|
|
30114
|
+
this.#timer.schedule(
|
|
30115
|
+
() => this.#flushActivity(activity.activityId),
|
|
30116
|
+
AGENT_ACTIVITY_COALESCING_MILLISECONDS
|
|
30117
|
+
)
|
|
30118
|
+
);
|
|
30119
|
+
}
|
|
30120
|
+
return Promise.resolve();
|
|
30121
|
+
};
|
|
30122
|
+
#discardPending = (activityId) => {
|
|
30123
|
+
this.#scheduled.get(activityId)?.cancel();
|
|
30124
|
+
this.#scheduled.delete(activityId);
|
|
30125
|
+
this.#pending.delete(activityId);
|
|
30126
|
+
};
|
|
30127
|
+
#flushActivity = (activityId) => {
|
|
30128
|
+
const activity = this.#pending.get(activityId);
|
|
30129
|
+
this.#discardPending(activityId);
|
|
30130
|
+
if (activity !== void 0) {
|
|
30131
|
+
this.#publish(activity);
|
|
30132
|
+
}
|
|
30133
|
+
};
|
|
30134
|
+
};
|
|
30135
|
+
function encodeDaemonActivity(command, activity) {
|
|
30136
|
+
return encodeAgentActivityEvent({
|
|
30137
|
+
activityId: activity.activityId,
|
|
30138
|
+
activityType: activity.activityType,
|
|
30139
|
+
commandId: command.commandId,
|
|
30140
|
+
content: activity.content,
|
|
30141
|
+
detail: activity.detail,
|
|
30142
|
+
input: activity.input,
|
|
30143
|
+
kind: AGENT_ACTIVITY_KIND,
|
|
30144
|
+
locations: activity.locations,
|
|
30145
|
+
name: activity.name,
|
|
30146
|
+
output: activity.output,
|
|
30147
|
+
sequence: activity.sequence,
|
|
30148
|
+
sessionId: command.sessionId,
|
|
30149
|
+
status: activity.status,
|
|
30150
|
+
title: activity.title,
|
|
30151
|
+
toolKind: activity.toolKind
|
|
30152
|
+
});
|
|
30153
|
+
}
|
|
29367
30154
|
function reportFailure(publisher, command, code, message, attemptId) {
|
|
29368
30155
|
publisher.recordAttempt(
|
|
29369
30156
|
command.sessionId,
|
|
@@ -29537,10 +30324,16 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
|
|
|
29537
30324
|
})
|
|
29538
30325
|
);
|
|
29539
30326
|
} catch (error61) {
|
|
30327
|
+
if (signal.aborted) {
|
|
30328
|
+
signal.throwIfAborted();
|
|
30329
|
+
}
|
|
29540
30330
|
reportOperationFailure(socket, command.requestId, command.sessionId, error61);
|
|
29541
30331
|
}
|
|
29542
30332
|
}
|
|
29543
|
-
async function executePrompt(outbox, publisher, command, config2, directories, audit, sessions, attemptId, signal) {
|
|
30333
|
+
async function executePrompt(outbox, publisher, command, config2, directories, audit, sessions, attemptId, timer, signal) {
|
|
30334
|
+
const activities = new CoalescingDaemonActivityPublisher(timer, (activity) => {
|
|
30335
|
+
publisher.recordAttempt(command.sessionId, encodeDaemonActivity(command, activity), attemptId);
|
|
30336
|
+
});
|
|
29544
30337
|
try {
|
|
29545
30338
|
const resolved = await resolveSessionDirectories(
|
|
29546
30339
|
directories,
|
|
@@ -29597,30 +30390,7 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
29597
30390
|
cwd: resolved.cwd,
|
|
29598
30391
|
disposition: command.disposition,
|
|
29599
30392
|
images: attachments.images,
|
|
29600
|
-
onActivity:
|
|
29601
|
-
publisher.recordAttempt(
|
|
29602
|
-
command.sessionId,
|
|
29603
|
-
encodeAgentActivityEvent({
|
|
29604
|
-
activityId: activity.activityId,
|
|
29605
|
-
activityType: activity.activityType,
|
|
29606
|
-
commandId: command.commandId,
|
|
29607
|
-
content: activity.content,
|
|
29608
|
-
detail: activity.detail,
|
|
29609
|
-
input: activity.input,
|
|
29610
|
-
kind: AGENT_ACTIVITY_KIND,
|
|
29611
|
-
locations: activity.locations,
|
|
29612
|
-
name: activity.name,
|
|
29613
|
-
output: activity.output,
|
|
29614
|
-
sequence: activity.sequence,
|
|
29615
|
-
sessionId: command.sessionId,
|
|
29616
|
-
status: activity.status,
|
|
29617
|
-
title: activity.title,
|
|
29618
|
-
toolKind: activity.toolKind
|
|
29619
|
-
}),
|
|
29620
|
-
attemptId
|
|
29621
|
-
);
|
|
29622
|
-
return Promise.resolve();
|
|
29623
|
-
},
|
|
30393
|
+
onActivity: activities.record,
|
|
29624
30394
|
onText: (text, messageId) => {
|
|
29625
30395
|
publisher.recordAttempt(
|
|
29626
30396
|
command.sessionId,
|
|
@@ -29643,6 +30413,7 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
29643
30413
|
});
|
|
29644
30414
|
stopReason = result.stopReason;
|
|
29645
30415
|
}
|
|
30416
|
+
activities.flush();
|
|
29646
30417
|
publisher.recordAttempt(
|
|
29647
30418
|
command.sessionId,
|
|
29648
30419
|
encodeSessionCompletedEvent({
|
|
@@ -29660,6 +30431,7 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
29660
30431
|
sessionId: command.sessionId
|
|
29661
30432
|
});
|
|
29662
30433
|
} catch (error61) {
|
|
30434
|
+
activities.flush();
|
|
29663
30435
|
audit.record({
|
|
29664
30436
|
commandId: command.commandId,
|
|
29665
30437
|
event: "session_failed",
|
|
@@ -29698,7 +30470,10 @@ function botExecutionAgent(agent, contextHandle, socketPath) {
|
|
|
29698
30470
|
agent.capabilities
|
|
29699
30471
|
);
|
|
29700
30472
|
}
|
|
29701
|
-
async function executeBotPrompt(outbox, publisher, command, config2, directories, audit, sessions, grants, contexts, applicator, ipc, attemptId, signal) {
|
|
30473
|
+
async function executeBotPrompt(outbox, publisher, command, config2, directories, audit, sessions, grants, contexts, applicator, ipc, attemptId, timer, signal) {
|
|
30474
|
+
const activities = new CoalescingDaemonActivityPublisher(timer, (activity) => {
|
|
30475
|
+
publisher.recordAttempt(command.sessionId, encodeDaemonActivity(command, activity), attemptId);
|
|
30476
|
+
});
|
|
29702
30477
|
try {
|
|
29703
30478
|
const deadline = Date.parse(command.executionDeadlineAt);
|
|
29704
30479
|
const remaining = deadline - Date.now();
|
|
@@ -29782,30 +30557,7 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29782
30557
|
commandId: command.commandId,
|
|
29783
30558
|
cwd: resolved.cwd,
|
|
29784
30559
|
images: attachments.images,
|
|
29785
|
-
onActivity:
|
|
29786
|
-
publisher.recordAttempt(
|
|
29787
|
-
command.sessionId,
|
|
29788
|
-
encodeAgentActivityEvent({
|
|
29789
|
-
activityId: activity.activityId,
|
|
29790
|
-
activityType: activity.activityType,
|
|
29791
|
-
commandId: command.commandId,
|
|
29792
|
-
content: activity.content,
|
|
29793
|
-
detail: activity.detail,
|
|
29794
|
-
input: activity.input,
|
|
29795
|
-
kind: AGENT_ACTIVITY_KIND,
|
|
29796
|
-
locations: activity.locations,
|
|
29797
|
-
name: activity.name,
|
|
29798
|
-
output: activity.output,
|
|
29799
|
-
sequence: activity.sequence,
|
|
29800
|
-
sessionId: command.sessionId,
|
|
29801
|
-
status: activity.status,
|
|
29802
|
-
title: activity.title,
|
|
29803
|
-
toolKind: activity.toolKind
|
|
29804
|
-
}),
|
|
29805
|
-
attemptId
|
|
29806
|
-
);
|
|
29807
|
-
return Promise.resolve();
|
|
29808
|
-
},
|
|
30560
|
+
onActivity: activities.record,
|
|
29809
30561
|
onText: (text, messageId) => {
|
|
29810
30562
|
publisher.recordAttempt(
|
|
29811
30563
|
command.sessionId,
|
|
@@ -29825,6 +30577,7 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29825
30577
|
sessionId: command.sessionId,
|
|
29826
30578
|
signal: executionSignal
|
|
29827
30579
|
});
|
|
30580
|
+
activities.flush();
|
|
29828
30581
|
publisher.recordAttempt(
|
|
29829
30582
|
command.sessionId,
|
|
29830
30583
|
encodeSessionCompletedEvent({
|
|
@@ -29849,6 +30602,7 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29849
30602
|
lease.release();
|
|
29850
30603
|
}
|
|
29851
30604
|
} catch (error61) {
|
|
30605
|
+
activities.flush();
|
|
29852
30606
|
const failure = Date.parse(command.executionDeadlineAt) <= Date.now() ? new LocalBotAuthorizationError("turn_expired", "The Bot execution deadline has expired", {
|
|
29853
30607
|
cause: error61
|
|
29854
30608
|
}) : error61;
|
|
@@ -29888,15 +30642,15 @@ function waitForRelayRetry(signal, timer) {
|
|
|
29888
30642
|
signal.addEventListener("abort", finish, { once: true });
|
|
29889
30643
|
});
|
|
29890
30644
|
}
|
|
29891
|
-
async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
|
|
30645
|
+
async function publishAgentCatalogUntilAvailable(config2, diagnostics, signal, timer) {
|
|
29892
30646
|
try {
|
|
29893
30647
|
await publishAgentCatalog(config2, signal);
|
|
29894
30648
|
return;
|
|
29895
|
-
} catch {
|
|
30649
|
+
} catch (error61) {
|
|
29896
30650
|
if (signal.aborted) {
|
|
29897
30651
|
return;
|
|
29898
30652
|
}
|
|
29899
|
-
|
|
30653
|
+
diagnostics.catalogFailed(error61);
|
|
29900
30654
|
}
|
|
29901
30655
|
while (!signal.aborted) {
|
|
29902
30656
|
await waitForRelayRetry(signal, timer);
|
|
@@ -29910,11 +30664,13 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
|
|
|
29910
30664
|
}
|
|
29911
30665
|
}
|
|
29912
30666
|
}
|
|
29913
|
-
async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, onConnected, signal, timer) {
|
|
30667
|
+
async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, connectionEpoch, diagnostics, onConnected, signal, timer) {
|
|
29914
30668
|
const relayUrl = new URL(config2.relayUrl);
|
|
30669
|
+
relayUrl.searchParams.set("deliveryReceipts", "1");
|
|
29915
30670
|
relayUrl.searchParams.set("liveness", "1");
|
|
29916
30671
|
const socket = await connectRelay(relayUrl, signal);
|
|
29917
30672
|
const reconnectingTurns = [...activeTurns.values()];
|
|
30673
|
+
diagnostics.connectionOpened(connectionEpoch);
|
|
29918
30674
|
onConnected();
|
|
29919
30675
|
const connectionController = new AbortController();
|
|
29920
30676
|
const nativeRequests = /* @__PURE__ */ new Map();
|
|
@@ -29923,7 +30679,6 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
29923
30679
|
await new Promise((resolve6, reject) => {
|
|
29924
30680
|
let finished = false;
|
|
29925
30681
|
const cleanup = () => {
|
|
29926
|
-
connectionRefresh.close();
|
|
29927
30682
|
connectionLiveness.close();
|
|
29928
30683
|
signal.removeEventListener("abort", stop);
|
|
29929
30684
|
socket.removeEventListener("close", handleClose);
|
|
@@ -29941,61 +30696,282 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
29941
30696
|
cleanup();
|
|
29942
30697
|
resolve6();
|
|
29943
30698
|
};
|
|
29944
|
-
const rejectConnection = () => {
|
|
30699
|
+
const rejectConnection = (failure) => {
|
|
29945
30700
|
if (finished) {
|
|
29946
30701
|
return;
|
|
29947
30702
|
}
|
|
29948
30703
|
finished = true;
|
|
29949
30704
|
cleanup();
|
|
29950
|
-
reject(
|
|
30705
|
+
reject(failure);
|
|
29951
30706
|
};
|
|
29952
30707
|
const stop = () => {
|
|
30708
|
+
diagnostics.connectionClosed(connectionEpoch, 1e3, "Daemon stopped", "daemon_stop");
|
|
29953
30709
|
closeRelaySocket(socket, 1e3, "Daemon stopped");
|
|
29954
30710
|
resolveConnection();
|
|
29955
30711
|
};
|
|
29956
|
-
const
|
|
29957
|
-
|
|
29958
|
-
|
|
30712
|
+
const failAndClose = (failure, code, reason, source) => {
|
|
30713
|
+
diagnostics.connectionFailed(connectionEpoch, failure, source);
|
|
30714
|
+
diagnostics.connectionClosed(connectionEpoch, code, reason, source);
|
|
30715
|
+
closeRelaySocket(socket, code, reason);
|
|
30716
|
+
rejectConnection(failure);
|
|
30717
|
+
};
|
|
30718
|
+
const processingDeliveryIds = /* @__PURE__ */ new Set();
|
|
30719
|
+
const processDeliveredPrompt = async (delivery) => {
|
|
30720
|
+
const command = decodeSessionPromptCommand(delivery.payload);
|
|
30721
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
30722
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30723
|
+
}
|
|
30724
|
+
const active = activeTurns.get(command.commandId);
|
|
30725
|
+
if (active !== void 0) {
|
|
30726
|
+
await active.completion;
|
|
30727
|
+
return;
|
|
30728
|
+
}
|
|
30729
|
+
const receipt = outbox.claimExecution(command.commandId, command.sessionId, delivery.payload);
|
|
30730
|
+
if (receipt.kind === "duplicate") {
|
|
30731
|
+
if (receipt.state === "running") {
|
|
30732
|
+
reportFailure(
|
|
30733
|
+
publisher,
|
|
30734
|
+
command,
|
|
30735
|
+
"agent_execution_interrupted",
|
|
30736
|
+
"The local Agent execution was interrupted before it completed",
|
|
30737
|
+
receipt.attemptId
|
|
30738
|
+
);
|
|
30739
|
+
outbox.transitionExecution(command.commandId, "failed");
|
|
30740
|
+
return;
|
|
30741
|
+
}
|
|
30742
|
+
if (receipt.state !== "dispatching") {
|
|
30743
|
+
return;
|
|
30744
|
+
}
|
|
30745
|
+
}
|
|
30746
|
+
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
30747
|
+
activeTurns.set(command.commandId, turn);
|
|
30748
|
+
if (command.disposition !== SessionPromptDisposition.Steer) {
|
|
30749
|
+
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
30750
|
+
}
|
|
30751
|
+
try {
|
|
30752
|
+
await executePrompt(
|
|
30753
|
+
outbox,
|
|
30754
|
+
publisher,
|
|
30755
|
+
command,
|
|
30756
|
+
config2,
|
|
30757
|
+
directories,
|
|
30758
|
+
audit,
|
|
30759
|
+
sessions,
|
|
30760
|
+
receipt.attemptId,
|
|
30761
|
+
timer,
|
|
30762
|
+
turn.signal
|
|
30763
|
+
);
|
|
30764
|
+
} finally {
|
|
30765
|
+
activeTurns.delete(command.commandId);
|
|
30766
|
+
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
30767
|
+
activeAttemptIds.delete(command.sessionId);
|
|
30768
|
+
}
|
|
30769
|
+
turn.finish();
|
|
30770
|
+
}
|
|
30771
|
+
};
|
|
30772
|
+
const processDeliveredPayload = async (delivery) => {
|
|
30773
|
+
const kind = decodeMessageKind(delivery.payload);
|
|
30774
|
+
if (kind === SESSION_CANCEL_KIND) {
|
|
30775
|
+
const cancellation = decodeSessionCancelCommand(delivery.payload);
|
|
30776
|
+
if (cancellation.sessionId !== delivery.sessionId) {
|
|
30777
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30778
|
+
}
|
|
30779
|
+
const turn = activeTurns.get(cancellation.commandId);
|
|
30780
|
+
if (turn === void 0 || !turn.matches(cancellation) || !turn.requestCancellation()) {
|
|
30781
|
+
return;
|
|
30782
|
+
}
|
|
30783
|
+
audit.record({
|
|
30784
|
+
commandId: cancellation.commandId,
|
|
30785
|
+
event: "session_cancellation_requested",
|
|
30786
|
+
sessionId: cancellation.sessionId
|
|
30787
|
+
});
|
|
30788
|
+
await sessions.cancelPrompt(cancellation.sessionId);
|
|
30789
|
+
return;
|
|
30790
|
+
}
|
|
30791
|
+
if (kind === SESSION_CONFIGURE_KIND) {
|
|
30792
|
+
const command = decodeSessionConfigureCommand(delivery.payload);
|
|
30793
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
30794
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30795
|
+
}
|
|
30796
|
+
await executeSessionConfigure(
|
|
30797
|
+
publisher,
|
|
30798
|
+
socket,
|
|
30799
|
+
command,
|
|
30800
|
+
config2,
|
|
30801
|
+
directories,
|
|
30802
|
+
audit,
|
|
30803
|
+
sessions,
|
|
30804
|
+
connectionController.signal
|
|
30805
|
+
);
|
|
30806
|
+
return;
|
|
30807
|
+
}
|
|
30808
|
+
if (kind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
30809
|
+
const command = decodeSessionPermissionRespondCommand(delivery.payload);
|
|
30810
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
30811
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30812
|
+
}
|
|
30813
|
+
try {
|
|
30814
|
+
await sessions.respondPermission(command);
|
|
30815
|
+
audit.record({
|
|
30816
|
+
commandId: command.interactionId,
|
|
30817
|
+
event: "session_permission_resolved",
|
|
30818
|
+
sessionId: command.sessionId
|
|
30819
|
+
});
|
|
30820
|
+
} catch (error61) {
|
|
30821
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
30822
|
+
}
|
|
30823
|
+
return;
|
|
30824
|
+
}
|
|
30825
|
+
if (kind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
30826
|
+
const command = decodeSessionElicitationRespondCommand(delivery.payload);
|
|
30827
|
+
if (command.sessionId !== delivery.sessionId) {
|
|
30828
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30829
|
+
}
|
|
30830
|
+
try {
|
|
30831
|
+
await sessions.respondElicitation(command);
|
|
30832
|
+
audit.record({
|
|
30833
|
+
commandId: command.interactionId,
|
|
30834
|
+
event: "session_elicitation_resolved",
|
|
30835
|
+
sessionId: command.sessionId
|
|
30836
|
+
});
|
|
30837
|
+
} catch (error61) {
|
|
30838
|
+
reportOperationFailure(socket, command.interactionId, command.sessionId, error61);
|
|
30839
|
+
}
|
|
30840
|
+
return;
|
|
30841
|
+
}
|
|
30842
|
+
if (kind === SESSION_PROMPT_KIND) {
|
|
30843
|
+
await processDeliveredPrompt(delivery);
|
|
30844
|
+
return;
|
|
30845
|
+
}
|
|
30846
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
30847
|
+
};
|
|
30848
|
+
const processRuntimeDelivery = (delivery, state) => {
|
|
30849
|
+
if (state === "processed" || processingDeliveryIds.has(delivery.deliveryId)) {
|
|
30850
|
+
return;
|
|
30851
|
+
}
|
|
30852
|
+
processingDeliveryIds.add(delivery.deliveryId);
|
|
30853
|
+
void processDeliveredPayload(delivery).then(() => {
|
|
30854
|
+
outbox.markRuntimeDeliveryProcessed(delivery.deliveryId, delivery.sessionId);
|
|
30855
|
+
}).catch((error61) => {
|
|
30856
|
+
if (connectionController.signal.aborted) {
|
|
30857
|
+
return;
|
|
30858
|
+
}
|
|
30859
|
+
console.error("Mobius daemon could not process a durable Runtime delivery", error61);
|
|
30860
|
+
failAndClose(
|
|
30861
|
+
new Error("Runtime delivery processing failed", { cause: error61 }),
|
|
30862
|
+
4008,
|
|
30863
|
+
"Invalid Runtime delivery",
|
|
30864
|
+
"delivery"
|
|
30865
|
+
);
|
|
30866
|
+
}).finally(() => processingDeliveryIds.delete(delivery.deliveryId));
|
|
30867
|
+
};
|
|
30868
|
+
const receiveRuntimeDelivery = (delivery) => {
|
|
30869
|
+
const payloadKind = decodeMessageKind(delivery.payload);
|
|
30870
|
+
let payloadSessionId = "";
|
|
30871
|
+
if (payloadKind === SESSION_CANCEL_KIND) {
|
|
30872
|
+
payloadSessionId = decodeSessionCancelCommand(delivery.payload).sessionId;
|
|
30873
|
+
} else if (payloadKind === SESSION_CONFIGURE_KIND) {
|
|
30874
|
+
payloadSessionId = decodeSessionConfigureCommand(delivery.payload).sessionId;
|
|
30875
|
+
} else if (payloadKind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
30876
|
+
payloadSessionId = decodeSessionPermissionRespondCommand(delivery.payload).sessionId;
|
|
30877
|
+
} else if (payloadKind === SESSION_ELICITATION_RESPOND_KIND) {
|
|
30878
|
+
payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
|
|
30879
|
+
} else if (payloadKind === SESSION_PROMPT_KIND) {
|
|
30880
|
+
payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
|
|
30881
|
+
} else {
|
|
30882
|
+
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
30883
|
+
}
|
|
30884
|
+
if (payloadSessionId !== delivery.sessionId) {
|
|
30885
|
+
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
30886
|
+
}
|
|
30887
|
+
const stored = outbox.claimRuntimeDelivery(delivery);
|
|
30888
|
+
send(
|
|
30889
|
+
socket,
|
|
30890
|
+
encodeRuntimeDeliveryReceived({
|
|
30891
|
+
deliveryId: delivery.deliveryId,
|
|
30892
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
30893
|
+
sessionId: delivery.sessionId
|
|
30894
|
+
})
|
|
30895
|
+
);
|
|
30896
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
30897
|
+
};
|
|
30898
|
+
const resumeRuntimeDeliveries = () => {
|
|
30899
|
+
for (const stored of outbox.runtimeDeliveries()) {
|
|
30900
|
+
const delivery = {
|
|
30901
|
+
deliveryId: stored.deliveryId,
|
|
30902
|
+
kind: RUNTIME_DELIVERY_KIND,
|
|
30903
|
+
payload: stored.payload,
|
|
30904
|
+
sessionId: stored.sessionId
|
|
30905
|
+
};
|
|
30906
|
+
if (stored.state !== "relay_committed") {
|
|
30907
|
+
send(
|
|
30908
|
+
socket,
|
|
30909
|
+
encodeRuntimeDeliveryReceived({
|
|
30910
|
+
deliveryId: stored.deliveryId,
|
|
30911
|
+
kind: RUNTIME_DELIVERY_RECEIVED_KIND,
|
|
30912
|
+
sessionId: stored.sessionId
|
|
30913
|
+
})
|
|
30914
|
+
);
|
|
30915
|
+
}
|
|
30916
|
+
processRuntimeDelivery(delivery, stored.state);
|
|
30917
|
+
}
|
|
29959
30918
|
};
|
|
29960
30919
|
const connectionLiveness = new RelayConnectionLiveness(timer, {
|
|
29961
30920
|
send: (message) => send(socket, message),
|
|
29962
|
-
unresponsive: () => {
|
|
30921
|
+
unresponsive: (heartbeatId, timeoutMilliseconds) => {
|
|
30922
|
+
diagnostics.heartbeatTimedOut(connectionEpoch, heartbeatId, timeoutMilliseconds);
|
|
30923
|
+
diagnostics.connectionClosed(
|
|
30924
|
+
connectionEpoch,
|
|
30925
|
+
4001,
|
|
30926
|
+
"Relay liveness check timed out",
|
|
30927
|
+
"heartbeat_timeout"
|
|
30928
|
+
);
|
|
29963
30929
|
closeRelaySocket(socket, 4001, "Relay liveness check timed out");
|
|
29964
30930
|
resolveConnection();
|
|
29965
30931
|
}
|
|
29966
30932
|
});
|
|
29967
|
-
const connectionRefresh = new RelayConnectionRefresh(
|
|
29968
|
-
timer,
|
|
29969
|
-
() => activeTurns.size === 0,
|
|
29970
|
-
refreshConnection
|
|
29971
|
-
);
|
|
29972
30933
|
signal.addEventListener("abort", stop, { once: true });
|
|
29973
|
-
const handleClose = () => {
|
|
30934
|
+
const handleClose = (event) => {
|
|
30935
|
+
diagnostics.connectionClosed(connectionEpoch, event.code, event.reason, "relay");
|
|
29974
30936
|
resolveConnection();
|
|
29975
30937
|
};
|
|
29976
|
-
const handleError = () => {
|
|
30938
|
+
const handleError = (event) => {
|
|
29977
30939
|
if (signal.aborted) {
|
|
29978
30940
|
resolveConnection();
|
|
29979
30941
|
return;
|
|
29980
30942
|
}
|
|
29981
|
-
|
|
30943
|
+
const cause = Reflect.get(event, "error");
|
|
30944
|
+
const failure = new Error("Relay WebSocket emitted an error", { cause: cause ?? event });
|
|
30945
|
+
diagnostics.connectionFailed(connectionEpoch, failure, "socket_error");
|
|
30946
|
+
diagnostics.connectionClosed(connectionEpoch, 1006, "WebSocket error", "socket_error");
|
|
30947
|
+
rejectConnection(failure);
|
|
29982
30948
|
};
|
|
29983
30949
|
const handleMessage = (event) => {
|
|
29984
30950
|
const encoded = event.data;
|
|
29985
30951
|
if (typeof encoded !== "string") {
|
|
29986
|
-
|
|
29987
|
-
rejectConnection();
|
|
30952
|
+
failAndClose(new Error("Relay sent a non-text message"), 4003, "Text message required", "protocol");
|
|
29988
30953
|
return;
|
|
29989
30954
|
}
|
|
29990
30955
|
try {
|
|
29991
30956
|
const kind = decodeMessageKind(encoded);
|
|
30957
|
+
if (kind === RUNTIME_DELIVERY_COMMITTED_KIND) {
|
|
30958
|
+
const committed = decodeRuntimeDeliveryCommitted(encoded);
|
|
30959
|
+
if (!outbox.markRuntimeDeliveryCommitted(committed.deliveryId, committed.sessionId)) {
|
|
30960
|
+
console.warn("Mobius daemon ignored confirmation for an unknown Runtime delivery");
|
|
30961
|
+
}
|
|
30962
|
+
return;
|
|
30963
|
+
}
|
|
30964
|
+
if (kind === RUNTIME_DELIVERY_KIND) {
|
|
30965
|
+
receiveRuntimeDelivery(decodeRuntimeDelivery(encoded));
|
|
30966
|
+
return;
|
|
30967
|
+
}
|
|
29992
30968
|
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
29993
|
-
|
|
30969
|
+
publisher.acknowledge(decodeSessionEventAcknowledgement(encoded));
|
|
29994
30970
|
return;
|
|
29995
30971
|
}
|
|
29996
30972
|
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
29997
30973
|
const rejection = decodeSessionEventRejection(encoded);
|
|
29998
|
-
if (
|
|
30974
|
+
if (publisher.quarantine(rejection)) {
|
|
29999
30975
|
audit.record({
|
|
30000
30976
|
commandId: rejection.eventId,
|
|
30001
30977
|
details: { code: rejection.code },
|
|
@@ -30374,6 +31350,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30374
31350
|
applicator,
|
|
30375
31351
|
ipc,
|
|
30376
31352
|
receipt2.attemptId,
|
|
31353
|
+
timer,
|
|
30377
31354
|
turn2.signal
|
|
30378
31355
|
).catch((error61) => {
|
|
30379
31356
|
console.error("Mobius daemon Bot turn failed", error61);
|
|
@@ -30383,7 +31360,6 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30383
31360
|
activeAttemptIds.delete(command2.sessionId);
|
|
30384
31361
|
}
|
|
30385
31362
|
turn2.finish();
|
|
30386
|
-
connectionRefresh.afterTurnFinished();
|
|
30387
31363
|
});
|
|
30388
31364
|
return;
|
|
30389
31365
|
}
|
|
@@ -30412,6 +31388,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30412
31388
|
audit,
|
|
30413
31389
|
sessions,
|
|
30414
31390
|
receipt.attemptId,
|
|
31391
|
+
timer,
|
|
30415
31392
|
turn.signal
|
|
30416
31393
|
).catch((error61) => {
|
|
30417
31394
|
console.error("Mobius daemon turn failed", error61);
|
|
@@ -30421,12 +31398,19 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30421
31398
|
activeAttemptIds.delete(command.sessionId);
|
|
30422
31399
|
}
|
|
30423
31400
|
turn.finish();
|
|
30424
|
-
connectionRefresh.afterTurnFinished();
|
|
30425
31401
|
});
|
|
30426
31402
|
} catch (error61) {
|
|
30427
31403
|
console.error("Mobius daemon rejected a message", error61);
|
|
30428
|
-
|
|
30429
|
-
|
|
31404
|
+
if (error61 instanceof RuntimeDeliveryInboxCapacityError) {
|
|
31405
|
+
failAndClose(error61, 4013, "Runtime delivery queue full", "delivery_backpressure");
|
|
31406
|
+
return;
|
|
31407
|
+
}
|
|
31408
|
+
failAndClose(
|
|
31409
|
+
new Error("Relay sent an invalid protocol message", { cause: error61 }),
|
|
31410
|
+
4008,
|
|
31411
|
+
"Invalid protocol message",
|
|
31412
|
+
"protocol"
|
|
31413
|
+
);
|
|
30430
31414
|
}
|
|
30431
31415
|
};
|
|
30432
31416
|
socket.addEventListener("close", handleClose);
|
|
@@ -30438,21 +31422,19 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30438
31422
|
return;
|
|
30439
31423
|
}
|
|
30440
31424
|
publisher.connect(socket);
|
|
30441
|
-
|
|
30442
|
-
connectionRefresh.afterTurnFinished
|
|
30443
|
-
);
|
|
31425
|
+
resumeRuntimeDeliveries();
|
|
30444
31426
|
},
|
|
30445
31427
|
(error61) => {
|
|
30446
31428
|
if (finished) {
|
|
30447
31429
|
return;
|
|
30448
31430
|
}
|
|
30449
31431
|
console.error("Mobius daemon could not reconcile active Agent turns", error61);
|
|
30450
|
-
|
|
30451
|
-
|
|
31432
|
+
failAndClose(
|
|
31433
|
+
new Error("Active Agent turn reconciliation failed", { cause: error61 }),
|
|
30452
31434
|
ACTIVE_TURN_RECONCILIATION_CLOSE_CODE,
|
|
30453
|
-
"Active Agent turn reconciliation failed"
|
|
31435
|
+
"Active Agent turn reconciliation failed",
|
|
31436
|
+
"reconciliation"
|
|
30454
31437
|
);
|
|
30455
|
-
rejectConnection();
|
|
30456
31438
|
}
|
|
30457
31439
|
);
|
|
30458
31440
|
if (signal.aborted) {
|
|
@@ -30496,6 +31478,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
30496
31478
|
const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
|
|
30497
31479
|
const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
|
|
30498
31480
|
const installationObserver = new DaemonInstallationObserver();
|
|
31481
|
+
const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
|
|
30499
31482
|
const nativeSessions = new NativeSessionService(config2, directories, sessions, audit);
|
|
30500
31483
|
const installations = new AgentInstallationManager(
|
|
30501
31484
|
specifications,
|
|
@@ -30503,7 +31486,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
30503
31486
|
installationObserver,
|
|
30504
31487
|
installationAudit
|
|
30505
31488
|
);
|
|
30506
|
-
let
|
|
31489
|
+
let connectionEpoch = 0;
|
|
30507
31490
|
let connectionAnnounced = false;
|
|
30508
31491
|
const announceConnection = () => {
|
|
30509
31492
|
if (connectionAnnounced) {
|
|
@@ -30519,10 +31502,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
30519
31502
|
`
|
|
30520
31503
|
);
|
|
30521
31504
|
};
|
|
30522
|
-
const catalogPublication = publishAgentCatalogUntilAvailable(config2, signal, timer);
|
|
31505
|
+
const catalogPublication = publishAgentCatalogUntilAvailable(config2, diagnostics, signal, timer);
|
|
30523
31506
|
try {
|
|
30524
31507
|
await ipc.listen(signal);
|
|
30525
31508
|
while (!signal.aborted) {
|
|
31509
|
+
connectionEpoch += 1;
|
|
30526
31510
|
try {
|
|
30527
31511
|
await runRelayConnection(
|
|
30528
31512
|
config2,
|
|
@@ -30540,19 +31524,17 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
30540
31524
|
ipc,
|
|
30541
31525
|
activeTurns,
|
|
30542
31526
|
activeAttemptIds,
|
|
31527
|
+
connectionEpoch,
|
|
31528
|
+
diagnostics,
|
|
30543
31529
|
announceConnection,
|
|
30544
31530
|
signal,
|
|
30545
31531
|
timer
|
|
30546
31532
|
);
|
|
30547
|
-
|
|
30548
|
-
} catch {
|
|
31533
|
+
} catch (error61) {
|
|
30549
31534
|
if (signal.aborted) {
|
|
30550
31535
|
return;
|
|
30551
31536
|
}
|
|
30552
|
-
|
|
30553
|
-
console.warn("Mobius daemon is waiting for the relay");
|
|
30554
|
-
retryAnnounced = true;
|
|
30555
|
-
}
|
|
31537
|
+
diagnostics.connectionFailed(connectionEpoch, error61, "connection");
|
|
30556
31538
|
}
|
|
30557
31539
|
await waitForRelayRetry(signal, timer);
|
|
30558
31540
|
}
|
|
@@ -30708,12 +31690,12 @@ function decodePairingResponse(value, credentialField, expectedKeys) {
|
|
|
30708
31690
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
30709
31691
|
}
|
|
30710
31692
|
const channelId = value["channelId"];
|
|
30711
|
-
const
|
|
31693
|
+
const runtimeCredential2 = value[credentialField];
|
|
30712
31694
|
const runtimeId = value["runtimeId"];
|
|
30713
|
-
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN7.test(channelId) || typeof
|
|
31695
|
+
if (typeof channelId !== "string" || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN7.test(runtimeId)) {
|
|
30714
31696
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
30715
31697
|
}
|
|
30716
|
-
return { channelId, runtimeCredential, runtimeId };
|
|
31698
|
+
return { channelId, runtimeCredential: runtimeCredential2, runtimeId };
|
|
30717
31699
|
}
|
|
30718
31700
|
async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
|
|
30719
31701
|
const agents = localAgents.map((agent) => ({
|
|
@@ -30748,7 +31730,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
30748
31730
|
}
|
|
30749
31731
|
return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
|
|
30750
31732
|
}
|
|
30751
|
-
async function persistConnection(channelId, relayOrigin,
|
|
31733
|
+
async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
|
|
30752
31734
|
const connectionsDirectory = join16(readStateDirectory(environment), "connections");
|
|
30753
31735
|
await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
|
|
30754
31736
|
const connectionPath = join16(connectionsDirectory, `${channelId}.json`);
|
|
@@ -30760,7 +31742,7 @@ async function persistConnection(channelId, relayOrigin, runtimeCredential, defa
|
|
|
30760
31742
|
defaultWorkspace,
|
|
30761
31743
|
channelId,
|
|
30762
31744
|
relayOrigin: relayOrigin.toString(),
|
|
30763
|
-
runtimeCredential
|
|
31745
|
+
runtimeCredential: runtimeCredential2
|
|
30764
31746
|
},
|
|
30765
31747
|
null,
|
|
30766
31748
|
2
|
|
@@ -30777,16 +31759,16 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
30777
31759
|
}
|
|
30778
31760
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
30779
31761
|
const channelId = value["channelId"];
|
|
30780
|
-
const
|
|
31762
|
+
const runtimeCredential2 = value["runtimeCredential"] ?? value["daemonToken"];
|
|
30781
31763
|
const relayOrigin = value["relayOrigin"];
|
|
30782
|
-
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN7.test(channelId) || typeof
|
|
31764
|
+
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
|
|
30783
31765
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
30784
31766
|
}
|
|
30785
31767
|
return {
|
|
30786
31768
|
defaultWorkspace,
|
|
30787
31769
|
channelId,
|
|
30788
31770
|
relayOrigin: parseRelayOrigin(relayOrigin),
|
|
30789
|
-
runtimeCredential
|
|
31771
|
+
runtimeCredential: runtimeCredential2
|
|
30790
31772
|
};
|
|
30791
31773
|
}
|
|
30792
31774
|
async function readSavedConnection(channelId, environment) {
|