@moxt-ai/mobius 0.0.324 → 0.0.326

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 (41) hide show
  1. package/dist/cli/handler/daemon/upgrade.d.ts.map +1 -1
  2. package/dist/cli/handler/daemon/upgrade.js +2 -5
  3. package/dist/cli/handler/daemon/upgrade.js.map +1 -1
  4. package/dist/cli.js +349 -291
  5. package/dist/cli.js.map +4 -4
  6. package/dist/daemon/lifecycle/manager-client.d.ts +1 -1
  7. package/dist/daemon/lifecycle/manager-client.d.ts.map +1 -1
  8. package/dist/daemon/lifecycle/manager-client.js +9 -1
  9. package/dist/daemon/lifecycle/manager-client.js.map +1 -1
  10. package/dist/daemon/lifecycle/worker.js +2 -2
  11. package/dist/daemon/lifecycle/worker.js.map +1 -1
  12. package/dist/daemon/pairing/pair-local-machine.d.ts +1 -0
  13. package/dist/daemon/pairing/pair-local-machine.d.ts.map +1 -1
  14. package/dist/daemon/pairing/pair-local-machine.js +10 -3
  15. package/dist/daemon/pairing/pair-local-machine.js.map +1 -1
  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 +10 -0
  22. package/dist/runtime/command/registry/prompt.js.map +1 -1
  23. package/dist/runtime.js +63 -73
  24. package/dist/runtime.js.map +4 -4
  25. package/dist/schema/acp-session-store/execution-identity.d.ts +57 -0
  26. package/dist/schema/acp-session-store/execution-identity.d.ts.map +1 -0
  27. package/dist/schema/acp-session-store/execution-identity.js +8 -0
  28. package/dist/schema/acp-session-store/execution-identity.js.map +1 -0
  29. package/dist/schema/acp-session-store/index.d.ts +1 -0
  30. package/dist/schema/acp-session-store/index.d.ts.map +1 -1
  31. package/dist/schema/acp-session-store/index.js +1 -0
  32. package/dist/schema/acp-session-store/index.js.map +1 -1
  33. package/dist/session/turn/execution-receipts.d.ts +3 -1
  34. package/dist/session/turn/execution-receipts.d.ts.map +1 -1
  35. package/dist/session/turn/execution-receipts.js +10 -4
  36. package/dist/session/turn/execution-receipts.js.map +1 -1
  37. package/dist/storage/session/execution-receipt-table.d.ts +5 -0
  38. package/dist/storage/session/execution-receipt-table.d.ts.map +1 -1
  39. package/dist/storage/session/execution-receipt-table.js +32 -6
  40. package/dist/storage/session/execution-receipt-table.js.map +1 -1
  41. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -780,8 +780,8 @@ var require_gt = __commonJS({
780
780
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gt.js"(exports, module) {
781
781
  "use strict";
782
782
  var compare = require_compare();
783
- var gt4 = (a, b2, loose) => compare(a, b2, loose) > 0;
784
- module.exports = gt4;
783
+ var gt5 = (a, b2, loose) => compare(a, b2, loose) > 0;
784
+ module.exports = gt5;
785
785
  }
786
786
  });
787
787
 
@@ -841,7 +841,7 @@ var require_cmp = __commonJS({
841
841
  "use strict";
842
842
  var eq3 = require_eq();
843
843
  var neq = require_neq();
844
- var gt4 = require_gt();
844
+ var gt5 = require_gt();
845
845
  var gte3 = require_gte();
846
846
  var lt3 = require_lt();
847
847
  var lte3 = require_lte();
@@ -870,7 +870,7 @@ var require_cmp = __commonJS({
870
870
  case "!=":
871
871
  return neq(a, b2, loose);
872
872
  case ">":
873
- return gt4(a, b2, loose);
873
+ return gt5(a, b2, loose);
874
874
  case ">=":
875
875
  return gte3(a, b2, loose);
876
876
  case "<":
@@ -1599,7 +1599,7 @@ var require_min_version = __commonJS({
1599
1599
  "use strict";
1600
1600
  var SemVer = require_semver();
1601
1601
  var Range = require_range();
1602
- var gt4 = require_gt();
1602
+ var gt5 = require_gt();
1603
1603
  var minVersion = (range, loose) => {
1604
1604
  range = new Range(range, loose);
1605
1605
  let minver = new SemVer("0.0.0");
@@ -1627,7 +1627,7 @@ var require_min_version = __commonJS({
1627
1627
  /* fallthrough */
1628
1628
  case "":
1629
1629
  case ">=":
1630
- if (!setMin || gt4(compver, setMin)) {
1630
+ if (!setMin || gt5(compver, setMin)) {
1631
1631
  setMin = compver;
1632
1632
  }
1633
1633
  break;
@@ -1639,7 +1639,7 @@ var require_min_version = __commonJS({
1639
1639
  throw new Error(`Unexpected operation: ${comparator.operator}`);
1640
1640
  }
1641
1641
  });
1642
- if (setMin && (!minver || gt4(minver, setMin))) {
1642
+ if (setMin && (!minver || gt5(minver, setMin))) {
1643
1643
  minver = setMin;
1644
1644
  }
1645
1645
  }
@@ -1677,7 +1677,7 @@ var require_outside = __commonJS({
1677
1677
  var { ANY } = Comparator;
1678
1678
  var Range = require_range();
1679
1679
  var satisfies3 = require_satisfies();
1680
- var gt4 = require_gt();
1680
+ var gt5 = require_gt();
1681
1681
  var lt3 = require_lt();
1682
1682
  var lte3 = require_lte();
1683
1683
  var gte3 = require_gte();
@@ -1687,7 +1687,7 @@ var require_outside = __commonJS({
1687
1687
  let gtfn, ltefn, ltfn, comp, ecomp;
1688
1688
  switch (hilo) {
1689
1689
  case ">":
1690
- gtfn = gt4;
1690
+ gtfn = gt5;
1691
1691
  ltefn = lte3;
1692
1692
  ltfn = lt3;
1693
1693
  comp = ">";
@@ -1696,7 +1696,7 @@ var require_outside = __commonJS({
1696
1696
  case "<":
1697
1697
  gtfn = lt3;
1698
1698
  ltefn = gte3;
1699
- ltfn = gt4;
1699
+ ltfn = gt5;
1700
1700
  comp = "<";
1701
1701
  ecomp = "<=";
1702
1702
  break;
@@ -1874,10 +1874,10 @@ var require_subset = __commonJS({
1874
1874
  }
1875
1875
  }
1876
1876
  const eqSet = /* @__PURE__ */ new Set();
1877
- let gt4, lt3;
1877
+ let gt5, lt3;
1878
1878
  for (const c of sub) {
1879
1879
  if (c.operator === ">" || c.operator === ">=") {
1880
- gt4 = higherGT(gt4, c, options);
1880
+ gt5 = higherGT(gt5, c, options);
1881
1881
  } else if (c.operator === "<" || c.operator === "<=") {
1882
1882
  lt3 = lowerLT(lt3, c, options);
1883
1883
  } else {
@@ -1888,16 +1888,16 @@ var require_subset = __commonJS({
1888
1888
  return null;
1889
1889
  }
1890
1890
  let gtltComp;
1891
- if (gt4 && lt3) {
1892
- gtltComp = compare(gt4.semver, lt3.semver, options);
1891
+ if (gt5 && lt3) {
1892
+ gtltComp = compare(gt5.semver, lt3.semver, options);
1893
1893
  if (gtltComp > 0) {
1894
1894
  return null;
1895
- } else if (gtltComp === 0 && (gt4.operator !== ">=" || lt3.operator !== "<=")) {
1895
+ } else if (gtltComp === 0 && (gt5.operator !== ">=" || lt3.operator !== "<=")) {
1896
1896
  return null;
1897
1897
  }
1898
1898
  }
1899
1899
  for (const eq3 of eqSet) {
1900
- if (gt4 && !satisfies3(eq3, String(gt4), options)) {
1900
+ if (gt5 && !satisfies3(eq3, String(gt5), options)) {
1901
1901
  return null;
1902
1902
  }
1903
1903
  if (lt3 && !satisfies3(eq3, String(lt3), options)) {
@@ -1913,25 +1913,25 @@ var require_subset = __commonJS({
1913
1913
  let higher, lower;
1914
1914
  let hasDomLT, hasDomGT;
1915
1915
  let needDomLTPre = lt3 && !options.includePrerelease && lt3.semver.prerelease.length ? lt3.semver : false;
1916
- let needDomGTPre = gt4 && !options.includePrerelease && gt4.semver.prerelease.length ? gt4.semver : false;
1916
+ let needDomGTPre = gt5 && !options.includePrerelease && gt5.semver.prerelease.length ? gt5.semver : false;
1917
1917
  if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt3.operator === "<" && needDomLTPre.prerelease[0] === 0) {
1918
1918
  needDomLTPre = false;
1919
1919
  }
1920
1920
  for (const c of dom) {
1921
1921
  hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">=";
1922
1922
  hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<=";
1923
- if (gt4) {
1923
+ if (gt5) {
1924
1924
  if (needDomGTPre) {
1925
1925
  if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) {
1926
1926
  needDomGTPre = false;
1927
1927
  }
1928
1928
  }
1929
1929
  if (c.operator === ">" || c.operator === ">=") {
1930
- higher = higherGT(gt4, c, options);
1931
- if (higher === c && higher !== gt4) {
1930
+ higher = higherGT(gt5, c, options);
1931
+ if (higher === c && higher !== gt5) {
1932
1932
  return false;
1933
1933
  }
1934
- } else if (gt4.operator === ">=" && !c.test(gt4.semver)) {
1934
+ } else if (gt5.operator === ">=" && !c.test(gt5.semver)) {
1935
1935
  return false;
1936
1936
  }
1937
1937
  }
@@ -1950,14 +1950,14 @@ var require_subset = __commonJS({
1950
1950
  return false;
1951
1951
  }
1952
1952
  }
1953
- if (!c.operator && (lt3 || gt4) && gtltComp !== 0) {
1953
+ if (!c.operator && (lt3 || gt5) && gtltComp !== 0) {
1954
1954
  return false;
1955
1955
  }
1956
1956
  }
1957
- if (gt4 && hasDomLT && !lt3 && gtltComp !== 0) {
1957
+ if (gt5 && hasDomLT && !lt3 && gtltComp !== 0) {
1958
1958
  return false;
1959
1959
  }
1960
- if (lt3 && hasDomGT && !gt4 && gtltComp !== 0) {
1960
+ if (lt3 && hasDomGT && !gt5 && gtltComp !== 0) {
1961
1961
  return false;
1962
1962
  }
1963
1963
  if (needDomGTPre || needDomLTPre) {
@@ -2006,7 +2006,7 @@ var require_semver2 = __commonJS({
2006
2006
  var compareBuild = require_compare_build();
2007
2007
  var sort = require_sort();
2008
2008
  var rsort = require_rsort();
2009
- var gt4 = require_gt();
2009
+ var gt5 = require_gt();
2010
2010
  var lt3 = require_lt();
2011
2011
  var eq3 = require_eq();
2012
2012
  var neq = require_neq();
@@ -2045,7 +2045,7 @@ var require_semver2 = __commonJS({
2045
2045
  compareBuild,
2046
2046
  sort,
2047
2047
  rsort,
2048
- gt: gt4,
2048
+ gt: gt5,
2049
2049
  lt: lt3,
2050
2050
  eq: eq3,
2051
2051
  neq,
@@ -2086,7 +2086,7 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.324",
2089
+ version: "0.0.326",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -75069,12 +75069,12 @@ var init_event_log = __esm({
75069
75069
  textContentSchema = external_exports.object({ ...contentFields, text: boundedString2, type: external_exports.literal("text") }).readonly();
75070
75070
  imageContentSchema = external_exports.object({
75071
75071
  ...contentFields,
75072
- data: boundedString2,
75072
+ data: external_exports.string(),
75073
75073
  mimeType: shortString,
75074
75074
  type: external_exports.literal("image"),
75075
75075
  uri: boundedString2.nullable().optional()
75076
75076
  }).readonly();
75077
- audioContentSchema = external_exports.object({ ...contentFields, data: boundedString2, mimeType: shortString, type: external_exports.literal("audio") }).readonly();
75077
+ audioContentSchema = external_exports.object({ ...contentFields, data: external_exports.string(), mimeType: shortString, type: external_exports.literal("audio") }).readonly();
75078
75078
  externalImageContentSchema = external_exports.object({
75079
75079
  ...contentFields,
75080
75080
  byteLength: external_exports.number().int().positive().safe(),
@@ -75115,7 +75115,7 @@ var init_event_log = __esm({
75115
75115
  uri: boundedString2
75116
75116
  }).readonly();
75117
75117
  blobResourceSchema = external_exports.object({
75118
- blob: boundedString2,
75118
+ blob: external_exports.string(),
75119
75119
  mimeType: shortString.nullable().optional(),
75120
75120
  uri: boundedString2
75121
75121
  }).readonly();
@@ -84023,6 +84023,10 @@ var init_acp_session_store_migrations = __esm({
84023
84023
  {
84024
84024
  "name": "0007_busy_excalibur.sql",
84025
84025
  "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"
84026
+ },
84027
+ {
84028
+ "name": "0008_execution_identity.sql",
84029
+ "sql": "CREATE TABLE `execution_identity` (\n `command_id` text PRIMARY KEY NOT NULL,\n `session_id` text NOT NULL,\n `command_hash` text NOT NULL\n);\n"
84026
84030
  }
84027
84031
  ];
84028
84032
  }
@@ -91350,243 +91354,9 @@ var init_version_data = __esm({
91350
91354
  }
91351
91355
  });
91352
91356
 
91353
- // src/storage/daemon/control-token.ts
91354
- import { randomBytes } from "node:crypto";
91355
- import { readFile as readFile8, writeFile as writeFile3 } from "node:fs/promises";
91356
- import { join as join26 } from "node:path";
91357
- function controlTokenPath(stateDirectory) {
91358
- return join26(stateDirectory, "manager.token");
91359
- }
91360
- async function readOrCreateControlToken(stateDirectory) {
91361
- const path8 = controlTokenPath(stateDirectory);
91362
- try {
91363
- return (await readFile8(path8, "utf8")).trim();
91364
- } catch (cause) {
91365
- if (!isNodeError(cause, "ENOENT")) {
91366
- throw cause;
91367
- }
91368
- }
91369
- const token = randomBytes(32).toString("base64url");
91370
- try {
91371
- await writeFile3(path8, `${token}
91372
- `, { flag: "wx", mode: 384 });
91373
- return token;
91374
- } catch (cause) {
91375
- if (!isNodeError(cause, "EEXIST")) {
91376
- throw cause;
91377
- }
91378
- return (await readFile8(path8, "utf8")).trim();
91379
- }
91380
- }
91381
- var init_control_token = __esm({
91382
- "src/storage/daemon/control-token.ts"() {
91383
- "use strict";
91384
- init_node_error();
91385
- }
91386
- });
91387
-
91388
- // src/daemon/control/local-client.ts
91389
- import { createHash as createHash6 } from "node:crypto";
91390
- import { createConnection } from "node:net";
91391
- function controlSocketPath(stateDirectory, endpoint = "manager") {
91392
- const installationHash = createHash6("sha256").update(endpoint === "manager" ? stateDirectory : `${stateDirectory}:worker`).digest("hex").slice(0, 32);
91393
- return managerPlatform.controlSocketPath(installationHash);
91394
- }
91395
- async function readSocketMessage(socket, signal) {
91396
- signal.throwIfAborted();
91397
- return await new Promise((resolve21, reject2) => {
91398
- let encoded = "";
91399
- const finish = (error62, value) => {
91400
- signal.removeEventListener("abort", abort);
91401
- socket.removeAllListeners("data");
91402
- socket.removeAllListeners("error");
91403
- socket.removeAllListeners("end");
91404
- if (error62 === void 0) {
91405
- resolve21(value);
91406
- } else {
91407
- reject2(error62);
91408
- }
91409
- };
91410
- const abort = () => {
91411
- socket.destroy();
91412
- finish(signal.reason);
91413
- };
91414
- socket.on("data", (chunk) => {
91415
- encoded += chunk.toString("utf8");
91416
- if (encoded.length > MAXIMUM_MESSAGE_BYTES) {
91417
- finish(new Error("The manager message is too large"));
91418
- socket.destroy();
91419
- return;
91420
- }
91421
- const newline = encoded.indexOf("\n");
91422
- if (newline >= 0) {
91423
- try {
91424
- finish(void 0, JSON.parse(encoded.slice(0, newline)));
91425
- } catch (cause) {
91426
- finish(cause);
91427
- }
91428
- }
91429
- });
91430
- socket.once("error", finish);
91431
- socket.once("end", () => finish(new Error("The manager connection closed without a response")));
91432
- signal.addEventListener("abort", abort, { once: true });
91433
- });
91434
- }
91435
- async function sendLocalRequest(stateDirectory, endpoint, command, signal) {
91436
- const token = await readOrCreateControlToken(stateDirectory);
91437
- const deadline = AbortSignal.any([signal, AbortSignal.timeout(CONTROL_TIMEOUT_MILLISECONDS)]);
91438
- deadline.throwIfAborted();
91439
- const socket = createConnection(controlSocketPath(stateDirectory, endpoint));
91440
- try {
91441
- await new Promise((resolve21, reject2) => {
91442
- const abort = () => {
91443
- socket.destroy();
91444
- reject2(deadline.reason);
91445
- };
91446
- socket.once("connect", () => {
91447
- deadline.removeEventListener("abort", abort);
91448
- resolve21();
91449
- });
91450
- socket.once("error", reject2);
91451
- deadline.addEventListener("abort", abort, { once: true });
91452
- });
91453
- socket.write(`${JSON.stringify({ ...command, token })}
91454
- `);
91455
- return await readSocketMessage(socket, deadline);
91456
- } finally {
91457
- socket.destroy();
91458
- }
91459
- }
91460
- var CONTROL_TIMEOUT_MILLISECONDS, MAXIMUM_MESSAGE_BYTES, managerPlatform;
91461
- var init_local_client = __esm({
91462
- "src/daemon/control/local-client.ts"() {
91463
- "use strict";
91464
- init_control_token();
91465
- init_platform();
91466
- CONTROL_TIMEOUT_MILLISECONDS = 13e4;
91467
- MAXIMUM_MESSAGE_BYTES = 64 * 1024;
91468
- managerPlatform = platformSupportFor(process.platform);
91469
- }
91470
- });
91471
-
91472
- // src/daemon/control/protocol.ts
91473
- var workerLaunch, transition, daemonSwitchState, lifecycleCommand, lifecycleResponse;
91474
- var init_protocol2 = __esm({
91475
- "src/daemon/control/protocol.ts"() {
91476
- "use strict";
91477
- init_zod();
91478
- workerLaunch = external_exports.object({
91479
- executable: external_exports.string().min(1),
91480
- entry: external_exports.string().min(1),
91481
- version: external_exports.string().min(1).max(128)
91482
- }).readonly();
91483
- transition = {
91484
- id: external_exports.string().min(1).max(256),
91485
- context: external_exports.string().max(256),
91486
- previous: workerLaunch,
91487
- next: workerLaunch
91488
- };
91489
- daemonSwitchState = external_exports.discriminatedUnion("kind", [
91490
- external_exports.object({ ...transition, kind: external_exports.literal("switching") }),
91491
- external_exports.object({ ...transition, kind: external_exports.literal("switched") }),
91492
- external_exports.object({
91493
- ...transition,
91494
- kind: external_exports.literal("rolled-back"),
91495
- code: external_exports.string(),
91496
- message: external_exports.string(),
91497
- stdout: external_exports.string().max(4096),
91498
- stderr: external_exports.string().max(4096),
91499
- retryAfter: external_exports.number().int().nonnegative()
91500
- })
91501
- ]).readonly();
91502
- lifecycleCommand = external_exports.discriminatedUnion("kind", [
91503
- external_exports.object({ kind: external_exports.literal("status") }),
91504
- external_exports.object({ kind: external_exports.literal("ensure"), launch: workerLaunch }),
91505
- external_exports.object({ kind: external_exports.literal("stop") }),
91506
- external_exports.object({
91507
- kind: external_exports.literal("switch"),
91508
- id: external_exports.string().min(1).max(256),
91509
- context: external_exports.string().max(256),
91510
- launch: workerLaunch
91511
- }),
91512
- external_exports.object({ kind: external_exports.literal("switch-status"), wait: external_exports.boolean() })
91513
- ]).readonly();
91514
- lifecycleResponse = external_exports.discriminatedUnion("kind", [
91515
- external_exports.object({
91516
- kind: external_exports.literal("status"),
91517
- protocolVersion: external_exports.literal(2),
91518
- worker: external_exports.object({ pid: external_exports.number().int().positive(), version: external_exports.string() }).readonly().nullable()
91519
- }),
91520
- external_exports.object({ kind: external_exports.literal("switch-status"), state: daemonSwitchState.nullable() }),
91521
- external_exports.object({ kind: external_exports.literal("stopped") }),
91522
- external_exports.object({ kind: external_exports.literal("switching") }),
91523
- external_exports.object({ kind: external_exports.literal("error"), code: external_exports.string(), message: external_exports.string() })
91524
- ]).readonly();
91525
- }
91526
- });
91527
-
91528
- // src/daemon/control/switch-status.ts
91529
- async function readSwitchStatus(directory, signal, wait = false) {
91530
- const response = lifecycleResponse.parse(
91531
- await sendLocalRequest(directory, "manager", { kind: "switch-status", wait }, signal)
91532
- );
91533
- if (response.kind !== "switch-status") {
91534
- throw new Error("The manager could not return the switch status");
91535
- }
91536
- return response.state;
91537
- }
91538
- var init_switch_status = __esm({
91539
- "src/daemon/control/switch-status.ts"() {
91540
- "use strict";
91541
- init_local_client();
91542
- init_protocol2();
91543
- }
91544
- });
91545
-
91546
- // src/daemon/upgrades/data.ts
91547
- async function prepareVersionData(version2, signal, environment = process.env, fallbackVersion = null) {
91548
- signal.throwIfAborted();
91549
- const root = readStateDirectory(environment);
91550
- const targetVersion = runtimeUpgradeVersionSchema.parse(version2);
91551
- if (await versionDataExists(root, targetVersion, signal)) {
91552
- return;
91553
- }
91554
- const previous = await readCurrentDataVersion(root, signal) ?? fallbackVersion;
91555
- if (previous === null) {
91556
- return;
91557
- }
91558
- const leftBehind = await copyVersionData(root, runtimeUpgradeVersionSchema.parse(previous), targetVersion, signal);
91559
- for (const entry of leftBehind) {
91560
- process.stderr.write(
91561
- `Mobius did not carry ${entry} into version ${targetVersion}: an earlier Mobius ran with that installation as its state root.
91562
- `
91563
- );
91564
- }
91565
- }
91566
- async function discardRolledBackData(version2, signal) {
91567
- await discardVersionData(readStateDirectory(), runtimeUpgradeVersionSchema.parse(version2), signal);
91568
- }
91569
- async function recordCurrentData(version2, signal) {
91570
- await writeCurrentDataVersion(readStateDirectory(), runtimeUpgradeVersionSchema.parse(version2), signal);
91571
- }
91572
- async function prepareUpgradeData(controlDirectory, version2, signal) {
91573
- const transition2 = await readSwitchStatus(controlDirectory, signal);
91574
- const previous = transition2?.kind === "switching" && transition2.next.version === version2 ? transition2.previous.version : null;
91575
- await prepareVersionData(version2, signal, process.env, previous);
91576
- }
91577
- var init_data = __esm({
91578
- "src/daemon/upgrades/data.ts"() {
91579
- "use strict";
91580
- init_protocol();
91581
- init_version_data();
91582
- init_state_directory();
91583
- init_switch_status();
91584
- }
91585
- });
91586
-
91587
91357
  // src/daemon/pairing/pair-local-machine.ts
91588
91358
  import { hostname as hostname3 } from "node:os";
91589
- import { basename as basename7, join as join27, resolve as resolve16 } from "node:path";
91359
+ import { basename as basename7, join as join26, resolve as resolve16 } from "node:path";
91590
91360
  import { fetch as fetch3 } from "undici";
91591
91361
  function hasExactKeys2(value, expectedKeys) {
91592
91362
  const keys = Object.keys(value);
@@ -91839,11 +91609,15 @@ async function openMobiusControlInstallation(signal, environment) {
91839
91609
  );
91840
91610
  }
91841
91611
  async function openMobiusCliInstallation(signal, environment) {
91842
- await prepareVersionData(package_default.version, signal, environment);
91612
+ const root = readStateDirectory(environment);
91613
+ const version2 = await readCurrentDataVersion(root, signal) ?? package_default.version;
91614
+ return await openMobiusVersionInstallation(version2, signal, environment);
91615
+ }
91616
+ async function openMobiusVersionInstallation(version2, signal, environment) {
91843
91617
  return await openRuntimeInstallationStore(
91844
91618
  {
91845
91619
  applicationId: MOBIUS_CLI_APPLICATION_ID,
91846
- stateDirectory: join27(readStateDirectory(environment), "versions", package_default.version)
91620
+ stateDirectory: join26(readStateDirectory(environment), "versions", version2)
91847
91621
  },
91848
91622
  signal
91849
91623
  );
@@ -91882,11 +91656,11 @@ var init_pair_local_machine = __esm({
91882
91656
  init_resolve_catalog_agent();
91883
91657
  init_config();
91884
91658
  init_runtime_installation_store();
91659
+ init_version_data();
91885
91660
  init_local_files();
91886
91661
  init_state_directory();
91887
91662
  init_environment_proxy();
91888
91663
  init_value_utils();
91889
- init_data();
91890
91664
  PAIRING_TIMEOUT_MILLISECONDS = 2e4;
91891
91665
  PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
91892
91666
  TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
@@ -92115,20 +91889,20 @@ var init_agents = __esm({
92115
91889
  });
92116
91890
 
92117
91891
  // src/storage/daemon/manager-lock.ts
92118
- import { readFile as readFile9, unlink as unlink4, writeFile as writeFile4 } from "node:fs/promises";
92119
- import { join as join28 } from "node:path";
91892
+ import { readFile as readFile8, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
91893
+ import { join as join27 } from "node:path";
92120
91894
  async function acquireManagerLock(stateDirectory, name2 = "manager.lock") {
92121
- const path8 = join28(stateDirectory, name2);
91895
+ const path8 = join27(stateDirectory, name2);
92122
91896
  for (let attempt = 0; attempt < 2; attempt += 1) {
92123
91897
  try {
92124
- await writeFile4(path8, `${process.pid.toString()}
91898
+ await writeFile3(path8, `${process.pid.toString()}
92125
91899
  `, { flag: "wx", mode: 384 });
92126
91900
  return async () => await unlink4(path8).catch(() => void 0);
92127
91901
  } catch (cause) {
92128
91902
  if (!isNodeError(cause, "EEXIST")) {
92129
91903
  throw cause;
92130
91904
  }
92131
- const encoded = await readFile9(path8, "utf8").catch(() => "");
91905
+ const encoded = await readFile8(path8, "utf8").catch(() => "");
92132
91906
  const pid = Number(encoded.trim());
92133
91907
  if (Number.isSafeInteger(pid) && pid > 1) {
92134
91908
  try {
@@ -92147,7 +91921,7 @@ async function acquireManagerLock(stateDirectory, name2 = "manager.lock") {
92147
91921
  }
92148
91922
  async function managerLockExists(stateDirectory) {
92149
91923
  try {
92150
- await readFile9(join28(stateDirectory, "manager.lock"), "utf8");
91924
+ await readFile8(join27(stateDirectory, "manager.lock"), "utf8");
92151
91925
  return true;
92152
91926
  } catch (cause) {
92153
91927
  if (isNodeError(cause, "ENOENT")) {
@@ -92163,6 +91937,125 @@ var init_manager_lock = __esm({
92163
91937
  }
92164
91938
  });
92165
91939
 
91940
+ // src/storage/daemon/control-token.ts
91941
+ import { randomBytes } from "node:crypto";
91942
+ import { readFile as readFile9, writeFile as writeFile4 } from "node:fs/promises";
91943
+ import { join as join28 } from "node:path";
91944
+ function controlTokenPath(stateDirectory) {
91945
+ return join28(stateDirectory, "manager.token");
91946
+ }
91947
+ async function readOrCreateControlToken(stateDirectory) {
91948
+ const path8 = controlTokenPath(stateDirectory);
91949
+ try {
91950
+ return (await readFile9(path8, "utf8")).trim();
91951
+ } catch (cause) {
91952
+ if (!isNodeError(cause, "ENOENT")) {
91953
+ throw cause;
91954
+ }
91955
+ }
91956
+ const token = randomBytes(32).toString("base64url");
91957
+ try {
91958
+ await writeFile4(path8, `${token}
91959
+ `, { flag: "wx", mode: 384 });
91960
+ return token;
91961
+ } catch (cause) {
91962
+ if (!isNodeError(cause, "EEXIST")) {
91963
+ throw cause;
91964
+ }
91965
+ return (await readFile9(path8, "utf8")).trim();
91966
+ }
91967
+ }
91968
+ var init_control_token = __esm({
91969
+ "src/storage/daemon/control-token.ts"() {
91970
+ "use strict";
91971
+ init_node_error();
91972
+ }
91973
+ });
91974
+
91975
+ // src/daemon/control/local-client.ts
91976
+ import { createHash as createHash6 } from "node:crypto";
91977
+ import { createConnection } from "node:net";
91978
+ function controlSocketPath(stateDirectory, endpoint = "manager") {
91979
+ const installationHash = createHash6("sha256").update(endpoint === "manager" ? stateDirectory : `${stateDirectory}:worker`).digest("hex").slice(0, 32);
91980
+ return managerPlatform.controlSocketPath(installationHash);
91981
+ }
91982
+ async function readSocketMessage(socket, signal) {
91983
+ signal.throwIfAborted();
91984
+ return await new Promise((resolve21, reject2) => {
91985
+ let encoded = "";
91986
+ const finish = (error62, value) => {
91987
+ signal.removeEventListener("abort", abort);
91988
+ socket.removeAllListeners("data");
91989
+ socket.removeAllListeners("error");
91990
+ socket.removeAllListeners("end");
91991
+ if (error62 === void 0) {
91992
+ resolve21(value);
91993
+ } else {
91994
+ reject2(error62);
91995
+ }
91996
+ };
91997
+ const abort = () => {
91998
+ socket.destroy();
91999
+ finish(signal.reason);
92000
+ };
92001
+ socket.on("data", (chunk) => {
92002
+ encoded += chunk.toString("utf8");
92003
+ if (encoded.length > MAXIMUM_MESSAGE_BYTES) {
92004
+ finish(new Error("The manager message is too large"));
92005
+ socket.destroy();
92006
+ return;
92007
+ }
92008
+ const newline = encoded.indexOf("\n");
92009
+ if (newline >= 0) {
92010
+ try {
92011
+ finish(void 0, JSON.parse(encoded.slice(0, newline)));
92012
+ } catch (cause) {
92013
+ finish(cause);
92014
+ }
92015
+ }
92016
+ });
92017
+ socket.once("error", finish);
92018
+ socket.once("end", () => finish(new Error("The manager connection closed without a response")));
92019
+ signal.addEventListener("abort", abort, { once: true });
92020
+ });
92021
+ }
92022
+ async function sendLocalRequest(stateDirectory, endpoint, command, signal) {
92023
+ const token = await readOrCreateControlToken(stateDirectory);
92024
+ const deadline = AbortSignal.any([signal, AbortSignal.timeout(CONTROL_TIMEOUT_MILLISECONDS)]);
92025
+ deadline.throwIfAborted();
92026
+ const socket = createConnection(controlSocketPath(stateDirectory, endpoint));
92027
+ try {
92028
+ await new Promise((resolve21, reject2) => {
92029
+ const abort = () => {
92030
+ socket.destroy();
92031
+ reject2(deadline.reason);
92032
+ };
92033
+ socket.once("connect", () => {
92034
+ deadline.removeEventListener("abort", abort);
92035
+ resolve21();
92036
+ });
92037
+ socket.once("error", reject2);
92038
+ deadline.addEventListener("abort", abort, { once: true });
92039
+ });
92040
+ socket.write(`${JSON.stringify({ ...command, token })}
92041
+ `);
92042
+ return await readSocketMessage(socket, deadline);
92043
+ } finally {
92044
+ socket.destroy();
92045
+ }
92046
+ }
92047
+ var CONTROL_TIMEOUT_MILLISECONDS, MAXIMUM_MESSAGE_BYTES, managerPlatform;
92048
+ var init_local_client = __esm({
92049
+ "src/daemon/control/local-client.ts"() {
92050
+ "use strict";
92051
+ init_control_token();
92052
+ init_platform();
92053
+ CONTROL_TIMEOUT_MILLISECONDS = 13e4;
92054
+ MAXIMUM_MESSAGE_BYTES = 64 * 1024;
92055
+ managerPlatform = platformSupportFor(process.platform);
92056
+ }
92057
+ });
92058
+
92166
92059
  // src/daemon/control/local-server.ts
92167
92060
  import { createServer } from "node:net";
92168
92061
  async function serveLocalControl(stateDirectory, endpoint, signal, handle, onListening = () => void 0, onResponse = () => void 0) {
@@ -92233,6 +92126,121 @@ var init_local_server = __esm({
92233
92126
  }
92234
92127
  });
92235
92128
 
92129
+ // src/daemon/control/protocol.ts
92130
+ var workerLaunch, transition, daemonSwitchState, lifecycleCommand, lifecycleResponse;
92131
+ var init_protocol2 = __esm({
92132
+ "src/daemon/control/protocol.ts"() {
92133
+ "use strict";
92134
+ init_zod();
92135
+ workerLaunch = external_exports.object({
92136
+ executable: external_exports.string().min(1),
92137
+ entry: external_exports.string().min(1),
92138
+ version: external_exports.string().min(1).max(128)
92139
+ }).readonly();
92140
+ transition = {
92141
+ id: external_exports.string().min(1).max(256),
92142
+ context: external_exports.string().max(256),
92143
+ previous: workerLaunch,
92144
+ next: workerLaunch
92145
+ };
92146
+ daemonSwitchState = external_exports.discriminatedUnion("kind", [
92147
+ external_exports.object({ ...transition, kind: external_exports.literal("switching") }),
92148
+ external_exports.object({ ...transition, kind: external_exports.literal("switched") }),
92149
+ external_exports.object({
92150
+ ...transition,
92151
+ kind: external_exports.literal("rolled-back"),
92152
+ code: external_exports.string(),
92153
+ message: external_exports.string(),
92154
+ stdout: external_exports.string().max(4096),
92155
+ stderr: external_exports.string().max(4096),
92156
+ retryAfter: external_exports.number().int().nonnegative()
92157
+ })
92158
+ ]).readonly();
92159
+ lifecycleCommand = external_exports.discriminatedUnion("kind", [
92160
+ external_exports.object({ kind: external_exports.literal("status") }),
92161
+ external_exports.object({ kind: external_exports.literal("ensure"), launch: workerLaunch }),
92162
+ external_exports.object({ kind: external_exports.literal("stop") }),
92163
+ external_exports.object({
92164
+ kind: external_exports.literal("switch"),
92165
+ id: external_exports.string().min(1).max(256),
92166
+ context: external_exports.string().max(256),
92167
+ launch: workerLaunch
92168
+ }),
92169
+ external_exports.object({ kind: external_exports.literal("switch-status"), wait: external_exports.boolean() })
92170
+ ]).readonly();
92171
+ lifecycleResponse = external_exports.discriminatedUnion("kind", [
92172
+ external_exports.object({
92173
+ kind: external_exports.literal("status"),
92174
+ protocolVersion: external_exports.literal(2),
92175
+ worker: external_exports.object({ pid: external_exports.number().int().positive(), version: external_exports.string() }).readonly().nullable()
92176
+ }),
92177
+ external_exports.object({ kind: external_exports.literal("switch-status"), state: daemonSwitchState.nullable() }),
92178
+ external_exports.object({ kind: external_exports.literal("stopped") }),
92179
+ external_exports.object({ kind: external_exports.literal("switching") }),
92180
+ external_exports.object({ kind: external_exports.literal("error"), code: external_exports.string(), message: external_exports.string() })
92181
+ ]).readonly();
92182
+ }
92183
+ });
92184
+
92185
+ // src/daemon/control/switch-status.ts
92186
+ async function readSwitchStatus(directory, signal, wait = false) {
92187
+ const response = lifecycleResponse.parse(
92188
+ await sendLocalRequest(directory, "manager", { kind: "switch-status", wait }, signal)
92189
+ );
92190
+ if (response.kind !== "switch-status") {
92191
+ throw new Error("The manager could not return the switch status");
92192
+ }
92193
+ return response.state;
92194
+ }
92195
+ var init_switch_status = __esm({
92196
+ "src/daemon/control/switch-status.ts"() {
92197
+ "use strict";
92198
+ init_local_client();
92199
+ init_protocol2();
92200
+ }
92201
+ });
92202
+
92203
+ // src/daemon/upgrades/data.ts
92204
+ async function prepareVersionData(version2, signal, environment = process.env, fallbackVersion = null) {
92205
+ signal.throwIfAborted();
92206
+ const root = readStateDirectory(environment);
92207
+ const targetVersion = runtimeUpgradeVersionSchema.parse(version2);
92208
+ if (await versionDataExists(root, targetVersion, signal)) {
92209
+ return;
92210
+ }
92211
+ const previous = await readCurrentDataVersion(root, signal) ?? fallbackVersion;
92212
+ if (previous === null) {
92213
+ return;
92214
+ }
92215
+ const leftBehind = await copyVersionData(root, runtimeUpgradeVersionSchema.parse(previous), targetVersion, signal);
92216
+ for (const entry of leftBehind) {
92217
+ process.stderr.write(
92218
+ `Mobius did not carry ${entry} into version ${targetVersion}: an earlier Mobius ran with that installation as its state root.
92219
+ `
92220
+ );
92221
+ }
92222
+ }
92223
+ async function discardRolledBackData(version2, signal) {
92224
+ await discardVersionData(readStateDirectory(), runtimeUpgradeVersionSchema.parse(version2), signal);
92225
+ }
92226
+ async function recordCurrentData(version2, signal) {
92227
+ await writeCurrentDataVersion(readStateDirectory(), runtimeUpgradeVersionSchema.parse(version2), signal);
92228
+ }
92229
+ async function prepareUpgradeData(controlDirectory, version2, signal) {
92230
+ const transition2 = await readSwitchStatus(controlDirectory, signal);
92231
+ const previous = transition2?.kind === "switching" && transition2.next.version === version2 ? transition2.previous.version : null;
92232
+ await prepareVersionData(version2, signal, process.env, previous);
92233
+ }
92234
+ var init_data = __esm({
92235
+ "src/daemon/upgrades/data.ts"() {
92236
+ "use strict";
92237
+ init_protocol();
92238
+ init_version_data();
92239
+ init_state_directory();
92240
+ init_switch_status();
92241
+ }
92242
+ });
92243
+
92236
92244
  // src/storage/logs/bounded-log.ts
92237
92245
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
92238
92246
  import { join as join29 } from "node:path";
@@ -93166,7 +93174,9 @@ async function waitForManagerExit(stateDirectory, signal) {
93166
93174
  }
93167
93175
  throw deadline.reason;
93168
93176
  }
93169
- async function ensureWorkingProcess(stateDirectory, version2, signal) {
93177
+ async function ensureWorkingProcess(stateDirectory, cliVersion, signal) {
93178
+ const current = await readCurrentDataVersion(readStateDirectory(), signal);
93179
+ const version2 = current !== null && (0, import_semver2.gt)(current, cliVersion) ? current : cliVersion;
93170
93180
  const launch = await prepareDaemonReleaseVersion(version2, signal);
93171
93181
  const deadline = AbortSignal.any([signal, AbortSignal.timeout(CONTROL_TIMEOUT_MILLISECONDS)]);
93172
93182
  await ensureManager(stateDirectory, launch, deadline);
@@ -93179,6 +93189,7 @@ async function ensureWorkingProcess(stateDirectory, version2, signal) {
93179
93189
  if (response.kind !== "status" || response.worker?.version !== version2) {
93180
93190
  throw new Error("The working daemon did not start");
93181
93191
  }
93192
+ return version2;
93182
93193
  }
93183
93194
  async function readWorkingProcessVersion(stateDirectory, signal) {
93184
93195
  try {
@@ -93254,10 +93265,14 @@ async function stopManager(stateDirectory, signal) {
93254
93265
  throw cause;
93255
93266
  }
93256
93267
  }
93268
+ var import_semver2;
93257
93269
  var init_manager_client = __esm({
93258
93270
  "src/daemon/lifecycle/manager-client.ts"() {
93259
93271
  "use strict";
93272
+ import_semver2 = __toESM(require_semver2(), 1);
93260
93273
  init_manager_lock();
93274
+ init_version_data();
93275
+ init_state_directory();
93261
93276
  init_node_error();
93262
93277
  init_local_client();
93263
93278
  init_protocol2();
@@ -93319,6 +93334,20 @@ var init_acp_session = __esm({
93319
93334
  }
93320
93335
  });
93321
93336
 
93337
+ // src/schema/acp-session-store/execution-identity.ts
93338
+ var executionIdentity;
93339
+ var init_execution_identity = __esm({
93340
+ "src/schema/acp-session-store/execution-identity.ts"() {
93341
+ "use strict";
93342
+ init_sqlite_core();
93343
+ executionIdentity = sqliteTable("execution_identity", {
93344
+ commandId: text("command_id").primaryKey(),
93345
+ sessionId: text("session_id").notNull(),
93346
+ commandHash: text("command_hash").notNull()
93347
+ });
93348
+ }
93349
+ });
93350
+
93322
93351
  // src/schema/acp-session-store/execution-receipt.ts
93323
93352
  var executionReceipt;
93324
93353
  var init_execution_receipt = __esm({
@@ -93356,6 +93385,7 @@ var init_acp_session_store = __esm({
93356
93385
  "src/schema/acp-session-store/index.ts"() {
93357
93386
  "use strict";
93358
93387
  init_acp_session();
93388
+ init_execution_identity();
93359
93389
  init_execution_receipt();
93360
93390
  init_session_live_event_position_allocation();
93361
93391
  }
@@ -93406,7 +93436,7 @@ var init_acp_session_table = __esm({
93406
93436
  });
93407
93437
 
93408
93438
  // src/storage/session/execution-receipt-table.ts
93409
- var receiptFields, receiptSchema, ExecutionReceiptTable;
93439
+ var receiptFields, receiptSchema, identitySchema, ExecutionReceiptTable;
93410
93440
  var init_execution_receipt_table = __esm({
93411
93441
  "src/storage/session/execution-receipt-table.ts"() {
93412
93442
  "use strict";
@@ -93429,11 +93459,16 @@ var init_execution_receipt_table = __esm({
93429
93459
  outcome: external_exports.string().nullable()
93430
93460
  })
93431
93461
  ]).readonly();
93462
+ identitySchema = external_exports.object({ sessionId: external_exports.string(), commandHash: external_exports.string() }).readonly();
93432
93463
  ExecutionReceiptTable = class {
93433
93464
  #database;
93434
93465
  constructor(database) {
93435
93466
  this.#database = database;
93436
93467
  }
93468
+ identity = (commandId) => {
93469
+ const row = this.#database.orm.select({ sessionId: executionIdentity.sessionId, commandHash: executionIdentity.commandHash }).from(executionIdentity).where(eq2(executionIdentity.commandId, commandId)).get();
93470
+ return row === void 0 ? void 0 : identitySchema.parse(row);
93471
+ };
93437
93472
  list = () => receiptSchema.array().parse(
93438
93473
  this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
93439
93474
  );
@@ -93450,7 +93485,7 @@ var init_execution_receipt_table = __esm({
93450
93485
  )
93451
93486
  ).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(1024).all();
93452
93487
  if (retained.length === 1024) {
93453
- this.#database.orm.delete(executionReceipt).where(
93488
+ this.#remove(
93454
93489
  and(
93455
93490
  eq2(executionReceipt.sessionId, receipt.sessionId),
93456
93491
  inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"]),
@@ -93459,12 +93494,25 @@ var init_execution_receipt_table = __esm({
93459
93494
  retained.map((row) => row.commandId)
93460
93495
  )
93461
93496
  )
93462
- ).run();
93497
+ );
93463
93498
  }
93464
93499
  });
93465
93500
  };
93466
93501
  remove = (commandId) => {
93467
- this.#database.orm.delete(executionReceipt).where(eq2(executionReceipt.commandId, commandId)).run();
93502
+ this.#database.transaction(() => this.#remove(eq2(executionReceipt.commandId, commandId)));
93503
+ };
93504
+ #remove = (condition) => {
93505
+ if (condition === void 0) {
93506
+ throw new Error("Execution receipt removal requires a scope");
93507
+ }
93508
+ this.#database.orm.insert(executionIdentity).select(
93509
+ this.#database.orm.select({
93510
+ commandId: executionReceipt.commandId,
93511
+ sessionId: executionReceipt.sessionId,
93512
+ commandHash: executionReceipt.commandHash
93513
+ }).from(executionReceipt).where(and(condition, eq2(executionReceipt.started, true)))
93514
+ ).onConflictDoNothing().run();
93515
+ this.#database.orm.delete(executionReceipt).where(condition).run();
93468
93516
  };
93469
93517
  };
93470
93518
  }
@@ -96864,7 +96912,7 @@ var init_execution_receipts = __esm({
96864
96912
  constructor(table, onCount = () => void 0) {
96865
96913
  this.#onCount = onCount;
96866
96914
  this.#table = table;
96867
- for (const row of table?.list() ?? []) {
96915
+ for (const row of table.list()) {
96868
96916
  this.#executions.set(row.commandId, row);
96869
96917
  this.#recoveredCommands.add(row.commandId);
96870
96918
  if (!isTerminal(row.state)) {
@@ -96880,7 +96928,7 @@ var init_execution_receipts = __esm({
96880
96928
  }
96881
96929
  #save = (commandId, receipt) => {
96882
96930
  if (!this.#closing) {
96883
- this.#table?.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
96931
+ this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
96884
96932
  }
96885
96933
  const previous = this.#executions.get(commandId);
96886
96934
  const wasActive = previous !== void 0 && !isTerminal(previous.state);
@@ -96956,9 +97004,9 @@ var init_execution_receipts = __esm({
96956
97004
  let existing = this.#executions.get(commandId);
96957
97005
  const previous = this.outcome(commandId);
96958
97006
  if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
97007
+ this.#table.remove(commandId);
96959
97008
  this.#executions.delete(commandId);
96960
97009
  this.#recoveredCommands.delete(commandId);
96961
- this.#table?.remove(commandId);
96962
97010
  this.#terminalCountBySession.set(
96963
97011
  sessionId,
96964
97012
  Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
@@ -96977,6 +97025,10 @@ var init_execution_receipts = __esm({
96977
97025
  outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
96978
97026
  };
96979
97027
  }
97028
+ const identity2 = this.#table.identity(commandId);
97029
+ if (identity2 !== void 0) {
97030
+ return identity2.sessionId === sessionId && identity2.commandHash === commandHash ? { kind: "expired" } : { kind: "conflict" };
97031
+ }
96980
97032
  const attemptId = randomUUID14();
96981
97033
  this.#save(commandId, {
96982
97034
  attemptId,
@@ -97027,9 +97079,9 @@ var init_execution_receipts = __esm({
97027
97079
  }
97028
97080
  for (const [commandId, receipt] of this.#executions) {
97029
97081
  if (receipt.sessionId === sessionId && isTerminal(receipt.state)) {
97082
+ this.#table.remove(commandId);
97030
97083
  this.#executions.delete(commandId);
97031
97084
  this.#recoveredCommands.delete(commandId);
97032
- this.#table?.remove(commandId);
97033
97085
  const remaining = (this.#terminalCountBySession.get(sessionId) ?? 1) - 1;
97034
97086
  if (remaining > 0) {
97035
97087
  this.#terminalCountBySession.set(sessionId, remaining);
@@ -100437,6 +100489,16 @@ var init_prompt2 = __esm({
100437
100489
  }
100438
100490
  return;
100439
100491
  }
100492
+ if (receipt.kind === "expired") {
100493
+ send(context.socket, {
100494
+ code: "command_result_expired",
100495
+ requestId: message.commandId,
100496
+ kind: "session.operation.failed",
100497
+ message: "This command already started. Its execution result is no longer available; it will not run again.",
100498
+ sessionId: message.sessionId
100499
+ });
100500
+ return;
100501
+ }
100440
100502
  const turn = context.sessionTurns.start(message, receipt.attemptId);
100441
100503
  context.eventProjection.requested(message);
100442
100504
  const queueChanged = () => {
@@ -102152,7 +102214,7 @@ async function runWorker(version2, signal) {
102152
102214
  async function runWorkerRuntime(version2, combined, shutdown, rejectionGuard) {
102153
102215
  const control = await openMobiusControlInstallation(combined, process.env);
102154
102216
  await prepareUpgradeData(control.stateDirectory, version2, combined);
102155
- const installation = await openMobiusCliInstallation(combined, process.env);
102217
+ const installation = await openMobiusVersionInstallation(version2, combined, process.env);
102156
102218
  const deadline = AbortSignal.any([combined, AbortSignal.timeout(15e3)]);
102157
102219
  let release = null;
102158
102220
  while (release === null) {
@@ -102324,11 +102386,7 @@ function registerUpgradeCommand(program2, context) {
102324
102386
  program2.command("upgrade").description("start the daemon if needed and upgrade it to the newest npm release").action(async () => {
102325
102387
  const signal = context.shutdownSignal;
102326
102388
  const control = await openMobiusControlInstallation(signal, process.env);
102327
- const running = await readWorkingProcessVersion(control.stateDirectory, signal);
102328
- const current = running ?? context.version;
102329
- if (running === null) {
102330
- await ensureWorkingProcess(control.stateDirectory, context.version, signal);
102331
- }
102389
+ const current = await readWorkingProcessVersion(control.stateDirectory, signal) ?? await ensureWorkingProcess(control.stateDirectory, context.version, signal);
102332
102390
  await reloadDaemon(control.stateDirectory, signal);
102333
102391
  const attempt = await requestDaemonReleaseUpgrade(control.stateDirectory, current, signal);
102334
102392
  if (attempt.kind === "current") {
@@ -102804,9 +102862,9 @@ var init_cli = __esm({
102804
102862
  });
102805
102863
 
102806
102864
  // src/cli/entrypoint.ts
102807
- var import_semver2 = __toESM(require_semver2(), 1);
102865
+ var import_semver3 = __toESM(require_semver2(), 1);
102808
102866
  init_package();
102809
- if (!(0, import_semver2.satisfies)(process.versions.node, package_default.engines.node)) {
102867
+ if (!(0, import_semver3.satisfies)(process.versions.node, package_default.engines.node)) {
102810
102868
  process.stderr.write(
102811
102869
  `Mobius requires Node.js ${package_default.engines.node}; found ${process.versions.node} at ${process.execPath}. Update Node.js and reinstall Mobius.
102812
102870
  `