@moxt-ai/mobius 0.0.300 → 0.0.302

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 (83) hide show
  1. package/dist/acp/harness/claude/endpoint.d.ts.map +1 -1
  2. package/dist/acp/harness/claude/endpoint.js +2 -0
  3. package/dist/acp/harness/claude/endpoint.js.map +1 -1
  4. package/dist/acp/harness/claude/parent-lifeline.d.ts +3 -0
  5. package/dist/acp/harness/claude/parent-lifeline.d.ts.map +1 -0
  6. package/dist/acp/harness/claude/parent-lifeline.js +73 -0
  7. package/dist/acp/harness/claude/parent-lifeline.js.map +1 -0
  8. package/dist/acp/harness/codex/agent.d.ts.map +1 -1
  9. package/dist/acp/harness/codex/agent.js +5 -1
  10. package/dist/acp/harness/codex/agent.js.map +1 -1
  11. package/dist/acp/harness/pi/endpoint.d.ts.map +1 -1
  12. package/dist/acp/harness/pi/endpoint.js +1 -0
  13. package/dist/acp/harness/pi/endpoint.js.map +1 -1
  14. package/dist/cli.js +595 -61
  15. package/dist/cli.js.map +4 -4
  16. package/dist/generated/acp-session-store-migrations.d.ts +3 -0
  17. package/dist/generated/acp-session-store-migrations.d.ts.map +1 -1
  18. package/dist/generated/acp-session-store-migrations.js +5 -1
  19. package/dist/generated/acp-session-store-migrations.js.map +1 -1
  20. package/dist/runtime/command/registry/prompt.d.ts.map +1 -1
  21. package/dist/runtime/command/registry/prompt.js +6 -0
  22. package/dist/runtime/command/registry/prompt.js.map +1 -1
  23. package/dist/runtime/engine.d.ts +1 -0
  24. package/dist/runtime/engine.d.ts.map +1 -1
  25. package/dist/runtime/engine.js +8 -0
  26. package/dist/runtime/engine.js.map +1 -1
  27. package/dist/runtime/run.d.ts +1 -0
  28. package/dist/runtime/run.d.ts.map +1 -1
  29. package/dist/runtime/run.js +3 -0
  30. package/dist/runtime/run.js.map +1 -1
  31. package/dist/runtime.js +560 -54
  32. package/dist/runtime.js.map +4 -4
  33. package/dist/schema/acp-session-store/execution-receipt.d.ts +136 -0
  34. package/dist/schema/acp-session-store/execution-receipt.d.ts.map +1 -0
  35. package/dist/schema/acp-session-store/execution-receipt.js +12 -0
  36. package/dist/schema/acp-session-store/execution-receipt.js.map +1 -0
  37. package/dist/schema/acp-session-store/index.d.ts +1 -0
  38. package/dist/schema/acp-session-store/index.d.ts.map +1 -1
  39. package/dist/schema/acp-session-store/index.js +1 -0
  40. package/dist/schema/acp-session-store/index.js.map +1 -1
  41. package/dist/session/api/session-api.d.ts +4 -0
  42. package/dist/session/api/session-api.d.ts.map +1 -1
  43. package/dist/session/api/session-api.js.map +1 -1
  44. package/dist/session/api/session-layer.d.ts +2 -0
  45. package/dist/session/api/session-layer.d.ts.map +1 -1
  46. package/dist/session/api/session-layer.js +25 -4
  47. package/dist/session/api/session-layer.js.map +1 -1
  48. package/dist/session/history/session-event-store.d.ts +7 -4
  49. package/dist/session/history/session-event-store.d.ts.map +1 -1
  50. package/dist/session/history/session-event-store.js +13 -7
  51. package/dist/session/history/session-event-store.js.map +1 -1
  52. package/dist/session/history/session-history.d.ts +1 -4
  53. package/dist/session/history/session-history.d.ts.map +1 -1
  54. package/dist/session/history/session-history.js +1 -4
  55. package/dist/session/history/session-history.js.map +1 -1
  56. package/dist/session/live/agent-session-restore.d.ts +1 -0
  57. package/dist/session/live/agent-session-restore.d.ts.map +1 -1
  58. package/dist/session/live/agent-session.d.ts +2 -0
  59. package/dist/session/live/agent-session.d.ts.map +1 -1
  60. package/dist/session/live/agent-session.js +15 -4
  61. package/dist/session/live/agent-session.js.map +1 -1
  62. package/dist/session/live/session-restore.d.ts.map +1 -1
  63. package/dist/session/live/session-restore.js +37 -0
  64. package/dist/session/live/session-restore.js.map +1 -1
  65. package/dist/session/manager/session-manager.d.ts.map +1 -1
  66. package/dist/session/manager/session-manager.js +11 -3
  67. package/dist/session/manager/session-manager.js.map +1 -1
  68. package/dist/session/prompt/execute-prompt.d.ts.map +1 -1
  69. package/dist/session/prompt/execute-prompt.js +6 -1
  70. package/dist/session/prompt/execute-prompt.js.map +1 -1
  71. package/dist/session/prompt/prompt-lifecycle.d.ts +1 -0
  72. package/dist/session/prompt/prompt-lifecycle.d.ts.map +1 -1
  73. package/dist/session/prompt/prompt-lifecycle.js +9 -1
  74. package/dist/session/prompt/prompt-lifecycle.js.map +1 -1
  75. package/dist/session/turn/execution-receipts.d.ts +23 -2
  76. package/dist/session/turn/execution-receipts.d.ts.map +1 -1
  77. package/dist/session/turn/execution-receipts.js +161 -10
  78. package/dist/session/turn/execution-receipts.js.map +1 -1
  79. package/dist/storage/session/execution-receipt-table.d.ts +45 -0
  80. package/dist/storage/session/execution-receipt-table.d.ts.map +1 -0
  81. package/dist/storage/session/execution-receipt-table.js +64 -0
  82. package/dist/storage/session/execution-receipt-table.js.map +1 -0
  83. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2086,16 +2086,28 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.300",
2089
+ version: "0.0.302",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
2093
2093
  mobius: "dist/cli.js"
2094
2094
  },
2095
2095
  exports: {
2096
- "./runtime": "./src/runtime.ts",
2097
- "./process": "./src/util/process/executable.ts",
2098
- "./filesystem": "./src/util/filesystem/private-path.ts"
2096
+ "./runtime": {
2097
+ "mobius-source": "./src/runtime.ts",
2098
+ types: "./dist/runtime.d.ts",
2099
+ default: "./dist/runtime.js"
2100
+ },
2101
+ "./process": {
2102
+ "mobius-source": "./src/util/process/executable.ts",
2103
+ types: "./dist/util/process/executable.d.ts",
2104
+ default: "./dist/util/process/executable.js"
2105
+ },
2106
+ "./filesystem": {
2107
+ "mobius-source": "./src/util/filesystem/private-path.ts",
2108
+ types: "./dist/util/filesystem/private-path.d.ts",
2109
+ default: "./dist/util/filesystem/private-path.js"
2110
+ }
2099
2111
  },
2100
2112
  files: [
2101
2113
  "dist"
@@ -5593,6 +5605,84 @@ var init_commander = __esm({
5593
5605
  }
5594
5606
  });
5595
5607
 
5608
+ // src/acp/harness/claude/parent-lifeline.ts
5609
+ import { spawn } from "node:child_process";
5610
+ import { Duplex } from "node:stream";
5611
+ function spawnClaudeWithParentLifeline(options) {
5612
+ options.signal.throwIfAborted();
5613
+ const child = spawn(process.execPath, ["-e", supervisor, "--", options.command, ...options.args], {
5614
+ cwd: options.cwd,
5615
+ env: options.env,
5616
+ stdio: ["pipe", "pipe", "pipe", "pipe"],
5617
+ windowsHide: true
5618
+ });
5619
+ const lifeline = child.stdio[3];
5620
+ if (child.stdin === null || child.stdout === null || child.stderr === null || !(lifeline instanceof Duplex)) {
5621
+ child.kill("SIGKILL");
5622
+ throw new Error("The Claude process supervisor has no parent lifeline");
5623
+ }
5624
+ let termination = "running";
5625
+ const stop = () => {
5626
+ termination = "requested";
5627
+ lifeline.end();
5628
+ return true;
5629
+ };
5630
+ options.signal.addEventListener("abort", stop, { once: true });
5631
+ if (options.signal.aborted) {
5632
+ stop();
5633
+ }
5634
+ child.once("close", () => options.signal.removeEventListener("abort", stop));
5635
+ child.stderr.pipe(process.stderr, { end: false });
5636
+ return {
5637
+ stdin: child.stdin,
5638
+ stdout: child.stdout,
5639
+ get killed() {
5640
+ return termination === "requested";
5641
+ },
5642
+ get exitCode() {
5643
+ return child.exitCode;
5644
+ },
5645
+ get signalCode() {
5646
+ return child.signalCode;
5647
+ },
5648
+ kill: stop,
5649
+ on: child.on.bind(child),
5650
+ once: child.once.bind(child),
5651
+ off: child.off.bind(child)
5652
+ };
5653
+ }
5654
+ var supervisor;
5655
+ var init_parent_lifeline = __esm({
5656
+ "src/acp/harness/claude/parent-lifeline.ts"() {
5657
+ "use strict";
5658
+ supervisor = `
5659
+ const { spawn, spawnSync } = require("node:child_process");
5660
+ const { Socket } = require("node:net");
5661
+ const [command, ...args] = process.argv.slice(1);
5662
+ const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"], detached: process.platform !== "win32", windowsHide: true });
5663
+ const lifeline = new Socket({ fd: 3, readable: true, writable: false });
5664
+ let exited = false;
5665
+ function terminate() {
5666
+ if (exited || child.pid === undefined) return;
5667
+ if (process.platform === "win32") {
5668
+ spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { timeout: 5000, windowsHide: true, stdio: "ignore" });
5669
+ } else {
5670
+ try { process.kill(-child.pid, "SIGKILL"); }
5671
+ catch (error) { if (error.code !== "ESRCH") throw error; }
5672
+ }
5673
+ }
5674
+ lifeline.on("end", terminate).on("error", terminate).resume();
5675
+ process.on("SIGTERM", terminate).on("SIGINT", terminate);
5676
+ process.stdin.pipe(child.stdin);
5677
+ child.stdin.on("error", () => {});
5678
+ child.stdout.pipe(process.stdout);
5679
+ child.stderr.pipe(process.stderr);
5680
+ child.once("error", (error) => { process.stderr.write(error.message); process.exitCode = 1; lifeline.destroy(); process.stdin.destroy(); });
5681
+ child.once("close", (code) => { exited = true; process.exitCode = code ?? 1; lifeline.destroy(); process.stdin.destroy(); });
5682
+ `;
5683
+ }
5684
+ });
5685
+
5596
5686
  // ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.3.257_@anthropic-ai+sdk@0.122.0_zod@4.6.5__@modelconte_b0b90ed00d211c5955785f7de7f8dbf4/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
5597
5687
  import { createRequire as $ne } from "node:module";
5598
5688
  import * as xr from "node:fs/promises";
@@ -66545,7 +66635,7 @@ async function runPromptWithCancellation(agent, params, signal) {
66545
66635
  function createClaudeAcpApp(options = {}) {
66546
66636
  let agent = null;
66547
66637
  const app = acpAgent({ name: "claude-code-acp" }).onConnect((connection) => {
66548
- agent = new ClaudeAcpAgent(new ClientConnection(connection.client, options.onSessionUpdate), options.logger, options.environment);
66638
+ agent = new ClaudeAcpAgent(new ClientConnection(connection.client, options.onSessionUpdate), options.logger, options.environment, options.spawnClaudeCodeProcess);
66549
66639
  options.onConnect?.(connection);
66550
66640
  }).onRequest(methods.agent.initialize, (ctx) => requiredAgent(agent).initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => requiredAgent(agent).newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => requiredAgent(agent).loadSession(ctx.params, ctx.signal)).onRequest(methods.agent.session.fork, (ctx) => requiredAgent(agent).unstable_forkSession(ctx.params, ctx.signal)).onRequest(methods.agent.session.list, (ctx) => requiredAgent(agent).listSessions(ctx.params, ctx.signal)).onRequest(methods.agent.session.delete, (ctx) => requiredAgent(agent).deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => requiredAgent(agent).resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => requiredAgent(agent).closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => requiredAgent(agent).setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => requiredAgent(agent).setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => requiredAgent(agent).authenticate(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => requiredAgent(agent).unstable_listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => requiredAgent(agent).unstable_setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => requiredAgent(agent).unstable_disableProvider(ctx.params)).onRequest(methods.agent.logout, (ctx) => requiredAgent(agent).logout(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => runPromptWithCancellation(requiredAgent(agent), ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => requiredAgent(agent).cancel(ctx.params)).onRequest(STEER_METHOD, { parse: parseSteerRequest }, (ctx) => requiredAgent(agent).steer(ctx.params)).onRequest(RENAME_METHOD, { parse: parseRenameRequest }, (ctx) => requiredAgent(agent).renameSession(ctx.params)).onRequest(GOAL_CONTROL_METHOD, { parse: parseGoalRequest }, (ctx) => requiredAgent(agent).goal(ctx.params));
66551
66641
  return { agent: () => agent, app };
@@ -66741,6 +66831,7 @@ var init_acp_agent = __esm({
66741
66831
  };
66742
66832
  mcpAuthentications = /* @__PURE__ */ new WeakMap();
66743
66833
  ClaudeAcpAgent = class {
66834
+ spawnClaudeCodeProcess;
66744
66835
  sessions;
66745
66836
  client;
66746
66837
  clientCapabilities;
@@ -66757,7 +66848,8 @@ var init_acp_agent = __esm({
66757
66848
  * return "cancelled". See {@link DEFAULT_FORCE_CANCEL_GRACE_MS}. Mutable so
66758
66849
  * tests can shrink it. */
66759
66850
  forceCancelGraceMs = DEFAULT_FORCE_CANCEL_GRACE_MS;
66760
- constructor(client2, logger, environment = process.env) {
66851
+ constructor(client2, logger, environment = process.env, spawnClaudeCodeProcess) {
66852
+ this.spawnClaudeCodeProcess = spawnClaudeCodeProcess;
66761
66853
  this.sessions = {};
66762
66854
  this.client = client2;
66763
66855
  this.logger = logger ?? console;
@@ -69334,6 +69426,7 @@ ${message.api_refusal_explanation}` : "";
69334
69426
  supportedDialogKinds: [REFUSAL_FALLBACK_DIALOG_KIND]
69335
69427
  } : {},
69336
69428
  pathToClaudeCodeExecutable: this.environment.CLAUDE_CODE_EXECUTABLE ?? await claudeCliPath(),
69429
+ ...this.spawnClaudeCodeProcess === void 0 ? {} : { spawnClaudeCodeProcess: this.spawnClaudeCodeProcess },
69337
69430
  extraArgs: {
69338
69431
  ...userProvidedOptions?.extraArgs,
69339
69432
  "replay-user-messages": ""
@@ -69609,6 +69702,7 @@ var ClaudeAcpEndpoint;
69609
69702
  var init_endpoint = __esm({
69610
69703
  "src/acp/harness/claude/endpoint.ts"() {
69611
69704
  "use strict";
69705
+ init_parent_lifeline();
69612
69706
  init_lib();
69613
69707
  ClaudeAcpEndpoint = class {
69614
69708
  #agent;
@@ -69622,6 +69716,7 @@ var init_endpoint = __esm({
69622
69716
  this.terminated = termination.promise;
69623
69717
  this.#resolveTermination = termination.resolve;
69624
69718
  const claude = createClaudeAcpApp({
69719
+ spawnClaudeCodeProcess: spawnClaudeWithParentLifeline,
69625
69720
  environment: Object.freeze({
69626
69721
  ...process.env,
69627
69722
  ...options.environment,
@@ -70256,7 +70351,7 @@ var init_platform = __esm({
70256
70351
  });
70257
70352
 
70258
70353
  // src/util/process/executable.ts
70259
- import { spawn as spawn2 } from "node:child_process";
70354
+ import { spawn as spawn3 } from "node:child_process";
70260
70355
  import { stat as stat4 } from "node:fs/promises";
70261
70356
  import { join as join12, resolve as resolve8 } from "node:path";
70262
70357
  async function resolveExecutablePath(requestedPath2, platform2 = process.platform) {
@@ -70422,7 +70517,7 @@ async function runBoundedProcess(options) {
70422
70517
  options.signal.throwIfAborted();
70423
70518
  const outputLimitBytes = options.outputLimitBytes ?? DEFAULT_OUTPUT_LIMIT_BYTES;
70424
70519
  const launch = executableLaunch2(options.command, options.arguments);
70425
- const child = spawn2(launch.command, [...launch.arguments], {
70520
+ const child = spawn3(launch.command, [...launch.arguments], {
70426
70521
  cwd: options.cwd,
70427
70522
  ...hostPlatform.spawnOptions,
70428
70523
  env: { ...options.environment },
@@ -71053,7 +71148,7 @@ var init_app_server_protocol = __esm({
71053
71148
  });
71054
71149
 
71055
71150
  // src/acp/harness/codex/app-server-client.ts
71056
- import { spawn as spawn3 } from "node:child_process";
71151
+ import { spawn as spawn4 } from "node:child_process";
71057
71152
  var INITIALIZE_TIMEOUT_MILLISECONDS, MESSAGE_OUTPUT_LIMIT_BYTES, CodexAppServerError, CodexAppServerClient;
71058
71153
  var init_app_server_client = __esm({
71059
71154
  "src/acp/harness/codex/app-server-client.ts"() {
@@ -71085,7 +71180,7 @@ var init_app_server_client = __esm({
71085
71180
  constructor(options) {
71086
71181
  this.#handlers = options.handlers;
71087
71182
  const launch = executableLaunch2(options.command, ["app-server"]);
71088
- this.#child = spawn3(launch.command, [...launch.arguments], {
71183
+ this.#child = spawn4(launch.command, [...launch.arguments], {
71089
71184
  cwd: options.cwd,
71090
71185
  ...platformSpawnOptions,
71091
71186
  env: { ...process.env, ...options.environment },
@@ -71468,12 +71563,12 @@ function presentToolItem(item) {
71468
71563
  };
71469
71564
  }
71470
71565
  if (item.type === "collabAgentToolCall") {
71471
- const spawn10 = item.tool === "spawnAgent";
71566
+ const spawn11 = item.tool === "spawnAgent";
71472
71567
  return {
71473
71568
  content: [],
71474
71569
  kind: "other",
71475
71570
  locations: [],
71476
- rawInput: spawn10 ? {
71571
+ rawInput: spawn11 ? {
71477
71572
  model: item.model,
71478
71573
  prompt: item.prompt,
71479
71574
  reasoningEffort: item.reasoningEffort,
@@ -71481,10 +71576,10 @@ function presentToolItem(item) {
71481
71576
  } : { receiverThreadIds: item.receiverThreadIds, senderThreadId: item.senderThreadId },
71482
71577
  rawOutput: {
71483
71578
  agentsStates: item.agentsStates,
71484
- ...spawn10 ? { receiverThreadIds: item.receiverThreadIds } : {}
71579
+ ...spawn11 ? { receiverThreadIds: item.receiverThreadIds } : {}
71485
71580
  },
71486
71581
  status: collaborationStatus(item.status),
71487
- title: spawn10 ? "Dispatch subagent" : "Wait for subagent"
71582
+ title: spawn11 ? "Dispatch subagent" : "Wait for subagent"
71488
71583
  };
71489
71584
  }
71490
71585
  if (item.type === "subAgentActivity" && item.kind === "started") {
@@ -73624,6 +73719,9 @@ function decodeSessionPromptCommand(encoded) {
73624
73719
  directoryId: readDirectoryIdentifier(value, "directoryId"),
73625
73720
  disposition,
73626
73721
  images,
73722
+ ...value["historyPolicy"] === void 0 ? {} : {
73723
+ historyPolicy: readHistoryPolicy(value)
73724
+ },
73627
73725
  kind: SESSION_PROMPT_KIND,
73628
73726
  prompt,
73629
73727
  resources,
@@ -73632,6 +73730,13 @@ function decodeSessionPromptCommand(encoded) {
73632
73730
  targetCommandId
73633
73731
  };
73634
73732
  }
73733
+ function readHistoryPolicy(value) {
73734
+ const field = value["historyPolicy"];
73735
+ if (field === SessionHistoryPolicy.Eager || field === SessionHistoryPolicy.ExecutionOnly) {
73736
+ return field;
73737
+ }
73738
+ throw new ProtocolMessageError("Invalid value field: historyPolicy");
73739
+ }
73635
73740
  function decodeSessionCancelCommand(encoded) {
73636
73741
  const value = parseJson(encoded);
73637
73742
  assertKind(value, SESSION_CANCEL_KIND);
@@ -73663,7 +73768,7 @@ function encodeSessionCancelCommand(message) {
73663
73768
  function encodeSessionPromptDispositionCommand(message) {
73664
73769
  return JSON.stringify(decodeSessionPromptDispositionCommand(JSON.stringify(message)));
73665
73770
  }
73666
- var SESSION_PROMPT_KIND, SESSION_PROMPT_DISPOSITION_KIND, SESSION_CANCEL_KIND, SessionPromptDisposition, MAX_PROMPT_LENGTH, MAX_PROMPT_ATTACHMENT_LENGTH, promptImageSchema, promptResourceSchema, decodePromptImagesValue, decodePromptResourcesValue;
73771
+ var SESSION_PROMPT_KIND, SESSION_PROMPT_DISPOSITION_KIND, SESSION_CANCEL_KIND, SessionPromptDisposition, SessionHistoryPolicy, MAX_PROMPT_LENGTH, MAX_PROMPT_ATTACHMENT_LENGTH, promptImageSchema, promptResourceSchema, decodePromptImagesValue, decodePromptResourcesValue;
73667
73772
  var init_commands = __esm({
73668
73773
  "../mobius-sdk/src/protocol/session/prompt/commands.ts"() {
73669
73774
  "use strict";
@@ -73679,6 +73784,10 @@ var init_commands = __esm({
73679
73784
  Reject: "reject",
73680
73785
  Steer: "steer"
73681
73786
  });
73787
+ SessionHistoryPolicy = Object.freeze({
73788
+ Eager: "eager",
73789
+ ExecutionOnly: "execution-only"
73790
+ });
73682
73791
  MAX_PROMPT_LENGTH = 1e5;
73683
73792
  MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
73684
73793
  promptImageSchema = external_exports.object({
@@ -75612,7 +75721,11 @@ var init_agent = __esm({
75612
75721
  const decoded = threadListResponseSchema.parse(
75613
75722
  await this.#appServer.request(
75614
75723
  "thread/list",
75615
- { cursor: context.params.cursor ?? null },
75724
+ {
75725
+ cursor: context.params.cursor ?? null,
75726
+ // Codex defaults to interactive sources and otherwise hides exec handoffs.
75727
+ sourceKinds: ["cli", "vscode", "exec", "appServer"]
75728
+ },
75616
75729
  AbortSignal.any([context.signal, AbortSignal.timeout(SESSION_LIST_TIMEOUT_MILLISECONDS2)])
75617
75730
  )
75618
75731
  );
@@ -75866,7 +75979,7 @@ var init_command2 = __esm({
75866
75979
  });
75867
75980
 
75868
75981
  // src/acp/harness/pi/upstream/dist/pi-rpc/process.js
75869
- import { spawn as spawn4 } from "node:child_process";
75982
+ import { spawn as spawn5 } from "node:child_process";
75870
75983
  import * as readline from "node:readline";
75871
75984
  function stripAnsi(s) {
75872
75985
  return s.replace(ANSI_ESCAPE_REGEX, "");
@@ -75970,7 +76083,7 @@ var init_process = __esm({
75970
76083
  args.push("--fork", params.origin.sessionPath);
75971
76084
  break;
75972
76085
  }
75973
- const child = spawn4(cmd, args, {
76086
+ const child = spawn5(cmd, args, {
75974
76087
  cwd: params.cwd,
75975
76088
  stdio: "pipe",
75976
76089
  env: params.environment,
@@ -79410,6 +79523,77 @@ ${JSON.stringify(stats, null, 2)}`;
79410
79523
  }, 0);
79411
79524
  return { sessionId: session.sessionId, configOptions, modes };
79412
79525
  }
79526
+ async resumeSession(params) {
79527
+ if (!isAbsolute11(params.cwd)) {
79528
+ throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
79529
+ }
79530
+ this.sessions.close(params.sessionId);
79531
+ this.lastSessionCwd = params.cwd;
79532
+ const stored = this.findStoredSession(params.sessionId);
79533
+ if (!stored) {
79534
+ throw RequestError7.invalidParams(`Unknown sessionId: ${params.sessionId}`);
79535
+ }
79536
+ const session = await this.restoreSession(params.sessionId, {
79537
+ cwd: params.cwd,
79538
+ mcpServers: params.mcpServers
79539
+ });
79540
+ let configuration;
79541
+ try {
79542
+ configuration = await getSessionConfiguration(session.proc);
79543
+ } catch (err) {
79544
+ this.sessions.close(session.sessionId);
79545
+ throw err;
79546
+ }
79547
+ const { configOptions, models, modes } = configuration;
79548
+ const enableSkillCommands = getEnableSkillCommands(params.cwd, this.environment);
79549
+ const fileCommands = loadSlashCommands(params.cwd, this.environment);
79550
+ this.sessions.closeAllExcept?.(session.sessionId);
79551
+ this.store.upsert({
79552
+ sessionId: params.sessionId,
79553
+ cwd: params.cwd,
79554
+ sessionFile: stored.sessionFile
79555
+ });
79556
+ const response = {
79557
+ configOptions,
79558
+ models,
79559
+ modes,
79560
+ _meta: {
79561
+ piAcp: {
79562
+ startupInfo: null
79563
+ }
79564
+ }
79565
+ };
79566
+ setTimeout(() => {
79567
+ void (async () => {
79568
+ await session.publishContextUsage();
79569
+ try {
79570
+ const pi2 = await session.proc.getCommands();
79571
+ const { commands } = toAvailableCommandsFromPiGetCommands(pi2, {
79572
+ enableSkillCommands,
79573
+ includeExtensionCommands: false
79574
+ });
79575
+ await this.conn.sessionUpdate({
79576
+ sessionId: session.sessionId,
79577
+ update: {
79578
+ sessionUpdate: "available_commands_update",
79579
+ availableCommands: mergeCommands(commands, builtinAvailableCommands())
79580
+ }
79581
+ });
79582
+ return;
79583
+ } catch {
79584
+ }
79585
+ await this.conn.sessionUpdate({
79586
+ sessionId: session.sessionId,
79587
+ update: {
79588
+ sessionUpdate: "available_commands_update",
79589
+ availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())
79590
+ }
79591
+ });
79592
+ })().catch(() => {
79593
+ });
79594
+ }, 0);
79595
+ return response;
79596
+ }
79413
79597
  async loadSession(params) {
79414
79598
  if (!isAbsolute11(params.cwd)) {
79415
79599
  throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
@@ -79689,6 +79873,9 @@ var init_endpoint2 = __esm({
79689
79873
  ).onRequest(
79690
79874
  methods5.agent.session.load,
79691
79875
  async (context) => await piAgentOrThrow(piAgent).loadSession(context.params)
79876
+ ).onRequest(
79877
+ methods5.agent.session.resume,
79878
+ async (context) => await piAgentOrThrow(piAgent).resumeSession(context.params)
79692
79879
  ).onRequest(
79693
79880
  methods5.agent.session.list,
79694
79881
  async (context) => await piAgentOrThrow(piAgent).listSessions(context.params)
@@ -80215,7 +80402,7 @@ var init_create_client = __esm({
80215
80402
  });
80216
80403
 
80217
80404
  // src/agent/discovery/acp-readiness-probe.ts
80218
- import { spawn as spawn5 } from "node:child_process";
80405
+ import { spawn as spawn6 } from "node:child_process";
80219
80406
  import {
80220
80407
  methods as methods8,
80221
80408
  ndJsonStream as ndJsonStream2,
@@ -80372,7 +80559,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
80372
80559
  }
80373
80560
  }
80374
80561
  const launch = executableLaunch2(agent.adapterPath, agent.arguments);
80375
- const child = spawn5(launch.command, [...launch.arguments], {
80562
+ const child = spawn6(launch.command, [...launch.arguments], {
80376
80563
  cwd: defaultWorkspace,
80377
80564
  ...platformSpawnOptions,
80378
80565
  env: { ...environment, ...agent.environment },
@@ -83043,7 +83230,7 @@ var init_worker_lifecycle_log = __esm({
83043
83230
  });
83044
83231
 
83045
83232
  // src/daemon/lifecycle/worker-process.ts
83046
- import { spawn as spawn6 } from "node:child_process";
83233
+ import { spawn as spawn7 } from "node:child_process";
83047
83234
  import { isAbsolute as isAbsolute13, resolve as resolve16 } from "node:path";
83048
83235
  function currentWorkerLaunch(version2) {
83049
83236
  const entry = process.argv[1];
@@ -83103,7 +83290,7 @@ var init_worker_process = __esm({
83103
83290
  constructor(launch, signal, environment) {
83104
83291
  signal.throwIfAborted();
83105
83292
  this.launch = launch;
83106
- this.#child = spawn6(launch.executable, [launch.entry, "__worker"], {
83293
+ this.#child = spawn7(launch.executable, [launch.entry, "__worker"], {
83107
83294
  env: environment,
83108
83295
  windowsHide: true,
83109
83296
  stdio: ["ignore", "pipe", "pipe", "ipc"]
@@ -83436,9 +83623,9 @@ var init_manager2 = __esm({
83436
83623
  });
83437
83624
 
83438
83625
  // src/daemon/lifecycle/manager-client.ts
83439
- import { spawn as spawn7 } from "node:child_process";
83626
+ import { spawn as spawn8 } from "node:child_process";
83440
83627
  async function spawnManager() {
83441
- const child = spawn7(process.execPath, [process.argv[1] ?? "", "__manager"], {
83628
+ const child = spawn8(process.execPath, [process.argv[1] ?? "", "__manager"], {
83442
83629
  detached: true,
83443
83630
  windowsHide: true,
83444
83631
  env: process.env,
@@ -83844,7 +84031,7 @@ var init_history_images = __esm({
83844
84031
  });
83845
84032
 
83846
84033
  // src/acp/native-history/codex/codex-history.ts
83847
- import { spawn as spawn8 } from "node:child_process";
84034
+ import { spawn as spawn9 } from "node:child_process";
83848
84035
  function bounded(value, maximum) {
83849
84036
  return value.slice(0, maximum);
83850
84037
  }
@@ -84220,7 +84407,7 @@ async function readCodexHistoryWithOptions(agent, cwd, nativeSessionId, signal,
84220
84407
  }
84221
84408
  signal.throwIfAborted();
84222
84409
  const launch = executableLaunch2(agent.agentIdentity.realPath, ["app-server"]);
84223
- const child = spawn8(launch.command, [...launch.arguments], {
84410
+ const child = spawn9(launch.command, [...launch.arguments], {
84224
84411
  cwd,
84225
84412
  env: { ...process.env, ...agent.environment },
84226
84413
  ...platformSpawnOptions,
@@ -90233,6 +90420,25 @@ var init_acp_session = __esm({
90233
90420
  }
90234
90421
  });
90235
90422
 
90423
+ // src/schema/acp-session-store/execution-receipt.ts
90424
+ var executionReceipt;
90425
+ var init_execution_receipt = __esm({
90426
+ "src/schema/acp-session-store/execution-receipt.ts"() {
90427
+ "use strict";
90428
+ init_sqlite_core();
90429
+ executionReceipt = sqliteTable("execution_receipt", {
90430
+ commandId: text("command_id").primaryKey(),
90431
+ sessionId: text("session_id").notNull(),
90432
+ commandHash: text("command_hash").notNull(),
90433
+ attemptId: text("attempt_id").notNull(),
90434
+ state: text("state").notNull(),
90435
+ started: integer2("started", { mode: "boolean" }).notNull(),
90436
+ outcome: text("outcome"),
90437
+ updatedAt: text("updated_at").notNull()
90438
+ });
90439
+ }
90440
+ });
90441
+
90236
90442
  // src/schema/acp-session-store/session-live-event-position-allocation.ts
90237
90443
  var sessionLiveEventPositionAllocation;
90238
90444
  var init_session_live_event_position_allocation = __esm({
@@ -90251,6 +90457,7 @@ var init_acp_session_store = __esm({
90251
90457
  "src/schema/acp-session-store/index.ts"() {
90252
90458
  "use strict";
90253
90459
  init_acp_session();
90460
+ init_execution_receipt();
90254
90461
  init_session_live_event_position_allocation();
90255
90462
  }
90256
90463
  });
@@ -90299,6 +90506,71 @@ var init_acp_session_table = __esm({
90299
90506
  }
90300
90507
  });
90301
90508
 
90509
+ // src/storage/session/execution-receipt-table.ts
90510
+ var receiptFields, receiptSchema, ExecutionReceiptTable;
90511
+ var init_execution_receipt_table = __esm({
90512
+ "src/storage/session/execution-receipt-table.ts"() {
90513
+ "use strict";
90514
+ init_drizzle_orm();
90515
+ init_zod();
90516
+ init_acp_session_store();
90517
+ receiptFields = external_exports.object({
90518
+ commandId: external_exports.string(),
90519
+ sessionId: external_exports.string(),
90520
+ commandHash: external_exports.string(),
90521
+ attemptId: external_exports.string(),
90522
+ updatedAt: external_exports.string()
90523
+ });
90524
+ receiptSchema = external_exports.discriminatedUnion("state", [
90525
+ receiptFields.extend({ state: external_exports.literal("dispatching"), started: external_exports.literal(false), outcome: external_exports.null() }),
90526
+ receiptFields.extend({ state: external_exports.literal("running"), started: external_exports.literal(true), outcome: external_exports.string().nullable() }),
90527
+ receiptFields.extend({
90528
+ state: external_exports.enum(["succeeded", "failed", "cancelled"]),
90529
+ started: external_exports.boolean(),
90530
+ outcome: external_exports.string().nullable()
90531
+ })
90532
+ ]).readonly();
90533
+ ExecutionReceiptTable = class {
90534
+ #database;
90535
+ constructor(database) {
90536
+ this.#database = database;
90537
+ }
90538
+ list = () => receiptSchema.array().parse(
90539
+ this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
90540
+ );
90541
+ save = (receipt) => {
90542
+ this.#database.transaction(() => {
90543
+ this.#database.orm.insert(executionReceipt).values(receipt).onConflictDoUpdate({ target: executionReceipt.commandId, set: receipt }).run();
90544
+ if (receipt.state === "dispatching" || receipt.state === "running") {
90545
+ return;
90546
+ }
90547
+ const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(
90548
+ and(
90549
+ eq2(executionReceipt.sessionId, receipt.sessionId),
90550
+ inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"])
90551
+ )
90552
+ ).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(1024).all();
90553
+ if (retained.length === 1024) {
90554
+ this.#database.orm.delete(executionReceipt).where(
90555
+ and(
90556
+ eq2(executionReceipt.sessionId, receipt.sessionId),
90557
+ inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"]),
90558
+ notInArray(
90559
+ executionReceipt.commandId,
90560
+ retained.map((row) => row.commandId)
90561
+ )
90562
+ )
90563
+ ).run();
90564
+ }
90565
+ });
90566
+ };
90567
+ remove = (commandId) => {
90568
+ this.#database.orm.delete(executionReceipt).where(eq2(executionReceipt.commandId, commandId)).run();
90569
+ };
90570
+ };
90571
+ }
90572
+ });
90573
+
90302
90574
  // src/storage/session/live-event-position-table.ts
90303
90575
  var allocationRowSchema, LiveEventPositionTable;
90304
90576
  var init_live_event_position_table = __esm({
@@ -90552,6 +90824,10 @@ var init_acp_session_store_migrations = __esm({
90552
90824
  {
90553
90825
  "name": "0006_live_event_position_allocation.sql",
90554
90826
  "sql": "CREATE TABLE `session_live_event_position_allocation` (\n `allocated_position` integer DEFAULT 10000 NOT NULL,\n `session_id` text PRIMARY KEY NOT NULL\n);\n"
90827
+ },
90828
+ {
90829
+ "name": "0007_busy_excalibur.sql",
90830
+ "sql": "CREATE TABLE `execution_receipt` (\n `command_id` text PRIMARY KEY NOT NULL,\n `session_id` text NOT NULL,\n `command_hash` text NOT NULL,\n `attempt_id` text NOT NULL,\n `state` text NOT NULL,\n `started` integer NOT NULL,\n `outcome` text,\n `updated_at` text NOT NULL\n);\n"
90555
90831
  }
90556
90832
  ];
90557
90833
  }
@@ -91170,12 +91446,12 @@ var init_session_event_id_allocator = __esm({
91170
91446
 
91171
91447
  // src/session/history/session-event-store.ts
91172
91448
  import { randomUUID as randomUUID12 } from "node:crypto";
91173
- function liveEvent(sessionId, sessionGenerationId, eventId, position, event) {
91449
+ function liveEvent(sessionId, sessionGenerationId, eventId, position, event, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) {
91174
91450
  return {
91175
91451
  eventId,
91176
91452
  ...event,
91177
91453
  position: position.toString(),
91178
- recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
91454
+ recordedAt,
91179
91455
  sessionGenerationId,
91180
91456
  sessionId
91181
91457
  };
@@ -91336,7 +91612,7 @@ var init_session_event_store = __esm({
91336
91612
  }
91337
91613
  return resolved;
91338
91614
  };
91339
- append = (sessionId, event) => {
91615
+ append = (sessionId, event, recordedAt) => {
91340
91616
  const session = this.#session(sessionId);
91341
91617
  const allocatedPosition = this.#allocatedPositionBySession.get(sessionId) ?? 9999;
91342
91618
  if (allocatedPosition === Number.MAX_SAFE_INTEGER) {
@@ -91349,7 +91625,8 @@ var init_session_event_store = __esm({
91349
91625
  session.sessionGenerationId,
91350
91626
  this.#eventIds.allocate(sessionId, session.sessionGenerationId),
91351
91627
  position,
91352
- event
91628
+ event,
91629
+ recordedAt
91353
91630
  );
91354
91631
  session.apply(recorded, this.#resolver(session));
91355
91632
  return recorded;
@@ -91390,12 +91667,14 @@ var init_session_event_store = __esm({
91390
91667
  };
91391
91668
  };
91392
91669
  CachedSessionEventStore = class {
91670
+ #terminalOutcomes;
91393
91671
  #cacheTable;
91394
91672
  #eventIds;
91395
91673
  #liveEventPositions;
91396
91674
  #sessions = /* @__PURE__ */ new Map();
91397
91675
  #flushSchedule = { kind: "idle" };
91398
- constructor(cacheTable, liveEventPositions, eventIds = new InMemorySessionEventIdAllocator()) {
91676
+ constructor(cacheTable, liveEventPositions, eventIds = new InMemorySessionEventIdAllocator(), terminalOutcomes = () => []) {
91677
+ this.#terminalOutcomes = terminalOutcomes;
91399
91678
  this.#eventIds = eventIds;
91400
91679
  this.#liveEventPositions = liveEventPositions;
91401
91680
  this.#cacheTable = cacheTable;
@@ -91428,7 +91707,7 @@ var init_session_event_store = __esm({
91428
91707
  }
91429
91708
  return resolved;
91430
91709
  };
91431
- append = (sessionId, event) => {
91710
+ append = (sessionId, event, recordedAt) => {
91432
91711
  if (this.#flushSchedule.kind === "closed") {
91433
91712
  throw new Error("The V2 Session event store is closed");
91434
91713
  }
@@ -91439,7 +91718,8 @@ var init_session_event_store = __esm({
91439
91718
  session.sessionGenerationId,
91440
91719
  this.#eventIds.allocate(sessionId, session.sessionGenerationId),
91441
91720
  position,
91442
- event
91721
+ event,
91722
+ recordedAt
91443
91723
  );
91444
91724
  session.apply(recorded, this.#resolver(sessionId, session));
91445
91725
  this.#sessions.set(sessionId, session);
@@ -91528,6 +91808,9 @@ var init_session_event_store = __esm({
91528
91808
  this.#deletePersisted(sessionId, previous?.sessionGenerationId);
91529
91809
  const sessionGenerationId = randomUUID12();
91530
91810
  this.#sessions.set(sessionId, new SessionEvents(sessionGenerationId));
91811
+ for (const { event, recordedAt } of this.#terminalOutcomes(sessionId)) {
91812
+ this.append(sessionId, event, recordedAt);
91813
+ }
91531
91814
  };
91532
91815
  materializedEventCount = (sessionId) => this.#sessions.get(sessionId)?.materializedCount ?? 0;
91533
91816
  close = () => {
@@ -91648,7 +91931,7 @@ var init_prompt_content = __esm({
91648
91931
  });
91649
91932
 
91650
91933
  // src/acp/connection/agent-connection.ts
91651
- import { spawn as spawn9 } from "node:child_process";
91934
+ import { spawn as spawn10 } from "node:child_process";
91652
91935
  import { ndJsonStream as ndJsonStream3, RequestError as RequestError9 } from "@agentclientprotocol/sdk";
91653
91936
  function requestErrorMessage(error62) {
91654
91937
  const fallback = truncate2(error62.message, 500);
@@ -91767,7 +92050,7 @@ var init_agent_connection = __esm({
91767
92050
  return;
91768
92051
  }
91769
92052
  const launch = executableLaunch2(agent.adapterPath, agent.arguments);
91770
- const child = spawn9(launch.command, [...launch.arguments], {
92053
+ const child = spawn10(launch.command, [...launch.arguments], {
91771
92054
  cwd,
91772
92055
  ...platformSpawnOptions,
91773
92056
  env: { ...process.env, ...agent.environment },
@@ -93121,6 +93404,19 @@ var init_agent_turn = __esm({
93121
93404
 
93122
93405
  // src/session/live/session-restore.ts
93123
93406
  import { methods as methods10 } from "@agentclientprotocol/sdk";
93407
+ function hasMethodNotFoundCode(cause) {
93408
+ const visited = /* @__PURE__ */ new Set();
93409
+ let current = cause;
93410
+ while ((current instanceof Error || typeof current === "object" && current !== null) && !visited.has(current)) {
93411
+ visited.add(current);
93412
+ const code = Reflect.get(current, "code");
93413
+ if (code === -32601 || code === "METHOD_NOT_FOUND" || code === "method_not_found") {
93414
+ return true;
93415
+ }
93416
+ current = current instanceof Error ? current.cause : void 0;
93417
+ }
93418
+ return false;
93419
+ }
93124
93420
  async function restoreSession(session, signal, recovery, origin) {
93125
93421
  if (origin !== void 0) {
93126
93422
  session.setSessionTitle(origin.title);
@@ -93187,6 +93483,9 @@ async function restoreSession(session, signal, recovery, origin) {
93187
93483
  }
93188
93484
  session.setPrompted(true);
93189
93485
  session.setRestored(true);
93486
+ if (recovery.kind === "execution-only") {
93487
+ session.startExecutionOnlyCapture();
93488
+ }
93190
93489
  lifecycleResponse2 = forked;
93191
93490
  } else if (stored instanceof FoundStoredSession && stored.session.agentId === session.agentId && stored.session.cwd === session.cwd && arraysEqual(stored.session.additionalDirectories, session.additionalDirectories)) {
93192
93491
  session.selectNativeSession(stored.session.nativeSessionId);
@@ -93205,6 +93504,37 @@ async function restoreSession(session, signal, recovery, origin) {
93205
93504
  "session-load",
93206
93505
  async () => (await session.loadSession(signal, "ACP agent exited while loading a session")).response
93207
93506
  );
93507
+ } else if (recovery.kind === "execution-only") {
93508
+ try {
93509
+ lifecycleResponse2 = await session.metrics.measure(
93510
+ "session-resume",
93511
+ async () => await session.race(
93512
+ session.agentRequest(
93513
+ methods10.agent.session.resume,
93514
+ {
93515
+ additionalDirectories: [...session.additionalDirectories],
93516
+ cwd: session.cwd,
93517
+ mcpServers: [],
93518
+ sessionId: session.nativeSessionId()
93519
+ },
93520
+ { cancellationSignal: signal }
93521
+ ),
93522
+ "ACP agent exited while resuming a session",
93523
+ signal
93524
+ )
93525
+ );
93526
+ } catch (cause) {
93527
+ signal.throwIfAborted();
93528
+ if (cause instanceof AcpExecutionError && !hasMethodNotFoundCode(cause)) {
93529
+ throw cause;
93530
+ }
93531
+ throw new AcpExecutionError(
93532
+ "This Agent cannot continue a persisted session without replaying native history",
93533
+ { cause },
93534
+ "execution_only_unsupported"
93535
+ );
93536
+ }
93537
+ session.startExecutionOnlyCapture();
93208
93538
  } else if (session.capabilities.resumeSession) {
93209
93539
  lifecycleResponse2 = await session.metrics.measure(
93210
93540
  "session-resume",
@@ -93264,6 +93594,9 @@ async function restoreSession(session, signal, recovery, origin) {
93264
93594
  );
93265
93595
  session.selectNativeSession(created.sessionId);
93266
93596
  session.setNativeHistoryOwnership({ kind: "fresh-session" });
93597
+ if (recovery.kind === "execution-only") {
93598
+ session.startExecutionOnlyCapture();
93599
+ }
93267
93600
  lifecycleResponse2 = created;
93268
93601
  }
93269
93602
  session.restrictSessionCapabilities(lifecycleResponse2);
@@ -93579,6 +93912,16 @@ var init_agent_session = __esm({
93579
93912
  }
93580
93913
  await this.#completedHistory(signal, "ACP agent exited while loading history");
93581
93914
  };
93915
+ /** Starts live event capture without asking the native Agent to replay its persisted history. */
93916
+ startExecutionOnlyCapture = () => {
93917
+ if (this.#sessionLoad.kind !== "not-requested") {
93918
+ return;
93919
+ }
93920
+ this.#sessionLoad = {
93921
+ history: new HistoryReplayCapture(this.#store.events, this.#mobiusSessionId),
93922
+ kind: "execution-only"
93923
+ };
93924
+ };
93582
93925
  loadHistoryEvents = async (eventLimit, cursor, signal) => {
93583
93926
  if (!this.#capabilities.loadSession) {
93584
93927
  throw new AcpExecutionError(
@@ -93829,7 +94172,7 @@ var init_agent_session = __esm({
93829
94172
  response: {}
93830
94173
  };
93831
94174
  }
93832
- if (this.#capabilities.loadSession) {
94175
+ if (this.#capabilities.loadSession && this.#sessionLoad.kind !== "execution-only") {
93833
94176
  await this.#completedHistory(options.signal, "ACP agent exited while loading history before a prompt");
93834
94177
  }
93835
94178
  const prompt = this.buildPrompt(options);
@@ -94028,14 +94371,14 @@ var init_agent_session = __esm({
94028
94371
  onElicitationComplete = (notification) => this.#interactions.onElicitationComplete(notification);
94029
94372
  onUpdate = (notification) => this.#updates.receive(notification);
94030
94373
  recordControlEvent = async (event) => {
94031
- if (this.#sessionLoad.kind !== "loaded") {
94374
+ if (this.#sessionLoad.kind !== "loaded" && this.#sessionLoad.kind !== "execution-only") {
94032
94375
  return false;
94033
94376
  }
94034
94377
  await this.recordLifecycleEvent(event);
94035
94378
  return true;
94036
94379
  };
94037
94380
  recordLifecycleEvent = async (event) => {
94038
- if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded") {
94381
+ if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded" && this.#sessionLoad.kind !== "execution-only") {
94039
94382
  return;
94040
94383
  }
94041
94384
  const liveEvent2 = this.#sessionLoad.history.recordLifecycle(event);
@@ -94056,7 +94399,7 @@ var init_agent_session = __esm({
94056
94399
  const rawUpdate = decodeAcpSessionUpdate(JSON.stringify(externalized.event));
94057
94400
  if (this.#sessionLoad.kind === "capturing") {
94058
94401
  await this.#sessionLoad.history.record(update, rawUpdate);
94059
- } else if (this.#sessionLoad.kind === "loaded") {
94402
+ } else if (this.#sessionLoad.kind === "loaded" || this.#sessionLoad.kind === "execution-only") {
94060
94403
  const onSessionEvent = this.#getObserver().onSessionEvent;
94061
94404
  await this.#sessionLoad.history.record(update, rawUpdate, async (liveEvent2) => {
94062
94405
  await onSessionEvent?.(liveEvent2);
@@ -95043,13 +95386,14 @@ var init_session_manager = __esm({
95043
95386
  }
95044
95387
  async #replaceExecutionPreparation(existing, options) {
95045
95388
  const desiredConfigOptions = existing.prepared().configOptions;
95389
+ const recovery = options.recovery ?? { kind: "interactive-only" };
95046
95390
  return await this.#executionProcesses.prepare(options.sessionId, async () => {
95047
95391
  await this.#retireSessionProcess(options.sessionId, existing, async () => await existing.close());
95048
95392
  const runtime = await this.#startRetainedSessionProcess(
95049
95393
  options,
95050
95394
  async () => await AgentSession.start(
95051
95395
  options,
95052
- { kind: "interactive-only" },
95396
+ recovery,
95053
95397
  () => this.#observer,
95054
95398
  this.#store,
95055
95399
  unmeasuredOperationMetrics,
@@ -95227,6 +95571,7 @@ var init_session_manager = __esm({
95227
95571
  });
95228
95572
  });
95229
95573
  prepareExecutionSession = async (options) => this.#operations.run(options, async (options2) => {
95574
+ const recovery = options2.recovery ?? { kind: "interactive-only" };
95230
95575
  this.#assertOpen(options2.sessionId);
95231
95576
  const pending = this.#executionProcesses.pending(options2.sessionId);
95232
95577
  if (pending !== void 0) {
@@ -95235,7 +95580,7 @@ var init_session_manager = __esm({
95235
95580
  }
95236
95581
  const existing = this.#executionProcesses.get(options2.sessionId);
95237
95582
  if (existing === void 0) {
95238
- return (await this.#startPreparation(options2, { kind: "interactive-only" })).prepared();
95583
+ return (await this.#startPreparation(options2, recovery)).prepared();
95239
95584
  }
95240
95585
  if (!existing.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
95241
95586
  throw new AcpExecutionError(
@@ -95245,6 +95590,9 @@ var init_session_manager = __esm({
95245
95590
  );
95246
95591
  }
95247
95592
  if (existing.usesEnvironment(options2.agent.environment)) {
95593
+ if (recovery.kind === "execution-only") {
95594
+ existing.startExecutionOnlyCapture();
95595
+ }
95248
95596
  this.#executionProcesses.touch(options2.sessionId, existing);
95249
95597
  return existing.prepared();
95250
95598
  }
@@ -95539,10 +95887,13 @@ var init_session_manager = __esm({
95539
95887
  "session_identity_mismatch"
95540
95888
  );
95541
95889
  }
95890
+ if (options2.recovery?.kind === "execution-only") {
95891
+ existing.startExecutionOnlyCapture();
95892
+ }
95542
95893
  this.#executionProcesses.touch(options2.sessionId, existing);
95543
95894
  return existing;
95544
95895
  }
95545
- await this.prepareSession(options2);
95896
+ await this.#prepareSession(options2, options2.recovery ?? { kind: "interactive-only" }, "reopen");
95546
95897
  const started = this.#executionProcesses.get(options2.sessionId);
95547
95898
  if (started === void 0) {
95548
95899
  throw new AcpExecutionError("ACP session did not start");
@@ -96100,6 +96451,7 @@ var PromptLifecycle;
96100
96451
  var init_prompt_lifecycle = __esm({
96101
96452
  "src/session/prompt/prompt-lifecycle.ts"() {
96102
96453
  "use strict";
96454
+ init_protocol();
96103
96455
  PromptLifecycle = class {
96104
96456
  #sink;
96105
96457
  #terminal = /* @__PURE__ */ new Map();
@@ -96181,6 +96533,13 @@ var init_prompt_lifecycle = __esm({
96181
96533
  }
96182
96534
  this.#queued.delete(commandId);
96183
96535
  };
96536
+ replayOutcome = async (sessionId, event) => {
96537
+ if (event.type !== "lifecycle-metadata" || !("commandId" in event.payload)) {
96538
+ return;
96539
+ }
96540
+ await this.#recordLifecycle(sessionId, event);
96541
+ this.publishTerminal(sessionId, event.payload.commandId);
96542
+ };
96184
96543
  queueChanged = async (sessionId) => {
96185
96544
  await this.#recordLifecycle(sessionId, {
96186
96545
  type: "lifecycle-metadata",
@@ -96214,7 +96573,7 @@ var init_prompt_lifecycle = __esm({
96214
96573
  type: "lifecycle-metadata",
96215
96574
  payload: { kind: "prompt.failed-before-start", commandId, code, message }
96216
96575
  });
96217
- if (!recorded) {
96576
+ if (!recorded || code === SESSION_CLOSED_ERROR_CODE) {
96218
96577
  this.#sink.publishOperationFailure(sessionId, commandId, code, message);
96219
96578
  }
96220
96579
  };
@@ -96239,21 +96598,154 @@ var MAX_TERMINAL_RECEIPTS, ExecutionReceipts;
96239
96598
  var init_execution_receipts = __esm({
96240
96599
  "src/session/turn/execution-receipts.ts"() {
96241
96600
  "use strict";
96601
+ init_protocol();
96602
+ init_zod();
96242
96603
  MAX_TERMINAL_RECEIPTS = 1024;
96243
96604
  ExecutionReceipts = class {
96244
96605
  #executions = /* @__PURE__ */ new Map();
96606
+ #recoveredCommands = /* @__PURE__ */ new Set();
96245
96607
  #terminalCountBySession = /* @__PURE__ */ new Map();
96608
+ #table;
96609
+ #closing = false;
96610
+ #activeCount = 0;
96611
+ #onCount;
96612
+ constructor(table, onCount = () => void 0) {
96613
+ this.#onCount = onCount;
96614
+ this.#table = table;
96615
+ for (const row of table?.list() ?? []) {
96616
+ this.#executions.set(row.commandId, row);
96617
+ this.#recoveredCommands.add(row.commandId);
96618
+ if (!isTerminal(row.state)) {
96619
+ this.#activeCount += 1;
96620
+ }
96621
+ if (isTerminal(row.state)) {
96622
+ this.#terminalCountBySession.set(
96623
+ row.sessionId,
96624
+ (this.#terminalCountBySession.get(row.sessionId) ?? 0) + 1
96625
+ );
96626
+ }
96627
+ }
96628
+ }
96629
+ #save = (commandId, receipt) => {
96630
+ if (!this.#closing) {
96631
+ this.#table?.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
96632
+ }
96633
+ const previous = this.#executions.get(commandId);
96634
+ const wasActive = previous !== void 0 && !isTerminal(previous.state);
96635
+ if (isTerminal(receipt.state)) {
96636
+ this.#executions.delete(commandId);
96637
+ }
96638
+ this.#executions.set(commandId, receipt);
96639
+ this.#activeCount += Number(!isTerminal(receipt.state)) - Number(wasActive);
96640
+ this.#onCount(this.#activeCount);
96641
+ if (isTerminal(receipt.state) && (previous === void 0 || !isTerminal(previous.state))) {
96642
+ this.#terminalCountBySession.set(
96643
+ receipt.sessionId,
96644
+ (this.#terminalCountBySession.get(receipt.sessionId) ?? 0) + 1
96645
+ );
96646
+ this.pruneTerminalReceipts(receipt.sessionId);
96647
+ }
96648
+ };
96649
+ beginShutdown = () => {
96650
+ this.#closing = true;
96651
+ };
96652
+ outcome = (commandId) => {
96653
+ const receipt = this.#executions.get(commandId);
96654
+ return receipt?.outcome === null || receipt === void 0 ? void 0 : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
96655
+ };
96656
+ recordOutcome = (event) => {
96657
+ if (event.type !== "lifecycle-metadata") {
96658
+ return;
96659
+ }
96660
+ const payload = event.payload;
96661
+ if (payload.kind !== "prompt.completed" && payload.kind !== "prompt.failed" && payload.kind !== "prompt.failed-before-start") {
96662
+ return;
96663
+ }
96664
+ const receipt = this.#executions.get(payload.commandId);
96665
+ if (receipt === void 0) {
96666
+ return;
96667
+ }
96668
+ const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
96669
+ this.#save(payload.commandId, {
96670
+ ...receipt,
96671
+ state: payload.kind === "prompt.completed" ? payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed",
96672
+ outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
96673
+ });
96674
+ };
96675
+ recover = () => {
96676
+ const recovered = [];
96677
+ for (const [commandId, receipt] of [...this.#executions]) {
96678
+ const event = receipt.outcome === null ? {
96679
+ type: "lifecycle-metadata",
96680
+ payload: receipt.started ? {
96681
+ kind: "prompt.failed",
96682
+ commandId,
96683
+ attemptId: receipt.attemptId,
96684
+ code: "runtime_restarted",
96685
+ message: "The local runtime restarted while this request was running"
96686
+ } : {
96687
+ kind: "prompt.failed-before-start",
96688
+ commandId,
96689
+ code: "runtime_restarted",
96690
+ message: "The local runtime restarted before this request started"
96691
+ }
96692
+ } : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
96693
+ const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
96694
+ recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
96695
+ if (!isTerminal(receipt.state)) {
96696
+ const state = event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
96697
+ this.#save(commandId, { ...receipt, state, outcome: JSON.stringify({ ...event, recordedAt }) });
96698
+ }
96699
+ }
96700
+ return recovered;
96701
+ };
96702
+ terminalOutcomes = (sessionId) => [...this.#executions.values()].flatMap((receipt) => {
96703
+ if (receipt.sessionId !== sessionId || receipt.outcome === null) {
96704
+ return [];
96705
+ }
96706
+ const decoded = JSON.parse(receipt.outcome);
96707
+ return [
96708
+ {
96709
+ event: sessionEventPayloadSchema.parse(decoded),
96710
+ recordedAt: external_exports.object({ recordedAt: external_exports.string() }).parse(decoded).recordedAt
96711
+ }
96712
+ ];
96713
+ });
96246
96714
  claimExecution = (commandId, sessionId, commandJson) => {
96247
96715
  const commandHash = createHash7("sha256").update(commandJson).digest("hex");
96248
- const existing = this.#executions.get(commandId);
96716
+ let existing = this.#executions.get(commandId);
96717
+ const previous = this.outcome(commandId);
96718
+ if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
96719
+ this.#executions.delete(commandId);
96720
+ this.#recoveredCommands.delete(commandId);
96721
+ this.#table?.remove(commandId);
96722
+ this.#terminalCountBySession.set(
96723
+ sessionId,
96724
+ Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
96725
+ );
96726
+ existing = void 0;
96727
+ }
96249
96728
  if (existing !== void 0) {
96250
96729
  if (existing.sessionId !== sessionId || existing.commandHash !== commandHash) {
96251
96730
  return { kind: "conflict" };
96252
96731
  }
96253
- return { attemptId: existing.attemptId, commandId, kind: "duplicate", state: existing.state };
96732
+ return {
96733
+ attemptId: existing.attemptId,
96734
+ commandId,
96735
+ kind: "duplicate",
96736
+ state: existing.state,
96737
+ outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
96738
+ };
96254
96739
  }
96255
96740
  const attemptId = randomUUID14();
96256
- this.#executions.set(commandId, { attemptId, commandHash, sessionId, state: "dispatching" });
96741
+ this.#save(commandId, {
96742
+ attemptId,
96743
+ commandHash,
96744
+ sessionId,
96745
+ state: "dispatching",
96746
+ started: false,
96747
+ outcome: null
96748
+ });
96257
96749
  return { attemptId, commandId, kind: "accepted", state: "dispatching" };
96258
96750
  };
96259
96751
  transitionExecution = (commandId, state) => {
@@ -96268,16 +96760,13 @@ var init_execution_receipts = __esm({
96268
96760
  if (!allowed) {
96269
96761
  throw new Error("The runtime execution transition is invalid");
96270
96762
  }
96271
- this.#executions.set(commandId, { ...current, state });
96272
- if (isTerminal(state)) {
96273
- this.#terminalCountBySession.set(
96274
- current.sessionId,
96275
- (this.#terminalCountBySession.get(current.sessionId) ?? 0) + 1
96276
- );
96277
- this.pruneTerminalReceipts(current.sessionId);
96763
+ if (state === "running") {
96764
+ this.#save(commandId, { ...current, state, started: true });
96765
+ } else if (isTerminal(state)) {
96766
+ this.#save(commandId, { ...current, state });
96278
96767
  }
96279
96768
  };
96280
- /** Receipts disappear when the runtime process exits. */
96769
+ /** Only commands without a terminal result can still be cancelled. */
96281
96770
  findUnsettledAttemptId = (commandId, sessionId) => {
96282
96771
  const receipt = this.#executions.get(commandId);
96283
96772
  return receipt?.sessionId === sessionId && !isTerminal(receipt.state) ? receipt.attemptId : null;
@@ -96288,7 +96777,9 @@ var init_execution_receipts = __esm({
96288
96777
  };
96289
96778
  close = () => {
96290
96779
  this.#executions.clear();
96780
+ this.#recoveredCommands.clear();
96291
96781
  this.#terminalCountBySession.clear();
96782
+ this.#activeCount = 0;
96292
96783
  };
96293
96784
  pruneTerminalReceipts = (sessionId) => {
96294
96785
  if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
@@ -96297,6 +96788,8 @@ var init_execution_receipts = __esm({
96297
96788
  for (const [commandId, receipt] of this.#executions) {
96298
96789
  if (receipt.sessionId === sessionId && isTerminal(receipt.state)) {
96299
96790
  this.#executions.delete(commandId);
96791
+ this.#recoveredCommands.delete(commandId);
96792
+ this.#table?.remove(commandId);
96300
96793
  const remaining = (this.#terminalCountBySession.get(sessionId) ?? 1) - 1;
96301
96794
  if (remaining > 0) {
96302
96795
  this.#terminalCountBySession.set(sessionId, remaining);
@@ -96847,10 +97340,14 @@ function buildSessionLayer(options) {
96847
97340
  const databases = channelSessionDatabasePaths(stateDirectory, channelId);
96848
97341
  const sessionDatabase = openAcpSessionDatabase(databases.sessions);
96849
97342
  let events;
97343
+ let operations;
96850
97344
  try {
97345
+ operations = new ExecutionReceipts(new ExecutionReceiptTable(sessionDatabase), options.onExecutionCountChange);
96851
97346
  events = new CachedSessionEventStore(
96852
97347
  new SessionEventCacheTable(openSessionEventCacheDatabase(databases.events)),
96853
- new SqliteSessionLiveEventPosition(new LiveEventPositionTable(sessionDatabase))
97348
+ new SqliteSessionLiveEventPosition(new LiveEventPositionTable(sessionDatabase)),
97349
+ void 0,
97350
+ (sessionId) => operations.terminalOutcomes(sessionId)
96854
97351
  );
96855
97352
  } catch (error62) {
96856
97353
  sessionDatabase.close();
@@ -96858,11 +97355,13 @@ function buildSessionLayer(options) {
96858
97355
  }
96859
97356
  const sessionStore = new SqliteSessionStore(new AcpSessionTable(sessionDatabase), events);
96860
97357
  const externalContent = new LocalExternalContentStore(stateDirectory);
96861
- const operations = new ExecutionReceipts();
96862
97358
  const activeSessions = new SessionTurns(operations, options.turnActivity);
96863
97359
  const directories = new WorkspaceDirectoryService(bindingId, defaultWorkspace);
96864
97360
  const manager = new SessionManager2({
96865
- observer: new SessionLayerObserver((event) => eventProjection.record(event), sink.publishInfo),
97361
+ observer: new SessionLayerObserver((event) => {
97362
+ operations.recordOutcome(event);
97363
+ eventProjection.record(event);
97364
+ }, sink.publishInfo),
96866
97365
  store: sessionStore,
96867
97366
  adapters: harnessAdapters,
96868
97367
  sessionIdentity: "native",
@@ -96883,7 +97382,15 @@ function buildSessionLayer(options) {
96883
97382
  });
96884
97383
  const eventProjection = new PromptLifecycle(
96885
97384
  sink,
96886
- (sessionId, event) => manager.recordLifecycleEvent(sessionId, event),
97385
+ async (sessionId, event) => {
97386
+ if (await manager.recordLifecycleEvent(sessionId, event)) {
97387
+ return true;
97388
+ }
97389
+ const recorded = events.append(sessionId, event);
97390
+ operations.recordOutcome(recorded);
97391
+ eventProjection.record(recorded);
97392
+ return true;
97393
+ },
96887
97394
  activeSessions.recordSessionEvent
96888
97395
  );
96889
97396
  const nativeSessions = new NativeSessionService(
@@ -96906,7 +97413,13 @@ function buildSessionLayer(options) {
96906
97413
  );
96907
97414
  })
96908
97415
  );
97416
+ const recoveredEvents = operations.recover().map(({ sessionId, event, recordedAt }) => events.append(sessionId, event, recordedAt));
96909
97417
  return {
97418
+ publishRecoveredOutcomes: () => {
97419
+ for (const event of recoveredEvents) {
97420
+ sink.publish(event);
97421
+ }
97422
+ },
96910
97423
  activeSessions,
96911
97424
  directories,
96912
97425
  eventProjection,
@@ -96924,6 +97437,7 @@ var init_session_layer = __esm({
96924
97437
  init_registry();
96925
97438
  init_content_externalizer();
96926
97439
  init_acp_session_table();
97440
+ init_execution_receipt_table();
96927
97441
  init_live_event_position_table();
96928
97442
  init_session_event_cache_table();
96929
97443
  init_local_databases();
@@ -98804,12 +99318,14 @@ async function executePrompt({
98804
99318
  const appliedSettings = command.sessionConfigurations === void 0 ? void 0 : agentForSessionConfiguration(agent, command.sessionConfigurations);
98805
99319
  const executionAgent = appliedSettings?.agent ?? agent;
98806
99320
  const sessionConfigurations = appliedSettings?.sessionConfigurations;
99321
+ const recovery = command.historyPolicy === SessionHistoryPolicy.ExecutionOnly ? { kind: "execution-only" } : { kind: "interactive-only" };
98807
99322
  const preparation = {
98808
99323
  additionalDirectories: resolved.additionalDirectories,
98809
99324
  agent: executionAgent,
98810
99325
  cwd: resolved.cwd,
98811
99326
  sessionId: command.sessionId,
98812
- signal
99327
+ signal,
99328
+ recovery
98813
99329
  };
98814
99330
  let prepared = await sessions.prepareExecutionSession(preparation);
98815
99331
  if (command.sessionConfigurations !== void 0) {
@@ -98878,7 +99394,8 @@ async function executePrompt({
98878
99394
  resources: attachments.resources,
98879
99395
  sessionId: command.sessionId,
98880
99396
  signal,
98881
- targetCommandId: command.targetCommandId
99397
+ targetCommandId: command.targetCommandId,
99398
+ recovery
98882
99399
  });
98883
99400
  stopReason = result.stopReason;
98884
99401
  }
@@ -99076,6 +99593,12 @@ var init_prompt2 = __esm({
99076
99593
  return;
99077
99594
  }
99078
99595
  if (receipt.kind === "duplicate") {
99596
+ const outcome = receipt.outcome;
99597
+ if (outcome !== void 0) {
99598
+ void context.eventProjection.replayOutcome(message.sessionId, outcome).catch((cause) => {
99599
+ console.error("Could not replay the persisted execution outcome", cause);
99600
+ });
99601
+ }
99079
99602
  return;
99080
99603
  }
99081
99604
  const turn = context.sessionTurns.start(message, receipt.attemptId);
@@ -100282,7 +100805,8 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
100282
100805
  resolveAgent: (agentId, resolveSignal) => resolveCatalogAgent(config2, agentId, resolveSignal),
100283
100806
  sink: publisher,
100284
100807
  stateDirectory: config2.localContext.stateDirectory,
100285
- timer
100808
+ timer,
100809
+ onExecutionCountChange: options.onExecutionCountChange ?? (() => void 0)
100286
100810
  });
100287
100811
  const {
100288
100812
  activeSessions,
@@ -100352,6 +100876,7 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
100352
100876
  reportUpgradeAvailability,
100353
100877
  diagnostics,
100354
100878
  onConnected: () => {
100879
+ layer.publishRecoveredOutcomes();
100355
100880
  if (catalogPublished) {
100356
100881
  options.onConnectionStatus?.("online");
100357
100882
  }
@@ -100374,6 +100899,7 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
100374
100899
  }
100375
100900
  } finally {
100376
100901
  shutdown.abort();
100902
+ operations.beginShutdown();
100377
100903
  await activeSessions.close();
100378
100904
  try {
100379
100905
  await catalogPublication;
@@ -100468,6 +100994,10 @@ var init_engine = __esm({
100468
100994
  MobiusRuntimeEngine = class {
100469
100995
  #config;
100470
100996
  #options;
100997
+ #activeTurnCount = 0;
100998
+ get activeTurnCount() {
100999
+ return this.#activeTurnCount;
101000
+ }
100471
101001
  #state = new IdleMobiusRuntimeState();
100472
101002
  constructor(config2, options = {}) {
100473
101003
  validateRuntimeConfiguration(config2);
@@ -100483,11 +101013,15 @@ var init_engine = __esm({
100483
101013
  try {
100484
101014
  await runRuntime(this.#config, signal, void 0, {
100485
101015
  ...this.#options.turnActivity === void 0 ? {} : { turnActivity: this.#options.turnActivity },
101016
+ onExecutionCountChange: (count) => {
101017
+ this.#activeTurnCount = count;
101018
+ },
100486
101019
  ...this.#options.onConnectionStatus === void 0 ? {} : { onConnectionStatus: this.#options.onConnectionStatus },
100487
101020
  ...this.#options.reportUpgradeAvailability === void 0 ? {} : { reportUpgradeAvailability: this.#options.reportUpgradeAvailability },
100488
101021
  ...this.#options.processLogsDirectory === void 0 ? {} : { processLogsDirectory: this.#options.processLogsDirectory }
100489
101022
  });
100490
101023
  } finally {
101024
+ this.#activeTurnCount = 0;
100491
101025
  this.#state = new FinishedMobiusRuntimeState();
100492
101026
  }
100493
101027
  };