@moxt-ai/mobius 0.0.13 → 0.0.15

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 (91) hide show
  1. package/dist/acp/create-client.d.ts.map +1 -1
  2. package/dist/acp/create-client.js +16 -1
  3. package/dist/acp/create-client.js.map +1 -1
  4. package/dist/agent-catalog/agent-discovery.d.ts +1 -1
  5. package/dist/agent-catalog/agent-discovery.d.ts.map +1 -1
  6. package/dist/agent-catalog/agent-discovery.js +2 -2
  7. package/dist/agent-catalog/agent-discovery.js.map +1 -1
  8. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts +13 -0
  9. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts.map +1 -0
  10. package/dist/agent-catalog/agents/cursor-cli-agent.js +25 -0
  11. package/dist/agent-catalog/agents/cursor-cli-agent.js.map +1 -0
  12. package/dist/agent-catalog/agents/grok-build-agent.d.ts +18 -0
  13. package/dist/agent-catalog/agents/grok-build-agent.d.ts.map +1 -0
  14. package/dist/agent-catalog/agents/grok-build-agent.js +75 -0
  15. package/dist/agent-catalog/agents/grok-build-agent.js.map +1 -0
  16. package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -1
  17. package/dist/agent-catalog/agents/supported-agent-specifications.js +6 -0
  18. package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
  19. package/dist/agent-catalog/agents/verify-session-creation.d.ts +3 -0
  20. package/dist/agent-catalog/agents/verify-session-creation.d.ts.map +1 -0
  21. package/dist/agent-catalog/agents/verify-session-creation.js +16 -0
  22. package/dist/agent-catalog/agents/verify-session-creation.js.map +1 -0
  23. package/dist/agent-catalog/agents/workbuddy-agent.d.ts +15 -0
  24. package/dist/agent-catalog/agents/workbuddy-agent.d.ts.map +1 -0
  25. package/dist/agent-catalog/agents/workbuddy-agent.js +41 -0
  26. package/dist/agent-catalog/agents/workbuddy-agent.js.map +1 -0
  27. package/dist/agent-catalog/discover-local-agents.d.ts +3 -0
  28. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  29. package/dist/agent-catalog/discover-local-agents.js +4 -10
  30. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  31. package/dist/agent-catalog/local-agent.d.ts +1 -2
  32. package/dist/agent-catalog/local-agent.d.ts.map +1 -1
  33. package/dist/agent-catalog/local-agent.js +1 -3
  34. package/dist/agent-catalog/local-agent.js.map +1 -1
  35. package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
  36. package/dist/agent-catalog/publish-agent-catalog.js +0 -1
  37. package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
  38. package/dist/agent-installation/agent-installation-manager.d.ts +1 -8
  39. package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
  40. package/dist/agent-installation/agent-installation-manager.js +7 -24
  41. package/dist/agent-installation/agent-installation-manager.js.map +1 -1
  42. package/dist/agent-installation/fixed-agent-install-recipe.d.ts +20 -0
  43. package/dist/agent-installation/fixed-agent-install-recipe.d.ts.map +1 -0
  44. package/dist/agent-installation/fixed-agent-install-recipe.js +18 -0
  45. package/dist/agent-installation/fixed-agent-install-recipe.js.map +1 -0
  46. package/dist/agent-installation/fixed-agent-install-recipes.d.ts +5 -18
  47. package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
  48. package/dist/agent-installation/fixed-agent-install-recipes.js +9 -16
  49. package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
  50. package/dist/agent-installation/grok-build-install-recipe.d.ts +12 -0
  51. package/dist/agent-installation/grok-build-install-recipe.d.ts.map +1 -0
  52. package/dist/agent-installation/grok-build-install-recipe.js +102 -0
  53. package/dist/agent-installation/grok-build-install-recipe.js.map +1 -0
  54. package/dist/agent-installation/grok-managed-package.d.ts +4 -0
  55. package/dist/agent-installation/grok-managed-package.d.ts.map +1 -0
  56. package/dist/agent-installation/grok-managed-package.js +34 -0
  57. package/dist/agent-installation/grok-managed-package.js.map +1 -0
  58. package/dist/agent-installation/managed-npm-package.d.ts +8 -0
  59. package/dist/agent-installation/managed-npm-package.d.ts.map +1 -1
  60. package/dist/agent-installation/managed-npm-package.js +32 -3
  61. package/dist/agent-installation/managed-npm-package.js.map +1 -1
  62. package/dist/agent-installation/workbuddy-install-recipe.d.ts +12 -0
  63. package/dist/agent-installation/workbuddy-install-recipe.d.ts.map +1 -0
  64. package/dist/agent-installation/workbuddy-install-recipe.js +51 -0
  65. package/dist/agent-installation/workbuddy-install-recipe.js.map +1 -0
  66. package/dist/agent-installation/workbuddy-managed-package.d.ts +10 -0
  67. package/dist/agent-installation/workbuddy-managed-package.d.ts.map +1 -0
  68. package/dist/agent-installation/workbuddy-managed-package.js +11 -0
  69. package/dist/agent-installation/workbuddy-managed-package.js.map +1 -0
  70. package/dist/cli.js +1289 -837
  71. package/dist/cli.js.map +4 -4
  72. package/dist/config.d.ts.map +1 -1
  73. package/dist/config.js +2 -1
  74. package/dist/config.js.map +1 -1
  75. package/dist/index.js +1411 -959
  76. package/dist/index.js.map +4 -4
  77. package/dist/pairing/pair-local-machine.d.ts.map +1 -1
  78. package/dist/pairing/pair-local-machine.js +3 -3
  79. package/dist/pairing/pair-local-machine.js.map +1 -1
  80. package/dist/run-daemon.d.ts.map +1 -1
  81. package/dist/run-daemon.js +3 -12
  82. package/dist/run-daemon.js.map +1 -1
  83. package/package.json +2 -2
  84. package/dist/agent-installation/installation-grants.d.ts +0 -2
  85. package/dist/agent-installation/installation-grants.d.ts.map +0 -1
  86. package/dist/agent-installation/installation-grants.js +0 -51
  87. package/dist/agent-installation/installation-grants.js.map +0 -1
  88. package/dist/agent-installation/local-installation-authorizer.d.ts +0 -7
  89. package/dist/agent-installation/local-installation-authorizer.d.ts.map +0 -1
  90. package/dist/agent-installation/local-installation-authorizer.js +0 -32
  91. package/dist/agent-installation/local-installation-authorizer.js.map +0 -1
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/cli.ts
9
- import { mkdir as mkdir5 } from "node:fs/promises";
9
+ import { mkdir as mkdir6 } from "node:fs/promises";
10
10
 
11
11
  // src/agent-catalog/local-agent.ts
12
12
  import { realpathSync, statSync } from "node:fs";
@@ -521,11 +521,9 @@ var LocalAgentDefinition = class {
521
521
  var InstallableAgentDefinition = class {
522
522
  id;
523
523
  label;
524
- requiresLocalApproval;
525
- constructor(id, label, requiresLocalApproval = true) {
524
+ constructor(id, label) {
526
525
  this.id = id;
527
526
  this.label = label;
528
- this.requiresLocalApproval = requiresLocalApproval;
529
527
  }
530
528
  };
531
529
  var LocalAgentCatalogSnapshot = class {
@@ -644,7 +642,7 @@ var LocalAgentInventory = class {
644
642
  discoveries;
645
643
  installable;
646
644
  unavailable;
647
- constructor(discoveries, grantedAgents = /* @__PURE__ */ new Set(), platform = process.platform, architecture = process.arch) {
645
+ constructor(discoveries, platform = process.platform, architecture = process.arch) {
648
646
  const available = [];
649
647
  const unavailable = [];
650
648
  for (const discovery of discoveries) {
@@ -667,8 +665,7 @@ var LocalAgentInventory = class {
667
665
  ).map(
668
666
  (discovery) => new InstallableAgentDefinition(
669
667
  discovery.specification.id,
670
- discovery.specification.label,
671
- !grantedAgents.has(discovery.specification.id)
668
+ discovery.specification.label
672
669
  )
673
670
  )
674
671
  );
@@ -752,70 +749,17 @@ function formatAgentDiagnostics(inventory, json2) {
752
749
  `;
753
750
  }
754
751
 
755
- // src/agent-installation/installation-grants.ts
756
- import { open } from "node:fs/promises";
757
- import { join as join2 } from "node:path";
758
- var MAX_GRANT_FILE_LENGTH = 16 * 1024;
759
- var AGENT_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
760
- function isRecord(value) {
761
- return typeof value === "object" && value !== null && !Array.isArray(value);
762
- }
763
- async function readGrantedAgents(stateDirectory) {
764
- const path2 = join2(stateDirectory, "installation-grants.json");
765
- let handle;
766
- try {
767
- handle = await open(path2, "r");
768
- } catch (error61) {
769
- if (error61 instanceof Error && "code" in error61 && error61.code === "ENOENT") {
770
- return /* @__PURE__ */ new Set();
771
- }
772
- throw error61;
773
- }
774
- try {
775
- const metadata = await handle.stat();
776
- if (!metadata.isFile() || metadata.size > MAX_GRANT_FILE_LENGTH || typeof process.getuid === "function" && metadata.uid !== process.getuid() || process.platform !== "win32" && (metadata.mode & 63) !== 0) {
777
- throw new Error("The local installation grant file is not private");
778
- }
779
- const encoded = await handle.readFile({ encoding: "utf8" });
780
- const value = JSON.parse(encoded);
781
- if (!isRecord(value) || Object.keys(value).length !== 1 || !Array.isArray(value["agents"])) {
782
- throw new Error("The local installation grant file is invalid");
783
- }
784
- const agents = /* @__PURE__ */ new Set();
785
- for (const candidate of value["agents"]) {
786
- if (typeof candidate !== "string" || !AGENT_ID_PATTERN.test(candidate) || agents.has(candidate)) {
787
- throw new Error("The local installation grant file is invalid");
788
- }
789
- agents.add(candidate);
790
- }
791
- return agents;
792
- } finally {
793
- await handle.close();
794
- }
795
- }
796
-
797
- // src/storage/state-directory.ts
798
- import { homedir } from "node:os";
799
- import { join as join3, resolve as resolve2 } from "node:path";
800
- function readStateDirectory(environment = process.env) {
801
- const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
802
- if (configured !== void 0 && configured.length > 0) {
803
- return resolve2(configured);
804
- }
805
- return join3(homedir(), ".mobius");
806
- }
807
-
808
752
  // src/agent-installation/managed-npm-package.ts
809
753
  import {
810
754
  mkdir,
811
755
  mkdtemp,
812
- open as open2,
756
+ open,
813
757
  realpath as realpath2,
814
758
  rename,
815
759
  rm,
816
760
  stat as stat2
817
761
  } from "node:fs/promises";
818
- import { delimiter, dirname, isAbsolute, join as join4, relative, sep } from "node:path";
762
+ import { delimiter, dirname, isAbsolute, join as join2, relative, sep } from "node:path";
819
763
  var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
820
764
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
821
765
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -834,6 +778,7 @@ var ManagedNpmPackageDefinition = class {
834
778
  };
835
779
  var SriManagedNpmPackageDefinition = class extends ManagedNpmPackageDefinition {
836
780
  integrity;
781
+ requiredDependencies = Object.freeze([]);
837
782
  tarballUrl;
838
783
  constructor(packageName, version2, executableName, integrity, tarballUrl) {
839
784
  super(packageName, version2, executableName);
@@ -841,6 +786,18 @@ var SriManagedNpmPackageDefinition = class extends ManagedNpmPackageDefinition {
841
786
  this.tarballUrl = tarballUrl;
842
787
  }
843
788
  };
789
+ var SriManagedNpmDependencyDefinition = class {
790
+ integrity;
791
+ packageName;
792
+ tarballUrl;
793
+ version;
794
+ constructor(packageName, version2, integrity, tarballUrl) {
795
+ this.integrity = integrity;
796
+ this.packageName = packageName;
797
+ this.tarballUrl = tarballUrl;
798
+ this.version = version2;
799
+ }
800
+ };
844
801
  var ManagedNpmPackageError = class extends Error {
845
802
  code;
846
803
  constructor(code, message, options = {}) {
@@ -849,11 +806,11 @@ var ManagedNpmPackageError = class extends Error {
849
806
  this.name = "ManagedNpmPackageError";
850
807
  }
851
808
  };
852
- function isRecord2(value) {
809
+ function isRecord(value) {
853
810
  return typeof value === "object" && value !== null && !Array.isArray(value);
854
811
  }
855
812
  function packagePath(root, packageName) {
856
- return join4(root, "node_modules", ...packageName.split("/"));
813
+ return join2(root, "node_modules", ...packageName.split("/"));
857
814
  }
858
815
  function isContainedPath(root, candidate) {
859
816
  const difference = relative(root, candidate);
@@ -861,7 +818,7 @@ function isContainedPath(root, candidate) {
861
818
  }
862
819
  async function readJsonRecord(path2, maximumBytes) {
863
820
  try {
864
- const handle = await open2(path2, "r");
821
+ const handle = await open(path2, "r");
865
822
  try {
866
823
  const metadata = await handle.stat();
867
824
  if (!metadata.isFile() || metadata.size > maximumBytes) {
@@ -873,7 +830,7 @@ async function readJsonRecord(path2, maximumBytes) {
873
830
  const value = JSON.parse(
874
831
  await handle.readFile({ encoding: "utf8" })
875
832
  );
876
- if (!isRecord2(value)) {
833
+ if (!isRecord(value)) {
877
834
  throw new ManagedNpmPackageError(
878
835
  "managed_package_verification_failed",
879
836
  "The managed npm package metadata is invalid"
@@ -899,7 +856,7 @@ function readBinPath(packageMetadata, executableName) {
899
856
  if (typeof bin === "string") {
900
857
  return bin;
901
858
  }
902
- if (isRecord2(bin) && typeof bin[executableName] === "string") {
859
+ if (isRecord(bin) && typeof bin[executableName] === "string") {
903
860
  return bin[executableName];
904
861
  }
905
862
  throw new ManagedNpmPackageError(
@@ -907,7 +864,7 @@ function readBinPath(packageMetadata, executableName) {
907
864
  "The managed npm package executable declaration is invalid"
908
865
  );
909
866
  }
910
- function verifyPackageLock(lock, definition) {
867
+ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
911
868
  if (lock["lockfileVersion"] !== 3) {
912
869
  throw new ManagedNpmPackageError(
913
870
  "managed_package_verification_failed",
@@ -915,7 +872,7 @@ function verifyPackageLock(lock, definition) {
915
872
  );
916
873
  }
917
874
  const packages = lock["packages"];
918
- if (!isRecord2(packages)) {
875
+ if (!isRecord(packages)) {
919
876
  throw new ManagedNpmPackageError(
920
877
  "managed_package_verification_failed",
921
878
  "The managed npm package lockfile is invalid"
@@ -926,10 +883,10 @@ function verifyPackageLock(lock, definition) {
926
883
  let matches = 0;
927
884
  for (const [key, candidate] of Object.entries(packages)) {
928
885
  const normalizedKey = key.replaceAll("\\", "/");
929
- if (definition.verifyDependencyClosure && normalizedKey.length > 0) {
886
+ if (verifyDependencyClosure && normalizedKey.length > 0) {
930
887
  let resolved;
931
888
  try {
932
- if (!normalizedKey.split("/").includes("node_modules") || !isRecord2(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
889
+ if (!normalizedKey.split("/").includes("node_modules") || !isRecord(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
933
890
  throw new Error("Invalid locked dependency");
934
891
  }
935
892
  resolved = new URL(candidate["resolved"]);
@@ -952,13 +909,35 @@ function verifyPackageLock(lock, definition) {
952
909
  matches += 1;
953
910
  }
954
911
  }
955
- if (matches !== 1 || !isRecord2(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
912
+ if (matches !== 1 || !isRecord(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
956
913
  throw new ManagedNpmPackageError(
957
914
  "managed_package_verification_failed",
958
915
  "The managed npm package lockfile does not match the pinned artifact"
959
916
  );
960
917
  }
961
918
  }
919
+ async function verifyRequiredDependency(rootPath, lock, definition) {
920
+ const dependencyRoot = await realpath2(
921
+ packagePath(rootPath, definition.packageName)
922
+ );
923
+ if (!isContainedPath(rootPath, dependencyRoot)) {
924
+ throw new ManagedNpmPackageError(
925
+ "managed_package_verification_failed",
926
+ "The required managed npm dependency escaped its private cache"
927
+ );
928
+ }
929
+ const metadata = await readJsonRecord(
930
+ join2(dependencyRoot, "package.json"),
931
+ PACKAGE_METADATA_LIMIT_BYTES
932
+ );
933
+ if (metadata["name"] !== definition.packageName || metadata["version"] !== definition.version) {
934
+ throw new ManagedNpmPackageError(
935
+ "managed_package_verification_failed",
936
+ "The required managed npm dependency identity is invalid"
937
+ );
938
+ }
939
+ verifyPackageLockEntry(lock, definition, false);
940
+ }
962
941
  async function validateManagedNpmPackage(root, definition) {
963
942
  try {
964
943
  return await validateManagedNpmPackageContents(root, definition);
@@ -985,7 +964,7 @@ async function validateManagedNpmPackageContents(root, definition) {
985
964
  );
986
965
  }
987
966
  const metadata = await readJsonRecord(
988
- join4(packageRoot, "package.json"),
967
+ join2(packageRoot, "package.json"),
989
968
  PACKAGE_METADATA_LIMIT_BYTES
990
969
  );
991
970
  if (metadata["name"] !== definition.packageName || metadata["version"] !== definition.version) {
@@ -995,17 +974,22 @@ async function validateManagedNpmPackageContents(root, definition) {
995
974
  );
996
975
  }
997
976
  if (definition instanceof SriManagedNpmPackageDefinition) {
998
- verifyPackageLock(
999
- await readJsonRecord(
1000
- join4(rootPath, "package-lock.json"),
1001
- PACKAGE_LOCK_LIMIT_BYTES
1002
- ),
1003
- definition
977
+ const lock = await readJsonRecord(
978
+ join2(rootPath, "package-lock.json"),
979
+ PACKAGE_LOCK_LIMIT_BYTES
980
+ );
981
+ verifyPackageLockEntry(
982
+ lock,
983
+ definition,
984
+ definition.verifyDependencyClosure
1004
985
  );
986
+ for (const dependency of definition.requiredDependencies) {
987
+ await verifyRequiredDependency(rootPath, lock, dependency);
988
+ }
1005
989
  }
1006
990
  const declaredBin = readBinPath(metadata, definition.executableName);
1007
991
  const executable = await resolveExecutablePath(
1008
- join4(packageRoot, declaredBin)
992
+ join2(packageRoot, declaredBin)
1009
993
  );
1010
994
  if (executable === null || !isContainedPath(rootPath, executable.path)) {
1011
995
  throw new ManagedNpmPackageError(
@@ -1031,7 +1015,7 @@ var ManagedNpmPackageInstaller = class {
1031
1015
  const parent = dirname(root);
1032
1016
  await mkdir(parent, { mode: 448, recursive: true });
1033
1017
  const staging = await mkdtemp(
1034
- join4(parent, `.${definition.version}.staging-`)
1018
+ join2(parent, `.${definition.version}.staging-`)
1035
1019
  );
1036
1020
  try {
1037
1021
  const npm = await findExecutableOnPath(
@@ -1061,9 +1045,9 @@ var ManagedNpmPackageInstaller = class {
1061
1045
  `${definition.packageName}@${definition.version}`
1062
1046
  );
1063
1047
  const installEnvironment = {
1064
- HOME: join4(staging, "home"),
1048
+ HOME: join2(staging, "home"),
1065
1049
  NPM_CONFIG_AUDIT: "false",
1066
- NPM_CONFIG_CACHE: join4(staging, ".npm-cache"),
1050
+ NPM_CONFIG_CACHE: join2(staging, ".npm-cache"),
1067
1051
  NPM_CONFIG_FUND: "false",
1068
1052
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
1069
1053
  NPM_CONFIG_PACKAGE_LOCK: "true",
@@ -1085,8 +1069,8 @@ var ManagedNpmPackageInstaller = class {
1085
1069
  timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS
1086
1070
  });
1087
1071
  await Promise.all([
1088
- rm(join4(staging, ".npm-cache"), { force: true, recursive: true }),
1089
- rm(join4(staging, "home"), { force: true, recursive: true })
1072
+ rm(join2(staging, ".npm-cache"), { force: true, recursive: true }),
1073
+ rm(join2(staging, "home"), { force: true, recursive: true })
1090
1074
  ]);
1091
1075
  await validateManagedNpmPackage(staging, definition);
1092
1076
  try {
@@ -1122,7 +1106,7 @@ var ManagedNpmPackageInstaller = class {
1122
1106
  };
1123
1107
 
1124
1108
  // src/agent-catalog/agent-specification.ts
1125
- import { join as join5 } from "node:path";
1109
+ import { join as join3 } from "node:path";
1126
1110
  var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
1127
1111
  var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
1128
1112
  var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
@@ -1136,7 +1120,7 @@ var LocalAgentSpecification = class {
1136
1120
  resolveManagedAgent = async (stateDirectory, platform, signal) => {
1137
1121
  signal.throwIfAborted();
1138
1122
  const executable = await resolveExecutablePath(
1139
- join5(stateDirectory, ...this.managedAgentExecutablePath),
1123
+ join3(stateDirectory, ...this.managedAgentExecutablePath),
1140
1124
  platform
1141
1125
  );
1142
1126
  signal.throwIfAborted();
@@ -1241,9 +1225,84 @@ var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
1241
1225
  managedAgentExecutablePath = ["agents", "codex", "bin", "codex"];
1242
1226
  };
1243
1227
 
1228
+ // src/agent-catalog/agent-probe-error.ts
1229
+ var AgentProbeError = class extends Error {
1230
+ code;
1231
+ constructor(code, message, options = {}) {
1232
+ super(message, options);
1233
+ this.code = code;
1234
+ this.name = "AgentProbeError";
1235
+ }
1236
+ };
1237
+
1238
+ // src/agent-catalog/agents/verify-session-creation.ts
1239
+ import {
1240
+ methods
1241
+ } from "@agentclientprotocol/sdk";
1242
+ async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
1243
+ const session = await connection.agent.request(
1244
+ methods.agent.session.new,
1245
+ {
1246
+ additionalDirectories: [],
1247
+ cwd: defaultWorkspace,
1248
+ mcpServers: []
1249
+ },
1250
+ { cancellationSignal: signal }
1251
+ );
1252
+ if (session.sessionId.length === 0) {
1253
+ throw new AgentProbeError(
1254
+ "acp_incompatible",
1255
+ `${label} returned an invalid ACP session`
1256
+ );
1257
+ }
1258
+ if (capabilities.sessionCapabilities?.close != null) {
1259
+ await connection.agent.request(
1260
+ methods.agent.session.close,
1261
+ { sessionId: session.sessionId },
1262
+ { cancellationSignal: signal }
1263
+ );
1264
+ }
1265
+ }
1266
+
1267
+ // src/agent-catalog/agents/cursor-cli-agent.ts
1268
+ var CURSOR_CLI_TESTED_VERSION = "2026.09.02-c22c1a3";
1269
+ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
1270
+ adapterVersion = CURSOR_CLI_TESTED_VERSION;
1271
+ authenticationCommand = () => "cursor-agent login";
1272
+ agentExecutable = "cursor-agent";
1273
+ id = "cursor";
1274
+ label = "Cursor CLI";
1275
+ constructor() {
1276
+ super(
1277
+ "MOBIUS_CURSOR_PATH",
1278
+ ["--disable-auto-update", "acp"],
1279
+ ["agents", "cursor", CURSOR_CLI_TESTED_VERSION, "bin", "cursor-agent"]
1280
+ );
1281
+ }
1282
+ supportsInstallation = (_platform, _architecture) => false;
1283
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
1284
+ const capabilities = initialized.agentCapabilities ?? {};
1285
+ if (capabilities.loadSession !== true || capabilities.sessionCapabilities?.list == null || !(initialized.authMethods ?? []).some(
1286
+ (method) => method.id === "cursor_login"
1287
+ )) {
1288
+ throw new AgentProbeError(
1289
+ "acp_incompatible",
1290
+ "Cursor CLI reported an unsupported ACP capability set"
1291
+ );
1292
+ }
1293
+ await verifySessionCreation(
1294
+ connection,
1295
+ capabilities,
1296
+ defaultWorkspace,
1297
+ signal,
1298
+ this.label
1299
+ );
1300
+ };
1301
+ };
1302
+
1244
1303
  // src/agent-catalog/agents/deepseek-harness-agent.ts
1245
1304
  import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
1246
- import { isAbsolute as isAbsolute2, join as join6, normalize } from "node:path";
1305
+ import { isAbsolute as isAbsolute2, join as join5, normalize } from "node:path";
1247
1306
 
1248
1307
  // src/agent-installation/deepseek-managed-package.ts
1249
1308
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -1261,15 +1320,16 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
1261
1320
  "https://registry.npmjs.org/@deepseek-ai/dsh/-/dsh-0.1.2-rc.1.tgz"
1262
1321
  );
1263
1322
 
1264
- // src/agent-catalog/agent-probe-error.ts
1265
- var AgentProbeError = class extends Error {
1266
- code;
1267
- constructor(code, message, options = {}) {
1268
- super(message, options);
1269
- this.code = code;
1270
- this.name = "AgentProbeError";
1323
+ // src/storage/state-directory.ts
1324
+ import { homedir } from "node:os";
1325
+ import { join as join4, resolve as resolve2 } from "node:path";
1326
+ function readStateDirectory(environment = process.env) {
1327
+ const configured = environment["MOBIUS_STATE_DIRECTORY"]?.trim();
1328
+ if (configured !== void 0 && configured.length > 0) {
1329
+ return resolve2(configured);
1271
1330
  }
1272
- };
1331
+ return join4(homedir(), ".mobius");
1332
+ }
1273
1333
 
1274
1334
  // src/agent-catalog/agents/deepseek-harness-agent.ts
1275
1335
  async function validateAgentHome(path2) {
@@ -1328,7 +1388,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
1328
1388
  context.signal
1329
1389
  );
1330
1390
  if (managed.path === agent.path) {
1331
- selectedHome = join6(
1391
+ selectedHome = join5(
1332
1392
  readStateDirectory(context.environment),
1333
1393
  "agents",
1334
1394
  this.id,
@@ -1349,7 +1409,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
1349
1409
  resolveManagedAgent = async (stateDirectory, _platform, signal) => {
1350
1410
  signal.throwIfAborted();
1351
1411
  const executable = await validateManagedNpmPackage(
1352
- join6(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
1412
+ join5(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
1353
1413
  DEEPSEEK_HARNESS_PACKAGE
1354
1414
  );
1355
1415
  signal.throwIfAborted();
@@ -1369,6 +1429,166 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
1369
1429
  };
1370
1430
  };
1371
1431
 
1432
+ // src/agent-catalog/agents/grok-build-agent.ts
1433
+ import { realpath as realpath4 } from "node:fs/promises";
1434
+ import { isAbsolute as isAbsolute3, join as join6, relative as relative2, sep as sep2 } from "node:path";
1435
+
1436
+ // src/agent-installation/grok-managed-package.ts
1437
+ var GROK_BUILD_MANAGED_VERSION = "1.0.21";
1438
+ var GrokBuildManagedPackage = class extends SriManagedNpmPackageDefinition {
1439
+ dependencyResolutionArguments = Object.freeze([
1440
+ "--before=2026-09-04T19:51:47.325Z"
1441
+ ]);
1442
+ includeOptionalDependencies = true;
1443
+ requiredDependencies;
1444
+ verifyDependencyClosure = true;
1445
+ constructor(requiredDependency) {
1446
+ super(
1447
+ "@xai-official/grok",
1448
+ GROK_BUILD_MANAGED_VERSION,
1449
+ "grok",
1450
+ "sha512-6yQqC+h1o+ObaqCxImK23dhkrOX1DEBMOKaH6fCK+B4gX0/8XIKZp0n7iKyBdK8KZa5vhMn7pS45kjX49Tps5g==",
1451
+ "https://registry.npmjs.org/@xai-official/grok/-/grok-1.0.21.tgz"
1452
+ );
1453
+ this.requiredDependencies = Object.freeze([requiredDependency]);
1454
+ }
1455
+ };
1456
+ var GROK_DARWIN_ARM64_PACKAGE = new SriManagedNpmDependencyDefinition(
1457
+ "@xai-official/grok-darwin-arm64",
1458
+ GROK_BUILD_MANAGED_VERSION,
1459
+ "sha512-I4pKZGnR6Mv4MJOJsB9B/i2o0ODF4eZtp4jHN5feoTqKIeAUVg38OzBtE8aN/wZa7Xg+qhnf6Jd1tcAFvMoFtQ==",
1460
+ "https://registry.npmjs.org/@xai-official/grok-darwin-arm64/-/grok-darwin-arm64-1.0.21.tgz"
1461
+ );
1462
+ var GROK_DARWIN_X64_PACKAGE = new SriManagedNpmDependencyDefinition(
1463
+ "@xai-official/grok-darwin-x64",
1464
+ GROK_BUILD_MANAGED_VERSION,
1465
+ "sha512-h0nFj3NZ9Kz8w6fQ6UDxxeSIhC1WjwwoRE92iNbG//tZy6YGkppR3s7oRVtt4Xl0CJANKUt0EusyIYnnAvKLzw==",
1466
+ "https://registry.npmjs.org/@xai-official/grok-darwin-x64/-/grok-darwin-x64-1.0.21.tgz"
1467
+ );
1468
+ var GROK_LINUX_ARM64_PACKAGE = new SriManagedNpmDependencyDefinition(
1469
+ "@xai-official/grok-linux-arm64",
1470
+ GROK_BUILD_MANAGED_VERSION,
1471
+ "sha512-Jlwz9XtZPNKz/V/ydifC8OVu3hIZz7pmoStt8c4KCqkSWjWiZ/PBIC0iJiq8rvByhx5Z0EdSyq8ZXVwtocceGA==",
1472
+ "https://registry.npmjs.org/@xai-official/grok-linux-arm64/-/grok-linux-arm64-1.0.21.tgz"
1473
+ );
1474
+ var GROK_LINUX_X64_PACKAGE = new SriManagedNpmDependencyDefinition(
1475
+ "@xai-official/grok-linux-x64",
1476
+ GROK_BUILD_MANAGED_VERSION,
1477
+ "sha512-AjDV5ifEz5LFG2Jt5IlhAeEkJati/wOvCchVbR4eIj2ogjvmXoXlzBrYRXuAJpXBy5q0se/Yuez5FxDU9Ju81w==",
1478
+ "https://registry.npmjs.org/@xai-official/grok-linux-x64/-/grok-linux-x64-1.0.21.tgz"
1479
+ );
1480
+ function grokBuildManagedPackage(platform, architecture) {
1481
+ if (platform === "darwin" && architecture === "arm64") {
1482
+ return new GrokBuildManagedPackage(GROK_DARWIN_ARM64_PACKAGE);
1483
+ }
1484
+ if (platform === "darwin" && architecture === "x64") {
1485
+ return new GrokBuildManagedPackage(GROK_DARWIN_X64_PACKAGE);
1486
+ }
1487
+ if (platform === "linux" && architecture === "arm64") {
1488
+ return new GrokBuildManagedPackage(GROK_LINUX_ARM64_PACKAGE);
1489
+ }
1490
+ if (platform === "linux" && architecture === "x64") {
1491
+ return new GrokBuildManagedPackage(GROK_LINUX_X64_PACKAGE);
1492
+ }
1493
+ throw new Error("Grok Build does not publish a package for this platform");
1494
+ }
1495
+
1496
+ // src/agent-catalog/agents/grok-build-agent.ts
1497
+ function isContainedPath2(root, candidate) {
1498
+ const difference = relative2(root, candidate);
1499
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
1500
+ }
1501
+ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
1502
+ adapterVersion = GROK_BUILD_MANAGED_VERSION;
1503
+ authenticationCommand = () => "grok login";
1504
+ agentExecutable = "grok";
1505
+ agentVersionArguments = ["version"];
1506
+ adapterVersionArguments = ["version"];
1507
+ id = "grok-build";
1508
+ label = "Grok Build";
1509
+ constructor() {
1510
+ super(
1511
+ "MOBIUS_GROK_BUILD_PATH",
1512
+ ["--no-auto-update", "agent", "stdio"],
1513
+ [
1514
+ "agents",
1515
+ "grok-build",
1516
+ GROK_BUILD_MANAGED_VERSION,
1517
+ "home",
1518
+ "bin",
1519
+ "grok"
1520
+ ]
1521
+ );
1522
+ }
1523
+ createLaunchEnvironment = async (agent, context) => {
1524
+ const stateDirectory = readStateDirectory(context.environment);
1525
+ try {
1526
+ const managed = await this.resolveManagedAgent(
1527
+ stateDirectory,
1528
+ context.platform ?? process.platform,
1529
+ context.signal
1530
+ );
1531
+ if (managed.path === agent.path) {
1532
+ return Object.freeze({
1533
+ GROK_HOME: await realpath4(
1534
+ join6(
1535
+ stateDirectory,
1536
+ "agents",
1537
+ this.id,
1538
+ GROK_BUILD_MANAGED_VERSION,
1539
+ "home"
1540
+ )
1541
+ )
1542
+ });
1543
+ }
1544
+ } catch {
1545
+ context.signal.throwIfAborted();
1546
+ }
1547
+ return Object.freeze({});
1548
+ };
1549
+ resolveManagedAgent = async (stateDirectory, platform, signal) => {
1550
+ signal.throwIfAborted();
1551
+ const versionRoot = await realpath4(
1552
+ join6(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION)
1553
+ );
1554
+ await validateManagedNpmPackage(
1555
+ join6(versionRoot, "package"),
1556
+ grokBuildManagedPackage(platform, process.arch)
1557
+ );
1558
+ const executable = await resolveExecutablePath(
1559
+ join6(versionRoot, "home", "bin", "grok"),
1560
+ platform
1561
+ );
1562
+ signal.throwIfAborted();
1563
+ if (executable === null || !isContainedPath2(versionRoot, executable.path)) {
1564
+ throw new AgentProbeError(
1565
+ "managed_agent_invalid",
1566
+ "The managed Grok Build executable is invalid"
1567
+ );
1568
+ }
1569
+ return executable;
1570
+ };
1571
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
1572
+ const capabilities = initialized.agentCapabilities ?? {};
1573
+ const session = capabilities.sessionCapabilities;
1574
+ if (capabilities.loadSession !== true || session?.close == null || session.list == null || session.resume == null || !(initialized.authMethods ?? []).some(
1575
+ (method) => method.id === "xai.api_key" || method.id === "grok.com"
1576
+ )) {
1577
+ throw new AgentProbeError(
1578
+ "acp_incompatible",
1579
+ "Grok Build reported an unsupported ACP capability set"
1580
+ );
1581
+ }
1582
+ await verifySessionCreation(
1583
+ connection,
1584
+ capabilities,
1585
+ defaultWorkspace,
1586
+ signal,
1587
+ this.label
1588
+ );
1589
+ };
1590
+ };
1591
+
1372
1592
  // src/agent-catalog/agents/opencode-agent.ts
1373
1593
  import { join as join8 } from "node:path";
1374
1594
 
@@ -1380,18 +1600,18 @@ import {
1380
1600
  copyFile,
1381
1601
  mkdir as mkdir2,
1382
1602
  mkdtemp as mkdtemp2,
1383
- open as open4,
1384
- realpath as realpath4,
1603
+ open as open3,
1604
+ realpath as realpath5,
1385
1605
  rename as rename2,
1386
1606
  rm as rm2,
1387
1607
  stat as stat4,
1388
1608
  writeFile
1389
1609
  } from "node:fs/promises";
1390
- import { dirname as dirname2, isAbsolute as isAbsolute3, join as join7, relative as relative2, sep as sep2 } from "node:path";
1610
+ import { dirname as dirname2, isAbsolute as isAbsolute4, join as join7, relative as relative3, sep as sep3 } from "node:path";
1391
1611
 
1392
1612
  // src/agent-installation/verified-download.ts
1393
1613
  import { createHash } from "node:crypto";
1394
- import { open as open3, unlink } from "node:fs/promises";
1614
+ import { open as open2, unlink } from "node:fs/promises";
1395
1615
  import { fetch } from "undici";
1396
1616
 
1397
1617
  // src/network/environment-proxy.ts
@@ -1523,7 +1743,7 @@ async function downloadVerifiedFile(options, transport = new UndiciInstallerDown
1523
1743
  );
1524
1744
  }
1525
1745
  }
1526
- handle = await open3(options.destination, "wx", 384);
1746
+ handle = await open2(options.destination, "wx", 384);
1527
1747
  const digest = createHash("sha256");
1528
1748
  const reader = fetched.response.body.getReader();
1529
1749
  let bytes = 0;
@@ -1633,12 +1853,12 @@ var ManagedAgentArchiveError = class extends Error {
1633
1853
  var ManagedAgentArchiveDownloader = class {
1634
1854
  download = async (options) => await downloadVerifiedFile(options);
1635
1855
  };
1636
- function isRecord3(value) {
1856
+ function isRecord2(value) {
1637
1857
  return typeof value === "object" && value !== null && !Array.isArray(value);
1638
1858
  }
1639
- function isContainedPath2(root, candidate) {
1640
- const difference = relative2(root, candidate);
1641
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
1859
+ function isContainedPath3(root, candidate) {
1860
+ const difference = relative3(root, candidate);
1861
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute4(difference);
1642
1862
  }
1643
1863
  async function hashFile(path2, signal) {
1644
1864
  signal.throwIfAborted();
@@ -1673,7 +1893,7 @@ async function hashFile(path2, signal) {
1673
1893
  async function readManifest(path2) {
1674
1894
  let handle;
1675
1895
  try {
1676
- handle = await open4(path2, "r");
1896
+ handle = await open3(path2, "r");
1677
1897
  } catch (error61) {
1678
1898
  throw new ManagedAgentArchiveError(
1679
1899
  "managed_archive_verification_failed",
@@ -1692,7 +1912,7 @@ async function readManifest(path2) {
1692
1912
  const parsed = JSON.parse(
1693
1913
  await handle.readFile({ encoding: "utf8" })
1694
1914
  );
1695
- if (!isRecord3(parsed)) {
1915
+ if (!isRecord2(parsed)) {
1696
1916
  throw new ManagedAgentArchiveError(
1697
1917
  "managed_archive_verification_failed",
1698
1918
  "The managed Agent archive manifest is invalid"
@@ -1714,7 +1934,7 @@ async function readManifest(path2) {
1714
1934
  }
1715
1935
  async function validateManagedAgentArchive(root, definition, signal) {
1716
1936
  try {
1717
- const rootPath = await realpath4(root);
1937
+ const rootPath = await realpath5(root);
1718
1938
  const rootMetadata = await stat4(rootPath);
1719
1939
  if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
1720
1940
  throw new Error("Managed Agent root is not user-owned");
@@ -1726,7 +1946,7 @@ async function validateManagedAgentArchive(root, definition, signal) {
1726
1946
  const executable = await resolveExecutablePath(
1727
1947
  join7(rootPath, "bin", definition.executableName)
1728
1948
  );
1729
- if (executable === null || !isContainedPath2(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
1949
+ if (executable === null || !isContainedPath3(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
1730
1950
  throw new Error("Managed Agent executable is invalid");
1731
1951
  }
1732
1952
  return executable;
@@ -1782,7 +2002,7 @@ var ManagedAgentArchiveInstaller = class {
1782
2002
  const archivePath = join7(working, definition.archiveName);
1783
2003
  const extractionRoot = join7(working, "extracted");
1784
2004
  await mkdir2(extractionRoot, { mode: 448 });
1785
- const canonicalExtractionRoot = await realpath4(extractionRoot);
2005
+ const canonicalExtractionRoot = await realpath5(extractionRoot);
1786
2006
  const download = await this.#downloader.download({
1787
2007
  allowedHosts: /* @__PURE__ */ new Set([
1788
2008
  "github.com",
@@ -1820,11 +2040,11 @@ var ManagedAgentArchiveInstaller = class {
1820
2040
  signal,
1821
2041
  timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
1822
2042
  });
1823
- const extracted = await realpath4(
2043
+ const extracted = await realpath5(
1824
2044
  join7(canonicalExtractionRoot, definition.executableName)
1825
2045
  );
1826
2046
  const extractedMetadata = await stat4(extracted);
1827
- if (!isContainedPath2(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
2047
+ if (!isContainedPath3(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
1828
2048
  throw new ManagedAgentArchiveError(
1829
2049
  "managed_archive_verification_failed",
1830
2050
  "The managed Agent archive executable is invalid"
@@ -1979,7 +2199,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
1979
2199
  // src/agent-catalog/agents/pi-agent.ts
1980
2200
  import { join as join9 } from "node:path";
1981
2201
  import {
1982
- methods
2202
+ methods as methods2
1983
2203
  } from "@agentclientprotocol/sdk";
1984
2204
 
1985
2205
  // src/agent-installation/pi-managed-packages.ts
@@ -2051,7 +2271,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
2051
2271
  );
2052
2272
  }
2053
2273
  const session = await connection.agent.request(
2054
- methods.agent.session.new,
2274
+ methods2.agent.session.new,
2055
2275
  {
2056
2276
  additionalDirectories: [],
2057
2277
  cwd: defaultWorkspace,
@@ -2066,7 +2286,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
2066
2286
  );
2067
2287
  }
2068
2288
  const prompt = await connection.agent.request(
2069
- methods.agent.session.prompt,
2289
+ methods2.agent.session.prompt,
2070
2290
  {
2071
2291
  prompt: [{ text: "/session", type: "text" }],
2072
2292
  sessionId: session.sessionId
@@ -2082,6 +2302,77 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
2082
2302
  };
2083
2303
  };
2084
2304
 
2305
+ // src/agent-catalog/agents/workbuddy-agent.ts
2306
+ import { join as join10 } from "node:path";
2307
+
2308
+ // src/agent-installation/workbuddy-managed-package.ts
2309
+ var WORKBUDDY_MANAGED_VERSION = "2.146.0";
2310
+ var WorkBuddyManagedPackage = class extends SriManagedNpmPackageDefinition {
2311
+ dependencyResolutionArguments = Object.freeze([
2312
+ "--before=2026-09-05T12:39:25.295Z"
2313
+ ]);
2314
+ includeOptionalDependencies = true;
2315
+ verifyDependencyClosure = true;
2316
+ };
2317
+ var WORKBUDDY_MANAGED_PACKAGE = new WorkBuddyManagedPackage(
2318
+ "@tencent-ai/codebuddy-code",
2319
+ WORKBUDDY_MANAGED_VERSION,
2320
+ "codebuddy",
2321
+ "sha512-81V+8rzYJY8PezHZMs4VZN2nvoijrsRWIuCERTr6hELotcxaZaAcqbQQSbHJcN8eTlFE5TRPlzMI4oEkLCat4A==",
2322
+ "https://registry.npmjs.org/@tencent-ai/codebuddy-code/-/codebuddy-code-2.146.0.tgz"
2323
+ );
2324
+
2325
+ // src/agent-catalog/agents/workbuddy-agent.ts
2326
+ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
2327
+ adapterVersion = WORKBUDDY_MANAGED_VERSION;
2328
+ authenticationCommand = () => "codebuddy";
2329
+ agentExecutable = "codebuddy";
2330
+ id = "workbuddy";
2331
+ label = "WorkBuddy";
2332
+ constructor() {
2333
+ super(
2334
+ "MOBIUS_WORKBUDDY_PATH",
2335
+ ["--acp"],
2336
+ [
2337
+ "agents",
2338
+ "workbuddy",
2339
+ WORKBUDDY_MANAGED_VERSION,
2340
+ "node_modules",
2341
+ "@tencent-ai",
2342
+ "codebuddy-code",
2343
+ "bin",
2344
+ "codebuddy"
2345
+ ]
2346
+ );
2347
+ }
2348
+ createLaunchEnvironment = () => Promise.resolve(Object.freeze({ DISABLE_AUTOUPDATER: "1" }));
2349
+ resolveManagedAgent = async (stateDirectory, _platform, signal) => {
2350
+ signal.throwIfAborted();
2351
+ const executable = await validateManagedNpmPackage(
2352
+ join10(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
2353
+ WORKBUDDY_MANAGED_PACKAGE
2354
+ );
2355
+ signal.throwIfAborted();
2356
+ return executable;
2357
+ };
2358
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
2359
+ const capabilities = initialized.agentCapabilities ?? {};
2360
+ if (capabilities.loadSession !== true || (initialized.authMethods ?? []).length === 0) {
2361
+ throw new AgentProbeError(
2362
+ "acp_incompatible",
2363
+ "WorkBuddy reported an unsupported ACP capability set"
2364
+ );
2365
+ }
2366
+ await verifySessionCreation(
2367
+ connection,
2368
+ capabilities,
2369
+ defaultWorkspace,
2370
+ signal,
2371
+ this.label
2372
+ );
2373
+ };
2374
+ };
2375
+
2085
2376
  // src/agent-catalog/agents/supported-agent-specifications.ts
2086
2377
  function supportedLocalAgentSpecifications() {
2087
2378
  return Object.freeze([
@@ -2089,14 +2380,17 @@ function supportedLocalAgentSpecifications() {
2089
2380
  new ClaudeCodeAgentSpecification(),
2090
2381
  new PiAgentSpecification(),
2091
2382
  new DeepSeekHarnessAgentSpecification(),
2092
- new OpenCodeAgentSpecification()
2383
+ new OpenCodeAgentSpecification(),
2384
+ new CursorCliAgentSpecification(),
2385
+ new GrokBuildAgentSpecification(),
2386
+ new WorkBuddyAgentSpecification()
2093
2387
  ]);
2094
2388
  }
2095
2389
 
2096
2390
  // src/agent-catalog/acp-readiness-probe.ts
2097
2391
  import { spawn as spawn2 } from "node:child_process";
2098
2392
  import {
2099
- methods as methods3,
2393
+ methods as methods4,
2100
2394
  ndJsonStream,
2101
2395
  PROTOCOL_VERSION,
2102
2396
  RequestError
@@ -2105,25 +2399,47 @@ import {
2105
2399
  // src/acp/create-client.ts
2106
2400
  import {
2107
2401
  client,
2108
- methods as methods2
2402
+ methods as methods3
2109
2403
  } from "@agentclientprotocol/sdk";
2404
+ function discardExtensionParams(_params) {
2405
+ return Object.freeze({});
2406
+ }
2110
2407
  var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
2111
- methods2.client.session.requestPermission,
2408
+ methods3.client.session.requestPermission,
2112
2409
  async (context) => await handler.onPermission(context.params, context.signal)
2113
2410
  ).onRequest(
2114
- methods2.client.elicitation.create,
2411
+ methods3.client.elicitation.create,
2115
2412
  async (context) => await handler.onElicitation(context.params, context.signal)
2116
- ).onNotification(methods2.client.session.update, async (context) => {
2413
+ ).onNotification(methods3.client.session.update, async (context) => {
2117
2414
  await handler.onUpdate(context.params);
2118
- }).onNotification(methods2.client.elicitation.complete, async (context) => {
2415
+ }).onNotification(methods3.client.elicitation.complete, async (context) => {
2119
2416
  await handler.onElicitationComplete(context.params);
2120
- });
2417
+ }).onRequest("cursor/ask_question", discardExtensionParams, async () => ({
2418
+ outcome: {
2419
+ outcome: "skipped",
2420
+ reason: "Mobius does not expose Cursor question extensions"
2421
+ }
2422
+ })).onRequest("cursor/create_plan", discardExtensionParams, async () => ({
2423
+ outcome: { outcome: "cancelled" }
2424
+ })).onNotification(
2425
+ "cursor/update_todos",
2426
+ discardExtensionParams,
2427
+ async () => Promise.resolve()
2428
+ ).onNotification(
2429
+ "cursor/task",
2430
+ discardExtensionParams,
2431
+ async () => Promise.resolve()
2432
+ ).onNotification(
2433
+ "cursor/generate_image",
2434
+ discardExtensionParams,
2435
+ async () => Promise.resolve()
2436
+ );
2121
2437
 
2122
2438
  // src/agent-catalog/executable-discovery.ts
2123
- import { isAbsolute as isAbsolute4, join as join11 } from "node:path";
2439
+ import { isAbsolute as isAbsolute5, join as join12 } from "node:path";
2124
2440
 
2125
2441
  // src/agent-installation/managed-adapter-installer.ts
2126
- import { join as join10 } from "node:path";
2442
+ import { join as join11 } from "node:path";
2127
2443
  var ManagedAdapterInstallError = class extends Error {
2128
2444
  code;
2129
2445
  constructor(code, message, options = {}) {
@@ -2185,7 +2501,7 @@ var ManagedAdapterInstaller = class {
2185
2501
  this.#stateDirectory = options.stateDirectory;
2186
2502
  }
2187
2503
  install = async (specification, signal) => {
2188
- const root = join10(
2504
+ const root = join11(
2189
2505
  this.#stateDirectory,
2190
2506
  "adapters",
2191
2507
  specification.id,
@@ -2224,7 +2540,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
2224
2540
  let managed;
2225
2541
  try {
2226
2542
  managed = await validateManagedAdapter(
2227
- join11(
2543
+ join12(
2228
2544
  readStateDirectory(context.environment),
2229
2545
  "adapters",
2230
2546
  specification.id,
@@ -2240,7 +2556,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
2240
2556
  async function resolveSpecificationExecutables(executableName, overrideVariable, resolveManaged, context) {
2241
2557
  const override = context.environment[overrideVariable];
2242
2558
  if (override !== void 0) {
2243
- if (override.length === 0 || !isAbsolute4(override)) {
2559
+ if (override.length === 0 || !isAbsolute5(override)) {
2244
2560
  return [];
2245
2561
  }
2246
2562
  const executable = await resolveExecutablePath(override, context.platform);
@@ -2351,41 +2667,41 @@ var DiscoveryAcpHandler = class {
2351
2667
  };
2352
2668
  function readableAcpStream(input2) {
2353
2669
  let byteLength = 0;
2354
- let open7 = true;
2670
+ let open6 = true;
2355
2671
  return new ReadableStream({
2356
2672
  start(controller) {
2357
2673
  input2.on("data", (chunk) => {
2358
- if (!open7) {
2674
+ if (!open6) {
2359
2675
  return;
2360
2676
  }
2361
2677
  if (!(chunk instanceof Uint8Array)) {
2362
- open7 = false;
2678
+ open6 = false;
2363
2679
  controller.error(new Error("ACP adapter produced invalid output"));
2364
2680
  return;
2365
2681
  }
2366
2682
  byteLength += chunk.byteLength;
2367
2683
  if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
2368
- open7 = false;
2684
+ open6 = false;
2369
2685
  controller.error(new Error("ACP adapter output limit exceeded"));
2370
2686
  return;
2371
2687
  }
2372
2688
  controller.enqueue(new Uint8Array(chunk));
2373
2689
  });
2374
2690
  input2.once("end", () => {
2375
- if (open7) {
2376
- open7 = false;
2691
+ if (open6) {
2692
+ open6 = false;
2377
2693
  controller.close();
2378
2694
  }
2379
2695
  });
2380
2696
  input2.once("error", (error61) => {
2381
- if (open7) {
2382
- open7 = false;
2697
+ if (open6) {
2698
+ open6 = false;
2383
2699
  controller.error(error61);
2384
2700
  }
2385
2701
  });
2386
2702
  },
2387
2703
  cancel() {
2388
- open7 = false;
2704
+ open6 = false;
2389
2705
  }
2390
2706
  });
2391
2707
  }
@@ -2454,7 +2770,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
2454
2770
  try {
2455
2771
  const initialized = await Promise.race([
2456
2772
  connection.agent.request(
2457
- methods3.agent.initialize,
2773
+ methods4.agent.initialize,
2458
2774
  {
2459
2775
  clientCapabilities: {},
2460
2776
  clientInfo: { name: "mobius", version: "0.0.3" },
@@ -2665,16 +2981,8 @@ async function discoverLocalAgentInventory(options) {
2665
2981
  async (specification) => await discoverAgent(specification, options)
2666
2982
  )
2667
2983
  );
2668
- let grantedAgents = /* @__PURE__ */ new Set();
2669
- try {
2670
- grantedAgents = await readGrantedAgents(
2671
- readStateDirectory(options.environment)
2672
- );
2673
- } catch {
2674
- }
2675
2984
  return new LocalAgentInventory(
2676
2985
  discoveries,
2677
- grantedAgents,
2678
2986
  options.platform,
2679
2987
  options.architecture
2680
2988
  );
@@ -2731,470 +3039,7 @@ var AuditStore = class {
2731
3039
  };
2732
3040
 
2733
3041
  // src/config.ts
2734
- import { join as join12 } from "node:path";
2735
- function loadDefaultWorkspace() {
2736
- const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = process.env;
2737
- return configuredWorkspace ?? join12(readStateDirectory(), "workspace");
2738
- }
2739
- function createDaemonConfig(connection, agents = [], installableAgents = []) {
2740
- return {
2741
- agents,
2742
- defaultWorkspace: connection.defaultWorkspace,
2743
- auditDatabasePath: connection.auditDatabasePath,
2744
- bindingId: "workspace",
2745
- catalog: new LocalAgentCatalog(agents, installableAgents),
2746
- channelId: connection.channelId,
2747
- installableAgents,
2748
- relayUrl: connection.relayUrl
2749
- };
2750
- }
2751
-
2752
- // src/pairing/pair-local-machine.ts
2753
- import { randomUUID } from "node:crypto";
2754
- import {
2755
- mkdir as mkdir3,
2756
- open as open5,
2757
- realpath as realpath5,
2758
- rename as rename3,
2759
- stat as stat5,
2760
- writeFile as writeFile2
2761
- } from "node:fs/promises";
2762
- import { hostname } from "node:os";
2763
- import { basename, join as join13, resolve as resolve3 } from "node:path";
2764
- import { fetch as fetch2 } from "undici";
2765
- var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
2766
- var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
2767
- var IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
2768
- var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
2769
- var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
2770
- var CLAIM_RESPONSE_KEYS = [
2771
- "channelId",
2772
- "daemonToken",
2773
- "runtimeId"
2774
- ];
2775
- var SAVED_CONNECTION_KEYS = [
2776
- "defaultWorkspace",
2777
- "channelId",
2778
- "daemonToken",
2779
- "relayOrigin"
2780
- ];
2781
- var PairingClientError = class extends Error {
2782
- code;
2783
- constructor(code, message, options = {}) {
2784
- super(message, options);
2785
- this.code = code;
2786
- this.name = "PairingClientError";
2787
- }
2788
- };
2789
- function isRecord4(value) {
2790
- return typeof value === "object" && value !== null && !Array.isArray(value);
2791
- }
2792
- function hasExactKeys(value, expectedKeys) {
2793
- const keys = Object.keys(value);
2794
- return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
2795
- }
2796
- function readSingleOption(arguments_, option) {
2797
- const values = [];
2798
- for (let index = 0; index < arguments_.length; index += 1) {
2799
- if (arguments_[index] !== option) {
2800
- continue;
2801
- }
2802
- const value = arguments_[index + 1];
2803
- if (value === void 0 || value.startsWith("--")) {
2804
- throw new PairingClientError(
2805
- "invalid_arguments",
2806
- `${option} requires a value`
2807
- );
2808
- }
2809
- values.push(value);
2810
- index += 1;
2811
- }
2812
- if (values.length !== 1) {
2813
- throw new PairingClientError(
2814
- "invalid_arguments",
2815
- `${option} must be provided exactly once`
2816
- );
2817
- }
2818
- return values[0] ?? "";
2819
- }
2820
- function assertKnownArguments(arguments_) {
2821
- for (let index = 0; index < arguments_.length; index += 2) {
2822
- const option = arguments_[index];
2823
- if (option !== "--url" && option !== "--code" && option !== "--workspace") {
2824
- throw new PairingClientError(
2825
- "invalid_arguments",
2826
- `Unknown pairing option: ${option ?? "missing option"}`
2827
- );
2828
- }
2829
- }
2830
- }
2831
- function parseRelayOrigin(value) {
2832
- let url2;
2833
- try {
2834
- url2 = new URL(value);
2835
- } catch (error61) {
2836
- throw new PairingClientError(
2837
- "invalid_relay_url",
2838
- "The relay URL is invalid",
2839
- { cause: error61 }
2840
- );
2841
- }
2842
- if (url2.protocol !== "https:" && url2.protocol !== "http:") {
2843
- throw new PairingClientError(
2844
- "invalid_relay_url",
2845
- "The relay URL must use http or https"
2846
- );
2847
- }
2848
- if (url2.username.length > 0 || url2.password.length > 0) {
2849
- throw new PairingClientError(
2850
- "invalid_relay_url",
2851
- "The relay URL cannot contain credentials"
2852
- );
2853
- }
2854
- if (url2.protocol === "http:" && url2.hostname !== "127.0.0.1" && url2.hostname !== "localhost") {
2855
- throw new PairingClientError(
2856
- "invalid_relay_url",
2857
- "A remote relay must use https"
2858
- );
2859
- }
2860
- url2.hash = "";
2861
- url2.pathname = "/";
2862
- url2.search = "";
2863
- return url2;
2864
- }
2865
- function parsePairingCode(value) {
2866
- const code = value.trim().toUpperCase();
2867
- if (!PAIRING_CODE_PATTERN.test(code)) {
2868
- throw new PairingClientError(
2869
- "invalid_pairing_code",
2870
- "The pairing code must match the code shown in the browser"
2871
- );
2872
- }
2873
- return code;
2874
- }
2875
- function parsePairCommand(arguments_) {
2876
- assertKnownArguments(arguments_);
2877
- return {
2878
- code: parsePairingCode(readSingleOption(arguments_, "--code")),
2879
- relayOrigin: parseRelayOrigin(readSingleOption(arguments_, "--url")),
2880
- workspace: arguments_.includes("--workspace") ? readSingleOption(arguments_, "--workspace") : loadDefaultWorkspace()
2881
- };
2882
- }
2883
- function parseChannelArgument(arguments_) {
2884
- if (arguments_.length !== 2 || arguments_[0] !== "--channel") {
2885
- throw new PairingClientError(
2886
- "invalid_arguments",
2887
- "Usage: mobius start --channel <channel-id>"
2888
- );
2889
- }
2890
- const channelId = arguments_[1] ?? "";
2891
- if (!IDENTIFIER_PATTERN.test(channelId)) {
2892
- throw new PairingClientError(
2893
- "invalid_channel_id",
2894
- "The saved channel ID is invalid"
2895
- );
2896
- }
2897
- return channelId;
2898
- }
2899
- async function resolveDefaultWorkspace(path2) {
2900
- const requestedWorkspace = resolve3(path2);
2901
- try {
2902
- await mkdir3(requestedWorkspace, { recursive: true, mode: 448 });
2903
- const defaultWorkspace = await realpath5(requestedWorkspace);
2904
- const metadata = await stat5(defaultWorkspace);
2905
- if (!metadata.isDirectory()) {
2906
- throw new PairingClientError(
2907
- "invalid_workspace",
2908
- "The default workspace is not a directory"
2909
- );
2910
- }
2911
- return defaultWorkspace;
2912
- } catch (error61) {
2913
- if (error61 instanceof PairingClientError) {
2914
- throw error61;
2915
- }
2916
- throw new PairingClientError(
2917
- "invalid_workspace",
2918
- "The default workspace cannot be resolved",
2919
- { cause: error61 }
2920
- );
2921
- }
2922
- }
2923
- async function readJsonResponse(response) {
2924
- if (response.headers.get("cf-mitigated") === "challenge") {
2925
- throw new PairingClientError(
2926
- "relay_challenge",
2927
- "Cloudflare is protecting this temporary preview. Claim the deployment or use an authenticated deployment, then pair again"
2928
- );
2929
- }
2930
- const encoded = await response.text();
2931
- try {
2932
- return JSON.parse(encoded);
2933
- } catch (error61) {
2934
- throw new PairingClientError(
2935
- "invalid_relay_response",
2936
- "The relay returned an invalid response",
2937
- { cause: error61 }
2938
- );
2939
- }
2940
- }
2941
- function readRelayError(value) {
2942
- if (isRecord4(value)) {
2943
- const error61 = value["error"];
2944
- if (isRecord4(error61)) {
2945
- const code = error61["code"];
2946
- const message = error61["message"];
2947
- if (typeof code === "string" && typeof message === "string") {
2948
- return new PairingClientError(code, message);
2949
- }
2950
- }
2951
- }
2952
- return new PairingClientError(
2953
- "pairing_failed",
2954
- "The relay could not pair this machine"
2955
- );
2956
- }
2957
- function decodeClaimResponse(value) {
2958
- if (!isRecord4(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
2959
- throw new PairingClientError(
2960
- "invalid_relay_response",
2961
- "The relay returned an invalid pairing response"
2962
- );
2963
- }
2964
- const channelId = value["channelId"];
2965
- const daemonToken = value["daemonToken"];
2966
- const runtimeId = value["runtimeId"];
2967
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN.test(runtimeId)) {
2968
- throw new PairingClientError(
2969
- "invalid_relay_response",
2970
- "The relay returned an invalid pairing response"
2971
- );
2972
- }
2973
- return { channelId, daemonToken, runtimeId };
2974
- }
2975
- async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
2976
- const agents = localAgents.map((agent) => ({
2977
- id: agent.id,
2978
- label: agent.label
2979
- }));
2980
- const endpoint = new URL("/mobius/api/pairings/claim", options.relayOrigin);
2981
- let response;
2982
- try {
2983
- response = await fetch2(endpoint, {
2984
- body: JSON.stringify({
2985
- agents,
2986
- installableAgents: installableAgents.map((agent) => ({
2987
- id: agent.id,
2988
- label: agent.label,
2989
- requiresLocalApproval: agent.requiresLocalApproval
2990
- })),
2991
- machineName: hostname(),
2992
- pairingCode: options.code,
2993
- workspaceName: basename(defaultWorkspace) || "Local workspace"
2994
- }),
2995
- dispatcher: environmentProxyDispatcher,
2996
- headers: { "content-type": "application/json" },
2997
- method: "POST",
2998
- signal: AbortSignal.any([
2999
- signal,
3000
- AbortSignal.timeout(PAIRING_TIMEOUT_MILLISECONDS)
3001
- ])
3002
- });
3003
- } catch (error61) {
3004
- throw new PairingClientError(
3005
- "relay_unavailable",
3006
- "The pairing relay could not be reached",
3007
- { cause: error61 }
3008
- );
3009
- }
3010
- const value = await readJsonResponse(response);
3011
- if (!response.ok) {
3012
- throw readRelayError(value);
3013
- }
3014
- return decodeClaimResponse(value);
3015
- }
3016
- async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
3017
- const connectionsDirectory = join13(readStateDirectory(), "connections");
3018
- await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
3019
- const connectionPath = join13(connectionsDirectory, `${channelId}.json`);
3020
- const temporaryPath = join13(
3021
- connectionsDirectory,
3022
- `.${channelId}.${randomUUID()}.tmp`
3023
- );
3024
- await writeFile2(
3025
- temporaryPath,
3026
- `${JSON.stringify(
3027
- {
3028
- defaultWorkspace,
3029
- channelId,
3030
- daemonToken,
3031
- relayOrigin: relayOrigin.toString()
3032
- },
3033
- null,
3034
- 2
3035
- )}
3036
- `,
3037
- { flag: "wx", mode: 384 }
3038
- );
3039
- await rename3(temporaryPath, connectionPath);
3040
- return connectionPath;
3041
- }
3042
- function decodeSavedConnection(value, expectedChannelId) {
3043
- if (!isRecord4(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
3044
- throw new PairingClientError(
3045
- "invalid_connection",
3046
- "The saved connection is invalid"
3047
- );
3048
- }
3049
- const defaultWorkspace = value["defaultWorkspace"];
3050
- const channelId = value["channelId"];
3051
- const daemonToken = value["daemonToken"];
3052
- const relayOrigin = value["relayOrigin"];
3053
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
3054
- throw new PairingClientError(
3055
- "invalid_connection",
3056
- "The saved connection is invalid"
3057
- );
3058
- }
3059
- return {
3060
- defaultWorkspace,
3061
- channelId,
3062
- daemonToken,
3063
- relayOrigin: parseRelayOrigin(relayOrigin)
3064
- };
3065
- }
3066
- async function readSavedConnection(channelId) {
3067
- const connectionPath = join13(
3068
- readStateDirectory(),
3069
- "connections",
3070
- `${channelId}.json`
3071
- );
3072
- let encoded = "";
3073
- const handle = await open5(connectionPath, "r");
3074
- try {
3075
- const metadata = await handle.stat();
3076
- if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
3077
- throw new PairingClientError(
3078
- "invalid_connection",
3079
- "The saved connection is invalid"
3080
- );
3081
- }
3082
- encoded = await handle.readFile({ encoding: "utf8" });
3083
- } finally {
3084
- await handle.close();
3085
- }
3086
- let value;
3087
- try {
3088
- value = JSON.parse(encoded);
3089
- } catch (error61) {
3090
- throw new PairingClientError(
3091
- "invalid_connection",
3092
- "The saved connection is invalid",
3093
- { cause: error61 }
3094
- );
3095
- }
3096
- const connection = decodeSavedConnection(value, channelId);
3097
- return {
3098
- defaultWorkspace: await resolveDefaultWorkspace(
3099
- connection.defaultWorkspace
3100
- ),
3101
- channelId: connection.channelId,
3102
- daemonToken: connection.daemonToken,
3103
- relayOrigin: connection.relayOrigin
3104
- };
3105
- }
3106
- function assertInventoryUsable(inventory) {
3107
- if (inventory.available.length + inventory.installable.length === 0) {
3108
- throw new PairingClientError(
3109
- "no_supported_agent",
3110
- "No supported Agent is ready or safely installable on this machine"
3111
- );
3112
- }
3113
- }
3114
- function buildPairedDaemon(connection, connectionPath, inventory) {
3115
- assertInventoryUsable(inventory);
3116
- const relayUrl = new URL(
3117
- `/mobius/api/channels/${encodeURIComponent(connection.channelId)}/daemon`,
3118
- connection.relayOrigin
3119
- );
3120
- relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
3121
- relayUrl.searchParams.set("token", connection.daemonToken);
3122
- const auditDatabasePath = join13(
3123
- readStateDirectory(),
3124
- "audit",
3125
- `${connection.channelId}.sqlite`
3126
- );
3127
- return {
3128
- channelUrl: new URL(
3129
- `/channels/${encodeURIComponent(connection.channelId)}`,
3130
- connection.relayOrigin
3131
- ).toString(),
3132
- config: createDaemonConfig(
3133
- {
3134
- defaultWorkspace: connection.defaultWorkspace,
3135
- auditDatabasePath,
3136
- channelId: connection.channelId,
3137
- relayUrl
3138
- },
3139
- inventory.readyAgents(),
3140
- inventory.installable
3141
- ),
3142
- connectionPath
3143
- };
3144
- }
3145
- async function pairLocalMachine(arguments_, signal = new AbortController().signal) {
3146
- const options = parsePairCommand(arguments_);
3147
- const defaultWorkspace = await resolveDefaultWorkspace(options.workspace);
3148
- const inventory = await discoverLocalAgentInventory({
3149
- defaultWorkspace,
3150
- environment: process.env,
3151
- signal
3152
- });
3153
- assertInventoryUsable(inventory);
3154
- const agents = inventory.readyAgents();
3155
- const claim2 = await claimPairing(
3156
- options,
3157
- defaultWorkspace,
3158
- agents,
3159
- inventory.installable,
3160
- signal
3161
- );
3162
- const connectionPath = await persistConnection(
3163
- claim2.channelId,
3164
- options.relayOrigin,
3165
- claim2.daemonToken,
3166
- defaultWorkspace
3167
- );
3168
- return buildPairedDaemon(
3169
- {
3170
- defaultWorkspace,
3171
- channelId: claim2.channelId,
3172
- daemonToken: claim2.daemonToken,
3173
- relayOrigin: options.relayOrigin
3174
- },
3175
- connectionPath,
3176
- inventory
3177
- );
3178
- }
3179
- async function resumeLocalMachine(arguments_, signal = new AbortController().signal) {
3180
- const channelId = parseChannelArgument(arguments_);
3181
- const connectionPath = join13(
3182
- readStateDirectory(),
3183
- "connections",
3184
- `${channelId}.json`
3185
- );
3186
- const connection = await readSavedConnection(channelId);
3187
- const inventory = await discoverLocalAgentInventory({
3188
- defaultWorkspace: connection.defaultWorkspace,
3189
- environment: process.env,
3190
- signal
3191
- });
3192
- return buildPairedDaemon(connection, connectionPath, inventory);
3193
- }
3194
-
3195
- // src/run-daemon.ts
3196
- import { basename as basename3 } from "node:path";
3197
- import { styleText } from "node:util";
3042
+ import { join as join13 } from "node:path";
3198
3043
 
3199
3044
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
3200
3045
  var external_exports = {};
@@ -3336,7 +3181,7 @@ __export(external_exports, {
3336
3181
  guid: () => guid2,
3337
3182
  hash: () => hash,
3338
3183
  hex: () => hex2,
3339
- hostname: () => hostname3,
3184
+ hostname: () => hostname2,
3340
3185
  httpUrl: () => httpUrl,
3341
3186
  includes: () => _includes,
3342
3187
  input: () => input,
@@ -5082,7 +4927,7 @@ __export(regexes_exports, {
5082
4927
  extendedDuration: () => extendedDuration,
5083
4928
  guid: () => guid,
5084
4929
  hex: () => hex,
5085
- hostname: () => hostname2,
4930
+ hostname: () => hostname,
5086
4931
  html5Email: () => html5Email,
5087
4932
  httpProtocol: () => httpProtocol,
5088
4933
  idnEmail: () => idnEmail,
@@ -5156,15 +5001,15 @@ function emoji() {
5156
5001
  }
5157
5002
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
5158
5003
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
5159
- var mac = (delimiter2) => {
5160
- const escapedDelim = escapeRegex(delimiter2 ?? ":");
5004
+ var mac = (delimiter3) => {
5005
+ const escapedDelim = escapeRegex(delimiter3 ?? ":");
5161
5006
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
5162
5007
  };
5163
5008
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
5164
5009
  var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
5165
5010
  var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
5166
5011
  var base64url = /^[A-Za-z0-9_-]*$/;
5167
- var hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
5012
+ var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
5168
5013
  var domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
5169
5014
  var httpProtocol = /^https?$/;
5170
5015
  var e164 = /^\+[1-9]\d{6,14}$/;
@@ -8214,7 +8059,7 @@ function bucketFor(state, inst) {
8214
8059
  return bucket;
8215
8060
  }
8216
8061
  var handoff;
8217
- var open6 = [];
8062
+ var open4 = [];
8218
8063
  var memo = {
8219
8064
  alloc(_inst, payload, empty) {
8220
8065
  const bucket = handoff;
@@ -8223,7 +8068,7 @@ var memo = {
8223
8068
  handoff = void 0;
8224
8069
  const entry = { value: empty, issues: null };
8225
8070
  bucket.set(payload.value, entry);
8226
- open6.push(entry);
8071
+ open4.push(entry);
8227
8072
  return empty;
8228
8073
  },
8229
8074
  guard(inst) {
@@ -8289,10 +8134,10 @@ var memo = {
8289
8134
  return payload;
8290
8135
  }
8291
8136
  handoff = bucket;
8292
- const depth = open6.length;
8137
+ const depth = open4.length;
8293
8138
  const result = base(payload, ctx);
8294
8139
  handoff = void 0;
8295
- const entry = open6.length > depth ? open6.pop() : void 0;
8140
+ const entry = open4.length > depth ? open4.pop() : void 0;
8296
8141
  if (result instanceof Promise) {
8297
8142
  return result.then((r) => {
8298
8143
  if (entry)
@@ -19676,7 +19521,7 @@ __export(schemas_exports2, {
19676
19521
  guid: () => guid2,
19677
19522
  hash: () => hash,
19678
19523
  hex: () => hex2,
19679
- hostname: () => hostname3,
19524
+ hostname: () => hostname2,
19680
19525
  httpUrl: () => httpUrl,
19681
19526
  instanceof: () => _instanceof,
19682
19527
  int: () => int,
@@ -20347,7 +20192,7 @@ var ZodCustomStringFormat = /* @__PURE__ */ $constructor("ZodCustomStringFormat"
20347
20192
  function stringFormat(format, fnOrRegex, _params = {}) {
20348
20193
  return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
20349
20194
  }
20350
- function hostname3(_params) {
20195
+ function hostname2(_params) {
20351
20196
  return _stringFormat(ZodCustomStringFormat, "hostname", regexes_exports.hostname, _params);
20352
20197
  }
20353
20198
  function hex2(_params) {
@@ -22132,15 +21977,14 @@ var SESSION_OPERATION_FAILED_KIND = "session.operation.failed";
22132
21977
  var AGENT_CONTENT_KIND = "agent.content";
22133
21978
  var AGENT_INSTALL_REQUEST_KIND = "agent.install.request";
22134
21979
  var AGENT_INSTALL_CANCEL_KIND = "agent.install.cancel";
22135
- var AGENT_INSTALL_AWAITING_APPROVAL_KIND = "agent.install.awaiting_approval";
22136
21980
  var AGENT_INSTALL_STARTED_KIND = "agent.install.started";
22137
21981
  var AGENT_INSTALL_PROGRESS_KIND = "agent.install.progress";
22138
21982
  var AGENT_INSTALL_COMPLETED_KIND = "agent.install.completed";
22139
21983
  var AGENT_INSTALL_FAILED_KIND = "agent.install.failed";
22140
21984
  var AGENT_INSTALL_CANCELLED_KIND = "agent.install.cancelled";
22141
- var IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
21985
+ var IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22142
21986
  var DIRECTORY_IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
22143
- var IDENTIFIER = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN2);
21987
+ var IDENTIFIER = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN);
22144
21988
  var DIRECTORY_IDENTIFIER = external_exports.string().min(1).max(2048).regex(DIRECTORY_IDENTIFIER_PATTERN);
22145
21989
  var SHORT_TEXT = external_exports.string().max(500);
22146
21990
  var LONG_TEXT = external_exports.string().max(1e5);
@@ -22438,10 +22282,6 @@ var agentInstallCancelCommandSchema = external_exports.strictObject({
22438
22282
  kind: external_exports.literal(AGENT_INSTALL_CANCEL_KIND),
22439
22283
  requestId: IDENTIFIER
22440
22284
  }).readonly();
22441
- var agentInstallAwaitingApprovalEventSchema = external_exports.strictObject({
22442
- ...agentInstallIdentityFields,
22443
- kind: external_exports.literal(AGENT_INSTALL_AWAITING_APPROVAL_KIND)
22444
- }).readonly();
22445
22285
  var agentInstallStartedEventSchema = external_exports.strictObject({
22446
22286
  ...agentInstallIdentityFields,
22447
22287
  kind: external_exports.literal(AGENT_INSTALL_STARTED_KIND)
@@ -22524,7 +22364,6 @@ var encodeSessionOperationFailedEvent = (message) => encode3(message, sessionOpe
22524
22364
  var encodeAgentContentEvent = (message) => encode3(message, agentContentEventSchema);
22525
22365
  var decodeAgentInstallRequestCommand = (encoded) => decode3(encoded, agentInstallRequestCommandSchema);
22526
22366
  var decodeAgentInstallCancelCommand = (encoded) => decode3(encoded, agentInstallCancelCommandSchema);
22527
- var encodeAgentInstallAwaitingApprovalEvent = (message) => encode3(message, agentInstallAwaitingApprovalEventSchema);
22528
22367
  var encodeAgentInstallStartedEvent = (message) => encode3(message, agentInstallStartedEventSchema);
22529
22368
  var encodeAgentInstallProgressEvent = (message) => encode3(message, agentInstallProgressEventSchema);
22530
22369
  var encodeAgentInstallCompletedEvent = (message) => encode3(message, agentInstallCompletedEventSchema);
@@ -22549,7 +22388,7 @@ var SESSION_COMPLETED_KIND = "session.completed";
22549
22388
  var SESSION_FAILED_KIND = "session.failed";
22550
22389
 
22551
22390
  // ../protocol/src/codecs/messages.ts
22552
- var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22391
+ var IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22553
22392
  var DIRECTORY_IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
22554
22393
  var MAX_PROMPT_LENGTH = 1e4;
22555
22394
  var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
@@ -22581,7 +22420,7 @@ var ProtocolMessageError = class extends Error {
22581
22420
  this.name = "ProtocolMessageError";
22582
22421
  }
22583
22422
  };
22584
- function isRecord5(value) {
22423
+ function isRecord3(value) {
22585
22424
  return typeof value === "object" && value !== null && !Array.isArray(value);
22586
22425
  }
22587
22426
  function parseJson2(encoded) {
@@ -22593,7 +22432,7 @@ function parseJson2(encoded) {
22593
22432
  cause: error61
22594
22433
  });
22595
22434
  }
22596
- if (!isRecord5(value)) {
22435
+ if (!isRecord3(value)) {
22597
22436
  throw new ProtocolMessageError("Message must be a JSON object");
22598
22437
  }
22599
22438
  return value;
@@ -22677,7 +22516,7 @@ function readActivityContent(value) {
22677
22516
  }
22678
22517
  function readActivityDetail(value) {
22679
22518
  const field = value["detail"];
22680
- if (!isRecord5(field)) {
22519
+ if (!isRecord3(field)) {
22681
22520
  throw new ProtocolMessageError("Invalid activity detail field");
22682
22521
  }
22683
22522
  const kind = readString(field, "kind", 32);
@@ -22724,7 +22563,7 @@ function readActivityDetail(value) {
22724
22563
  }
22725
22564
  function readIdentifier(value, key) {
22726
22565
  const field = readString(value, key, 128);
22727
- if (!IDENTIFIER_PATTERN3.test(field)) {
22566
+ if (!IDENTIFIER_PATTERN2.test(field)) {
22728
22567
  throw new ProtocolMessageError(`Invalid identifier field: ${key}`);
22729
22568
  }
22730
22569
  return field;
@@ -22924,6 +22763,29 @@ function encodeSessionFailedEvent(message) {
22924
22763
  return JSON.stringify(decodeSessionFailedEvent(JSON.stringify(message)));
22925
22764
  }
22926
22765
 
22766
+ // ../protocol/src/mobius-api.ts
22767
+ var MOBIUS_API_PREFIX = "/mobius/api";
22768
+ var API_PREFIX_PATTERN = /^\/[a-zA-Z0-9._~-]+(?:\/[a-zA-Z0-9._~-]+)*$/;
22769
+ var MobiusApiConfigurationError = class extends Error {
22770
+ code = "invalid_api_prefix";
22771
+ constructor() {
22772
+ super("The Mobius API prefix must be an absolute path without parameters");
22773
+ this.name = "MobiusApiConfigurationError";
22774
+ }
22775
+ };
22776
+ function parseMobiusApiPrefix(value) {
22777
+ if (typeof value !== "string" || !API_PREFIX_PATTERN.test(value)) {
22778
+ throw new MobiusApiConfigurationError();
22779
+ }
22780
+ return value;
22781
+ }
22782
+ function mobiusApiPath(resourcePath, apiPrefix = MOBIUS_API_PREFIX) {
22783
+ return `${parseMobiusApiPrefix(apiPrefix)}${resourcePath}`;
22784
+ }
22785
+ function mobiusApiUrl(origin, resourcePath, apiPrefix = MOBIUS_API_PREFIX) {
22786
+ return new URL(mobiusApiPath(resourcePath, apiPrefix), origin);
22787
+ }
22788
+
22927
22789
  // ../protocol/src/session-history.ts
22928
22790
  var SESSION_HISTORY_CHARACTER_LIMIT = 256e3;
22929
22791
  var SESSION_HISTORY_MESSAGE_LIMIT = 1e3;
@@ -23083,10 +22945,10 @@ var encodeNativeSessionResult = (value) => JSON.stringify(nativeSessionResultSch
23083
22945
  var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema, encoded);
23084
22946
 
23085
22947
  // ../protocol/src/resource-model.ts
23086
- var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22948
+ var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23087
22949
  var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
23088
22950
  var SHA256_PATTERN = /^[a-f0-9]{64}$/;
23089
- var identifierSchema = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4);
22951
+ var identifierSchema = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3);
23090
22952
  var timestampSchema = external_exports.string().datetime({ offset: true });
23091
22953
  var decimalSequenceSchema = external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN);
23092
22954
  var digestSchema = external_exports.string().length(64).regex(SHA256_PATTERN);
@@ -23572,13 +23434,13 @@ var commandReceiptSchema = external_exports.strictObject({
23572
23434
  var SESSION_EVENT_KIND = "session.event";
23573
23435
  var SESSION_EVENT_ACK_KIND = "session.event.ack";
23574
23436
  var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
23575
- var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23437
+ var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23576
23438
  var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
23577
23439
  var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
23578
23440
  var DECIMAL_SEQUENCE_PATTERN2 = /^(?:0|[1-9][0-9]*)$/;
23579
23441
  var eventSourceSchema = external_exports.discriminatedUnion("kind", [
23580
23442
  external_exports.strictObject({
23581
- attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23443
+ attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23582
23444
  kind: external_exports.literal("attempt"),
23583
23445
  sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2)
23584
23446
  }).readonly(),
@@ -23588,64 +23450,526 @@ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
23588
23450
  }).readonly()
23589
23451
  ]);
23590
23452
  var eventEnvelopeSchema = external_exports.strictObject({
23591
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23453
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23592
23454
  kind: external_exports.literal(SESSION_EVENT_KIND),
23593
23455
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
23594
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23456
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23595
23457
  source: eventSourceSchema
23596
23458
  }).readonly();
23597
23459
  var committedEventSchema = external_exports.strictObject({
23598
23460
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
23599
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23461
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23600
23462
  kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
23601
23463
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
23602
23464
  recordedAt: external_exports.string().datetime({ offset: true }),
23603
23465
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
23604
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23466
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23605
23467
  source: eventSourceSchema
23606
23468
  }).readonly();
23607
23469
  var eventAcknowledgementSchema = external_exports.strictObject({
23608
23470
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
23609
23471
  duplicate: external_exports.boolean(),
23610
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
23472
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
23611
23473
  kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
23612
23474
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
23613
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5)
23475
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
23614
23476
  }).readonly();
23615
23477
  function decode5(encoded, schema) {
23616
23478
  let value;
23617
23479
  try {
23618
23480
  value = JSON.parse(encoded);
23619
- } catch (cause) {
23620
- throw new ProtocolMessageError("Message is not valid JSON", { cause });
23481
+ } catch (cause) {
23482
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
23483
+ }
23484
+ const decoded = schema.safeParse(value);
23485
+ if (!decoded.success) {
23486
+ throw new ProtocolMessageError("Message does not match its schema", {
23487
+ cause: decoded.error
23488
+ });
23489
+ }
23490
+ return decoded.data;
23491
+ }
23492
+ var encode4 = (message, schema) => {
23493
+ const decoded = schema.safeParse(message);
23494
+ if (!decoded.success) {
23495
+ throw new ProtocolMessageError("Message does not match its schema", {
23496
+ cause: decoded.error
23497
+ });
23498
+ }
23499
+ return JSON.stringify(decoded.data);
23500
+ };
23501
+ var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
23502
+ var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
23503
+
23504
+ // src/config.ts
23505
+ function loadDefaultWorkspace() {
23506
+ const { MOBIUS_DEFAULT_WORKSPACE: configuredWorkspace } = process.env;
23507
+ return configuredWorkspace ?? join13(readStateDirectory(), "workspace");
23508
+ }
23509
+ function createDaemonConfig(connection, agents = [], installableAgents = []) {
23510
+ return {
23511
+ agents,
23512
+ defaultWorkspace: connection.defaultWorkspace,
23513
+ auditDatabasePath: connection.auditDatabasePath,
23514
+ bindingId: "workspace",
23515
+ catalog: new LocalAgentCatalog(agents, installableAgents),
23516
+ channelId: connection.channelId,
23517
+ installableAgents,
23518
+ relayUrl: connection.relayUrl
23519
+ };
23520
+ }
23521
+
23522
+ // src/pairing/pair-local-machine.ts
23523
+ import { randomUUID } from "node:crypto";
23524
+ import {
23525
+ mkdir as mkdir3,
23526
+ open as open5,
23527
+ realpath as realpath6,
23528
+ rename as rename3,
23529
+ stat as stat5,
23530
+ writeFile as writeFile2
23531
+ } from "node:fs/promises";
23532
+ import { hostname as hostname3 } from "node:os";
23533
+ import { basename, join as join14, resolve as resolve3 } from "node:path";
23534
+ import { fetch as fetch2 } from "undici";
23535
+ var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
23536
+ var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
23537
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23538
+ var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
23539
+ var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
23540
+ var CLAIM_RESPONSE_KEYS = [
23541
+ "channelId",
23542
+ "daemonToken",
23543
+ "runtimeId"
23544
+ ];
23545
+ var SAVED_CONNECTION_KEYS = [
23546
+ "defaultWorkspace",
23547
+ "channelId",
23548
+ "daemonToken",
23549
+ "relayOrigin"
23550
+ ];
23551
+ var PairingClientError = class extends Error {
23552
+ code;
23553
+ constructor(code, message, options = {}) {
23554
+ super(message, options);
23555
+ this.code = code;
23556
+ this.name = "PairingClientError";
23557
+ }
23558
+ };
23559
+ function isRecord4(value) {
23560
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23561
+ }
23562
+ function hasExactKeys(value, expectedKeys) {
23563
+ const keys = Object.keys(value);
23564
+ return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
23565
+ }
23566
+ function readSingleOption(arguments_, option) {
23567
+ const values = [];
23568
+ for (let index = 0; index < arguments_.length; index += 1) {
23569
+ if (arguments_[index] !== option) {
23570
+ continue;
23571
+ }
23572
+ const value = arguments_[index + 1];
23573
+ if (value === void 0 || value.startsWith("--")) {
23574
+ throw new PairingClientError(
23575
+ "invalid_arguments",
23576
+ `${option} requires a value`
23577
+ );
23578
+ }
23579
+ values.push(value);
23580
+ index += 1;
23581
+ }
23582
+ if (values.length !== 1) {
23583
+ throw new PairingClientError(
23584
+ "invalid_arguments",
23585
+ `${option} must be provided exactly once`
23586
+ );
23587
+ }
23588
+ return values[0] ?? "";
23589
+ }
23590
+ function assertKnownArguments(arguments_) {
23591
+ for (let index = 0; index < arguments_.length; index += 2) {
23592
+ const option = arguments_[index];
23593
+ if (option !== "--url" && option !== "--code" && option !== "--workspace") {
23594
+ throw new PairingClientError(
23595
+ "invalid_arguments",
23596
+ `Unknown pairing option: ${option ?? "missing option"}`
23597
+ );
23598
+ }
23599
+ }
23600
+ }
23601
+ function parseRelayOrigin(value) {
23602
+ let url2;
23603
+ try {
23604
+ url2 = new URL(value);
23605
+ } catch (error61) {
23606
+ throw new PairingClientError(
23607
+ "invalid_relay_url",
23608
+ "The relay URL is invalid",
23609
+ { cause: error61 }
23610
+ );
23611
+ }
23612
+ if (url2.protocol !== "https:" && url2.protocol !== "http:") {
23613
+ throw new PairingClientError(
23614
+ "invalid_relay_url",
23615
+ "The relay URL must use http or https"
23616
+ );
23617
+ }
23618
+ if (url2.username.length > 0 || url2.password.length > 0) {
23619
+ throw new PairingClientError(
23620
+ "invalid_relay_url",
23621
+ "The relay URL cannot contain credentials"
23622
+ );
23623
+ }
23624
+ if (url2.protocol === "http:" && url2.hostname !== "127.0.0.1" && url2.hostname !== "localhost") {
23625
+ throw new PairingClientError(
23626
+ "invalid_relay_url",
23627
+ "A remote relay must use https"
23628
+ );
23629
+ }
23630
+ url2.hash = "";
23631
+ url2.pathname = "/";
23632
+ url2.search = "";
23633
+ return url2;
23634
+ }
23635
+ function parsePairingCode(value) {
23636
+ const code = value.trim().toUpperCase();
23637
+ if (!PAIRING_CODE_PATTERN.test(code)) {
23638
+ throw new PairingClientError(
23639
+ "invalid_pairing_code",
23640
+ "The pairing code must match the code shown in the browser"
23641
+ );
23642
+ }
23643
+ return code;
23644
+ }
23645
+ function parsePairCommand(arguments_) {
23646
+ assertKnownArguments(arguments_);
23647
+ return {
23648
+ code: parsePairingCode(readSingleOption(arguments_, "--code")),
23649
+ relayOrigin: parseRelayOrigin(readSingleOption(arguments_, "--url")),
23650
+ workspace: arguments_.includes("--workspace") ? readSingleOption(arguments_, "--workspace") : loadDefaultWorkspace()
23651
+ };
23652
+ }
23653
+ function parseChannelArgument(arguments_) {
23654
+ if (arguments_.length !== 2 || arguments_[0] !== "--channel") {
23655
+ throw new PairingClientError(
23656
+ "invalid_arguments",
23657
+ "Usage: mobius start --channel <channel-id>"
23658
+ );
23659
+ }
23660
+ const channelId = arguments_[1] ?? "";
23661
+ if (!IDENTIFIER_PATTERN5.test(channelId)) {
23662
+ throw new PairingClientError(
23663
+ "invalid_channel_id",
23664
+ "The saved channel ID is invalid"
23665
+ );
23666
+ }
23667
+ return channelId;
23668
+ }
23669
+ async function resolveDefaultWorkspace(path2) {
23670
+ const requestedWorkspace = resolve3(path2);
23671
+ try {
23672
+ await mkdir3(requestedWorkspace, { recursive: true, mode: 448 });
23673
+ const defaultWorkspace = await realpath6(requestedWorkspace);
23674
+ const metadata = await stat5(defaultWorkspace);
23675
+ if (!metadata.isDirectory()) {
23676
+ throw new PairingClientError(
23677
+ "invalid_workspace",
23678
+ "The default workspace is not a directory"
23679
+ );
23680
+ }
23681
+ return defaultWorkspace;
23682
+ } catch (error61) {
23683
+ if (error61 instanceof PairingClientError) {
23684
+ throw error61;
23685
+ }
23686
+ throw new PairingClientError(
23687
+ "invalid_workspace",
23688
+ "The default workspace cannot be resolved",
23689
+ { cause: error61 }
23690
+ );
23691
+ }
23692
+ }
23693
+ async function readJsonResponse(response) {
23694
+ if (response.headers.get("cf-mitigated") === "challenge") {
23695
+ throw new PairingClientError(
23696
+ "relay_challenge",
23697
+ "Cloudflare is protecting this temporary preview. Claim the deployment or use an authenticated deployment, then pair again"
23698
+ );
23699
+ }
23700
+ const encoded = await response.text();
23701
+ try {
23702
+ return JSON.parse(encoded);
23703
+ } catch (error61) {
23704
+ throw new PairingClientError(
23705
+ "invalid_relay_response",
23706
+ "The relay returned an invalid response",
23707
+ { cause: error61 }
23708
+ );
23709
+ }
23710
+ }
23711
+ function readRelayError(value) {
23712
+ if (isRecord4(value)) {
23713
+ const error61 = value["error"];
23714
+ if (isRecord4(error61)) {
23715
+ const code = error61["code"];
23716
+ const message = error61["message"];
23717
+ if (typeof code === "string" && typeof message === "string") {
23718
+ return new PairingClientError(code, message);
23719
+ }
23720
+ }
23721
+ }
23722
+ return new PairingClientError(
23723
+ "pairing_failed",
23724
+ "The relay could not pair this machine"
23725
+ );
23726
+ }
23727
+ function decodeClaimResponse(value) {
23728
+ if (!isRecord4(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
23729
+ throw new PairingClientError(
23730
+ "invalid_relay_response",
23731
+ "The relay returned an invalid pairing response"
23732
+ );
23733
+ }
23734
+ const channelId = value["channelId"];
23735
+ const daemonToken = value["daemonToken"];
23736
+ const runtimeId = value["runtimeId"];
23737
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN5.test(runtimeId)) {
23738
+ throw new PairingClientError(
23739
+ "invalid_relay_response",
23740
+ "The relay returned an invalid pairing response"
23741
+ );
23742
+ }
23743
+ return { channelId, daemonToken, runtimeId };
23744
+ }
23745
+ async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
23746
+ const agents = localAgents.map((agent) => ({
23747
+ id: agent.id,
23748
+ label: agent.label
23749
+ }));
23750
+ const endpoint = mobiusApiUrl(options.relayOrigin, "/pairings/claim");
23751
+ let response;
23752
+ try {
23753
+ response = await fetch2(endpoint, {
23754
+ body: JSON.stringify({
23755
+ agents,
23756
+ installableAgents: installableAgents.map((agent) => ({
23757
+ id: agent.id,
23758
+ label: agent.label
23759
+ })),
23760
+ machineName: hostname3(),
23761
+ pairingCode: options.code,
23762
+ workspaceName: basename(defaultWorkspace) || "Local workspace"
23763
+ }),
23764
+ dispatcher: environmentProxyDispatcher,
23765
+ headers: { "content-type": "application/json" },
23766
+ method: "POST",
23767
+ signal: AbortSignal.any([
23768
+ signal,
23769
+ AbortSignal.timeout(PAIRING_TIMEOUT_MILLISECONDS)
23770
+ ])
23771
+ });
23772
+ } catch (error61) {
23773
+ throw new PairingClientError(
23774
+ "relay_unavailable",
23775
+ "The pairing relay could not be reached",
23776
+ { cause: error61 }
23777
+ );
23778
+ }
23779
+ const value = await readJsonResponse(response);
23780
+ if (!response.ok) {
23781
+ throw readRelayError(value);
23782
+ }
23783
+ return decodeClaimResponse(value);
23784
+ }
23785
+ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
23786
+ const connectionsDirectory = join14(readStateDirectory(), "connections");
23787
+ await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
23788
+ const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
23789
+ const temporaryPath = join14(
23790
+ connectionsDirectory,
23791
+ `.${channelId}.${randomUUID()}.tmp`
23792
+ );
23793
+ await writeFile2(
23794
+ temporaryPath,
23795
+ `${JSON.stringify(
23796
+ {
23797
+ defaultWorkspace,
23798
+ channelId,
23799
+ daemonToken,
23800
+ relayOrigin: relayOrigin.toString()
23801
+ },
23802
+ null,
23803
+ 2
23804
+ )}
23805
+ `,
23806
+ { flag: "wx", mode: 384 }
23807
+ );
23808
+ await rename3(temporaryPath, connectionPath);
23809
+ return connectionPath;
23810
+ }
23811
+ function decodeSavedConnection(value, expectedChannelId) {
23812
+ if (!isRecord4(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
23813
+ throw new PairingClientError(
23814
+ "invalid_connection",
23815
+ "The saved connection is invalid"
23816
+ );
23817
+ }
23818
+ const defaultWorkspace = value["defaultWorkspace"];
23819
+ const channelId = value["channelId"];
23820
+ const daemonToken = value["daemonToken"];
23821
+ const relayOrigin = value["relayOrigin"];
23822
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
23823
+ throw new PairingClientError(
23824
+ "invalid_connection",
23825
+ "The saved connection is invalid"
23826
+ );
23827
+ }
23828
+ return {
23829
+ defaultWorkspace,
23830
+ channelId,
23831
+ daemonToken,
23832
+ relayOrigin: parseRelayOrigin(relayOrigin)
23833
+ };
23834
+ }
23835
+ async function readSavedConnection(channelId) {
23836
+ const connectionPath = join14(
23837
+ readStateDirectory(),
23838
+ "connections",
23839
+ `${channelId}.json`
23840
+ );
23841
+ let encoded = "";
23842
+ const handle = await open5(connectionPath, "r");
23843
+ try {
23844
+ const metadata = await handle.stat();
23845
+ if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
23846
+ throw new PairingClientError(
23847
+ "invalid_connection",
23848
+ "The saved connection is invalid"
23849
+ );
23850
+ }
23851
+ encoded = await handle.readFile({ encoding: "utf8" });
23852
+ } finally {
23853
+ await handle.close();
23854
+ }
23855
+ let value;
23856
+ try {
23857
+ value = JSON.parse(encoded);
23858
+ } catch (error61) {
23859
+ throw new PairingClientError(
23860
+ "invalid_connection",
23861
+ "The saved connection is invalid",
23862
+ { cause: error61 }
23863
+ );
23621
23864
  }
23622
- const decoded = schema.safeParse(value);
23623
- if (!decoded.success) {
23624
- throw new ProtocolMessageError("Message does not match its schema", {
23625
- cause: decoded.error
23626
- });
23865
+ const connection = decodeSavedConnection(value, channelId);
23866
+ return {
23867
+ defaultWorkspace: await resolveDefaultWorkspace(
23868
+ connection.defaultWorkspace
23869
+ ),
23870
+ channelId: connection.channelId,
23871
+ daemonToken: connection.daemonToken,
23872
+ relayOrigin: connection.relayOrigin
23873
+ };
23874
+ }
23875
+ function assertInventoryUsable(inventory) {
23876
+ if (inventory.available.length + inventory.installable.length === 0) {
23877
+ throw new PairingClientError(
23878
+ "no_supported_agent",
23879
+ "No supported Agent is ready or safely installable on this machine"
23880
+ );
23627
23881
  }
23628
- return decoded.data;
23629
23882
  }
23630
- var encode4 = (message, schema) => {
23631
- const decoded = schema.safeParse(message);
23632
- if (!decoded.success) {
23633
- throw new ProtocolMessageError("Message does not match its schema", {
23634
- cause: decoded.error
23635
- });
23636
- }
23637
- return JSON.stringify(decoded.data);
23638
- };
23639
- var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
23640
- var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
23883
+ function buildPairedDaemon(connection, connectionPath, inventory) {
23884
+ assertInventoryUsable(inventory);
23885
+ const relayUrl = mobiusApiUrl(
23886
+ connection.relayOrigin,
23887
+ `/channels/${encodeURIComponent(connection.channelId)}/daemon`
23888
+ );
23889
+ relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
23890
+ relayUrl.searchParams.set("token", connection.daemonToken);
23891
+ const auditDatabasePath = join14(
23892
+ readStateDirectory(),
23893
+ "audit",
23894
+ `${connection.channelId}.sqlite`
23895
+ );
23896
+ return {
23897
+ channelUrl: new URL(
23898
+ `/channels/${encodeURIComponent(connection.channelId)}`,
23899
+ connection.relayOrigin
23900
+ ).toString(),
23901
+ config: createDaemonConfig(
23902
+ {
23903
+ defaultWorkspace: connection.defaultWorkspace,
23904
+ auditDatabasePath,
23905
+ channelId: connection.channelId,
23906
+ relayUrl
23907
+ },
23908
+ inventory.readyAgents(),
23909
+ inventory.installable
23910
+ ),
23911
+ connectionPath
23912
+ };
23913
+ }
23914
+ async function pairLocalMachine(arguments_, signal = new AbortController().signal) {
23915
+ const options = parsePairCommand(arguments_);
23916
+ const defaultWorkspace = await resolveDefaultWorkspace(options.workspace);
23917
+ const inventory = await discoverLocalAgentInventory({
23918
+ defaultWorkspace,
23919
+ environment: process.env,
23920
+ signal
23921
+ });
23922
+ assertInventoryUsable(inventory);
23923
+ const agents = inventory.readyAgents();
23924
+ const claim2 = await claimPairing(
23925
+ options,
23926
+ defaultWorkspace,
23927
+ agents,
23928
+ inventory.installable,
23929
+ signal
23930
+ );
23931
+ const connectionPath = await persistConnection(
23932
+ claim2.channelId,
23933
+ options.relayOrigin,
23934
+ claim2.daemonToken,
23935
+ defaultWorkspace
23936
+ );
23937
+ return buildPairedDaemon(
23938
+ {
23939
+ defaultWorkspace,
23940
+ channelId: claim2.channelId,
23941
+ daemonToken: claim2.daemonToken,
23942
+ relayOrigin: options.relayOrigin
23943
+ },
23944
+ connectionPath,
23945
+ inventory
23946
+ );
23947
+ }
23948
+ async function resumeLocalMachine(arguments_, signal = new AbortController().signal) {
23949
+ const channelId = parseChannelArgument(arguments_);
23950
+ const connectionPath = join14(
23951
+ readStateDirectory(),
23952
+ "connections",
23953
+ `${channelId}.json`
23954
+ );
23955
+ const connection = await readSavedConnection(channelId);
23956
+ const inventory = await discoverLocalAgentInventory({
23957
+ defaultWorkspace: connection.defaultWorkspace,
23958
+ environment: process.env,
23959
+ signal
23960
+ });
23961
+ return buildPairedDaemon(connection, connectionPath, inventory);
23962
+ }
23641
23963
 
23642
23964
  // src/run-daemon.ts
23965
+ import { basename as basename3 } from "node:path";
23966
+ import { styleText } from "node:util";
23643
23967
  import { WebSocket as WebSocket2 } from "undici";
23644
23968
 
23645
23969
  // src/acp/session-manager.ts
23646
23970
  import { spawn as spawn3 } from "node:child_process";
23647
23971
  import {
23648
- methods as methods4,
23972
+ methods as methods5,
23649
23973
  ndJsonStream as ndJsonStream2,
23650
23974
  PROTOCOL_VERSION as PROTOCOL_VERSION2,
23651
23975
  RequestError as RequestError2
@@ -23653,7 +23977,7 @@ import {
23653
23977
 
23654
23978
  // src/acp/activity.ts
23655
23979
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
23656
- function isRecord6(value) {
23980
+ function isRecord5(value) {
23657
23981
  return typeof value === "object" && value !== null && !Array.isArray(value);
23658
23982
  }
23659
23983
  var AcpActivity = class _AcpActivity {
@@ -23927,7 +24251,7 @@ function contentPhase(content) {
23927
24251
  return "";
23928
24252
  }
23929
24253
  const codex = metadata["codex"];
23930
- if (!isRecord6(codex)) {
24254
+ if (!isRecord5(codex)) {
23931
24255
  return "";
23932
24256
  }
23933
24257
  const phase = codex["phase"];
@@ -24561,7 +24885,7 @@ function createWritableAcpStream(output2) {
24561
24885
  function truncate2(value, maximumLength) {
24562
24886
  return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
24563
24887
  }
24564
- function isRecord7(value) {
24888
+ function isRecord6(value) {
24565
24889
  return typeof value === "object" && value !== null && !Array.isArray(value);
24566
24890
  }
24567
24891
  function readString3(value, fallback = "") {
@@ -24591,7 +24915,7 @@ function normalizeConfigValues(value) {
24591
24915
  }
24592
24916
  const normalized = [];
24593
24917
  for (const entry of value) {
24594
- if (!isRecord7(entry)) {
24918
+ if (!isRecord6(entry)) {
24595
24919
  continue;
24596
24920
  }
24597
24921
  const groupedOptions = entry["options"];
@@ -24599,7 +24923,7 @@ function normalizeConfigValues(value) {
24599
24923
  const groupId = readString3(entry["group"]);
24600
24924
  const groupName = readString3(entry["name"]);
24601
24925
  for (const groupedOption of groupedOptions) {
24602
- if (isRecord7(groupedOption)) {
24926
+ if (isRecord6(groupedOption)) {
24603
24927
  normalized.push(
24604
24928
  normalizeConfigValue(groupedOption, groupId, groupName)
24605
24929
  );
@@ -24615,7 +24939,7 @@ function normalizeConfigOptions(value, modes) {
24615
24939
  const normalized = [];
24616
24940
  if (Array.isArray(value)) {
24617
24941
  for (const option of value) {
24618
- if (!isRecord7(option)) {
24942
+ if (!isRecord6(option)) {
24619
24943
  continue;
24620
24944
  }
24621
24945
  const id = truncate2(readString3(option["id"]), 128);
@@ -24654,12 +24978,12 @@ function normalizeConfigOptions(value, modes) {
24654
24978
  }
24655
24979
  }
24656
24980
  }
24657
- if (isRecord7(modes)) {
24981
+ if (isRecord6(modes)) {
24658
24982
  const values = [];
24659
24983
  const availableModes = modes["availableModes"];
24660
24984
  if (Array.isArray(availableModes)) {
24661
24985
  for (const mode of availableModes) {
24662
- if (!isRecord7(mode)) {
24986
+ if (!isRecord6(mode)) {
24663
24987
  continue;
24664
24988
  }
24665
24989
  const id = truncate2(readString3(mode["id"]), 500);
@@ -24737,7 +25061,7 @@ function normalizeElicitationOptions(schema) {
24737
25061
  const oneOf = schema["oneOf"];
24738
25062
  if (Array.isArray(oneOf)) {
24739
25063
  for (const option of oneOf) {
24740
- if (isRecord7(option) && typeof option["const"] === "string") {
25064
+ if (isRecord6(option) && typeof option["const"] === "string") {
24741
25065
  normalized.push({
24742
25066
  description: truncate2(readString3(option["description"]), 500),
24743
25067
  label: truncate2(readString3(option["title"], option["const"]), 255),
@@ -24757,7 +25081,7 @@ function normalizeElicitationOptions(schema) {
24757
25081
  return normalized.slice(0, 200);
24758
25082
  }
24759
25083
  const items = schema["items"];
24760
- if (!isRecord7(items)) {
25084
+ if (!isRecord6(items)) {
24761
25085
  return normalized;
24762
25086
  }
24763
25087
  const anyOf = items["anyOf"];
@@ -24770,7 +25094,7 @@ function numericString(value) {
24770
25094
  return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
24771
25095
  }
24772
25096
  function normalizeElicitationFields(requestedSchema) {
24773
- if (!isRecord7(requestedSchema) || !isRecord7(requestedSchema["properties"])) {
25097
+ if (!isRecord6(requestedSchema) || !isRecord6(requestedSchema["properties"])) {
24774
25098
  return [];
24775
25099
  }
24776
25100
  const properties = requestedSchema["properties"];
@@ -24780,7 +25104,7 @@ function normalizeElicitationFields(requestedSchema) {
24780
25104
  );
24781
25105
  const normalized = [];
24782
25106
  for (const [name, property] of Object.entries(properties)) {
24783
- if (!isRecord7(property)) {
25107
+ if (!isRecord6(property)) {
24784
25108
  continue;
24785
25109
  }
24786
25110
  const type = elicitationFieldType(property["type"]);
@@ -24875,7 +25199,7 @@ function validateElicitationContent(encoded, requestedSchema) {
24875
25199
  "invalid_elicitation_response"
24876
25200
  );
24877
25201
  }
24878
- if (!isRecord7(decoded) || !isRecord7(requestedSchema) || !isRecord7(requestedSchema["properties"])) {
25202
+ if (!isRecord6(decoded) || !isRecord6(requestedSchema) || !isRecord6(requestedSchema["properties"])) {
24879
25203
  throw new AcpExecutionError(
24880
25204
  "Elicitation response does not match the requested form",
24881
25205
  {},
@@ -24899,7 +25223,7 @@ function validateElicitationContent(encoded, requestedSchema) {
24899
25223
  const validated = {};
24900
25224
  for (const [name, value] of Object.entries(decoded)) {
24901
25225
  const property = properties[name];
24902
- if (!isRecord7(property)) {
25226
+ if (!isRecord6(property)) {
24903
25227
  throw new AcpExecutionError(
24904
25228
  `Elicitation field ${name} was not requested`,
24905
25229
  {},
@@ -25190,7 +25514,7 @@ var AcpProcessSession = class _AcpProcessSession {
25190
25514
  try {
25191
25515
  await this.race(
25192
25516
  this.#connection.agent.request(
25193
- methods4.agent.session.load,
25517
+ methods5.agent.session.load,
25194
25518
  {
25195
25519
  additionalDirectories: [...this.#additionalDirectories],
25196
25520
  cwd: this.#cwd,
@@ -25212,7 +25536,7 @@ var AcpProcessSession = class _AcpProcessSession {
25212
25536
  async #initializeAgent(signal) {
25213
25537
  const initialized = await this.race(
25214
25538
  this.#connection.agent.request(
25215
- methods4.agent.initialize,
25539
+ methods5.agent.initialize,
25216
25540
  {
25217
25541
  clientCapabilities: {
25218
25542
  elicitation: { form: {}, url: {} },
@@ -25280,7 +25604,7 @@ var AcpProcessSession = class _AcpProcessSession {
25280
25604
  );
25281
25605
  const forked = await this.race(
25282
25606
  this.#connection.agent.request(
25283
- methods4.agent.session.fork,
25607
+ methods5.agent.session.fork,
25284
25608
  {
25285
25609
  sessionId: nativeSessionIdSchema.parse(origin.nativeSessionId),
25286
25610
  cwd: this.#cwd,
@@ -25313,7 +25637,7 @@ var AcpProcessSession = class _AcpProcessSession {
25313
25637
  if (this.#capabilities.resumeSession) {
25314
25638
  lifecycleResponse = await this.race(
25315
25639
  this.#connection.agent.request(
25316
- methods4.agent.session.resume,
25640
+ methods5.agent.session.resume,
25317
25641
  {
25318
25642
  additionalDirectories: [...this.#additionalDirectories],
25319
25643
  cwd: this.#cwd,
@@ -25330,7 +25654,7 @@ var AcpProcessSession = class _AcpProcessSession {
25330
25654
  try {
25331
25655
  lifecycleResponse = await this.race(
25332
25656
  this.#connection.agent.request(
25333
- methods4.agent.session.load,
25657
+ methods5.agent.session.load,
25334
25658
  {
25335
25659
  additionalDirectories: [...this.#additionalDirectories],
25336
25660
  cwd: this.#cwd,
@@ -25366,7 +25690,7 @@ var AcpProcessSession = class _AcpProcessSession {
25366
25690
  }
25367
25691
  const created = await this.race(
25368
25692
  this.#connection.agent.request(
25369
- methods4.agent.session.new,
25693
+ methods5.agent.session.new,
25370
25694
  {
25371
25695
  additionalDirectories: [...this.#additionalDirectories],
25372
25696
  cwd: this.#cwd,
@@ -25380,7 +25704,7 @@ var AcpProcessSession = class _AcpProcessSession {
25380
25704
  this.selectNativeSession(created.sessionId);
25381
25705
  lifecycleResponse = created;
25382
25706
  }
25383
- const lifecycleRecord = isRecord7(lifecycleResponse) ? lifecycleResponse : {};
25707
+ const lifecycleRecord = isRecord6(lifecycleResponse) ? lifecycleResponse : {};
25384
25708
  this.#configOptions = normalizeConfigOptions(
25385
25709
  lifecycleRecord["configOptions"],
25386
25710
  lifecycleRecord["modes"]
@@ -25409,7 +25733,7 @@ var AcpProcessSession = class _AcpProcessSession {
25409
25733
  );
25410
25734
  const response = await this.race(
25411
25735
  this.#connection.agent.request(
25412
- methods4.agent.session.list,
25736
+ methods5.agent.session.list,
25413
25737
  cursor === null ? {} : { cursor },
25414
25738
  { cancellationSignal: signal }
25415
25739
  ),
@@ -25434,7 +25758,7 @@ var AcpProcessSession = class _AcpProcessSession {
25434
25758
  );
25435
25759
  await this.race(
25436
25760
  this.#connection.agent.request(
25437
- methods4.agent.session.delete,
25761
+ methods5.agent.session.delete,
25438
25762
  { sessionId: nativeSessionIdSchema.parse(nativeSessionId) },
25439
25763
  { cancellationSignal: signal }
25440
25764
  ),
@@ -25465,7 +25789,7 @@ var AcpProcessSession = class _AcpProcessSession {
25465
25789
  if (existing.category === "mode") {
25466
25790
  await this.race(
25467
25791
  this.#connection.agent.request(
25468
- methods4.agent.session.setMode,
25792
+ methods5.agent.session.setMode,
25469
25793
  { modeId: options.value, sessionId: this.#nativeSessionId },
25470
25794
  { cancellationSignal: options.signal }
25471
25795
  ),
@@ -25478,7 +25802,7 @@ var AcpProcessSession = class _AcpProcessSession {
25478
25802
  } else {
25479
25803
  const response = await this.race(
25480
25804
  this.#connection.agent.request(
25481
- methods4.agent.session.setConfigOption,
25805
+ methods5.agent.session.setConfigOption,
25482
25806
  {
25483
25807
  configId: existing.id,
25484
25808
  sessionId: this.#nativeSessionId,
@@ -25497,7 +25821,7 @@ var AcpProcessSession = class _AcpProcessSession {
25497
25821
  } else {
25498
25822
  const response = await this.race(
25499
25823
  this.#connection.agent.request(
25500
- methods4.agent.session.setConfigOption,
25824
+ methods5.agent.session.setConfigOption,
25501
25825
  {
25502
25826
  configId: existing.id,
25503
25827
  sessionId: this.#nativeSessionId,
@@ -25596,7 +25920,7 @@ var AcpProcessSession = class _AcpProcessSession {
25596
25920
  try {
25597
25921
  const response = await this.race(
25598
25922
  this.#connection.agent.request(
25599
- methods4.agent.session.prompt,
25923
+ methods5.agent.session.prompt,
25600
25924
  { prompt, sessionId: this.#nativeSessionId },
25601
25925
  { cancellationSignal: options.signal }
25602
25926
  ),
@@ -25643,7 +25967,7 @@ var AcpProcessSession = class _AcpProcessSession {
25643
25967
  try {
25644
25968
  await this.cancelPendingInteractions();
25645
25969
  if (this.#turn.running) {
25646
- await this.#connection.agent.notify(methods4.agent.session.cancel, {
25970
+ await this.#connection.agent.notify(methods5.agent.session.cancel, {
25647
25971
  sessionId: this.#nativeSessionId
25648
25972
  });
25649
25973
  }
@@ -25999,7 +26323,7 @@ var AcpProcessSession = class _AcpProcessSession {
25999
26323
  if (this.#capabilities.closeSession && this.#nativeSessionId.length > 0) {
26000
26324
  try {
26001
26325
  await this.#connection.agent.request(
26002
- methods4.agent.session.close,
26326
+ methods5.agent.session.close,
26003
26327
  { sessionId: this.#nativeSessionId },
26004
26328
  {
26005
26329
  cancellationSignal: AbortSignal.timeout(
@@ -26636,8 +26960,7 @@ async function publishAgentCatalog(config2, signal) {
26636
26960
  })),
26637
26961
  installableAgents: catalog.installableAgents.map((agent) => ({
26638
26962
  id: agent.id,
26639
- label: agent.label,
26640
- requiresLocalApproval: agent.requiresLocalApproval
26963
+ label: agent.label
26641
26964
  }))
26642
26965
  }),
26643
26966
  dispatcher: environmentProxyDispatcher,
@@ -26678,12 +27001,6 @@ var RequestedInstallation = class extends AgentInstallation {
26678
27001
  super(requestId, agentId);
26679
27002
  }
26680
27003
  };
26681
- var AwaitingLocalApproval = class extends AgentInstallation {
26682
- status = "awaiting_local_approval";
26683
- constructor(requestId, agentId) {
26684
- super(requestId, agentId);
26685
- }
26686
- };
26687
27004
  var RunningInstallation = class extends AgentInstallation {
26688
27005
  stage;
26689
27006
  status = "running";
@@ -26738,9 +27055,9 @@ var InstallationJob = class {
26738
27055
  this.state = new RequestedInstallation(requestId, agentId);
26739
27056
  }
26740
27057
  };
26741
- function specificationFor(specifications, agentId) {
27058
+ function authorizedSpecificationFor(specifications, agentId) {
26742
27059
  for (const specification of specifications) {
26743
- if (specification.id === agentId) {
27060
+ if (specification.id === agentId && specification.supportsInstallation(process.platform, process.arch)) {
26744
27061
  return specification;
26745
27062
  }
26746
27063
  }
@@ -26759,14 +27076,12 @@ function executionFailure(error61) {
26759
27076
  var AgentInstallationManager = class {
26760
27077
  #activeAgents = /* @__PURE__ */ new Map();
26761
27078
  #audit;
26762
- #authorizer;
26763
27079
  #executor;
26764
27080
  #jobs = /* @__PURE__ */ new Map();
26765
27081
  #observer;
26766
27082
  #specifications;
26767
- constructor(specifications, authorizer, executor, observer, audit = new NullInstallationAudit()) {
27083
+ constructor(specifications, executor, observer, audit = new NullInstallationAudit()) {
26768
27084
  this.#audit = audit;
26769
- this.#authorizer = authorizer;
26770
27085
  this.#executor = executor;
26771
27086
  this.#observer = observer;
26772
27087
  this.#specifications = Object.freeze([...specifications]);
@@ -26797,7 +27112,7 @@ var AgentInstallationManager = class {
26797
27112
  command.requestId,
26798
27113
  command.agentId
26799
27114
  );
26800
- const specification = specificationFor(
27115
+ const specification = authorizedSpecificationFor(
26801
27116
  this.#specifications,
26802
27117
  command.agentId
26803
27118
  );
@@ -26900,45 +27215,14 @@ var AgentInstallationManager = class {
26900
27215
  }, INSTALLATION_DEADLINE_MILLISECONDS);
26901
27216
  const signal = job.controller.signal;
26902
27217
  try {
26903
- await this.#transition(
26904
- job,
26905
- new AwaitingLocalApproval(job.requestId, job.agentId)
26906
- );
26907
- this.#audit.record(
26908
- "agent_installation_awaiting_approval",
26909
- job.requestId,
26910
- job.agentId
26911
- );
26912
- const approved = await this.#authorizer.authorize(
26913
- specification.id,
26914
- specification.label,
26915
- job.requestId,
26916
- signal
26917
- );
26918
27218
  signal.throwIfAborted();
26919
- if (!approved) {
26920
- const denied = new FailedInstallation(
26921
- job.requestId,
26922
- job.agentId,
26923
- "installation_not_authorized",
26924
- "Installation was not approved on the local machine"
26925
- );
26926
- await this.#transition(job, denied);
26927
- this.#audit.record(
26928
- "agent_installation_denied",
26929
- job.requestId,
26930
- job.agentId
26931
- );
26932
- job.completion.resolve(denied);
26933
- return;
26934
- }
26935
27219
  this.#audit.record(
26936
27220
  "agent_installation_authorized",
26937
27221
  job.requestId,
26938
- job.agentId
27222
+ specification.id
26939
27223
  );
26940
27224
  await this.#executor.execute(
26941
- job.agentId,
27225
+ specification.id,
26942
27226
  job.requestId,
26943
27227
  async (stage) => {
26944
27228
  signal.throwIfAborted();
@@ -27208,12 +27492,10 @@ import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
27208
27492
  import { resolve as resolve4 } from "node:path";
27209
27493
 
27210
27494
  // src/agent-installation/fixed-agent-install-recipes.ts
27211
- import { mkdir as mkdir4, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27212
- import { join as join14 } from "node:path";
27213
- var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
27214
- var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
27215
- var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
27216
- var MINIMAL_PATH2 = "/usr/bin:/bin";
27495
+ import { mkdir as mkdir5, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27496
+ import { join as join17 } from "node:path";
27497
+
27498
+ // src/agent-installation/fixed-agent-install-recipe.ts
27217
27499
  var FixedAgentInstallRecipe = class {
27218
27500
  assertSupportedPlatform = () => {
27219
27501
  if (process.platform !== "darwin" && process.platform !== "linux" || process.arch !== "arm64" && process.arch !== "x64") {
@@ -27234,28 +27516,243 @@ var FixedAgentInstallRecipe = class {
27234
27516
  return executable;
27235
27517
  };
27236
27518
  };
27519
+
27520
+ // src/agent-installation/grok-build-install-recipe.ts
27521
+ import { mkdir as mkdir4, realpath as realpath7, stat as stat6 } from "node:fs/promises";
27522
+ import { delimiter as delimiter2, dirname as dirname5, isAbsolute as isAbsolute6, join as join15, relative as relative4, sep as sep4 } from "node:path";
27523
+ var INSTALL_TIMEOUT_MILLISECONDS2 = 5 * 60 * 1e3;
27524
+ function isContainedPath4(root, candidate) {
27525
+ const difference = relative4(root, candidate);
27526
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep4}`) && !isAbsolute6(difference);
27527
+ }
27528
+ async function resolveLifecycleScript(packageRoot) {
27529
+ try {
27530
+ const canonicalPackageRoot = await realpath7(packageRoot);
27531
+ const script = await realpath7(
27532
+ join15(canonicalPackageRoot, "bin", "postinstall.js")
27533
+ );
27534
+ const metadata = await stat6(script);
27535
+ if (!metadata.isFile() || !isContainedPath4(canonicalPackageRoot, script)) {
27536
+ throw new Error("Invalid Grok Build lifecycle script");
27537
+ }
27538
+ return script;
27539
+ } catch (error61) {
27540
+ throw new InstallationManagerError(
27541
+ "agent_verification_failed",
27542
+ "The managed Grok Build lifecycle script is invalid",
27543
+ { cause: error61 }
27544
+ );
27545
+ }
27546
+ }
27547
+ var GrokBuildInstallRecipe = class extends FixedAgentInstallRecipe {
27548
+ #npmInstaller;
27549
+ id = "grok-build";
27550
+ label = "Grok Build";
27551
+ releaseChannel = GROK_BUILD_MANAGED_VERSION;
27552
+ constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27553
+ super();
27554
+ this.#npmInstaller = npmInstaller;
27555
+ }
27556
+ install = async (options) => {
27557
+ this.assertSupportedPlatform();
27558
+ const definition = grokBuildManagedPackage(process.platform, process.arch);
27559
+ const versionRoot = join15(
27560
+ options.stateDirectory,
27561
+ "agents",
27562
+ this.id,
27563
+ GROK_BUILD_MANAGED_VERSION
27564
+ );
27565
+ const packageRoot = join15(versionRoot, "package");
27566
+ const managedHome = join15(versionRoot, "home");
27567
+ try {
27568
+ await mkdir4(managedHome, { mode: 448, recursive: true });
27569
+ const canonicalHome = await realpath7(managedHome);
27570
+ await options.report("downloading");
27571
+ await options.report("verifying");
27572
+ await options.report("installing_agent");
27573
+ await this.#npmInstaller.install(
27574
+ packageRoot,
27575
+ definition,
27576
+ options.environment,
27577
+ options.signal
27578
+ );
27579
+ options.audit.record(
27580
+ "agent_npm_package_verified",
27581
+ options.requestId,
27582
+ this.id,
27583
+ {
27584
+ integrity: definition.integrity,
27585
+ package: definition.packageName,
27586
+ version: definition.version
27587
+ }
27588
+ );
27589
+ const script = await resolveLifecycleScript(
27590
+ join15(packageRoot, "node_modules", "@xai-official", "grok")
27591
+ );
27592
+ await runBoundedProcess({
27593
+ arguments: [script],
27594
+ command: process.execPath,
27595
+ cwd: dirname5(script),
27596
+ environment: {
27597
+ GROK_HOME: canonicalHome,
27598
+ GROK_INSTALL_COMPLETIONS: "0",
27599
+ GROK_NPM_REGISTRY: "https://registry.npmjs.org/",
27600
+ HOME: canonicalHome,
27601
+ PATH: `${dirname5(process.execPath)}${delimiter2}/usr/bin${delimiter2}/bin`
27602
+ },
27603
+ outputLimitBytes: 64 * 1024,
27604
+ signal: options.signal,
27605
+ timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS2
27606
+ });
27607
+ options.audit.record(
27608
+ "agent_lifecycle_step_completed",
27609
+ options.requestId,
27610
+ this.id,
27611
+ {
27612
+ lifecycle: "postinstall",
27613
+ package: definition.packageName,
27614
+ version: definition.version
27615
+ }
27616
+ );
27617
+ return await this.requireInstalledExecutable(
27618
+ join15(canonicalHome, "bin", "grok")
27619
+ );
27620
+ } catch (error61) {
27621
+ if (options.signal.aborted) {
27622
+ options.signal.throwIfAborted();
27623
+ }
27624
+ if (error61 instanceof ManagedNpmPackageError) {
27625
+ if (error61.code === "managed_package_verification_failed") {
27626
+ throw new InstallationManagerError(
27627
+ "agent_verification_failed",
27628
+ "The managed Grok Build packages did not match their pinned artifacts",
27629
+ { cause: error61 }
27630
+ );
27631
+ }
27632
+ if (error61.code === "managed_package_publish_failed") {
27633
+ throw new InstallationManagerError(
27634
+ "agent_publish_failed",
27635
+ "The managed Grok Build package could not be published",
27636
+ { cause: error61 }
27637
+ );
27638
+ }
27639
+ throw new InstallationManagerError(error61.code, error61.message, {
27640
+ cause: error61
27641
+ });
27642
+ }
27643
+ if (error61 instanceof InstallationManagerError) {
27644
+ throw error61;
27645
+ }
27646
+ throw new InstallationManagerError(
27647
+ "agent_install_failed",
27648
+ "The fixed Grok Build installation recipe failed",
27649
+ { cause: error61 }
27650
+ );
27651
+ }
27652
+ };
27653
+ };
27654
+
27655
+ // src/agent-installation/workbuddy-install-recipe.ts
27656
+ import { join as join16 } from "node:path";
27657
+ var WorkBuddyInstallRecipe = class extends FixedAgentInstallRecipe {
27658
+ #npmInstaller;
27659
+ id = "workbuddy";
27660
+ label = "WorkBuddy";
27661
+ releaseChannel = WORKBUDDY_MANAGED_VERSION;
27662
+ constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27663
+ super();
27664
+ this.#npmInstaller = npmInstaller;
27665
+ }
27666
+ install = async (options) => {
27667
+ this.assertSupportedPlatform();
27668
+ try {
27669
+ await options.report("downloading");
27670
+ await options.report("verifying");
27671
+ await options.report("installing_agent");
27672
+ const executable = await this.#npmInstaller.install(
27673
+ join16(
27674
+ options.stateDirectory,
27675
+ "agents",
27676
+ this.id,
27677
+ WORKBUDDY_MANAGED_VERSION
27678
+ ),
27679
+ WORKBUDDY_MANAGED_PACKAGE,
27680
+ options.environment,
27681
+ options.signal
27682
+ );
27683
+ options.audit.record(
27684
+ "agent_npm_package_verified",
27685
+ options.requestId,
27686
+ this.id,
27687
+ {
27688
+ integrity: WORKBUDDY_MANAGED_PACKAGE.integrity,
27689
+ package: WORKBUDDY_MANAGED_PACKAGE.packageName,
27690
+ version: WORKBUDDY_MANAGED_PACKAGE.version
27691
+ }
27692
+ );
27693
+ return executable;
27694
+ } catch (error61) {
27695
+ if (options.signal.aborted) {
27696
+ options.signal.throwIfAborted();
27697
+ }
27698
+ if (error61 instanceof ManagedNpmPackageError) {
27699
+ if (error61.code === "managed_package_verification_failed") {
27700
+ throw new InstallationManagerError(
27701
+ "agent_verification_failed",
27702
+ "The managed WorkBuddy package did not match its pinned artifact",
27703
+ { cause: error61 }
27704
+ );
27705
+ }
27706
+ if (error61.code === "managed_package_publish_failed") {
27707
+ throw new InstallationManagerError(
27708
+ "agent_publish_failed",
27709
+ "The managed WorkBuddy package could not be published",
27710
+ { cause: error61 }
27711
+ );
27712
+ }
27713
+ throw new InstallationManagerError(error61.code, error61.message, {
27714
+ cause: error61
27715
+ });
27716
+ }
27717
+ if (error61 instanceof InstallationManagerError) {
27718
+ throw error61;
27719
+ }
27720
+ throw new InstallationManagerError(
27721
+ "agent_install_failed",
27722
+ "The fixed WorkBuddy installation recipe failed",
27723
+ { cause: error61 }
27724
+ );
27725
+ }
27726
+ };
27727
+ };
27728
+
27729
+ // src/agent-installation/fixed-agent-install-recipes.ts
27730
+ var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
27731
+ var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
27732
+ var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
27733
+ var MINIMAL_PATH2 = "/usr/bin:/bin";
27237
27734
  var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
27238
27735
  id = "codex";
27239
27736
  label = "Codex";
27240
27737
  releaseChannel = "latest";
27241
27738
  install = async (options) => {
27242
27739
  this.assertSupportedPlatform();
27243
- const root = join14(options.stateDirectory, "agents", this.id);
27244
- const temporaryRoot = join14(options.stateDirectory, "temporary");
27740
+ const root = join17(options.stateDirectory, "agents", this.id);
27741
+ const temporaryRoot = join17(options.stateDirectory, "temporary");
27245
27742
  await Promise.all([
27246
- mkdir4(root, { mode: 448, recursive: true }),
27247
- mkdir4(temporaryRoot, { mode: 448, recursive: true })
27743
+ mkdir5(root, { mode: 448, recursive: true }),
27744
+ mkdir5(temporaryRoot, { mode: 448, recursive: true })
27248
27745
  ]);
27249
27746
  const temporaryDirectory = await mkdtemp3(
27250
- join14(temporaryRoot, ".codex-install-")
27747
+ join17(temporaryRoot, ".codex-install-")
27251
27748
  );
27252
- const installerPath = join14(temporaryDirectory, "install.sh");
27253
- const installDirectory = join14(root, "bin");
27254
- const codexHome = join14(root, "home");
27749
+ const installerPath = join17(temporaryDirectory, "install.sh");
27750
+ const installDirectory = join17(root, "bin");
27751
+ const codexHome = join17(root, "home");
27255
27752
  try {
27256
27753
  await Promise.all([
27257
- mkdir4(installDirectory, { mode: 448, recursive: true }),
27258
- mkdir4(codexHome, { mode: 448, recursive: true })
27754
+ mkdir5(installDirectory, { mode: 448, recursive: true }),
27755
+ mkdir5(codexHome, { mode: 448, recursive: true })
27259
27756
  ]);
27260
27757
  await options.report("downloading");
27261
27758
  const download = await downloadVerifiedFile({
@@ -27295,7 +27792,7 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
27295
27792
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27296
27793
  });
27297
27794
  return await this.requireInstalledExecutable(
27298
- join14(installDirectory, "codex")
27795
+ join17(installDirectory, "codex")
27299
27796
  );
27300
27797
  } catch (error61) {
27301
27798
  if (options.signal.aborted) {
@@ -27319,17 +27816,17 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27319
27816
  releaseChannel = "stable";
27320
27817
  install = async (options) => {
27321
27818
  this.assertSupportedPlatform();
27322
- const root = join14(options.stateDirectory, "agents", this.id);
27323
- const managedHome = join14(root, "home");
27324
- const temporaryRoot = join14(options.stateDirectory, "temporary");
27819
+ const root = join17(options.stateDirectory, "agents", this.id);
27820
+ const managedHome = join17(root, "home");
27821
+ const temporaryRoot = join17(options.stateDirectory, "temporary");
27325
27822
  await Promise.all([
27326
- mkdir4(managedHome, { mode: 448, recursive: true }),
27327
- mkdir4(temporaryRoot, { mode: 448, recursive: true })
27823
+ mkdir5(managedHome, { mode: 448, recursive: true }),
27824
+ mkdir5(temporaryRoot, { mode: 448, recursive: true })
27328
27825
  ]);
27329
27826
  const temporaryDirectory = await mkdtemp3(
27330
- join14(temporaryRoot, ".claude-install-")
27827
+ join17(temporaryRoot, ".claude-install-")
27331
27828
  );
27332
- const installerPath = join14(temporaryDirectory, "install.sh");
27829
+ const installerPath = join17(temporaryDirectory, "install.sh");
27333
27830
  try {
27334
27831
  await options.report("downloading");
27335
27832
  const download = await downloadVerifiedFile({
@@ -27366,7 +27863,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27366
27863
  timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27367
27864
  });
27368
27865
  return await this.requireInstalledExecutable(
27369
- join14(managedHome, ".local", "bin", "claude")
27866
+ join17(managedHome, ".local", "bin", "claude")
27370
27867
  );
27371
27868
  } catch (error61) {
27372
27869
  if (options.signal.aborted) {
@@ -27400,7 +27897,7 @@ var PiInstallRecipe = class extends FixedAgentInstallRecipe {
27400
27897
  await options.report("verifying");
27401
27898
  await options.report("installing_agent");
27402
27899
  const executable = await this.#npmInstaller.install(
27403
- join14(
27900
+ join17(
27404
27901
  options.stateDirectory,
27405
27902
  "agents",
27406
27903
  this.id,
@@ -27467,18 +27964,18 @@ var DeepSeekHarnessInstallRecipe = class extends FixedAgentInstallRecipe {
27467
27964
  install = async (options) => {
27468
27965
  this.assertSupportedPlatform();
27469
27966
  try {
27470
- const managedHome = join14(
27967
+ const managedHome = join17(
27471
27968
  options.stateDirectory,
27472
27969
  "agents",
27473
27970
  this.id,
27474
27971
  "home"
27475
27972
  );
27476
- await mkdir4(managedHome, { mode: 448, recursive: true });
27973
+ await mkdir5(managedHome, { mode: 448, recursive: true });
27477
27974
  await options.report("downloading");
27478
27975
  await options.report("verifying");
27479
27976
  await options.report("installing_agent");
27480
27977
  const executable = await this.#npmInstaller.install(
27481
- join14(
27978
+ join17(
27482
27979
  options.stateDirectory,
27483
27980
  "agents",
27484
27981
  this.id,
@@ -27550,7 +28047,7 @@ var OpenCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27550
28047
  await options.report("verifying");
27551
28048
  await options.report("installing_agent");
27552
28049
  const executable = await this.#archiveInstaller.install(
27553
- join14(
28050
+ join17(
27554
28051
  options.stateDirectory,
27555
28052
  "agents",
27556
28053
  this.id,
@@ -27609,7 +28106,9 @@ function fixedAgentInstallRecipes() {
27609
28106
  new ClaudeCodeInstallRecipe(),
27610
28107
  new PiInstallRecipe(),
27611
28108
  new DeepSeekHarnessInstallRecipe(),
27612
- new OpenCodeInstallRecipe()
28109
+ new OpenCodeInstallRecipe(),
28110
+ new GrokBuildInstallRecipe(),
28111
+ new WorkBuddyInstallRecipe()
27613
28112
  ]);
27614
28113
  }
27615
28114
 
@@ -27850,41 +28349,6 @@ var FixedInstallationExecutor = class {
27850
28349
  };
27851
28350
  };
27852
28351
 
27853
- // src/agent-installation/local-installation-authorizer.ts
27854
- import { createInterface } from "node:readline/promises";
27855
- var ConsoleInstallationAuthorizer = class {
27856
- #stateDirectory;
27857
- constructor(stateDirectory) {
27858
- this.#stateDirectory = stateDirectory;
27859
- }
27860
- authorize = async (agentId, label, requestId, signal) => {
27861
- signal.throwIfAborted();
27862
- const grants = await readGrantedAgents(this.#stateDirectory);
27863
- signal.throwIfAborted();
27864
- if (grants.has(agentId)) {
27865
- return true;
27866
- }
27867
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
27868
- return false;
27869
- }
27870
- const prompt = createInterface({
27871
- input: process.stdin,
27872
- output: process.stdout
27873
- });
27874
- try {
27875
- const answer = await prompt.question(
27876
- `
27877
- Mobius Web requested installation of ${label} (${requestId}). Allow this fixed user-level recipe? [y/N] `,
27878
- { signal }
27879
- );
27880
- const normalized = answer.trim().toLowerCase();
27881
- return normalized === "y" || normalized === "yes";
27882
- } finally {
27883
- prompt.close();
27884
- }
27885
- };
27886
- };
27887
-
27888
28352
  // src/authorization/local-authorization-error.ts
27889
28353
  var LocalAuthorizationError = class extends Error {
27890
28354
  code = "local_authorization_failed";
@@ -27895,15 +28359,15 @@ var LocalAuthorizationError = class extends Error {
27895
28359
  };
27896
28360
 
27897
28361
  // src/authorization/workspace-directory.ts
27898
- import { readdir, realpath as realpath6, stat as stat6 } from "node:fs/promises";
28362
+ import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
27899
28363
  import { homedir as homedir2 } from "node:os";
27900
28364
  import {
27901
28365
  basename as basename2,
27902
- dirname as dirname5,
27903
- isAbsolute as isAbsolute5,
27904
- join as join15,
28366
+ dirname as dirname6,
28367
+ isAbsolute as isAbsolute7,
28368
+ join as join18,
27905
28369
  normalize as normalize2,
27906
- relative as relative3
28370
+ relative as relative5
27907
28371
  } from "node:path";
27908
28372
  var WorkspaceDirectoryListing = class {
27909
28373
  directoryId;
@@ -27953,20 +28417,20 @@ var WorkspaceDirectoryService = class {
27953
28417
  if (id === "home") return homedir2();
27954
28418
  if (id.startsWith("path-")) {
27955
28419
  const path2 = decodePath(id, "path-");
27956
- if (isAbsolute5(path2)) return path2;
28420
+ if (isAbsolute7(path2)) return path2;
27957
28421
  }
27958
28422
  throw new LocalAuthorizationError("The directory identifier is invalid");
27959
28423
  };
27960
28424
  resolvePath = async (requested, signal) => {
27961
28425
  signal.throwIfAborted();
27962
- if (!isAbsolute5(requested) || requested.includes("\0") || normalize2(requested) !== requested)
28426
+ if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested)
27963
28427
  throw new LocalAuthorizationError("The local directory path is invalid");
27964
28428
  try {
27965
- const target = await realpath6(requested);
28429
+ const target = await realpath8(requested);
27966
28430
  signal.throwIfAborted();
27967
- const metadata = await stat6(target);
28431
+ const metadata = await stat7(target);
27968
28432
  signal.throwIfAborted();
27969
- if (!isAbsolute5(target) || normalize2(target) !== target || !metadata.isDirectory())
28433
+ if (!isAbsolute7(target) || normalize2(target) !== target || !metadata.isDirectory())
27970
28434
  throw new LocalAuthorizationError(
27971
28435
  "The selected location is not a directory"
27972
28436
  );
@@ -27981,8 +28445,8 @@ var WorkspaceDirectoryService = class {
27981
28445
  }
27982
28446
  };
27983
28447
  label = (path2) => {
27984
- const suffix = relative3(homedir2(), path2);
27985
- return suffix === "" ? "~" : !isAbsolute5(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
28448
+ const suffix = relative5(homedir2(), path2);
28449
+ return suffix === "" ? "~" : !isAbsolute7(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27986
28450
  };
27987
28451
  identify = async (bindingId, requestedPath, signal) => {
27988
28452
  this.authorizeMachine(bindingId);
@@ -28010,7 +28474,7 @@ var WorkspaceDirectoryService = class {
28010
28474
  continue;
28011
28475
  }
28012
28476
  try {
28013
- const path2 = await this.resolvePath(join15(target, child.name), signal);
28477
+ const path2 = await this.resolvePath(join18(target, child.name), signal);
28014
28478
  entries.push({ directoryId: encodePath(path2), name: child.name });
28015
28479
  } catch (cause) {
28016
28480
  signal.throwIfAborted();
@@ -28018,7 +28482,7 @@ var WorkspaceDirectoryService = class {
28018
28482
  }
28019
28483
  }
28020
28484
  entries.sort((a, b) => a.name.localeCompare(b.name));
28021
- const parent = dirname5(target);
28485
+ const parent = dirname6(target);
28022
28486
  return new WorkspaceDirectoryListing(
28023
28487
  id,
28024
28488
  this.label(target),
@@ -28811,7 +29275,7 @@ var RelayConnectionLiveness = class {
28811
29275
 
28812
29276
  // src/relay-connection/session-event-outbox.ts
28813
29277
  import { mkdirSync as mkdirSync3 } from "node:fs";
28814
- import { dirname as dirname6 } from "node:path";
29278
+ import { dirname as dirname7 } from "node:path";
28815
29279
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
28816
29280
  function readPendingEnvelope(row) {
28817
29281
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
@@ -28826,7 +29290,7 @@ function readPendingEnvelope(row) {
28826
29290
  var SessionEventOutbox = class {
28827
29291
  #database;
28828
29292
  constructor(path2) {
28829
- mkdirSync3(dirname6(path2), { recursive: true });
29293
+ mkdirSync3(dirname7(path2), { recursive: true });
28830
29294
  this.#database = new DatabaseSync3(path2);
28831
29295
  this.#database.exec(`
28832
29296
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
@@ -29118,17 +29582,6 @@ var DaemonInstallationObserver = class {
29118
29582
  if (state instanceof RequestedInstallation) {
29119
29583
  return Promise.resolve();
29120
29584
  }
29121
- if (state instanceof AwaitingLocalApproval) {
29122
- this.#send(
29123
- socket,
29124
- encodeAgentInstallAwaitingApprovalEvent({
29125
- agentId: state.agentId,
29126
- kind: AGENT_INSTALL_AWAITING_APPROVAL_KIND,
29127
- requestId: state.requestId
29128
- })
29129
- );
29130
- return Promise.resolve();
29131
- }
29132
29585
  if (state instanceof RunningInstallation) {
29133
29586
  if (!this.#started.has(state.requestId)) {
29134
29587
  this.#started.add(state.requestId);
@@ -30025,7 +30478,6 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
30025
30478
  );
30026
30479
  const installations = new AgentInstallationManager(
30027
30480
  specifications,
30028
- new ConsoleInstallationAuthorizer(stateDirectory),
30029
30481
  installationExecutor,
30030
30482
  installationObserver,
30031
30483
  installationAudit
@@ -30133,7 +30585,7 @@ async function main() {
30133
30585
  if (arguments_.length > 1 || arguments_.length === 1 && arguments_[0] !== "--json") {
30134
30586
  throw new Error("Usage: mobius agents [--json]");
30135
30587
  }
30136
- await mkdir5(loadDefaultWorkspace(), { recursive: true, mode: 448 });
30588
+ await mkdir6(loadDefaultWorkspace(), { recursive: true, mode: 448 });
30137
30589
  const inventory = await discoverLocalAgentInventory({
30138
30590
  defaultWorkspace: loadDefaultWorkspace(),
30139
30591
  environment: process.env,