@moxt-ai/mobius 0.0.367 → 0.0.370

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.
Files changed (61) hide show
  1. package/NOTICE +27 -0
  2. package/THIRD-PARTY-NOTICES.txt +586 -0
  3. package/dist/{chunk-AJRLEZKJ.js → chunk-AF2SHMNS.js} +2 -2
  4. package/dist/{chunk-LNJNELNJ.js → chunk-F4ISBXGU.js} +6 -4
  5. package/dist/chunk-F4ISBXGU.js.map +7 -0
  6. package/dist/{chunk-KEI2PNYS.js → chunk-JYM22ZR6.js} +174 -64
  7. package/dist/{chunk-KEI2PNYS.js.map → chunk-JYM22ZR6.js.map} +3 -3
  8. package/dist/cli/handler/diagnose/config.d.ts +23 -0
  9. package/dist/cli/handler/diagnose/config.d.ts.map +1 -0
  10. package/dist/cli/handler/diagnose/config.js +55 -0
  11. package/dist/cli/handler/diagnose/config.js.map +1 -0
  12. package/dist/cli/handler/diagnose/index.d.ts +4 -0
  13. package/dist/cli/handler/diagnose/index.d.ts.map +1 -0
  14. package/dist/cli/handler/diagnose/index.js +314 -0
  15. package/dist/cli/handler/diagnose/index.js.map +1 -0
  16. package/dist/cli/handler/diagnose/routes.d.ts +16 -0
  17. package/dist/cli/handler/diagnose/routes.d.ts.map +1 -0
  18. package/dist/cli/handler/diagnose/routes.js +89 -0
  19. package/dist/cli/handler/diagnose/routes.js.map +1 -0
  20. package/dist/cli/handler/diagnose/worker.d.ts +3 -0
  21. package/dist/cli/handler/diagnose/worker.d.ts.map +1 -0
  22. package/dist/cli/handler/diagnose/worker.js +95 -0
  23. package/dist/cli/handler/diagnose/worker.js.map +1 -0
  24. package/dist/cli/index.d.ts.map +1 -1
  25. package/dist/cli/index.js +2 -0
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/{cli-DRFXM5PJ.js → cli-EY6WXGHE.js} +622 -39
  28. package/dist/{cli-DRFXM5PJ.js.map → cli-EY6WXGHE.js.map} +4 -4
  29. package/dist/cli.js +3 -3
  30. package/dist/engine/runtime/command/registry/interactions.d.ts.map +1 -1
  31. package/dist/engine/runtime/command/registry/interactions.js +0 -4
  32. package/dist/engine/runtime/command/registry/interactions.js.map +1 -1
  33. package/dist/engine/runtime/relay/connect.d.ts +1 -1
  34. package/dist/engine/runtime/relay/connect.d.ts.map +1 -1
  35. package/dist/engine/runtime/relay/connect.js +35 -2
  36. package/dist/engine/runtime/relay/connect.js.map +1 -1
  37. package/dist/engine/runtime/relay/diagnostics.d.ts +2 -0
  38. package/dist/engine/runtime/relay/diagnostics.d.ts.map +1 -1
  39. package/dist/engine/runtime/relay/diagnostics.js +26 -3
  40. package/dist/engine/runtime/relay/diagnostics.js.map +1 -1
  41. package/dist/engine/runtime/relay/run-relay-connection.d.ts.map +1 -1
  42. package/dist/engine/runtime/relay/run-relay-connection.js +3 -1
  43. package/dist/engine/runtime/relay/run-relay-connection.js.map +1 -1
  44. package/dist/engine/session/api/session-layer.d.ts.map +1 -1
  45. package/dist/engine/session/api/session-layer.js +1 -1
  46. package/dist/engine/session/api/session-layer.js.map +1 -1
  47. package/dist/engine/session/prompt/prompt-lifecycle.d.ts +2 -1
  48. package/dist/engine/session/prompt/prompt-lifecycle.d.ts.map +1 -1
  49. package/dist/engine/session/prompt/prompt-lifecycle.js +6 -5
  50. package/dist/engine/session/prompt/prompt-lifecycle.js.map +1 -1
  51. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  52. package/dist/engine/session/turn/execution-receipts.js +96 -42
  53. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  54. package/dist/engine.js +2 -2
  55. package/dist/storage/diagnostics/relay-probe-files.d.ts +7 -0
  56. package/dist/storage/diagnostics/relay-probe-files.d.ts.map +1 -0
  57. package/dist/storage/diagnostics/relay-probe-files.js +40 -0
  58. package/dist/storage/diagnostics/relay-probe-files.js.map +1 -0
  59. package/package.json +6 -4
  60. package/dist/chunk-LNJNELNJ.js.map +0 -7
  61. /package/dist/{chunk-AJRLEZKJ.js.map → chunk-AF2SHMNS.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../package.json"],
4
+ "sourcesContent": ["{\n \"name\": \"@moxt-ai/mobius\",\n \"version\": \"0.0.370\",\n \"description\": \"Mobius CLI for pairing and running local AI agent services.\",\n \"type\": \"module\",\n \"bin\": {\n \"mobius\": \"dist/cli.js\"\n },\n \"exports\": {\n \"./engine\": {\n \"mobius-source\": \"./src/exports/engine.ts\",\n \"types\": \"./dist/exports/engine.d.ts\",\n \"default\": \"./dist/engine.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"NOTICE\",\n \"THIRD-PARTY-NOTICES.txt\"\n ],\n \"engines\": {\n \"node\": \">=22.19.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"exports\": {\n \"./engine\": {\n \"types\": \"./dist/exports/engine.d.ts\",\n \"import\": \"./dist/engine.js\",\n \"default\": \"./dist/engine.js\"\n }\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/moxt-ai/mobius.git\",\n \"directory\": \"packages/cli\"\n },\n \"scripts\": {\n \"prebuild\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"build\": \"node scripts/build.ts && tsc --project tsconfig.build.json\",\n \"dev\": \"node --watch src/cli/entrypoint.ts\",\n \"pretypecheck\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"prepack\": \"pnpm build\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --project tsconfig.json && tsc --project tests/tsconfig.json\",\n \"pretest:controlled\": \"pnpm build\",\n \"test:controlled\": \"vitest run tests/sessions tests/runtime\",\n \"pretest:manual\": \"pnpm pretest:controlled\",\n \"test:manual\": \"vitest run tests/manual\",\n \"pretest:agents\": \"pnpm build\",\n \"test:agents\": \"vitest run tests/agents --maxWorkers=2\",\n \"pretest:pressure\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"test:pressure\": \"node tests/pressure/concurrent-sessions.mjs\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.3.257\",\n \"commander\": \"15.0.0\",\n \"semver\": \"^7.8.5\",\n \"undici\": \"8.12.2\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@anthropic-ai/sdk\": \"0.122.0\",\n \"@moxt-ai/mobius-sdk\": \"workspace:*\",\n \"@moxt-ai/mobius-test\": \"workspace:*\",\n \"@types/node\": \"^24.13.5\",\n \"@types/semver\": \"^7.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"drizzle-kit\": \"1.0.0-rc.4\",\n \"drizzle-orm\": \"1.0.0-rc.4\",\n \"esbuild\": \"0.28.2\",\n \"valibot\": \"1.5.0\",\n \"ws\": \"^8.21.3\"\n },\n \"keywords\": [],\n \"author\": \"Moxt\",\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/moxt-ai/mobius/issues\"\n },\n \"homepage\": \"https://github.com/moxt-ai/mobius#readme\"\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACI,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO;AAAA,IACH,QAAU;AAAA,EACd;AAAA,EACA,SAAW;AAAA,IACP,YAAY;AAAA,MACR,iBAAiB;AAAA,MACjB,OAAS;AAAA,MACT,SAAW;AAAA,IACf;AAAA,EACJ;AAAA,EACA,OAAS;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAAA,EACA,SAAW;AAAA,IACP,MAAQ;AAAA,EACZ;AAAA,EACA,eAAiB;AAAA,IACb,QAAU;AAAA,IACV,SAAW;AAAA,MACP,YAAY;AAAA,QACR,OAAS;AAAA,QACT,QAAU;AAAA,QACV,SAAW;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,YAAc;AAAA,IACV,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACjB;AAAA,EACA,SAAW;AAAA,IACP,UAAY;AAAA,IACZ,OAAS;AAAA,IACT,KAAO;AAAA,IACP,cAAgB;AAAA,IAChB,SAAW;AAAA,IACX,OAAS;AAAA,IACT,WAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,EACrB;AAAA,EACA,cAAgB;AAAA,IACZ,4BAA4B;AAAA,IAC5B,kCAAkC;AAAA,IAClC,WAAa;AAAA,IACb,QAAU;AAAA,IACV,QAAU;AAAA,IACV,KAAO;AAAA,EACX;AAAA,EACA,iBAAmB;AAAA,IACf,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe;AAAA,IACf,SAAW;AAAA,IACX,SAAW;AAAA,IACX,IAAM;AAAA,EACV;AAAA,EACA,UAAY,CAAC;AAAA,EACb,QAAU;AAAA,EACV,SAAW;AAAA,EACX,MAAQ;AAAA,IACJ,KAAO;AAAA,EACX;AAAA,EACA,UAAY;AAChB;",
6
+ "names": []
7
+ }
@@ -3,7 +3,7 @@ import {
3
3
  __export,
4
4
  __using,
5
5
  package_default
6
- } from "./chunk-LNJNELNJ.js";
6
+ } from "./chunk-F4ISBXGU.js";
7
7
 
8
8
  // src/engine/runtime/relay/runtime-revocation.ts
9
9
  var runtimeRevocationCloseCode = 1008;
@@ -88347,10 +88347,12 @@ var PromptLifecycle = class {
88347
88347
  #publications = /* @__PURE__ */ new Map();
88348
88348
  #queued = /* @__PURE__ */ new Map();
88349
88349
  #recordActiveTurn;
88350
+ #hasStarted;
88350
88351
  #recordLifecycle;
88351
- constructor(sink, recordLifecycle, recordActiveTurn) {
88352
+ constructor(sink, recordLifecycle, recordActiveTurn, hasStarted) {
88352
88353
  this.#recordLifecycle = recordLifecycle;
88353
88354
  this.#recordActiveTurn = recordActiveTurn;
88355
+ this.#hasStarted = hasStarted;
88354
88356
  this.#sink = sink;
88355
88357
  }
88356
88358
  requested = (command) => {
@@ -88363,15 +88365,14 @@ var PromptLifecycle = class {
88363
88365
  directoryId: command.directoryId,
88364
88366
  additionalDirectoryIds: command.additionalDirectoryIds
88365
88367
  },
88366
- phase: "queued",
88367
88368
  sessionId: command.sessionId,
88368
88369
  ...command.targetCommandId.length === 0 ? {} : { targetCommandId: command.targetCommandId }
88369
88370
  });
88370
88371
  };
88372
+ /** Metadata for an execution already claimed by the receipt owner. */
88371
88373
  started = (sessionId, commandId, attemptId, epoch, disposition) => {
88372
88374
  const request = this.#queued.get(commandId);
88373
88375
  if (request?.sessionId === sessionId) {
88374
- this.#queued.set(commandId, { ...request, phase: "running" });
88375
88376
  return {
88376
88377
  attemptId,
88377
88378
  content: request.content,
@@ -88446,7 +88447,7 @@ var PromptLifecycle = class {
88446
88447
  kind: "prompt.completed",
88447
88448
  commandId,
88448
88449
  stopReason,
88449
- ...request.phase === "queued" ? { execution: "not-started" } : {}
88450
+ ...this.#hasStarted(commandId, sessionId) ? {} : { execution: "not-started" }
88450
88451
  }
88451
88452
  });
88452
88453
  if (!recorded) {
@@ -88472,7 +88473,7 @@ var PromptLifecycle = class {
88472
88473
  }
88473
88474
  };
88474
88475
  promptRequestRecovery = (sessionId) => ({
88475
- queuedPromptRequests: [...this.#queued.values()].filter((request) => request.sessionId === sessionId && request.phase === "queued").map(({ commandId, content, disposition, targetCommandId }) => ({
88476
+ queuedPromptRequests: [...this.#queued.values()].filter((request) => request.sessionId === sessionId && !this.#hasStarted(request.commandId, sessionId)).map(({ commandId, content, disposition, targetCommandId }) => ({
88476
88477
  commandId,
88477
88478
  content,
88478
88479
  ...disposition === void 0 ? {} : { disposition },
@@ -88503,35 +88504,79 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
88503
88504
  // src/engine/session/turn/execution-receipts.ts
88504
88505
  import { createHash as createHash7, randomUUID as randomUUID15 } from "node:crypto";
88505
88506
  var MAX_TERMINAL_RECEIPTS = 1024;
88507
+ function executionStarted(state) {
88508
+ switch (state.kind) {
88509
+ case "pending":
88510
+ case "settled-before-start":
88511
+ return false;
88512
+ case "started":
88513
+ case "settled-after-start":
88514
+ return true;
88515
+ default: {
88516
+ const unreachable3 = state;
88517
+ throw new Error("Unexpected execution state", { cause: unreachable3 });
88518
+ }
88519
+ }
88520
+ }
88521
+ function executionOutcome(state) {
88522
+ switch (state.kind) {
88523
+ case "pending":
88524
+ case "started":
88525
+ return null;
88526
+ case "settled-before-start":
88527
+ case "settled-after-start":
88528
+ return state.outcome;
88529
+ default: {
88530
+ const unreachable3 = state;
88531
+ throw new Error("Unexpected execution state", { cause: unreachable3 });
88532
+ }
88533
+ }
88534
+ }
88535
+ function settledExecution(state, outcome) {
88536
+ return { kind: executionStarted(state) ? "settled-after-start" : "settled-before-start", outcome };
88537
+ }
88506
88538
  var ExecutionReceipts = class {
88507
88539
  #executions = /* @__PURE__ */ new Map();
88508
88540
  #recoveredCommands = /* @__PURE__ */ new Set();
88509
88541
  #table;
88510
88542
  #closing = false;
88511
- #activeCount = 0;
88512
88543
  #onCount;
88513
88544
  constructor(table, onCount = () => void 0) {
88514
88545
  this.#onCount = onCount;
88515
88546
  this.#table = table;
88516
- for (const row of table.list()) {
88517
- this.#executions.set(row.commandId, row);
88518
- this.#recoveredCommands.add(row.commandId);
88519
- if (row.outcome === null) {
88520
- this.#activeCount += 1;
88521
- }
88547
+ for (const { commandId, started, outcome, updatedAt: _updatedAt, ...identity2 } of table.list()) {
88548
+ const state = { kind: started ? "started" : "pending" };
88549
+ this.#executions.set(commandId, {
88550
+ ...identity2,
88551
+ state: outcome === null ? state : settledExecution(state, outcome)
88552
+ });
88553
+ this.#recoveredCommands.add(commandId);
88522
88554
  }
88523
88555
  }
88524
- #save = (commandId, receipt, liveOutcome = receipt.outcome) => {
88525
- const evicted = this.#closing ? [] : this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, MAX_TERMINAL_RECEIPTS);
88526
- const previous = this.#executions.get(commandId);
88527
- const wasActive = previous?.outcome === null;
88528
- this.#executions.set(commandId, { ...receipt, outcome: liveOutcome });
88556
+ #save = (commandId, receipt, durableOutcome = executionOutcome(receipt.state)) => {
88557
+ const { state, ...identity2 } = receipt;
88558
+ const evicted = this.#closing ? [] : this.#table.save(
88559
+ {
88560
+ ...identity2,
88561
+ commandId,
88562
+ started: executionStarted(state),
88563
+ outcome: durableOutcome,
88564
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
88565
+ },
88566
+ MAX_TERMINAL_RECEIPTS
88567
+ );
88568
+ this.#executions.set(commandId, receipt);
88529
88569
  for (const evictedCommandId of evicted) {
88530
88570
  this.#executions.delete(evictedCommandId);
88531
88571
  this.#recoveredCommands.delete(evictedCommandId);
88532
88572
  }
88533
- this.#activeCount += Number(receipt.outcome === null) - Number(wasActive);
88534
- this.#onCount(this.#activeCount);
88573
+ let activeCount = 0;
88574
+ for (const entry of this.#executions.values()) {
88575
+ if (executionOutcome(entry.state) === null) {
88576
+ activeCount += 1;
88577
+ }
88578
+ }
88579
+ this.#onCount(activeCount);
88535
88580
  };
88536
88581
  #nextAdmissionOrder = () => {
88537
88582
  let latest = 0;
@@ -88545,7 +88590,8 @@ var ExecutionReceipts = class {
88545
88590
  };
88546
88591
  outcome = (commandId) => {
88547
88592
  const receipt = this.#executions.get(commandId);
88548
- return receipt?.outcome === null || receipt === void 0 ? void 0 : decodeKnownSessionEventPayload(JSON.parse(receipt.outcome)) ?? void 0;
88593
+ const outcome = receipt === void 0 ? null : executionOutcome(receipt.state);
88594
+ return outcome === null ? void 0 : decodeKnownSessionEventPayload(JSON.parse(outcome)) ?? void 0;
88549
88595
  };
88550
88596
  /** The command's delivery as these receipts know it; another Session's command reads as unknown. */
88551
88597
  delivery = (commandId, sessionId) => {
@@ -88556,7 +88602,7 @@ var ExecutionReceipts = class {
88556
88602
  if (receipt.sessionId !== sessionId) {
88557
88603
  return { state: "unknown" };
88558
88604
  }
88559
- if (receipt.outcome === null) {
88605
+ if (executionOutcome(receipt.state) === null) {
88560
88606
  return { state: "accepted" };
88561
88607
  }
88562
88608
  const outcome = this.outcome(commandId);
@@ -88585,9 +88631,9 @@ var ExecutionReceipts = class {
88585
88631
  if (receipt.sessionId !== sessionId) {
88586
88632
  continue;
88587
88633
  }
88588
- const outcome2 = receipt.outcome === null ? void 0 : this.outcome(commandId);
88634
+ const outcome2 = this.outcome(commandId);
88589
88635
  const failedBeforeStart = outcome2?.type === "lifecycle-metadata" && outcome2.payload.kind === "prompt.failed-before-start";
88590
- if ((receipt.started || failedBeforeStart) && receipt.admissionOrder > latestOrder) {
88636
+ if ((executionStarted(receipt.state) || failedBeforeStart) && receipt.admissionOrder > latestOrder) {
88591
88637
  last = commandId;
88592
88638
  latestOrder = receipt.admissionOrder;
88593
88639
  }
@@ -88614,7 +88660,7 @@ var ExecutionReceipts = class {
88614
88660
  /** Started identities remain authoritative after their detailed receipt is evicted. */
88615
88661
  hasStarted = (commandId, sessionId) => {
88616
88662
  const receipt = this.#executions.get(commandId);
88617
- return receipt?.sessionId === sessionId && receipt.started || this.#table.identity(commandId)?.sessionId === sessionId;
88663
+ return receipt?.sessionId === sessionId && executionStarted(receipt.state) || this.#table.identity(commandId)?.sessionId === sessionId;
88618
88664
  };
88619
88665
  /** Reserves an unseen command for cancellation before a delayed prompt can claim its identity. */
88620
88666
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
@@ -88645,8 +88691,10 @@ var ExecutionReceipts = class {
88645
88691
  attemptId: randomUUID15(),
88646
88692
  commandHash,
88647
88693
  sessionId,
88648
- started: false,
88649
- outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
88694
+ state: {
88695
+ kind: "settled-before-start",
88696
+ outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
88697
+ }
88650
88698
  });
88651
88699
  return outcome;
88652
88700
  };
@@ -88666,16 +88714,17 @@ var ExecutionReceipts = class {
88666
88714
  const outcome = { type: "lifecycle-metadata", payload, recordedAt: event.recordedAt };
88667
88715
  this.#save(
88668
88716
  payload.commandId,
88669
- { ...receipt, outcome: JSON.stringify({ ...outcome, payload: sanitized }) },
88670
- JSON.stringify(outcome)
88717
+ { ...receipt, state: settledExecution(receipt.state, JSON.stringify(outcome)) },
88718
+ JSON.stringify({ ...outcome, payload: sanitized })
88671
88719
  );
88672
88720
  };
88673
88721
  recover = () => {
88674
88722
  const recovered = [];
88675
88723
  for (const [commandId, receipt] of [...this.#executions]) {
88676
- const event = receipt.outcome === null ? {
88724
+ const outcome = executionOutcome(receipt.state);
88725
+ const event = outcome === null ? {
88677
88726
  type: "lifecycle-metadata",
88678
- payload: receipt.started ? {
88727
+ payload: executionStarted(receipt.state) ? {
88679
88728
  kind: "prompt.failed",
88680
88729
  commandId,
88681
88730
  attemptId: receipt.attemptId,
@@ -88687,14 +88736,17 @@ var ExecutionReceipts = class {
88687
88736
  code: "runtime_restarted",
88688
88737
  message: "The local runtime restarted before this request started"
88689
88738
  }
88690
- } : decodeKnownSessionEventPayload(JSON.parse(receipt.outcome));
88739
+ } : decodeKnownSessionEventPayload(JSON.parse(outcome));
88691
88740
  if (event === null) {
88692
88741
  continue;
88693
88742
  }
88694
- const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
88743
+ const recordedAt = outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(outcome)).recordedAt;
88695
88744
  recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
88696
- if (receipt.outcome === null) {
88697
- this.#save(commandId, { ...receipt, outcome: JSON.stringify({ ...event, recordedAt }) });
88745
+ if (outcome === null) {
88746
+ this.#save(commandId, {
88747
+ ...receipt,
88748
+ state: settledExecution(receipt.state, JSON.stringify({ ...event, recordedAt }))
88749
+ });
88698
88750
  }
88699
88751
  }
88700
88752
  return recovered;
@@ -88703,7 +88755,7 @@ var ExecutionReceipts = class {
88703
88755
  const commandHash = createHash7("sha256").update(commandJson).digest("hex");
88704
88756
  let existing = this.#executions.get(commandId);
88705
88757
  const previous = this.outcome(commandId);
88706
- if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
88758
+ if (existing?.sessionId === sessionId && !executionStarted(existing.state) && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
88707
88759
  this.#table.remove(commandId);
88708
88760
  this.#executions.delete(commandId);
88709
88761
  this.#recoveredCommands.delete(commandId);
@@ -88730,8 +88782,7 @@ var ExecutionReceipts = class {
88730
88782
  attemptId,
88731
88783
  commandHash,
88732
88784
  sessionId,
88733
- started: false,
88734
- outcome: null
88785
+ state: { kind: "pending" }
88735
88786
  });
88736
88787
  return { attemptId, commandId, kind: "accepted" };
88737
88788
  };
@@ -88740,26 +88791,34 @@ var ExecutionReceipts = class {
88740
88791
  if (current === void 0) {
88741
88792
  throw new Error("The runtime execution receipt does not exist");
88742
88793
  }
88743
- if (current.outcome !== null) {
88744
- throw new Error("The runtime execution transition is invalid");
88745
- }
88746
- if (!current.started) {
88747
- this.#save(commandId, { ...current, started: true });
88794
+ const state = current.state;
88795
+ switch (state.kind) {
88796
+ case "pending":
88797
+ this.#save(commandId, { ...current, state: { kind: "started" } });
88798
+ return;
88799
+ case "started":
88800
+ return;
88801
+ case "settled-before-start":
88802
+ case "settled-after-start":
88803
+ throw new Error("The runtime execution transition is invalid");
88804
+ default: {
88805
+ const unreachable3 = state;
88806
+ throw new Error("Unexpected execution state", { cause: unreachable3 });
88807
+ }
88748
88808
  }
88749
88809
  };
88750
88810
  /** Only commands without a terminal result can still be cancelled. */
88751
88811
  findUnsettledAttemptId = (commandId, sessionId) => {
88752
88812
  const receipt = this.#executions.get(commandId);
88753
- return receipt?.sessionId === sessionId && receipt.outcome === null ? receipt.attemptId : null;
88813
+ return receipt?.sessionId === sessionId && executionOutcome(receipt.state) === null ? receipt.attemptId : null;
88754
88814
  };
88755
88815
  isTerminalExecution = (commandId, sessionId) => {
88756
88816
  const receipt = this.#executions.get(commandId);
88757
- return receipt?.sessionId === sessionId && receipt.outcome !== null;
88817
+ return receipt?.sessionId === sessionId && executionOutcome(receipt.state) !== null;
88758
88818
  };
88759
88819
  close = () => {
88760
88820
  this.#executions.clear();
88761
88821
  this.#recoveredCommands.clear();
88762
- this.#activeCount = 0;
88763
88822
  };
88764
88823
  };
88765
88824
 
@@ -89391,7 +89450,8 @@ function buildSessionLayer(options) {
89391
89450
  eventProjection.record(recorded);
89392
89451
  return true;
89393
89452
  },
89394
- activeSessions.recordSessionEvent
89453
+ activeSessions.recordSessionEvent,
89454
+ operations.hasStarted
89395
89455
  );
89396
89456
  const nativeSessions = new NativeSessionService(
89397
89457
  bindingId,
@@ -89966,7 +90026,7 @@ function sanitizeDiagnosticText(value) {
89966
90026
  const code = character.charCodeAt(0);
89967
90027
  return code < 32 || code === 127 ? " " : character;
89968
90028
  }).join("");
89969
- const withoutSecrets = printable.replace(/([?&](?:access_token|authorization|credential|key|secret|token)=)[^&\s]*/giu, "$1[redacted]").replace(/(?:https?|wss?):\/\/[^\s)]+/giu, (encodedUrl) => {
90029
+ const withoutSecrets = printable.replace(/\b(Bearer|Basic)\s+[^\s,;]+/giu, "$1 [redacted]").replace(/([?&](?:access_token|authorization|credential|key|secret|token)=)[^&\s]*/giu, "$1[redacted]").replace(/(?:https?|wss?):\/\/[^\s)]+/giu, (encodedUrl) => {
89970
90030
  try {
89971
90031
  return new URL(encodedUrl).origin;
89972
90032
  } catch {
@@ -89979,15 +90039,22 @@ function addFailureDetails(details, failure2) {
89979
90039
  let current = failure2;
89980
90040
  for (let depth = 0; depth < 3 && current instanceof Error; depth += 1) {
89981
90041
  const prefix = depth === 0 ? "failure" : `cause${depth.toString()}`;
89982
- details[`${prefix}Name`] = current.name;
90042
+ details[`${prefix}Name`] = sanitizeDiagnosticText(current.name);
89983
90043
  details[`${prefix}Message`] = sanitizeDiagnosticText(current.message);
89984
90044
  const code = Reflect.get(current, "code");
89985
90045
  if (typeof code === "string" || typeof code === "number") {
89986
- details[`${prefix}Code`] = String(code);
90046
+ details[`${prefix}Code`] = sanitizeDiagnosticText(String(code));
89987
90047
  }
89988
90048
  const statusCode = Reflect.get(current, "statusCode");
89989
90049
  if (typeof statusCode === "string" || typeof statusCode === "number") {
89990
- details[`${prefix}StatusCode`] = String(statusCode);
90050
+ details[`${prefix}StatusCode`] = sanitizeDiagnosticText(String(statusCode));
90051
+ }
90052
+ for (const field of ["syscall", "errno", "address", "port"]) {
90053
+ const value = Reflect.get(current, field);
90054
+ if (typeof value === "string" || typeof value === "number") {
90055
+ const key = depth === 0 ? field : `${prefix}${field.slice(0, 1).toUpperCase()}${field.slice(1)}`;
90056
+ details[key] = sanitizeDiagnosticText(String(value));
90057
+ }
89991
90058
  }
89992
90059
  const diagnosticDetails = Reflect.get(current, "diagnosticDetails");
89993
90060
  if (typeof diagnosticDetails === "object" && diagnosticDetails !== null) {
@@ -90000,6 +90067,11 @@ function addFailureDetails(details, failure2) {
90000
90067
  current = current.cause;
90001
90068
  }
90002
90069
  }
90070
+ function describeRelayFailure(failure2) {
90071
+ const details = {};
90072
+ addFailureDetails(details, failure2);
90073
+ return details;
90074
+ }
90003
90075
  var RelayConnectionDiagnostics = class {
90004
90076
  #lastSkippedLogAt = Number.NEGATIVE_INFINITY;
90005
90077
  #skippedCount = 0;
@@ -90053,6 +90125,16 @@ var RelayConnectionDiagnostics = class {
90053
90125
  addFailureDetails(details, failure2);
90054
90126
  this.#record("relay_connection_failed", details, true);
90055
90127
  };
90128
+ transportFailed = (connectionEpoch, failure2, source) => {
90129
+ const details = {
90130
+ connectionEpoch: connectionEpoch.toString(),
90131
+ relayOrigin: this.#relayOrigin,
90132
+ source,
90133
+ ...this.#route
90134
+ };
90135
+ addFailureDetails(details, failure2);
90136
+ this.#record("relay_transport_failed", details, true);
90137
+ };
90056
90138
  connectionOpened = (connectionEpoch) => {
90057
90139
  this.#record(
90058
90140
  "relay_connection_opened",
@@ -91270,15 +91352,6 @@ var sessionCancelBeforeStartCommand = {
91270
91352
  );
91271
91353
  return;
91272
91354
  }
91273
- if (turn.snapshot() !== null) {
91274
- reportOperationFailure(
91275
- socket,
91276
- message.commandId,
91277
- message.sessionId,
91278
- new SessionError("turn_already_started", "The command already started")
91279
- );
91280
- return;
91281
- }
91282
91355
  turn.requestCancellation();
91283
91356
  }
91284
91357
  };
@@ -92412,18 +92485,52 @@ var RelayConnectionError = class extends Error {
92412
92485
  this.name = "RelayConnectionError";
92413
92486
  }
92414
92487
  };
92415
- function connectRelay(url2, signal) {
92488
+ function connectRelay(url2, signal, transportFailed = () => void 0) {
92416
92489
  signal.throwIfAborted();
92417
92490
  return new Promise((resolve19, reject2) => {
92418
92491
  let releaseTransport = () => void 0;
92492
+ let removeTransportObserver = () => void 0;
92493
+ let released = false;
92494
+ const observeFailure = (failure2, source) => {
92495
+ if (!released && !signal.aborted) {
92496
+ transportFailed(failure2, source);
92497
+ }
92498
+ };
92499
+ const observeHandshake = (statusCode, expectedStatus) => {
92500
+ if (statusCode !== expectedStatus) {
92501
+ observeFailure(
92502
+ Object.assign(new Error("Relay rejected the WebSocket handshake"), {
92503
+ code: "relay_handshake_rejected",
92504
+ statusCode
92505
+ }),
92506
+ "handshake"
92507
+ );
92508
+ }
92509
+ };
92419
92510
  const dispatcher = environmentProxyDispatcher.compose((dispatch) => (options, handler) => {
92420
92511
  const trackedHandler = Object.create(handler);
92421
92512
  trackedHandler.onRequestStart = (controller, context) => {
92422
92513
  releaseTransport = (reason) => controller.abort(reason);
92423
92514
  handler.onRequestStart?.(controller, context);
92424
92515
  };
92516
+ trackedHandler.onResponseError = (controller, failure2) => {
92517
+ observeFailure(failure2, "request");
92518
+ handler.onResponseError?.(controller, failure2);
92519
+ };
92520
+ trackedHandler.onResponseStart = (controller, statusCode, responseHeaders, statusMessage) => {
92521
+ observeHandshake(statusCode, 101);
92522
+ handler.onResponseStart?.(controller, statusCode, responseHeaders, statusMessage);
92523
+ };
92425
92524
  trackedHandler.onRequestUpgrade = (controller, statusCode, responseHeaders, transport) => {
92525
+ observeHandshake(statusCode, Reflect.get(transport, "session") == null ? 101 : 200);
92426
92526
  releaseTransport = (reason) => transport.destroy(reason);
92527
+ const onTransportError = (failure2) => observeFailure(failure2, "socket");
92528
+ removeTransportObserver = () => {
92529
+ transport.off("error", onTransportError);
92530
+ transport.off("close", removeTransportObserver);
92531
+ };
92532
+ transport.on("error", onTransportError);
92533
+ transport.once("close", removeTransportObserver);
92427
92534
  return handler.onRequestUpgrade?.(controller, statusCode, responseHeaders, transport);
92428
92535
  };
92429
92536
  return dispatch(options, trackedHandler);
@@ -92436,12 +92543,12 @@ function connectRelay(url2, signal) {
92436
92543
  headers
92437
92544
  });
92438
92545
  socket.binaryType = "arraybuffer";
92439
- let released = false;
92440
92546
  const release = (reason) => {
92441
92547
  if (released) {
92442
92548
  return;
92443
92549
  }
92444
92550
  released = true;
92551
+ removeTransportObserver();
92445
92552
  releaseTransport(reason);
92446
92553
  };
92447
92554
  let finished = false;
@@ -92651,7 +92758,9 @@ async function runRelayConnection({
92651
92758
  }) {
92652
92759
  const relayUrl = new URL(config2.relayUrl);
92653
92760
  relayUrl.searchParams.set("liveness", "1");
92654
- const relay = await connectRelay(relayUrl, signal);
92761
+ const relay = await connectRelay(relayUrl, signal, (failure2, source) => {
92762
+ diagnostics.transportFailed(connectionEpoch, failure2, source);
92763
+ });
92655
92764
  const { socket } = relay;
92656
92765
  diagnostics.connectionOpened(connectionEpoch);
92657
92766
  const connectionController = new AbortController();
@@ -93464,6 +93573,7 @@ export {
93464
93573
  validatePairingId,
93465
93574
  prepareRuntimeConnection,
93466
93575
  RuntimeTurnActivity,
93576
+ describeRelayFailure,
93467
93577
  refreshAgentCatalog,
93468
93578
  RuntimeRelayRevokedError,
93469
93579
  RuntimeLoop,
@@ -93479,4 +93589,4 @@ export {
93479
93589
  * MIT Licensed
93480
93590
  *)
93481
93591
  */
93482
- //# sourceMappingURL=chunk-KEI2PNYS.js.map
93592
+ //# sourceMappingURL=chunk-JYM22ZR6.js.map