@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.
- package/dist/acp/create-client.d.ts.map +1 -1
- package/dist/acp/create-client.js +16 -1
- package/dist/acp/create-client.js.map +1 -1
- package/dist/agent-catalog/agent-discovery.d.ts +1 -1
- package/dist/agent-catalog/agent-discovery.d.ts.map +1 -1
- package/dist/agent-catalog/agent-discovery.js +2 -2
- package/dist/agent-catalog/agent-discovery.js.map +1 -1
- package/dist/agent-catalog/agents/cursor-cli-agent.d.ts +13 -0
- package/dist/agent-catalog/agents/cursor-cli-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/cursor-cli-agent.js +25 -0
- package/dist/agent-catalog/agents/cursor-cli-agent.js.map +1 -0
- package/dist/agent-catalog/agents/grok-build-agent.d.ts +18 -0
- package/dist/agent-catalog/agents/grok-build-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/grok-build-agent.js +75 -0
- package/dist/agent-catalog/agents/grok-build-agent.js.map +1 -0
- package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -1
- package/dist/agent-catalog/agents/supported-agent-specifications.js +6 -0
- package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
- package/dist/agent-catalog/agents/verify-session-creation.d.ts +3 -0
- package/dist/agent-catalog/agents/verify-session-creation.d.ts.map +1 -0
- package/dist/agent-catalog/agents/verify-session-creation.js +16 -0
- package/dist/agent-catalog/agents/verify-session-creation.js.map +1 -0
- package/dist/agent-catalog/agents/workbuddy-agent.d.ts +15 -0
- package/dist/agent-catalog/agents/workbuddy-agent.d.ts.map +1 -0
- package/dist/agent-catalog/agents/workbuddy-agent.js +41 -0
- package/dist/agent-catalog/agents/workbuddy-agent.js.map +1 -0
- package/dist/agent-catalog/discover-local-agents.d.ts +3 -0
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
- package/dist/agent-catalog/discover-local-agents.js +4 -10
- package/dist/agent-catalog/discover-local-agents.js.map +1 -1
- package/dist/agent-catalog/local-agent.d.ts +1 -2
- package/dist/agent-catalog/local-agent.d.ts.map +1 -1
- package/dist/agent-catalog/local-agent.js +1 -3
- package/dist/agent-catalog/local-agent.js.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.js +0 -1
- package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
- package/dist/agent-installation/agent-installation-manager.d.ts +1 -8
- package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
- package/dist/agent-installation/agent-installation-manager.js +7 -24
- package/dist/agent-installation/agent-installation-manager.js.map +1 -1
- package/dist/agent-installation/fixed-agent-install-recipe.d.ts +20 -0
- package/dist/agent-installation/fixed-agent-install-recipe.d.ts.map +1 -0
- package/dist/agent-installation/fixed-agent-install-recipe.js +18 -0
- package/dist/agent-installation/fixed-agent-install-recipe.js.map +1 -0
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts +5 -18
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
- package/dist/agent-installation/fixed-agent-install-recipes.js +9 -16
- package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
- package/dist/agent-installation/grok-build-install-recipe.d.ts +12 -0
- package/dist/agent-installation/grok-build-install-recipe.d.ts.map +1 -0
- package/dist/agent-installation/grok-build-install-recipe.js +102 -0
- package/dist/agent-installation/grok-build-install-recipe.js.map +1 -0
- package/dist/agent-installation/grok-managed-package.d.ts +4 -0
- package/dist/agent-installation/grok-managed-package.d.ts.map +1 -0
- package/dist/agent-installation/grok-managed-package.js +34 -0
- package/dist/agent-installation/grok-managed-package.js.map +1 -0
- package/dist/agent-installation/managed-npm-package.d.ts +8 -0
- package/dist/agent-installation/managed-npm-package.d.ts.map +1 -1
- package/dist/agent-installation/managed-npm-package.js +32 -3
- package/dist/agent-installation/managed-npm-package.js.map +1 -1
- package/dist/agent-installation/workbuddy-install-recipe.d.ts +12 -0
- package/dist/agent-installation/workbuddy-install-recipe.d.ts.map +1 -0
- package/dist/agent-installation/workbuddy-install-recipe.js +51 -0
- package/dist/agent-installation/workbuddy-install-recipe.js.map +1 -0
- package/dist/agent-installation/workbuddy-managed-package.d.ts +10 -0
- package/dist/agent-installation/workbuddy-managed-package.d.ts.map +1 -0
- package/dist/agent-installation/workbuddy-managed-package.js +11 -0
- package/dist/agent-installation/workbuddy-managed-package.js.map +1 -0
- package/dist/cli.js +1289 -837
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +1411 -959
- package/dist/index.js.map +4 -4
- package/dist/pairing/pair-local-machine.d.ts.map +1 -1
- package/dist/pairing/pair-local-machine.js +3 -3
- package/dist/pairing/pair-local-machine.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +3 -12
- package/dist/run-daemon.js.map +1 -1
- package/package.json +2 -2
- package/dist/agent-installation/installation-grants.d.ts +0 -2
- package/dist/agent-installation/installation-grants.d.ts.map +0 -1
- package/dist/agent-installation/installation-grants.js +0 -51
- package/dist/agent-installation/installation-grants.js.map +0 -1
- package/dist/agent-installation/local-installation-authorizer.d.ts +0 -7
- package/dist/agent-installation/local-installation-authorizer.d.ts.map +0 -1
- package/dist/agent-installation/local-installation-authorizer.js +0 -32
- 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
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (!
|
|
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 (
|
|
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
|
|
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 (!
|
|
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 (
|
|
886
|
+
if (verifyDependencyClosure && normalizedKey.length > 0) {
|
|
930
887
|
let resolved;
|
|
931
888
|
try {
|
|
932
|
-
if (!normalizedKey.split("/").includes("node_modules") || !
|
|
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 || !
|
|
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
|
-
|
|
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
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
1048
|
+
HOME: join2(staging, "home"),
|
|
1065
1049
|
NPM_CONFIG_AUDIT: "false",
|
|
1066
|
-
NPM_CONFIG_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(
|
|
1089
|
-
rm(
|
|
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
|
|
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
|
-
|
|
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
|
|
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/
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
1384
|
-
realpath as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1856
|
+
function isRecord2(value) {
|
|
1637
1857
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1638
1858
|
}
|
|
1639
|
-
function
|
|
1640
|
-
const difference =
|
|
1641
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${
|
|
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
|
|
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 (!
|
|
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
|
|
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 || !
|
|
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
|
|
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
|
|
2043
|
+
const extracted = await realpath5(
|
|
1824
2044
|
join7(canonicalExtractionRoot, definition.executableName)
|
|
1825
2045
|
);
|
|
1826
2046
|
const extractedMetadata = await stat4(extracted);
|
|
1827
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
2408
|
+
methods3.client.session.requestPermission,
|
|
2112
2409
|
async (context) => await handler.onPermission(context.params, context.signal)
|
|
2113
2410
|
).onRequest(
|
|
2114
|
-
|
|
2411
|
+
methods3.client.elicitation.create,
|
|
2115
2412
|
async (context) => await handler.onElicitation(context.params, context.signal)
|
|
2116
|
-
).onNotification(
|
|
2413
|
+
).onNotification(methods3.client.session.update, async (context) => {
|
|
2117
2414
|
await handler.onUpdate(context.params);
|
|
2118
|
-
}).onNotification(
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 || !
|
|
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
|
|
2670
|
+
let open6 = true;
|
|
2355
2671
|
return new ReadableStream({
|
|
2356
2672
|
start(controller) {
|
|
2357
2673
|
input2.on("data", (chunk) => {
|
|
2358
|
-
if (!
|
|
2674
|
+
if (!open6) {
|
|
2359
2675
|
return;
|
|
2360
2676
|
}
|
|
2361
2677
|
if (!(chunk instanceof Uint8Array)) {
|
|
2362
|
-
|
|
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
|
-
|
|
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 (
|
|
2376
|
-
|
|
2691
|
+
if (open6) {
|
|
2692
|
+
open6 = false;
|
|
2377
2693
|
controller.close();
|
|
2378
2694
|
}
|
|
2379
2695
|
});
|
|
2380
2696
|
input2.once("error", (error61) => {
|
|
2381
|
-
if (
|
|
2382
|
-
|
|
2697
|
+
if (open6) {
|
|
2698
|
+
open6 = false;
|
|
2383
2699
|
controller.error(error61);
|
|
2384
2700
|
}
|
|
2385
2701
|
});
|
|
2386
2702
|
},
|
|
2387
2703
|
cancel() {
|
|
2388
|
-
|
|
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
|
-
|
|
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
|
|
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: () =>
|
|
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: () =>
|
|
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 = (
|
|
5160
|
-
const escapedDelim = escapeRegex(
|
|
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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
8137
|
+
const depth = open4.length;
|
|
8293
8138
|
const result = base(payload, ctx);
|
|
8294
8139
|
handoff = void 0;
|
|
8295
|
-
const entry =
|
|
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: () =>
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
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
|
-
|
|
23631
|
-
|
|
23632
|
-
|
|
23633
|
-
|
|
23634
|
-
|
|
23635
|
-
|
|
23636
|
-
|
|
23637
|
-
|
|
23638
|
-
|
|
23639
|
-
|
|
23640
|
-
|
|
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
|
|
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
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (
|
|
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 (!
|
|
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 (
|
|
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 (!
|
|
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 (
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
27222
|
+
specification.id
|
|
26939
27223
|
);
|
|
26940
27224
|
await this.#executor.execute(
|
|
26941
|
-
|
|
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
|
|
27212
|
-
import { join as
|
|
27213
|
-
|
|
27214
|
-
|
|
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 =
|
|
27244
|
-
const temporaryRoot =
|
|
27740
|
+
const root = join17(options.stateDirectory, "agents", this.id);
|
|
27741
|
+
const temporaryRoot = join17(options.stateDirectory, "temporary");
|
|
27245
27742
|
await Promise.all([
|
|
27246
|
-
|
|
27247
|
-
|
|
27743
|
+
mkdir5(root, { mode: 448, recursive: true }),
|
|
27744
|
+
mkdir5(temporaryRoot, { mode: 448, recursive: true })
|
|
27248
27745
|
]);
|
|
27249
27746
|
const temporaryDirectory = await mkdtemp3(
|
|
27250
|
-
|
|
27747
|
+
join17(temporaryRoot, ".codex-install-")
|
|
27251
27748
|
);
|
|
27252
|
-
const installerPath =
|
|
27253
|
-
const installDirectory =
|
|
27254
|
-
const codexHome =
|
|
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
|
-
|
|
27258
|
-
|
|
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
|
-
|
|
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 =
|
|
27323
|
-
const managedHome =
|
|
27324
|
-
const temporaryRoot =
|
|
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
|
-
|
|
27327
|
-
|
|
27823
|
+
mkdir5(managedHome, { mode: 448, recursive: true }),
|
|
27824
|
+
mkdir5(temporaryRoot, { mode: 448, recursive: true })
|
|
27328
27825
|
]);
|
|
27329
27826
|
const temporaryDirectory = await mkdtemp3(
|
|
27330
|
-
|
|
27827
|
+
join17(temporaryRoot, ".claude-install-")
|
|
27331
27828
|
);
|
|
27332
|
-
const installerPath =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
27967
|
+
const managedHome = join17(
|
|
27471
27968
|
options.stateDirectory,
|
|
27472
27969
|
"agents",
|
|
27473
27970
|
this.id,
|
|
27474
27971
|
"home"
|
|
27475
27972
|
);
|
|
27476
|
-
await
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
27903
|
-
isAbsolute as
|
|
27904
|
-
join as
|
|
28366
|
+
dirname as dirname6,
|
|
28367
|
+
isAbsolute as isAbsolute7,
|
|
28368
|
+
join as join18,
|
|
27905
28369
|
normalize as normalize2,
|
|
27906
|
-
relative as
|
|
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 (
|
|
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 (!
|
|
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
|
|
28429
|
+
const target = await realpath8(requested);
|
|
27966
28430
|
signal.throwIfAborted();
|
|
27967
|
-
const metadata = await
|
|
28431
|
+
const metadata = await stat7(target);
|
|
27968
28432
|
signal.throwIfAborted();
|
|
27969
|
-
if (!
|
|
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 =
|
|
27985
|
-
return suffix === "" ? "~" : !
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
30588
|
+
await mkdir6(loadDefaultWorkspace(), { recursive: true, mode: 448 });
|
|
30137
30589
|
const inventory = await discoverLocalAgentInventory({
|
|
30138
30590
|
defaultWorkspace: loadDefaultWorkspace(),
|
|
30139
30591
|
environment: process.env,
|