@moxt-ai/mobius 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runtime.js CHANGED
@@ -21856,6 +21856,9 @@ var SESSION_CANCEL_KIND = "session.cancel";
21856
21856
  var RUNTIME_LIVENESS_READY_KIND = "runtime.liveness.ready";
21857
21857
  var RUNTIME_HEARTBEAT_KIND = "runtime.heartbeat";
21858
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";
21859
21862
  var SESSION_STARTED_KIND = "session.started";
21860
21863
  var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
21861
21864
  var AGENT_ACTIVITY_KIND = "agent.activity";
@@ -21878,6 +21881,7 @@ var DIRECTORY_IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
21878
21881
  var MAX_PROMPT_LENGTH = 1e4;
21879
21882
  var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
21880
21883
  var MAX_EVENT_TEXT_LENGTH = 1e5;
21884
+ var MAX_RUNTIME_DELIVERY_PAYLOAD_LENGTH = 8 * 1024 * 1024;
21881
21885
  var ACTIVITY_TYPES = /* @__PURE__ */ new Set(["plan", "progress", "reasoning", "tool"]);
21882
21886
  var ACTIVITY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "completed", "failed"]);
21883
21887
  var TOOL_KINDS = /* @__PURE__ */ new Set([
@@ -22156,6 +22160,37 @@ function decodeRuntimeHeartbeatAckEvent(encoded) {
22156
22160
  kind: RUNTIME_HEARTBEAT_ACK_KIND
22157
22161
  };
22158
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
+ }
22159
22194
  function decodeSessionStartedEvent(encoded) {
22160
22195
  const value = parseJson2(encoded);
22161
22196
  assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
@@ -22243,6 +22278,9 @@ function decodeSessionFailedEvent(encoded) {
22243
22278
  function encodeRuntimeHeartbeatEvent(message) {
22244
22279
  return JSON.stringify(decodeRuntimeHeartbeatEvent(JSON.stringify(message)));
22245
22280
  }
22281
+ function encodeRuntimeDeliveryReceived(message) {
22282
+ return JSON.stringify(decodeRuntimeDeliveryReceived(JSON.stringify(message)));
22283
+ }
22246
22284
  function encodeSessionStartedEvent(message) {
22247
22285
  return JSON.stringify(decodeSessionStartedEvent(JSON.stringify(message)));
22248
22286
  }
@@ -22941,7 +22979,8 @@ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
22941
22979
  var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
22942
22980
  var SessionEventRejectionCode = {
22943
22981
  SessionDeleted: "session_deleted",
22944
- SessionNotFound: "session_not_found"
22982
+ SessionNotFound: "session_not_found",
22983
+ SessionRejected: "session_rejected"
22945
22984
  };
22946
22985
  var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22947
22986
  var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
@@ -26418,6 +26457,23 @@ var AcpSessionManager = class {
26418
26457
 
26419
26458
  // src/agent-catalog/publish-agent-catalog.ts
26420
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
26421
26477
  var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
26422
26478
  var AgentCatalogPublishError = class extends Error {
26423
26479
  code = "agent_catalog_update_failed";
@@ -26427,8 +26483,7 @@ var AgentCatalogPublishError = class extends Error {
26427
26483
  }
26428
26484
  };
26429
26485
  function catalogEndpoint(config2) {
26430
- const endpoint = new URL(config2.relayUrl);
26431
- endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
26486
+ const endpoint = relayHttpEndpoint(config2.relayUrl);
26432
26487
  if (endpoint.pathname.endsWith("/daemon")) {
26433
26488
  endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/catalog`;
26434
26489
  return endpoint;
@@ -26459,7 +26514,7 @@ async function publishAgentCatalog(config2, signal) {
26459
26514
  installableAgents: catalog.installableAgents
26460
26515
  }),
26461
26516
  dispatcher: environmentProxyDispatcher,
26462
- headers: { "content-type": "application/json" },
26517
+ headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
26463
26518
  method: "PUT",
26464
26519
  signal: requestSignal
26465
26520
  });
@@ -28501,8 +28556,7 @@ function parseReference(resource) {
28501
28556
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
28502
28557
  }
28503
28558
  function downloadUrl(config2, command, reference) {
28504
- const url2 = new URL(config2.relayUrl);
28505
- url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
28559
+ const url2 = relayHttpEndpoint(config2.relayUrl);
28506
28560
  let channelPath = "";
28507
28561
  if (url2.pathname.endsWith("/daemon")) {
28508
28562
  channelPath = url2.pathname.slice(0, -"/daemon".length);
@@ -28514,7 +28568,6 @@ function downloadUrl(config2, command, reference) {
28514
28568
  channelPath = `${url2.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
28515
28569
  }
28516
28570
  url2.pathname = `${channelPath}/sessions/${encodeURIComponent(command.sessionId)}/commands/${encodeURIComponent(command.commandId)}/artifacts/${encodeURIComponent(reference.artifactId)}/content`;
28517
- url2.searchParams.delete("liveness");
28518
28571
  return url2;
28519
28572
  }
28520
28573
  async function responseBytes(response, expectedByteLength, signal) {
@@ -28565,7 +28618,11 @@ async function download(config2, command, reference, signal) {
28565
28618
  try {
28566
28619
  response = await fetch4(downloadUrl(config2, command, reference), {
28567
28620
  dispatcher: environmentProxyDispatcher,
28568
- headers: { accept: reference.resource.mimeType },
28621
+ headers: {
28622
+ accept: reference.resource.mimeType,
28623
+ "accept-encoding": "identity",
28624
+ ...runtimeAuthorization(config2.relayUrl)
28625
+ },
28569
28626
  signal: requestSignal
28570
28627
  });
28571
28628
  if (!response.ok) {
@@ -28675,12 +28732,8 @@ function connectRelay(url2, signal) {
28675
28732
  signal.throwIfAborted();
28676
28733
  return new Promise((resolve6, reject) => {
28677
28734
  const endpoint = new URL(url2);
28678
- const headers = {};
28679
- if (endpoint.pathname.endsWith("/v1/runtimes/connect")) {
28680
- const runtimeCredential = endpoint.searchParams.get("token") ?? "";
28681
- endpoint.searchParams.delete("token");
28682
- headers["authorization"] = `Bearer ${runtimeCredential}`;
28683
- }
28735
+ const headers = runtimeAuthorization(endpoint);
28736
+ endpoint.searchParams.delete("token");
28684
28737
  const socket = new WebSocket(endpoint, {
28685
28738
  dispatcher: environmentProxyDispatcher,
28686
28739
  headers
@@ -29003,6 +29056,42 @@ var RelayConnectionLiveness = class {
29003
29056
  import { mkdirSync as mkdirSync3 } from "node:fs";
29004
29057
  import { dirname as dirname7 } from "node:path";
29005
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
+ };
29006
29095
  function readPendingEnvelope(row) {
29007
29096
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
29008
29097
  throw new Error("SQLite returned an invalid session event outbox row");
@@ -29013,9 +29102,26 @@ function readPendingEnvelope(row) {
29013
29102
  }
29014
29103
  return envelope2;
29015
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
+ }
29016
29119
  var SessionEventOutbox = class {
29017
29120
  #database;
29018
- constructor(path2) {
29121
+ #limits;
29122
+ constructor(path2, limits = DEFAULT_OUTBOX_LIMITS) {
29123
+ validateLimits(limits);
29124
+ this.#limits = limits;
29019
29125
  mkdirSync3(dirname7(path2), { recursive: true });
29020
29126
  this.#database = new DatabaseSync4(path2);
29021
29127
  this.#database.exec(`
@@ -29024,6 +29130,7 @@ var SessionEventOutbox = class {
29024
29130
  event_id TEXT NOT NULL UNIQUE,
29025
29131
  session_id TEXT NOT NULL,
29026
29132
  source_key TEXT NOT NULL,
29133
+ byte_length INTEGER NOT NULL,
29027
29134
  envelope_json TEXT NOT NULL
29028
29135
  ) STRICT;
29029
29136
  CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
@@ -29034,7 +29141,7 @@ var SessionEventOutbox = class {
29034
29141
  session_id TEXT NOT NULL,
29035
29142
  envelope_json TEXT NOT NULL,
29036
29143
  rejection_code TEXT NOT NULL CHECK (
29037
- rejection_code IN ('session_deleted', 'session_not_found')
29144
+ rejection_code IN ('session_deleted', 'session_not_found', 'session_rejected')
29038
29145
  )
29039
29146
  ) STRICT;
29040
29147
  CREATE TABLE IF NOT EXISTS relay_session_event_sources (
@@ -29050,7 +29157,53 @@ var SessionEventOutbox = class {
29050
29157
  state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
29051
29158
  )
29052
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;
29053
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
+ }
29054
29207
  const outboxColumns = this.#database.prepare("PRAGMA table_info(relay_session_event_outbox)").all();
29055
29208
  const hasSourceKey = outboxColumns.some(
29056
29209
  (column) => typeof column === "object" && column !== null && Reflect.get(column, "name") === "source_key"
@@ -29061,6 +29214,15 @@ var SessionEventOutbox = class {
29061
29214
  ADD COLUMN source_key TEXT NOT NULL DEFAULT '';
29062
29215
  `);
29063
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
+ }
29064
29226
  this.#database.exec(`
29065
29227
  UPDATE relay_session_event_outbox
29066
29228
  SET source_key = CASE json_extract(envelope_json, '$.source.kind')
@@ -29069,6 +29231,16 @@ var SessionEventOutbox = class {
29069
29231
  ELSE 'runtime:' || session_id
29070
29232
  END
29071
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;
29072
29244
  CREATE INDEX IF NOT EXISTS relay_session_event_outbox_source_order
29073
29245
  ON relay_session_event_outbox(source_key, ordinal);
29074
29246
  `);
@@ -29129,13 +29301,19 @@ var SessionEventOutbox = class {
29129
29301
  const state = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
29130
29302
  return state === "succeeded" || state === "failed" || state === "cancelled";
29131
29303
  };
29132
- acknowledge = (acknowledgement) => this.#database.prepare(
29133
- `DELETE FROM relay_session_event_outbox
29134
- WHERE event_id = ? AND session_id = ?`
29135
- ).run(acknowledgement.eventId, acknowledgement.sessionId).changes === 1;
29304
+ acknowledge = (acknowledgement) => this.#removeAcknowledgedEvent(acknowledgement.eventId, acknowledgement.sessionId);
29136
29305
  quarantine = (rejection) => {
29137
29306
  this.#database.exec("BEGIN IMMEDIATE");
29138
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");
29139
29317
  const insertion = this.#database.prepare(
29140
29318
  `INSERT INTO relay_session_event_dead_letters (
29141
29319
  ordinal, event_id, session_id, envelope_json, rejection_code
@@ -29155,6 +29333,7 @@ var SessionEventOutbox = class {
29155
29333
  if (deletion.changes !== 1) {
29156
29334
  throw new Error("The rejected session event could not be removed from the durable outbox");
29157
29335
  }
29336
+ this.#decrementEventState(byteLength);
29158
29337
  this.#database.exec("COMMIT");
29159
29338
  return true;
29160
29339
  } catch (error61) {
@@ -29166,7 +29345,129 @@ var SessionEventOutbox = class {
29166
29345
  this.#database.close();
29167
29346
  };
29168
29347
  enqueue = (sessionId, payload, attemptId = null) => {
29169
- const sourceKey = attemptId === null ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
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}`;
29170
29471
  this.#database.exec("BEGIN IMMEDIATE");
29171
29472
  try {
29172
29473
  const row = this.#database.prepare(
@@ -29183,13 +29484,22 @@ var SessionEventOutbox = class {
29183
29484
  kind: SESSION_EVENT_KIND,
29184
29485
  payload,
29185
29486
  sessionId,
29186
- source: attemptId === null ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
29487
+ source: attemptId.length === 0 ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
29187
29488
  attemptId,
29188
29489
  kind: "attempt",
29189
29490
  sourceSeq: nextSourceSeq.toString()
29190
29491
  }
29191
29492
  };
29192
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
+ }
29193
29503
  this.#database.prepare(
29194
29504
  `INSERT INTO relay_session_event_sources (
29195
29505
  source_key, next_source_seq
@@ -29199,9 +29509,15 @@ var SessionEventOutbox = class {
29199
29509
  ).run(sourceKey, nextSourceSeq + 1);
29200
29510
  this.#database.prepare(
29201
29511
  `INSERT INTO relay_session_event_outbox (
29202
- event_id, session_id, source_key, envelope_json
29203
- ) VALUES (?, ?, ?, ?)`
29204
- ).run(envelope2.eventId, envelope2.sessionId, sourceKey, 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);
29205
29521
  this.#database.exec("COMMIT");
29206
29522
  return encoded;
29207
29523
  } catch (error61) {
@@ -29209,6 +29525,44 @@ var SessionEventOutbox = class {
29209
29525
  throw error61;
29210
29526
  }
29211
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
+ };
29212
29566
  pending = () => this.#database.prepare(
29213
29567
  `SELECT envelope_json
29214
29568
  FROM relay_session_event_outbox
@@ -29235,7 +29589,68 @@ var SessionEventOutbox = class {
29235
29589
  LIMIT ?`
29236
29590
  ).all(limit).map(readPendingEnvelope);
29237
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
+ };
29238
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
+ }
29239
29654
  function isDaemonExecutionState(value) {
29240
29655
  return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
29241
29656
  }
@@ -29454,8 +29869,7 @@ var ActiveTurnReconciliationError = class extends Error {
29454
29869
  }
29455
29870
  };
29456
29871
  function activeTurnReconciliationEndpoint(config2, turn) {
29457
- const endpoint = new URL(config2.relayUrl);
29458
- endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
29872
+ const endpoint = relayHttpEndpoint(config2.relayUrl);
29459
29873
  let channelPath = "";
29460
29874
  if (endpoint.pathname.endsWith("/daemon")) {
29461
29875
  channelPath = endpoint.pathname.slice(0, -"/daemon".length);
@@ -29467,7 +29881,6 @@ function activeTurnReconciliationEndpoint(config2, turn) {
29467
29881
  channelPath = `${endpoint.pathname.slice(0, -runtimePath.length)}/channels/${encodeURIComponent(config2.channelId)}`;
29468
29882
  }
29469
29883
  endpoint.pathname = `${channelPath}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
29470
- endpoint.searchParams.delete("liveness");
29471
29884
  return endpoint;
29472
29885
  }
29473
29886
  async function reconcileActiveTurn(config2, turn, signal) {
@@ -29479,7 +29892,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
29479
29892
  response = await fetch5(activeTurnReconciliationEndpoint(config2, turn), {
29480
29893
  body: JSON.stringify({ outcome: { kind: "running" } }),
29481
29894
  dispatcher: environmentProxyDispatcher,
29482
- headers: { "content-type": "application/json" },
29895
+ headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
29483
29896
  method: "POST",
29484
29897
  signal: requestSignal
29485
29898
  });
@@ -29547,17 +29960,31 @@ var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectio
29547
29960
  }
29548
29961
  };
29549
29962
  };
29550
- var SESSION_EVENT_REPLAY_WINDOW = 4;
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
+ }
29551
29977
  var DaemonSessionEventPublisher = class {
29552
29978
  #outbox;
29553
- #inFlightEventIds = /* @__PURE__ */ new Set();
29979
+ #inFlightEvents = /* @__PURE__ */ new Map();
29980
+ #inFlightBytes = 0;
29554
29981
  #connection = new DisconnectedDaemonSessionEventState();
29555
29982
  constructor(outbox) {
29556
29983
  this.#outbox = outbox;
29557
29984
  }
29558
29985
  connect = (socket) => {
29559
29986
  this.#connection = new ConnectedDaemonSessionEventState(socket);
29560
- this.#inFlightEventIds.clear();
29987
+ this.#clearInFlight();
29561
29988
  this.#publishNextBatch();
29562
29989
  };
29563
29990
  disconnect = (socket) => {
@@ -29565,10 +29992,15 @@ var DaemonSessionEventPublisher = class {
29565
29992
  return;
29566
29993
  }
29567
29994
  this.#connection = this.#connection.disconnect(socket);
29568
- this.#inFlightEventIds.clear();
29995
+ this.#clearInFlight();
29569
29996
  };
29570
29997
  recordAttempt = (sessionId, payload, attemptId) => {
29571
- this.#outbox.enqueue(sessionId, payload, attemptId);
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
+ }
29572
30004
  this.#publishNextBatch();
29573
30005
  };
29574
30006
  recordRuntime = (sessionId, payload) => {
@@ -29579,7 +30011,7 @@ var DaemonSessionEventPublisher = class {
29579
30011
  if (!this.#outbox.acknowledge(acknowledgement)) {
29580
30012
  return;
29581
30013
  }
29582
- this.#inFlightEventIds.delete(acknowledgement.eventId);
30014
+ this.#removeInFlight(acknowledgement.eventId);
29583
30015
  this.#publishNextBatch();
29584
30016
  };
29585
30017
  quarantine = (rejection) => {
@@ -29587,24 +30019,60 @@ var DaemonSessionEventPublisher = class {
29587
30019
  if (!quarantined) {
29588
30020
  return false;
29589
30021
  }
29590
- this.#inFlightEventIds.delete(rejection.eventId);
30022
+ this.#removeInFlight(rejection.eventId);
29591
30023
  this.#publishNextBatch();
29592
30024
  return true;
29593
30025
  };
29594
30026
  #publishNextBatch = () => {
29595
- if (this.#inFlightEventIds.size > 0) {
29596
- return;
29597
- }
29598
- const batch = this.#outbox.pendingBatch(SESSION_EVENT_REPLAY_WINDOW);
29599
- for (const encoded of batch) {
29600
- const envelope2 = decodeSessionEventEnvelope(encoded);
29601
- if (!this.#connection.send(encoded)) {
29602
- this.#inFlightEventIds.clear();
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) {
29603
30060
  return;
29604
30061
  }
29605
- this.#inFlightEventIds.add(envelope2.eventId);
29606
30062
  }
29607
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;
30075
+ };
29608
30076
  };
29609
30077
  var CoalescingDaemonActivityPublisher = class {
29610
30078
  #pending = /* @__PURE__ */ new Map();
@@ -29856,6 +30324,9 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
29856
30324
  })
29857
30325
  );
29858
30326
  } catch (error61) {
30327
+ if (signal.aborted) {
30328
+ signal.throwIfAborted();
30329
+ }
29859
30330
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
29860
30331
  }
29861
30332
  }
@@ -30195,6 +30666,7 @@ async function publishAgentCatalogUntilAvailable(config2, diagnostics, signal, t
30195
30666
  }
30196
30667
  async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, connectionEpoch, diagnostics, onConnected, signal, timer) {
30197
30668
  const relayUrl = new URL(config2.relayUrl);
30669
+ relayUrl.searchParams.set("deliveryReceipts", "1");
30198
30670
  relayUrl.searchParams.set("liveness", "1");
30199
30671
  const socket = await connectRelay(relayUrl, signal);
30200
30672
  const reconnectingTurns = [...activeTurns.values()];
@@ -30243,6 +30715,207 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30243
30715
  closeRelaySocket(socket, code, reason);
30244
30716
  rejectConnection(failure);
30245
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
+ }
30918
+ };
30246
30919
  const connectionLiveness = new RelayConnectionLiveness(timer, {
30247
30920
  send: (message) => send(socket, message),
30248
30921
  unresponsive: (heartbeatId, timeoutMilliseconds) => {
@@ -30281,6 +30954,17 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30281
30954
  }
30282
30955
  try {
30283
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
+ }
30284
30968
  if (kind === SESSION_EVENT_ACK_KIND) {
30285
30969
  publisher.acknowledge(decodeSessionEventAcknowledgement(encoded));
30286
30970
  return;
@@ -30717,6 +31401,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30717
31401
  });
30718
31402
  } catch (error61) {
30719
31403
  console.error("Mobius daemon rejected a message", error61);
31404
+ if (error61 instanceof RuntimeDeliveryInboxCapacityError) {
31405
+ failAndClose(error61, 4013, "Runtime delivery queue full", "delivery_backpressure");
31406
+ return;
31407
+ }
30720
31408
  failAndClose(
30721
31409
  new Error("Relay sent an invalid protocol message", { cause: error61 }),
30722
31410
  4008,
@@ -30734,6 +31422,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30734
31422
  return;
30735
31423
  }
30736
31424
  publisher.connect(socket);
31425
+ resumeRuntimeDeliveries();
30737
31426
  },
30738
31427
  (error61) => {
30739
31428
  if (finished) {
@@ -31001,12 +31690,12 @@ function decodePairingResponse(value, credentialField, expectedKeys) {
31001
31690
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
31002
31691
  }
31003
31692
  const channelId = value["channelId"];
31004
- const runtimeCredential = value[credentialField];
31693
+ const runtimeCredential2 = value[credentialField];
31005
31694
  const runtimeId = value["runtimeId"];
31006
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential !== "string" || !TOKEN_PATTERN2.test(runtimeCredential) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN7.test(runtimeId)) {
31695
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN7.test(runtimeId)) {
31007
31696
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
31008
31697
  }
31009
- return { channelId, runtimeCredential, runtimeId };
31698
+ return { channelId, runtimeCredential: runtimeCredential2, runtimeId };
31010
31699
  }
31011
31700
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
31012
31701
  const agents = localAgents.map((agent) => ({
@@ -31041,7 +31730,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
31041
31730
  }
31042
31731
  return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
31043
31732
  }
31044
- async function persistConnection(channelId, relayOrigin, runtimeCredential, defaultWorkspace, environment) {
31733
+ async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
31045
31734
  const connectionsDirectory = join16(readStateDirectory(environment), "connections");
31046
31735
  await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
31047
31736
  const connectionPath = join16(connectionsDirectory, `${channelId}.json`);
@@ -31053,7 +31742,7 @@ async function persistConnection(channelId, relayOrigin, runtimeCredential, defa
31053
31742
  defaultWorkspace,
31054
31743
  channelId,
31055
31744
  relayOrigin: relayOrigin.toString(),
31056
- runtimeCredential
31745
+ runtimeCredential: runtimeCredential2
31057
31746
  },
31058
31747
  null,
31059
31748
  2
@@ -31070,16 +31759,16 @@ function decodeSavedConnection(value, expectedChannelId) {
31070
31759
  }
31071
31760
  const defaultWorkspace = value["defaultWorkspace"];
31072
31761
  const channelId = value["channelId"];
31073
- const runtimeCredential = value["runtimeCredential"] ?? value["daemonToken"];
31762
+ const runtimeCredential2 = value["runtimeCredential"] ?? value["daemonToken"];
31074
31763
  const relayOrigin = value["relayOrigin"];
31075
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential !== "string" || !TOKEN_PATTERN2.test(runtimeCredential) || typeof relayOrigin !== "string") {
31764
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
31076
31765
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
31077
31766
  }
31078
31767
  return {
31079
31768
  defaultWorkspace,
31080
31769
  channelId,
31081
31770
  relayOrigin: parseRelayOrigin(relayOrigin),
31082
- runtimeCredential
31771
+ runtimeCredential: runtimeCredential2
31083
31772
  };
31084
31773
  }
31085
31774
  async function readSavedConnection(channelId, environment) {