@moxt-ai/mobius 0.0.9 → 0.0.10
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/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +11 -2
- package/dist/acp/session-manager.js.map +1 -1
- package/dist/agent-catalog/agent-diagnostics.d.ts.map +1 -1
- package/dist/agent-catalog/agent-diagnostics.js +6 -2
- package/dist/agent-catalog/agent-diagnostics.js.map +1 -1
- package/dist/agent-catalog/discover-local-agents.d.ts +35 -7
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
- package/dist/agent-catalog/discover-local-agents.js +137 -26
- package/dist/agent-catalog/discover-local-agents.js.map +1 -1
- package/dist/agent-catalog/local-agent.d.ts +2 -1
- package/dist/agent-catalog/local-agent.d.ts.map +1 -1
- package/dist/agent-catalog/local-agent.js +7 -1
- package/dist/agent-catalog/local-agent.js.map +1 -1
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts +1 -0
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
- package/dist/agent-installation/fixed-agent-install-recipes.js +48 -0
- package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.js +2 -0
- package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.d.ts +3 -2
- package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.js +25 -126
- package/dist/agent-installation/managed-adapter-installer.js.map +1 -1
- package/dist/agent-installation/managed-npm-package.d.ts +24 -0
- package/dist/agent-installation/managed-npm-package.d.ts.map +1 -0
- package/dist/agent-installation/managed-npm-package.js +227 -0
- package/dist/agent-installation/managed-npm-package.js.map +1 -0
- package/dist/agent-installation/pi-managed-packages.d.ts +4 -0
- package/dist/agent-installation/pi-managed-packages.d.ts.map +1 -0
- package/dist/agent-installation/pi-managed-packages.js +4 -0
- package/dist/agent-installation/pi-managed-packages.js.map +1 -0
- package/dist/cli.js +610 -159
- package/dist/cli.js.map +4 -4
- package/dist/index.js +601 -152
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -388,7 +388,11 @@ var LocalAgentDefinition = class {
|
|
|
388
388
|
environment;
|
|
389
389
|
id;
|
|
390
390
|
label;
|
|
391
|
-
|
|
391
|
+
promptTimeoutMilliseconds;
|
|
392
|
+
constructor(id, label, command, arguments_, environment = {}, adapterVersion = "", agentVersion = "", adapterIdentity = readTrustedIdentity(command), agentIdentity = adapterIdentity, promptTimeoutMilliseconds = 30 * 60 * 1e3) {
|
|
393
|
+
if (!Number.isSafeInteger(promptTimeoutMilliseconds) || promptTimeoutMilliseconds < 1) {
|
|
394
|
+
throw new Error("The local Agent prompt deadline is invalid");
|
|
395
|
+
}
|
|
392
396
|
this.adapterIdentity = adapterIdentity;
|
|
393
397
|
this.adapterPath = adapterIdentity.realPath;
|
|
394
398
|
this.adapterVersion = adapterVersion;
|
|
@@ -396,6 +400,7 @@ var LocalAgentDefinition = class {
|
|
|
396
400
|
this.agentVersion = agentVersion;
|
|
397
401
|
this.id = id;
|
|
398
402
|
this.label = label;
|
|
403
|
+
this.promptTimeoutMilliseconds = promptTimeoutMilliseconds;
|
|
399
404
|
this.command = adapterIdentity.realPath;
|
|
400
405
|
this.arguments = Object.freeze([...arguments_]);
|
|
401
406
|
this.environment = Object.freeze({ ...environment });
|
|
@@ -23587,12 +23592,27 @@ var AcpSessionManager = class {
|
|
|
23587
23592
|
"session_busy"
|
|
23588
23593
|
);
|
|
23589
23594
|
}
|
|
23595
|
+
const deadlineController = new AbortController();
|
|
23596
|
+
const deadlineError = new AcpExecutionError(
|
|
23597
|
+
"The local Agent prompt exceeded its deadline",
|
|
23598
|
+
{},
|
|
23599
|
+
"prompt_timeout"
|
|
23600
|
+
);
|
|
23601
|
+
const deadline = setTimeout(
|
|
23602
|
+
() => deadlineController.abort(deadlineError),
|
|
23603
|
+
options.agent.promptTimeoutMilliseconds
|
|
23604
|
+
);
|
|
23605
|
+
deadline.unref();
|
|
23606
|
+
const boundedOptions = {
|
|
23607
|
+
...options,
|
|
23608
|
+
signal: AbortSignal.any([options.signal, deadlineController.signal])
|
|
23609
|
+
};
|
|
23590
23610
|
this.#activeSessionIds.add(options.sessionId);
|
|
23591
23611
|
try {
|
|
23592
23612
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
23593
23613
|
return { stopReason: "cancelled" };
|
|
23594
23614
|
}
|
|
23595
|
-
const runtime = await this.ensureSession(
|
|
23615
|
+
const runtime = await this.ensureSession(boundedOptions);
|
|
23596
23616
|
if (this.#nativeOperations.has(
|
|
23597
23617
|
`${options.agent.id}:${runtime.nativeSessionId()}`
|
|
23598
23618
|
))
|
|
@@ -23604,7 +23624,7 @@ var AcpSessionManager = class {
|
|
|
23604
23624
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
23605
23625
|
return { stopReason: "cancelled" };
|
|
23606
23626
|
}
|
|
23607
|
-
return await runtime.prompt(
|
|
23627
|
+
return await runtime.prompt(boundedOptions);
|
|
23608
23628
|
} catch (error61) {
|
|
23609
23629
|
const failedRuntime = this.#sessions.get(options.sessionId);
|
|
23610
23630
|
if (failedRuntime !== void 0) {
|
|
@@ -23618,6 +23638,7 @@ var AcpSessionManager = class {
|
|
|
23618
23638
|
cause: error61
|
|
23619
23639
|
});
|
|
23620
23640
|
} finally {
|
|
23641
|
+
clearTimeout(deadline);
|
|
23621
23642
|
this.#activeSessionIds.delete(options.sessionId);
|
|
23622
23643
|
this.#cancellationRequests.delete(options.sessionId);
|
|
23623
23644
|
}
|
|
@@ -23919,16 +23940,17 @@ import {
|
|
|
23919
23940
|
writeFile
|
|
23920
23941
|
} from "node:fs/promises";
|
|
23921
23942
|
import { hostname as hostname3 } from "node:os";
|
|
23922
|
-
import { basename, join as
|
|
23943
|
+
import { basename, join as join8, resolve as resolve3 } from "node:path";
|
|
23923
23944
|
import { fetch } from "undici";
|
|
23924
23945
|
|
|
23925
23946
|
// src/agent-catalog/discover-local-agents.ts
|
|
23926
23947
|
import { spawn as spawn3 } from "node:child_process";
|
|
23927
|
-
import { isAbsolute, join as
|
|
23948
|
+
import { isAbsolute as isAbsolute2, join as join7 } from "node:path";
|
|
23928
23949
|
import {
|
|
23929
23950
|
methods as methods3,
|
|
23930
23951
|
ndJsonStream as ndJsonStream2,
|
|
23931
|
-
PROTOCOL_VERSION as PROTOCOL_VERSION2
|
|
23952
|
+
PROTOCOL_VERSION as PROTOCOL_VERSION2,
|
|
23953
|
+
RequestError
|
|
23932
23954
|
} from "@agentclientprotocol/sdk";
|
|
23933
23955
|
|
|
23934
23956
|
// src/agent-installation/installation-grants.ts
|
|
@@ -23974,6 +23996,9 @@ async function readGrantedAgents(stateDirectory) {
|
|
|
23974
23996
|
}
|
|
23975
23997
|
|
|
23976
23998
|
// src/agent-installation/managed-adapter-installer.ts
|
|
23999
|
+
import { join as join6 } from "node:path";
|
|
24000
|
+
|
|
24001
|
+
// src/agent-installation/managed-npm-package.ts
|
|
23977
24002
|
import {
|
|
23978
24003
|
mkdir,
|
|
23979
24004
|
mkdtemp,
|
|
@@ -23983,15 +24008,35 @@ import {
|
|
|
23983
24008
|
rm,
|
|
23984
24009
|
stat as stat2
|
|
23985
24010
|
} from "node:fs/promises";
|
|
23986
|
-
import { delimiter, dirname as dirname3, join as join5, relative } from "node:path";
|
|
23987
|
-
var
|
|
24011
|
+
import { delimiter, dirname as dirname3, isAbsolute, join as join5, relative, sep } from "node:path";
|
|
24012
|
+
var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
|
|
23988
24013
|
var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
|
|
23989
|
-
var
|
|
24014
|
+
var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
24015
|
+
var ManagedNpmPackageDefinition = class {
|
|
24016
|
+
executableName;
|
|
24017
|
+
packageName;
|
|
24018
|
+
version;
|
|
24019
|
+
constructor(packageName, version2, executableName) {
|
|
24020
|
+
this.executableName = executableName;
|
|
24021
|
+
this.packageName = packageName;
|
|
24022
|
+
this.version = version2;
|
|
24023
|
+
}
|
|
24024
|
+
};
|
|
24025
|
+
var SriManagedNpmPackageDefinition = class extends ManagedNpmPackageDefinition {
|
|
24026
|
+
integrity;
|
|
24027
|
+
tarballUrl;
|
|
24028
|
+
constructor(packageName, version2, executableName, integrity, tarballUrl) {
|
|
24029
|
+
super(packageName, version2, executableName);
|
|
24030
|
+
this.integrity = integrity;
|
|
24031
|
+
this.tarballUrl = tarballUrl;
|
|
24032
|
+
}
|
|
24033
|
+
};
|
|
24034
|
+
var ManagedNpmPackageError = class extends Error {
|
|
23990
24035
|
code;
|
|
23991
24036
|
constructor(code, message, options = {}) {
|
|
23992
24037
|
super(message, options);
|
|
23993
24038
|
this.code = code;
|
|
23994
|
-
this.name = "
|
|
24039
|
+
this.name = "ManagedNpmPackageError";
|
|
23995
24040
|
}
|
|
23996
24041
|
};
|
|
23997
24042
|
function isRecord5(value) {
|
|
@@ -24000,28 +24045,43 @@ function isRecord5(value) {
|
|
|
24000
24045
|
function packagePath(root, packageName) {
|
|
24001
24046
|
return join5(root, "node_modules", ...packageName.split("/"));
|
|
24002
24047
|
}
|
|
24003
|
-
|
|
24004
|
-
const
|
|
24048
|
+
function isContainedPath(root, candidate) {
|
|
24049
|
+
const difference = relative(root, candidate);
|
|
24050
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute(difference);
|
|
24051
|
+
}
|
|
24052
|
+
async function readJsonRecord(path2, maximumBytes) {
|
|
24005
24053
|
try {
|
|
24006
|
-
const
|
|
24007
|
-
|
|
24008
|
-
|
|
24009
|
-
|
|
24010
|
-
|
|
24054
|
+
const handle = await open3(path2, "r");
|
|
24055
|
+
try {
|
|
24056
|
+
const metadata = await handle.stat();
|
|
24057
|
+
if (!metadata.isFile() || metadata.size > maximumBytes) {
|
|
24058
|
+
throw new ManagedNpmPackageError(
|
|
24059
|
+
"managed_package_verification_failed",
|
|
24060
|
+
"The managed npm package metadata is invalid"
|
|
24061
|
+
);
|
|
24062
|
+
}
|
|
24063
|
+
const value = JSON.parse(
|
|
24064
|
+
await handle.readFile({ encoding: "utf8" })
|
|
24011
24065
|
);
|
|
24066
|
+
if (!isRecord5(value)) {
|
|
24067
|
+
throw new ManagedNpmPackageError(
|
|
24068
|
+
"managed_package_verification_failed",
|
|
24069
|
+
"The managed npm package metadata is invalid"
|
|
24070
|
+
);
|
|
24071
|
+
}
|
|
24072
|
+
return value;
|
|
24073
|
+
} finally {
|
|
24074
|
+
await handle.close();
|
|
24012
24075
|
}
|
|
24013
|
-
|
|
24014
|
-
|
|
24015
|
-
|
|
24016
|
-
if (!isRecord5(value)) {
|
|
24017
|
-
throw new ManagedAdapterInstallError(
|
|
24018
|
-
"adapter_verification_failed",
|
|
24019
|
-
"The managed adapter package metadata is invalid"
|
|
24020
|
-
);
|
|
24076
|
+
} catch (error61) {
|
|
24077
|
+
if (error61 instanceof ManagedNpmPackageError) {
|
|
24078
|
+
throw error61;
|
|
24021
24079
|
}
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24080
|
+
throw new ManagedNpmPackageError(
|
|
24081
|
+
"managed_package_verification_failed",
|
|
24082
|
+
"The managed npm package metadata is invalid",
|
|
24083
|
+
{ cause: error61 }
|
|
24084
|
+
);
|
|
24025
24085
|
}
|
|
24026
24086
|
}
|
|
24027
24087
|
function readBinPath(packageMetadata, executableName) {
|
|
@@ -24032,83 +24092,125 @@ function readBinPath(packageMetadata, executableName) {
|
|
|
24032
24092
|
if (isRecord5(bin) && typeof bin[executableName] === "string") {
|
|
24033
24093
|
return bin[executableName];
|
|
24034
24094
|
}
|
|
24035
|
-
throw new
|
|
24036
|
-
"
|
|
24037
|
-
"The managed
|
|
24095
|
+
throw new ManagedNpmPackageError(
|
|
24096
|
+
"managed_package_verification_failed",
|
|
24097
|
+
"The managed npm package executable declaration is invalid"
|
|
24038
24098
|
);
|
|
24039
24099
|
}
|
|
24040
|
-
|
|
24100
|
+
function verifyPackageLock(lock, definition) {
|
|
24101
|
+
if (lock["lockfileVersion"] !== 3) {
|
|
24102
|
+
throw new ManagedNpmPackageError(
|
|
24103
|
+
"managed_package_verification_failed",
|
|
24104
|
+
"The managed npm package lockfile is invalid"
|
|
24105
|
+
);
|
|
24106
|
+
}
|
|
24107
|
+
const packages = lock["packages"];
|
|
24108
|
+
if (!isRecord5(packages)) {
|
|
24109
|
+
throw new ManagedNpmPackageError(
|
|
24110
|
+
"managed_package_verification_failed",
|
|
24111
|
+
"The managed npm package lockfile is invalid"
|
|
24112
|
+
);
|
|
24113
|
+
}
|
|
24114
|
+
const suffix = `node_modules/${definition.packageName}`;
|
|
24115
|
+
let entry;
|
|
24116
|
+
let matches = 0;
|
|
24117
|
+
for (const [key, candidate] of Object.entries(packages)) {
|
|
24118
|
+
const normalizedKey = key.replaceAll("\\", "/");
|
|
24119
|
+
if (normalizedKey === suffix || normalizedKey.endsWith(`/${suffix}`)) {
|
|
24120
|
+
entry = candidate;
|
|
24121
|
+
matches += 1;
|
|
24122
|
+
}
|
|
24123
|
+
}
|
|
24124
|
+
if (matches !== 1 || !isRecord5(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
|
|
24125
|
+
throw new ManagedNpmPackageError(
|
|
24126
|
+
"managed_package_verification_failed",
|
|
24127
|
+
"The managed npm package lockfile does not match the pinned artifact"
|
|
24128
|
+
);
|
|
24129
|
+
}
|
|
24130
|
+
}
|
|
24131
|
+
async function validateManagedNpmPackage(root, definition) {
|
|
24132
|
+
try {
|
|
24133
|
+
return await validateManagedNpmPackageContents(root, definition);
|
|
24134
|
+
} catch (error61) {
|
|
24135
|
+
if (error61 instanceof ManagedNpmPackageError) {
|
|
24136
|
+
throw error61;
|
|
24137
|
+
}
|
|
24138
|
+
throw new ManagedNpmPackageError(
|
|
24139
|
+
"managed_package_verification_failed",
|
|
24140
|
+
"The managed npm package is invalid",
|
|
24141
|
+
{ cause: error61 }
|
|
24142
|
+
);
|
|
24143
|
+
}
|
|
24144
|
+
}
|
|
24145
|
+
async function validateManagedNpmPackageContents(root, definition) {
|
|
24041
24146
|
const rootPath = await realpath2(root);
|
|
24042
24147
|
const packageRoot = await realpath2(
|
|
24043
|
-
packagePath(rootPath,
|
|
24148
|
+
packagePath(rootPath, definition.packageName)
|
|
24044
24149
|
);
|
|
24045
|
-
|
|
24046
|
-
|
|
24047
|
-
|
|
24048
|
-
"
|
|
24049
|
-
"The managed adapter package escaped its private cache"
|
|
24150
|
+
if (!isContainedPath(rootPath, packageRoot)) {
|
|
24151
|
+
throw new ManagedNpmPackageError(
|
|
24152
|
+
"managed_package_verification_failed",
|
|
24153
|
+
"The managed npm package escaped its private cache"
|
|
24050
24154
|
);
|
|
24051
24155
|
}
|
|
24052
|
-
const metadata = await
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24156
|
+
const metadata = await readJsonRecord(
|
|
24157
|
+
join5(packageRoot, "package.json"),
|
|
24158
|
+
PACKAGE_METADATA_LIMIT_BYTES
|
|
24159
|
+
);
|
|
24160
|
+
if (metadata["name"] !== definition.packageName || metadata["version"] !== definition.version) {
|
|
24161
|
+
throw new ManagedNpmPackageError(
|
|
24162
|
+
"managed_package_verification_failed",
|
|
24163
|
+
"The managed npm package identity is invalid"
|
|
24057
24164
|
);
|
|
24058
24165
|
}
|
|
24059
|
-
|
|
24166
|
+
if (definition instanceof SriManagedNpmPackageDefinition) {
|
|
24167
|
+
verifyPackageLock(
|
|
24168
|
+
await readJsonRecord(
|
|
24169
|
+
join5(rootPath, "package-lock.json"),
|
|
24170
|
+
PACKAGE_LOCK_LIMIT_BYTES
|
|
24171
|
+
),
|
|
24172
|
+
definition
|
|
24173
|
+
);
|
|
24174
|
+
}
|
|
24175
|
+
const declaredBin = readBinPath(metadata, definition.executableName);
|
|
24060
24176
|
const executable = await resolveExecutablePath(
|
|
24061
24177
|
join5(packageRoot, declaredBin)
|
|
24062
24178
|
);
|
|
24063
|
-
if (executable === null) {
|
|
24064
|
-
throw new
|
|
24065
|
-
"
|
|
24066
|
-
"The managed
|
|
24067
|
-
);
|
|
24068
|
-
}
|
|
24069
|
-
const executableDifference = relative(rootPath, executable.path);
|
|
24070
|
-
if (executableDifference.startsWith("..") || executableDifference.length === 0) {
|
|
24071
|
-
throw new ManagedAdapterInstallError(
|
|
24072
|
-
"adapter_verification_failed",
|
|
24073
|
-
"The managed adapter executable escaped its private cache"
|
|
24179
|
+
if (executable === null || !isContainedPath(rootPath, executable.path)) {
|
|
24180
|
+
throw new ManagedNpmPackageError(
|
|
24181
|
+
"managed_package_verification_failed",
|
|
24182
|
+
"The managed npm package executable is invalid"
|
|
24074
24183
|
);
|
|
24075
24184
|
}
|
|
24076
24185
|
return executable;
|
|
24077
24186
|
}
|
|
24078
|
-
var
|
|
24079
|
-
|
|
24080
|
-
#stateDirectory;
|
|
24081
|
-
constructor(options) {
|
|
24082
|
-
this.#environment = options.environment;
|
|
24083
|
-
this.#stateDirectory = options.stateDirectory;
|
|
24084
|
-
}
|
|
24085
|
-
install = async (specification, signal) => {
|
|
24187
|
+
var ManagedNpmPackageInstaller = class {
|
|
24188
|
+
install = async (root, definition, environment, signal) => {
|
|
24086
24189
|
signal.throwIfAborted();
|
|
24087
|
-
const agentCache = join5(this.#stateDirectory, "adapters", specification.id);
|
|
24088
|
-
const published = join5(agentCache, specification.adapterVersion);
|
|
24089
24190
|
try {
|
|
24090
|
-
const metadata = await stat2(
|
|
24191
|
+
const metadata = await stat2(root);
|
|
24091
24192
|
if (metadata.isDirectory()) {
|
|
24092
|
-
return await
|
|
24193
|
+
return await validateManagedNpmPackage(root, definition);
|
|
24093
24194
|
}
|
|
24094
24195
|
} catch (error61) {
|
|
24095
24196
|
if (!(error61 instanceof Error) || !("code" in error61) || error61.code !== "ENOENT") {
|
|
24096
24197
|
throw error61;
|
|
24097
24198
|
}
|
|
24098
24199
|
}
|
|
24099
|
-
|
|
24200
|
+
const parent = dirname3(root);
|
|
24201
|
+
await mkdir(parent, { mode: 448, recursive: true });
|
|
24100
24202
|
const staging = await mkdtemp(
|
|
24101
|
-
join5(
|
|
24203
|
+
join5(parent, `.${definition.version}.staging-`)
|
|
24102
24204
|
);
|
|
24103
24205
|
try {
|
|
24104
24206
|
const npm = await findExecutableOnPath(
|
|
24105
24207
|
process.platform === "win32" ? "npm.cmd" : "npm",
|
|
24106
|
-
|
|
24208
|
+
environment
|
|
24107
24209
|
);
|
|
24108
24210
|
if (npm === null) {
|
|
24109
|
-
throw new
|
|
24211
|
+
throw new ManagedNpmPackageError(
|
|
24110
24212
|
"package_manager_not_found",
|
|
24111
|
-
"A supported npm executable is required to install the
|
|
24213
|
+
"A supported npm executable is required to install the managed package"
|
|
24112
24214
|
);
|
|
24113
24215
|
}
|
|
24114
24216
|
await runBoundedProcess({
|
|
@@ -24120,51 +24222,57 @@ var ManagedAdapterInstaller = class {
|
|
|
24120
24222
|
"--ignore-scripts",
|
|
24121
24223
|
"--no-audit",
|
|
24122
24224
|
"--no-fund",
|
|
24123
|
-
"--package-lock=
|
|
24124
|
-
"--save
|
|
24225
|
+
"--package-lock=true",
|
|
24226
|
+
"--save-exact",
|
|
24125
24227
|
"--registry=https://registry.npmjs.org/",
|
|
24126
|
-
`${
|
|
24228
|
+
`${definition.packageName}@${definition.version}`
|
|
24127
24229
|
],
|
|
24128
24230
|
command: npm.path,
|
|
24129
24231
|
cwd: staging,
|
|
24130
24232
|
environment: {
|
|
24131
24233
|
HOME: join5(staging, "home"),
|
|
24132
24234
|
NPM_CONFIG_AUDIT: "false",
|
|
24235
|
+
NPM_CONFIG_CACHE: join5(staging, ".npm-cache"),
|
|
24133
24236
|
NPM_CONFIG_FUND: "false",
|
|
24134
24237
|
NPM_CONFIG_IGNORE_SCRIPTS: "true",
|
|
24135
24238
|
NPM_CONFIG_OMIT: "optional",
|
|
24239
|
+
NPM_CONFIG_PACKAGE_LOCK: "true",
|
|
24136
24240
|
NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/",
|
|
24137
24241
|
PATH: `${dirname3(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
|
|
24138
24242
|
},
|
|
24139
24243
|
outputLimitBytes: 64 * 1024,
|
|
24140
24244
|
signal,
|
|
24141
|
-
timeoutMilliseconds:
|
|
24245
|
+
timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS
|
|
24142
24246
|
});
|
|
24143
|
-
await
|
|
24247
|
+
await Promise.all([
|
|
24248
|
+
rm(join5(staging, ".npm-cache"), { force: true, recursive: true }),
|
|
24249
|
+
rm(join5(staging, "home"), { force: true, recursive: true })
|
|
24250
|
+
]);
|
|
24251
|
+
await validateManagedNpmPackage(staging, definition);
|
|
24144
24252
|
try {
|
|
24145
|
-
await rename(staging,
|
|
24253
|
+
await rename(staging, root);
|
|
24146
24254
|
} catch (error61) {
|
|
24147
24255
|
try {
|
|
24148
|
-
return await
|
|
24256
|
+
return await validateManagedNpmPackage(root, definition);
|
|
24149
24257
|
} catch {
|
|
24150
|
-
throw new
|
|
24151
|
-
"
|
|
24152
|
-
"The managed
|
|
24258
|
+
throw new ManagedNpmPackageError(
|
|
24259
|
+
"managed_package_publish_failed",
|
|
24260
|
+
"The managed npm package could not be published",
|
|
24153
24261
|
{ cause: error61 }
|
|
24154
24262
|
);
|
|
24155
24263
|
}
|
|
24156
24264
|
}
|
|
24157
|
-
return await
|
|
24265
|
+
return await validateManagedNpmPackage(root, definition);
|
|
24158
24266
|
} catch (error61) {
|
|
24159
24267
|
if (signal.aborted) {
|
|
24160
24268
|
signal.throwIfAborted();
|
|
24161
24269
|
}
|
|
24162
|
-
if (error61 instanceof
|
|
24270
|
+
if (error61 instanceof ManagedNpmPackageError) {
|
|
24163
24271
|
throw error61;
|
|
24164
24272
|
}
|
|
24165
|
-
throw new
|
|
24166
|
-
"
|
|
24167
|
-
"The pinned
|
|
24273
|
+
throw new ManagedNpmPackageError(
|
|
24274
|
+
"managed_package_install_failed",
|
|
24275
|
+
"The pinned npm package could not be installed",
|
|
24168
24276
|
{ cause: error61 }
|
|
24169
24277
|
);
|
|
24170
24278
|
} finally {
|
|
@@ -24173,20 +24281,152 @@ var ManagedAdapterInstaller = class {
|
|
|
24173
24281
|
};
|
|
24174
24282
|
};
|
|
24175
24283
|
|
|
24284
|
+
// src/agent-installation/managed-adapter-installer.ts
|
|
24285
|
+
var ManagedAdapterInstallError = class extends Error {
|
|
24286
|
+
code;
|
|
24287
|
+
constructor(code, message, options = {}) {
|
|
24288
|
+
super(message, options);
|
|
24289
|
+
this.code = code;
|
|
24290
|
+
this.name = "ManagedAdapterInstallError";
|
|
24291
|
+
}
|
|
24292
|
+
};
|
|
24293
|
+
function translateError(error61) {
|
|
24294
|
+
if (error61 instanceof ManagedAdapterInstallError) {
|
|
24295
|
+
return error61;
|
|
24296
|
+
}
|
|
24297
|
+
if (error61 instanceof ManagedNpmPackageError) {
|
|
24298
|
+
if (error61.code === "package_manager_not_found") {
|
|
24299
|
+
return new ManagedAdapterInstallError(
|
|
24300
|
+
error61.code,
|
|
24301
|
+
"A supported npm executable is required to install the ACP adapter",
|
|
24302
|
+
{ cause: error61 }
|
|
24303
|
+
);
|
|
24304
|
+
}
|
|
24305
|
+
if (error61.code === "managed_package_verification_failed") {
|
|
24306
|
+
return new ManagedAdapterInstallError(
|
|
24307
|
+
"adapter_verification_failed",
|
|
24308
|
+
"The managed adapter did not match its pinned artifact",
|
|
24309
|
+
{ cause: error61 }
|
|
24310
|
+
);
|
|
24311
|
+
}
|
|
24312
|
+
if (error61.code === "managed_package_publish_failed") {
|
|
24313
|
+
return new ManagedAdapterInstallError(
|
|
24314
|
+
"adapter_publish_failed",
|
|
24315
|
+
"The managed adapter could not be published",
|
|
24316
|
+
{ cause: error61 }
|
|
24317
|
+
);
|
|
24318
|
+
}
|
|
24319
|
+
}
|
|
24320
|
+
return new ManagedAdapterInstallError(
|
|
24321
|
+
"adapter_install_failed",
|
|
24322
|
+
"The pinned ACP adapter could not be installed",
|
|
24323
|
+
{ cause: error61 }
|
|
24324
|
+
);
|
|
24325
|
+
}
|
|
24326
|
+
async function validateManagedAdapter(root, specification) {
|
|
24327
|
+
try {
|
|
24328
|
+
return await validateManagedNpmPackage(
|
|
24329
|
+
root,
|
|
24330
|
+
specification.adapterPackageDefinition
|
|
24331
|
+
);
|
|
24332
|
+
} catch (error61) {
|
|
24333
|
+
throw translateError(error61);
|
|
24334
|
+
}
|
|
24335
|
+
}
|
|
24336
|
+
var ManagedAdapterInstaller = class {
|
|
24337
|
+
#environment;
|
|
24338
|
+
#npmInstaller;
|
|
24339
|
+
#stateDirectory;
|
|
24340
|
+
constructor(options, npmInstaller = new ManagedNpmPackageInstaller()) {
|
|
24341
|
+
this.#environment = options.environment;
|
|
24342
|
+
this.#npmInstaller = npmInstaller;
|
|
24343
|
+
this.#stateDirectory = options.stateDirectory;
|
|
24344
|
+
}
|
|
24345
|
+
install = async (specification, signal) => {
|
|
24346
|
+
const root = join6(
|
|
24347
|
+
this.#stateDirectory,
|
|
24348
|
+
"adapters",
|
|
24349
|
+
specification.id,
|
|
24350
|
+
specification.adapterVersion
|
|
24351
|
+
);
|
|
24352
|
+
try {
|
|
24353
|
+
return await this.#npmInstaller.install(
|
|
24354
|
+
root,
|
|
24355
|
+
specification.adapterPackageDefinition,
|
|
24356
|
+
this.#environment,
|
|
24357
|
+
signal
|
|
24358
|
+
);
|
|
24359
|
+
} catch (error61) {
|
|
24360
|
+
if (signal.aborted) {
|
|
24361
|
+
signal.throwIfAborted();
|
|
24362
|
+
}
|
|
24363
|
+
throw translateError(error61);
|
|
24364
|
+
}
|
|
24365
|
+
};
|
|
24366
|
+
};
|
|
24367
|
+
|
|
24368
|
+
// src/agent-installation/pi-managed-packages.ts
|
|
24369
|
+
var PI_ACP_PACKAGE = new SriManagedNpmPackageDefinition(
|
|
24370
|
+
"pi-acp",
|
|
24371
|
+
"0.0.33",
|
|
24372
|
+
"pi-acp",
|
|
24373
|
+
"sha512-vX9kY1tK14E72G4dBAx+RGCk/k7XPjTHls6dLUxA8WSkBav6B6JHuSBv3eusp50LCR/GTRsR2kIKsG0Z5jANzw==",
|
|
24374
|
+
"https://registry.npmjs.org/pi-acp/-/pi-acp-0.0.33.tgz"
|
|
24375
|
+
);
|
|
24376
|
+
var PI_AGENT_PACKAGE = new SriManagedNpmPackageDefinition(
|
|
24377
|
+
"@earendil-works/pi-coding-agent",
|
|
24378
|
+
"0.85.0",
|
|
24379
|
+
"pi",
|
|
24380
|
+
"sha512-INxVkLAVfAMju5MojJpmyu/0bMP+r+ffZuS7UqVv32E2JwHBRbcHfELDfmFNvapEbgYfKN2r9OYO1p3TqDBR+g==",
|
|
24381
|
+
"https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.85.0.tgz"
|
|
24382
|
+
);
|
|
24383
|
+
|
|
24176
24384
|
// src/agent-catalog/discover-local-agents.ts
|
|
24177
24385
|
var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
|
|
24178
24386
|
var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
|
|
24179
24387
|
var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
|
|
24388
|
+
var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
|
|
24389
|
+
var PI_ACP_PROBE_TIMEOUT_MILLISECONDS = 3e4;
|
|
24390
|
+
var PI_PROMPT_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
|
|
24180
24391
|
var LocalAgentSpecification = class {
|
|
24392
|
+
acpProbeTimeoutMilliseconds = ACP_PROBE_TIMEOUT_MILLISECONDS;
|
|
24393
|
+
authenticationCommand = () => "";
|
|
24394
|
+
adapterVersionArguments = ["--version"];
|
|
24395
|
+
agentVersionArguments = ["--version"];
|
|
24396
|
+
promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
|
|
24397
|
+
get adapterExecutable() {
|
|
24398
|
+
return this.adapterPackageDefinition.executableName;
|
|
24399
|
+
}
|
|
24400
|
+
get adapterPackage() {
|
|
24401
|
+
return this.adapterPackageDefinition.packageName;
|
|
24402
|
+
}
|
|
24403
|
+
get adapterVersion() {
|
|
24404
|
+
return this.adapterPackageDefinition.version;
|
|
24405
|
+
}
|
|
24406
|
+
resolveManagedAgent = async (stateDirectory, platform) => {
|
|
24407
|
+
const executable = await resolveExecutablePath(
|
|
24408
|
+
join7(stateDirectory, ...this.managedAgentExecutablePath),
|
|
24409
|
+
platform
|
|
24410
|
+
);
|
|
24411
|
+
if (executable === null) {
|
|
24412
|
+
throw new Error("The managed Agent executable is unavailable");
|
|
24413
|
+
}
|
|
24414
|
+
return executable;
|
|
24415
|
+
};
|
|
24181
24416
|
recoveryCommand = () => `npm install -g --omit=optional ${this.adapterPackage}@${this.adapterVersion}`;
|
|
24182
24417
|
supportsInstallation = (platform, architecture) => (platform === "darwin" || platform === "linux") && (architecture === "arm64" || architecture === "x64");
|
|
24418
|
+
verifyAcp = (_connection, _initialized, _defaultWorkspace, _signal) => Promise.resolve();
|
|
24419
|
+
};
|
|
24420
|
+
var BridgedAcpAgentDefinition = class extends LocalAgentSpecification {
|
|
24183
24421
|
};
|
|
24184
|
-
var CodexAgentSpecification = class extends
|
|
24422
|
+
var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
24185
24423
|
adapterEnvironmentVariable = "CODEX_PATH";
|
|
24186
|
-
adapterExecutable = "codex-acp";
|
|
24187
24424
|
adapterOverrideVariable = "MOBIUS_CODEX_ACP_PATH";
|
|
24188
|
-
|
|
24189
|
-
|
|
24425
|
+
adapterPackageDefinition = new ManagedNpmPackageDefinition(
|
|
24426
|
+
"@agentclientprotocol/codex-acp",
|
|
24427
|
+
"1.8.0",
|
|
24428
|
+
"codex-acp"
|
|
24429
|
+
);
|
|
24190
24430
|
agentExecutable = "codex";
|
|
24191
24431
|
agentOverrideVariable = "MOBIUS_CODEX_PATH";
|
|
24192
24432
|
id = "codex";
|
|
@@ -24203,12 +24443,14 @@ var CodexAgentSpecification = class extends LocalAgentSpecification {
|
|
|
24203
24443
|
];
|
|
24204
24444
|
managedAgentExecutablePath = ["agents", "codex", "bin", "codex"];
|
|
24205
24445
|
};
|
|
24206
|
-
var ClaudeCodeAgentSpecification = class extends
|
|
24446
|
+
var ClaudeCodeAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
24207
24447
|
adapterEnvironmentVariable = "CLAUDE_CODE_EXECUTABLE";
|
|
24208
|
-
adapterExecutable = "claude-agent-acp";
|
|
24209
24448
|
adapterOverrideVariable = "MOBIUS_CLAUDE_ACP_PATH";
|
|
24210
|
-
|
|
24211
|
-
|
|
24449
|
+
adapterPackageDefinition = new ManagedNpmPackageDefinition(
|
|
24450
|
+
"@agentclientprotocol/claude-agent-acp",
|
|
24451
|
+
"0.73.0",
|
|
24452
|
+
"claude-agent-acp"
|
|
24453
|
+
);
|
|
24212
24454
|
agentExecutable = "claude";
|
|
24213
24455
|
agentOverrideVariable = "MOBIUS_CLAUDE_PATH";
|
|
24214
24456
|
id = "claude";
|
|
@@ -24232,10 +24474,86 @@ var ClaudeCodeAgentSpecification = class extends LocalAgentSpecification {
|
|
|
24232
24474
|
"claude"
|
|
24233
24475
|
];
|
|
24234
24476
|
};
|
|
24477
|
+
var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
24478
|
+
acpProbeTimeoutMilliseconds = PI_ACP_PROBE_TIMEOUT_MILLISECONDS;
|
|
24479
|
+
adapterEnvironmentVariable = "PI_ACP_PI_COMMAND";
|
|
24480
|
+
adapterOverrideVariable = "MOBIUS_PI_ACP_PATH";
|
|
24481
|
+
adapterPackageDefinition = PI_ACP_PACKAGE;
|
|
24482
|
+
adapterVersionArguments = [];
|
|
24483
|
+
authenticationCommand = () => "pi-acp --terminal-login";
|
|
24484
|
+
agentExecutable = "pi";
|
|
24485
|
+
agentOverrideVariable = "MOBIUS_PI_PATH";
|
|
24486
|
+
id = "pi";
|
|
24487
|
+
label = "Pi";
|
|
24488
|
+
managedAdapterExecutablePath = [
|
|
24489
|
+
"adapters",
|
|
24490
|
+
"pi",
|
|
24491
|
+
PI_ACP_PACKAGE.version,
|
|
24492
|
+
"node_modules",
|
|
24493
|
+
"pi-acp",
|
|
24494
|
+
"dist",
|
|
24495
|
+
"index.js"
|
|
24496
|
+
];
|
|
24497
|
+
managedAgentExecutablePath = [
|
|
24498
|
+
"agents",
|
|
24499
|
+
"pi",
|
|
24500
|
+
PI_AGENT_PACKAGE.version,
|
|
24501
|
+
"node_modules",
|
|
24502
|
+
"@earendil-works",
|
|
24503
|
+
"pi-coding-agent",
|
|
24504
|
+
"dist",
|
|
24505
|
+
"bundle",
|
|
24506
|
+
"cli.js"
|
|
24507
|
+
];
|
|
24508
|
+
promptTimeoutMilliseconds = PI_PROMPT_TIMEOUT_MILLISECONDS;
|
|
24509
|
+
resolveManagedAgent = async (stateDirectory, _platform) => await validateManagedNpmPackage(
|
|
24510
|
+
join7(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
|
|
24511
|
+
PI_AGENT_PACKAGE
|
|
24512
|
+
);
|
|
24513
|
+
verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
|
|
24514
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
24515
|
+
if (capabilities.loadSession !== true) {
|
|
24516
|
+
throw new AgentProbeError(
|
|
24517
|
+
"acp_incompatible",
|
|
24518
|
+
"Pi ACP adapter does not support session recovery"
|
|
24519
|
+
);
|
|
24520
|
+
}
|
|
24521
|
+
const session = await connection.agent.request(
|
|
24522
|
+
methods3.agent.session.new,
|
|
24523
|
+
{
|
|
24524
|
+
additionalDirectories: [],
|
|
24525
|
+
cwd: defaultWorkspace,
|
|
24526
|
+
mcpServers: []
|
|
24527
|
+
},
|
|
24528
|
+
{ cancellationSignal: signal }
|
|
24529
|
+
);
|
|
24530
|
+
if (session.sessionId.length === 0) {
|
|
24531
|
+
throw new AgentProbeError(
|
|
24532
|
+
"acp_incompatible",
|
|
24533
|
+
"Pi ACP adapter returned an invalid session"
|
|
24534
|
+
);
|
|
24535
|
+
}
|
|
24536
|
+
const prompt = await connection.agent.request(
|
|
24537
|
+
methods3.agent.session.prompt,
|
|
24538
|
+
{
|
|
24539
|
+
prompt: [{ text: "/session", type: "text" }],
|
|
24540
|
+
sessionId: session.sessionId
|
|
24541
|
+
},
|
|
24542
|
+
{ cancellationSignal: signal }
|
|
24543
|
+
);
|
|
24544
|
+
if (prompt.stopReason !== "end_turn") {
|
|
24545
|
+
throw new AgentProbeError(
|
|
24546
|
+
"acp_incompatible",
|
|
24547
|
+
"Pi ACP adapter did not complete its conformance prompt"
|
|
24548
|
+
);
|
|
24549
|
+
}
|
|
24550
|
+
};
|
|
24551
|
+
};
|
|
24235
24552
|
function supportedLocalAgentSpecifications() {
|
|
24236
24553
|
return Object.freeze([
|
|
24237
24554
|
new CodexAgentSpecification(),
|
|
24238
|
-
new ClaudeCodeAgentSpecification()
|
|
24555
|
+
new ClaudeCodeAgentSpecification(),
|
|
24556
|
+
new PiAgentSpecification()
|
|
24239
24557
|
]);
|
|
24240
24558
|
}
|
|
24241
24559
|
var AgentDiscovery = class {
|
|
@@ -24288,6 +24606,14 @@ var IncompatibleAdapter = class extends UnavailableAgent {
|
|
|
24288
24606
|
super(specification);
|
|
24289
24607
|
}
|
|
24290
24608
|
};
|
|
24609
|
+
var AuthenticationRequiredAgent = class extends UnavailableAgent {
|
|
24610
|
+
code = "authentication_required";
|
|
24611
|
+
message = "Agent authentication is required";
|
|
24612
|
+
status = "authentication_required";
|
|
24613
|
+
constructor(specification) {
|
|
24614
|
+
super(specification);
|
|
24615
|
+
}
|
|
24616
|
+
};
|
|
24291
24617
|
var LocalAgentInventory = class {
|
|
24292
24618
|
available;
|
|
24293
24619
|
discoveries;
|
|
@@ -24309,7 +24635,10 @@ var LocalAgentInventory = class {
|
|
|
24309
24635
|
this.discoveries = Object.freeze([...discoveries]);
|
|
24310
24636
|
this.installable = Object.freeze(
|
|
24311
24637
|
unavailable.filter(
|
|
24312
|
-
(discovery) => discovery.specification.supportsInstallation(
|
|
24638
|
+
(discovery) => !(discovery instanceof AuthenticationRequiredAgent) && discovery.specification.supportsInstallation(
|
|
24639
|
+
platform,
|
|
24640
|
+
architecture
|
|
24641
|
+
)
|
|
24313
24642
|
).map(
|
|
24314
24643
|
(discovery) => new InstallableAgentDefinition(
|
|
24315
24644
|
discovery.specification.id,
|
|
@@ -24336,17 +24665,21 @@ var DiscoveryAcpHandler = class {
|
|
|
24336
24665
|
onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
|
|
24337
24666
|
onUpdate = (_notification) => Promise.resolve();
|
|
24338
24667
|
};
|
|
24339
|
-
async function resolveManagedExecutable(
|
|
24340
|
-
|
|
24341
|
-
|
|
24342
|
-
|
|
24343
|
-
|
|
24668
|
+
async function resolveManagedExecutable(specification, options) {
|
|
24669
|
+
try {
|
|
24670
|
+
return await specification.resolveManagedAgent(
|
|
24671
|
+
readStateDirectory(options.environment),
|
|
24672
|
+
options.platform ?? process.platform
|
|
24673
|
+
);
|
|
24674
|
+
} catch {
|
|
24675
|
+
return null;
|
|
24676
|
+
}
|
|
24344
24677
|
}
|
|
24345
24678
|
async function resolveManagedAdapterExecutable(specification, options) {
|
|
24346
24679
|
let managed;
|
|
24347
24680
|
try {
|
|
24348
24681
|
managed = await validateManagedAdapter(
|
|
24349
|
-
|
|
24682
|
+
join7(
|
|
24350
24683
|
readStateDirectory(options.environment),
|
|
24351
24684
|
"adapters",
|
|
24352
24685
|
specification.id,
|
|
@@ -24362,7 +24695,7 @@ async function resolveManagedAdapterExecutable(specification, options) {
|
|
|
24362
24695
|
async function resolveSpecificationExecutables(executableName, overrideVariable, resolveManaged, options) {
|
|
24363
24696
|
const override = options.environment[overrideVariable];
|
|
24364
24697
|
if (override !== void 0) {
|
|
24365
|
-
if (override.length === 0 || !
|
|
24698
|
+
if (override.length === 0 || !isAbsolute2(override)) {
|
|
24366
24699
|
return [];
|
|
24367
24700
|
}
|
|
24368
24701
|
const executable = await resolveExecutablePath(override, options.platform);
|
|
@@ -24386,10 +24719,7 @@ async function resolveAgentExecutables(specification, options) {
|
|
|
24386
24719
|
return await resolveSpecificationExecutables(
|
|
24387
24720
|
specification.agentExecutable,
|
|
24388
24721
|
specification.agentOverrideVariable,
|
|
24389
|
-
async () => await resolveManagedExecutable(
|
|
24390
|
-
specification.managedAgentExecutablePath,
|
|
24391
|
-
options
|
|
24392
|
-
),
|
|
24722
|
+
async () => await resolveManagedExecutable(specification, options),
|
|
24393
24723
|
options
|
|
24394
24724
|
);
|
|
24395
24725
|
}
|
|
@@ -24412,9 +24742,9 @@ async function resolveAdapterExecutable(specification, options) {
|
|
|
24412
24742
|
function normalizedVersion(output2) {
|
|
24413
24743
|
return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
|
|
24414
24744
|
}
|
|
24415
|
-
async function probeVersion(executable, environment, defaultWorkspace, signal) {
|
|
24745
|
+
async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal) {
|
|
24416
24746
|
const result = await runBoundedProcess({
|
|
24417
|
-
arguments:
|
|
24747
|
+
arguments: arguments_,
|
|
24418
24748
|
command: executable.path,
|
|
24419
24749
|
cwd: defaultWorkspace,
|
|
24420
24750
|
environment,
|
|
@@ -24444,6 +24774,7 @@ async function findVerifiedAgentExecutable(specification, options) {
|
|
|
24444
24774
|
try {
|
|
24445
24775
|
const version2 = await probeVersion(
|
|
24446
24776
|
executable,
|
|
24777
|
+
specification.agentVersionArguments,
|
|
24447
24778
|
options.environment,
|
|
24448
24779
|
options.defaultWorkspace,
|
|
24449
24780
|
options.signal
|
|
@@ -24512,14 +24843,14 @@ function writableAcpStream(output2) {
|
|
|
24512
24843
|
}
|
|
24513
24844
|
});
|
|
24514
24845
|
}
|
|
24515
|
-
async function probeAcp(agent, environment, defaultWorkspace, signal) {
|
|
24846
|
+
async function probeAcp(specification, agent, environment, defaultWorkspace, signal) {
|
|
24516
24847
|
signal.throwIfAborted();
|
|
24517
24848
|
const controller = new AbortController();
|
|
24518
24849
|
let timedOut = false;
|
|
24519
24850
|
const timeout = setTimeout(() => {
|
|
24520
24851
|
timedOut = true;
|
|
24521
24852
|
controller.abort(new Error("ACP probe timed out"));
|
|
24522
|
-
},
|
|
24853
|
+
}, specification.acpProbeTimeoutMilliseconds);
|
|
24523
24854
|
const abort = () => controller.abort(signal.reason);
|
|
24524
24855
|
signal.addEventListener("abort", abort, { once: true });
|
|
24525
24856
|
if (signal.aborted) {
|
|
@@ -24578,6 +24909,13 @@ async function probeAcp(agent, environment, defaultWorkspace, signal) {
|
|
|
24578
24909
|
"ACP adapter selected an unsupported protocol version"
|
|
24579
24910
|
);
|
|
24580
24911
|
}
|
|
24912
|
+
await specification.verifyAcp(
|
|
24913
|
+
connection,
|
|
24914
|
+
initialized,
|
|
24915
|
+
defaultWorkspace,
|
|
24916
|
+
controller.signal
|
|
24917
|
+
);
|
|
24918
|
+
return normalizedVersion(initialized.agentInfo?.version ?? "");
|
|
24581
24919
|
} catch (error61) {
|
|
24582
24920
|
if (signal.aborted) {
|
|
24583
24921
|
signal.throwIfAborted();
|
|
@@ -24592,6 +24930,13 @@ async function probeAcp(agent, environment, defaultWorkspace, signal) {
|
|
|
24592
24930
|
if (error61 instanceof AgentProbeError) {
|
|
24593
24931
|
throw error61;
|
|
24594
24932
|
}
|
|
24933
|
+
if (error61 instanceof RequestError && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
|
|
24934
|
+
throw new AgentProbeError(
|
|
24935
|
+
"authentication_required",
|
|
24936
|
+
"Agent authentication is required",
|
|
24937
|
+
{ cause: error61 }
|
|
24938
|
+
);
|
|
24939
|
+
}
|
|
24595
24940
|
throw new AgentProbeError(
|
|
24596
24941
|
"acp_incompatible",
|
|
24597
24942
|
"ACP adapter initialization failed",
|
|
@@ -24608,6 +24953,9 @@ async function probeAcp(agent, environment, defaultWorkspace, signal) {
|
|
|
24608
24953
|
}
|
|
24609
24954
|
function probeFailure(specification, executableKind, error61) {
|
|
24610
24955
|
if (error61 instanceof AgentProbeError) {
|
|
24956
|
+
if (error61.code === "authentication_required") {
|
|
24957
|
+
return new AuthenticationRequiredAgent(specification);
|
|
24958
|
+
}
|
|
24611
24959
|
return error61.code === "acp_incompatible" ? new IncompatibleAdapter(specification) : new ProbeFailed(specification, error61.code, error61.message);
|
|
24612
24960
|
}
|
|
24613
24961
|
if (error61 instanceof ProcessExecutionError) {
|
|
@@ -24642,6 +24990,7 @@ async function discoverSpecification(specification, options) {
|
|
|
24642
24990
|
try {
|
|
24643
24991
|
agentVersion = await probeVersion(
|
|
24644
24992
|
agent,
|
|
24993
|
+
specification.agentVersionArguments,
|
|
24645
24994
|
options.environment,
|
|
24646
24995
|
options.defaultWorkspace,
|
|
24647
24996
|
options.signal
|
|
@@ -24656,15 +25005,18 @@ async function discoverSpecification(specification, options) {
|
|
|
24656
25005
|
for (const adapter of adapters) {
|
|
24657
25006
|
let adapterVersion = "";
|
|
24658
25007
|
try {
|
|
24659
|
-
|
|
24660
|
-
|
|
24661
|
-
|
|
24662
|
-
|
|
24663
|
-
|
|
24664
|
-
|
|
24665
|
-
|
|
24666
|
-
|
|
24667
|
-
|
|
25008
|
+
if (specification.adapterVersionArguments.length > 0) {
|
|
25009
|
+
adapterVersion = await probeVersion(
|
|
25010
|
+
adapter,
|
|
25011
|
+
specification.adapterVersionArguments,
|
|
25012
|
+
{
|
|
25013
|
+
...options.environment,
|
|
25014
|
+
[specification.adapterEnvironmentVariable]: agent.path
|
|
25015
|
+
},
|
|
25016
|
+
options.defaultWorkspace,
|
|
25017
|
+
options.signal
|
|
25018
|
+
);
|
|
25019
|
+
}
|
|
24668
25020
|
} catch (error61) {
|
|
24669
25021
|
if (options.signal.aborted) {
|
|
24670
25022
|
options.signal.throwIfAborted();
|
|
@@ -24681,16 +25033,39 @@ async function discoverSpecification(specification, options) {
|
|
|
24681
25033
|
adapterVersion,
|
|
24682
25034
|
agentVersion,
|
|
24683
25035
|
adapter.identity,
|
|
24684
|
-
agent.identity
|
|
25036
|
+
agent.identity,
|
|
25037
|
+
specification.promptTimeoutMilliseconds
|
|
24685
25038
|
);
|
|
24686
25039
|
try {
|
|
24687
|
-
await probeAcp(
|
|
25040
|
+
const acpVersion = await probeAcp(
|
|
25041
|
+
specification,
|
|
24688
25042
|
definition,
|
|
24689
25043
|
options.environment,
|
|
24690
25044
|
options.defaultWorkspace,
|
|
24691
25045
|
options.signal
|
|
24692
25046
|
);
|
|
24693
|
-
|
|
25047
|
+
const verifiedAdapterVersion = adapterVersion.length > 0 ? adapterVersion : acpVersion;
|
|
25048
|
+
if (verifiedAdapterVersion.length === 0) {
|
|
25049
|
+
throw new AgentProbeError(
|
|
25050
|
+
"acp_incompatible",
|
|
25051
|
+
"ACP adapter did not report a version"
|
|
25052
|
+
);
|
|
25053
|
+
}
|
|
25054
|
+
return new AvailableAgent(
|
|
25055
|
+
specification,
|
|
25056
|
+
new LocalAgentDefinition(
|
|
25057
|
+
specification.id,
|
|
25058
|
+
specification.label,
|
|
25059
|
+
adapter.path,
|
|
25060
|
+
[],
|
|
25061
|
+
{ [specification.adapterEnvironmentVariable]: agent.path },
|
|
25062
|
+
verifiedAdapterVersion,
|
|
25063
|
+
agentVersion,
|
|
25064
|
+
adapter.identity,
|
|
25065
|
+
agent.identity,
|
|
25066
|
+
specification.promptTimeoutMilliseconds
|
|
25067
|
+
)
|
|
25068
|
+
);
|
|
24694
25069
|
} catch (error61) {
|
|
24695
25070
|
if (options.signal.aborted) {
|
|
24696
25071
|
options.signal.throwIfAborted();
|
|
@@ -24980,10 +25355,10 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
24980
25355
|
return decodeClaimResponse(value);
|
|
24981
25356
|
}
|
|
24982
25357
|
async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
|
|
24983
|
-
const connectionsDirectory =
|
|
25358
|
+
const connectionsDirectory = join8(readStateDirectory(), "connections");
|
|
24984
25359
|
await mkdir2(connectionsDirectory, { mode: 448, recursive: true });
|
|
24985
|
-
const connectionPath =
|
|
24986
|
-
const temporaryPath =
|
|
25360
|
+
const connectionPath = join8(connectionsDirectory, `${channelId}.json`);
|
|
25361
|
+
const temporaryPath = join8(
|
|
24987
25362
|
connectionsDirectory,
|
|
24988
25363
|
`.${channelId}.${randomUUID()}.tmp`
|
|
24989
25364
|
);
|
|
@@ -25030,7 +25405,7 @@ function decodeSavedConnection(value, expectedChannelId) {
|
|
|
25030
25405
|
};
|
|
25031
25406
|
}
|
|
25032
25407
|
async function readSavedConnection(channelId) {
|
|
25033
|
-
const connectionPath =
|
|
25408
|
+
const connectionPath = join8(
|
|
25034
25409
|
readStateDirectory(),
|
|
25035
25410
|
"connections",
|
|
25036
25411
|
`${channelId}.json`
|
|
@@ -25085,7 +25460,7 @@ function buildPairedDaemon(connection, connectionPath, inventory) {
|
|
|
25085
25460
|
);
|
|
25086
25461
|
relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
25087
25462
|
relayUrl.searchParams.set("token", connection.daemonToken);
|
|
25088
|
-
const auditDatabasePath =
|
|
25463
|
+
const auditDatabasePath = join8(
|
|
25089
25464
|
readStateDirectory(),
|
|
25090
25465
|
"audit",
|
|
25091
25466
|
`${connection.channelId}.sqlite`
|
|
@@ -25144,7 +25519,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
|
|
|
25144
25519
|
}
|
|
25145
25520
|
async function resumeLocalMachine(arguments_, signal = new AbortController().signal) {
|
|
25146
25521
|
const channelId = parseChannelArgument(arguments_);
|
|
25147
|
-
const connectionPath =
|
|
25522
|
+
const connectionPath = join8(
|
|
25148
25523
|
readStateDirectory(),
|
|
25149
25524
|
"connections",
|
|
25150
25525
|
`${channelId}.json`
|
|
@@ -25767,7 +26142,7 @@ import { resolve as resolve4 } from "node:path";
|
|
|
25767
26142
|
|
|
25768
26143
|
// src/agent-installation/fixed-agent-install-recipes.ts
|
|
25769
26144
|
import { mkdir as mkdir3, mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
|
|
25770
|
-
import { join as
|
|
26145
|
+
import { join as join9 } from "node:path";
|
|
25771
26146
|
|
|
25772
26147
|
// src/agent-installation/verified-download.ts
|
|
25773
26148
|
import { createHash } from "node:crypto";
|
|
@@ -25991,18 +26366,18 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
|
25991
26366
|
releaseChannel = "latest";
|
|
25992
26367
|
install = async (options) => {
|
|
25993
26368
|
this.assertSupportedPlatform();
|
|
25994
|
-
const root =
|
|
25995
|
-
const temporaryRoot =
|
|
26369
|
+
const root = join9(options.stateDirectory, "agents", this.id);
|
|
26370
|
+
const temporaryRoot = join9(options.stateDirectory, "temporary");
|
|
25996
26371
|
await Promise.all([
|
|
25997
26372
|
mkdir3(root, { mode: 448, recursive: true }),
|
|
25998
26373
|
mkdir3(temporaryRoot, { mode: 448, recursive: true })
|
|
25999
26374
|
]);
|
|
26000
26375
|
const temporaryDirectory = await mkdtemp2(
|
|
26001
|
-
|
|
26376
|
+
join9(temporaryRoot, ".codex-install-")
|
|
26002
26377
|
);
|
|
26003
|
-
const installerPath =
|
|
26004
|
-
const installDirectory =
|
|
26005
|
-
const codexHome =
|
|
26378
|
+
const installerPath = join9(temporaryDirectory, "install.sh");
|
|
26379
|
+
const installDirectory = join9(root, "bin");
|
|
26380
|
+
const codexHome = join9(root, "home");
|
|
26006
26381
|
try {
|
|
26007
26382
|
await Promise.all([
|
|
26008
26383
|
mkdir3(installDirectory, { mode: 448, recursive: true }),
|
|
@@ -26046,7 +26421,7 @@ var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
|
26046
26421
|
timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
|
|
26047
26422
|
});
|
|
26048
26423
|
return await this.requireInstalledExecutable(
|
|
26049
|
-
|
|
26424
|
+
join9(installDirectory, "codex")
|
|
26050
26425
|
);
|
|
26051
26426
|
} catch (error61) {
|
|
26052
26427
|
if (options.signal.aborted) {
|
|
@@ -26070,17 +26445,17 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
|
26070
26445
|
releaseChannel = "stable";
|
|
26071
26446
|
install = async (options) => {
|
|
26072
26447
|
this.assertSupportedPlatform();
|
|
26073
|
-
const root =
|
|
26074
|
-
const managedHome =
|
|
26075
|
-
const temporaryRoot =
|
|
26448
|
+
const root = join9(options.stateDirectory, "agents", this.id);
|
|
26449
|
+
const managedHome = join9(root, "home");
|
|
26450
|
+
const temporaryRoot = join9(options.stateDirectory, "temporary");
|
|
26076
26451
|
await Promise.all([
|
|
26077
26452
|
mkdir3(managedHome, { mode: 448, recursive: true }),
|
|
26078
26453
|
mkdir3(temporaryRoot, { mode: 448, recursive: true })
|
|
26079
26454
|
]);
|
|
26080
26455
|
const temporaryDirectory = await mkdtemp2(
|
|
26081
|
-
|
|
26456
|
+
join9(temporaryRoot, ".claude-install-")
|
|
26082
26457
|
);
|
|
26083
|
-
const installerPath =
|
|
26458
|
+
const installerPath = join9(temporaryDirectory, "install.sh");
|
|
26084
26459
|
try {
|
|
26085
26460
|
await options.report("downloading");
|
|
26086
26461
|
const download = await downloadVerifiedFile({
|
|
@@ -26117,7 +26492,7 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
|
26117
26492
|
timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
|
|
26118
26493
|
});
|
|
26119
26494
|
return await this.requireInstalledExecutable(
|
|
26120
|
-
|
|
26495
|
+
join9(managedHome, ".local", "bin", "claude")
|
|
26121
26496
|
);
|
|
26122
26497
|
} catch (error61) {
|
|
26123
26498
|
if (options.signal.aborted) {
|
|
@@ -26135,10 +26510,82 @@ var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
|
26135
26510
|
}
|
|
26136
26511
|
};
|
|
26137
26512
|
};
|
|
26513
|
+
var PiInstallRecipe = class extends FixedAgentInstallRecipe {
|
|
26514
|
+
#npmInstaller;
|
|
26515
|
+
id = "pi";
|
|
26516
|
+
label = "Pi";
|
|
26517
|
+
releaseChannel = PI_AGENT_PACKAGE.version;
|
|
26518
|
+
constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
|
|
26519
|
+
super();
|
|
26520
|
+
this.#npmInstaller = npmInstaller;
|
|
26521
|
+
}
|
|
26522
|
+
install = async (options) => {
|
|
26523
|
+
this.assertSupportedPlatform();
|
|
26524
|
+
try {
|
|
26525
|
+
await options.report("downloading");
|
|
26526
|
+
await options.report("verifying");
|
|
26527
|
+
await options.report("installing_agent");
|
|
26528
|
+
const executable = await this.#npmInstaller.install(
|
|
26529
|
+
join9(
|
|
26530
|
+
options.stateDirectory,
|
|
26531
|
+
"agents",
|
|
26532
|
+
this.id,
|
|
26533
|
+
PI_AGENT_PACKAGE.version
|
|
26534
|
+
),
|
|
26535
|
+
PI_AGENT_PACKAGE,
|
|
26536
|
+
options.environment,
|
|
26537
|
+
options.signal
|
|
26538
|
+
);
|
|
26539
|
+
options.audit.record(
|
|
26540
|
+
"agent_npm_package_verified",
|
|
26541
|
+
options.requestId,
|
|
26542
|
+
this.id,
|
|
26543
|
+
{
|
|
26544
|
+
integrity: PI_AGENT_PACKAGE.integrity,
|
|
26545
|
+
package: PI_AGENT_PACKAGE.packageName,
|
|
26546
|
+
version: PI_AGENT_PACKAGE.version
|
|
26547
|
+
}
|
|
26548
|
+
);
|
|
26549
|
+
return executable;
|
|
26550
|
+
} catch (error61) {
|
|
26551
|
+
if (options.signal.aborted) {
|
|
26552
|
+
options.signal.throwIfAborted();
|
|
26553
|
+
}
|
|
26554
|
+
if (error61 instanceof ManagedNpmPackageError) {
|
|
26555
|
+
if (error61.code === "managed_package_verification_failed") {
|
|
26556
|
+
throw new InstallationManagerError(
|
|
26557
|
+
"agent_verification_failed",
|
|
26558
|
+
"The managed Pi package did not match its pinned artifact",
|
|
26559
|
+
{ cause: error61 }
|
|
26560
|
+
);
|
|
26561
|
+
}
|
|
26562
|
+
if (error61.code === "managed_package_publish_failed") {
|
|
26563
|
+
throw new InstallationManagerError(
|
|
26564
|
+
"agent_publish_failed",
|
|
26565
|
+
"The managed Pi package could not be published",
|
|
26566
|
+
{ cause: error61 }
|
|
26567
|
+
);
|
|
26568
|
+
}
|
|
26569
|
+
throw new InstallationManagerError(error61.code, error61.message, {
|
|
26570
|
+
cause: error61
|
|
26571
|
+
});
|
|
26572
|
+
}
|
|
26573
|
+
if (error61 instanceof InstallationManagerError) {
|
|
26574
|
+
throw error61;
|
|
26575
|
+
}
|
|
26576
|
+
throw new InstallationManagerError(
|
|
26577
|
+
"agent_install_failed",
|
|
26578
|
+
"The fixed Pi installation recipe failed",
|
|
26579
|
+
{ cause: error61 }
|
|
26580
|
+
);
|
|
26581
|
+
}
|
|
26582
|
+
};
|
|
26583
|
+
};
|
|
26138
26584
|
function fixedAgentInstallRecipes() {
|
|
26139
26585
|
return Object.freeze([
|
|
26140
26586
|
new CodexInstallRecipe(),
|
|
26141
|
-
new ClaudeCodeInstallRecipe()
|
|
26587
|
+
new ClaudeCodeInstallRecipe(),
|
|
26588
|
+
new PiInstallRecipe()
|
|
26142
26589
|
]);
|
|
26143
26590
|
}
|
|
26144
26591
|
|
|
@@ -26268,6 +26715,7 @@ var FixedInstallationExecutor = class {
|
|
|
26268
26715
|
if (agent === null) {
|
|
26269
26716
|
agent = await recipe.install({
|
|
26270
26717
|
audit: this.#audit,
|
|
26718
|
+
environment: this.#environment,
|
|
26271
26719
|
report,
|
|
26272
26720
|
requestId,
|
|
26273
26721
|
signal,
|
|
@@ -26349,6 +26797,7 @@ var FixedInstallationExecutor = class {
|
|
|
26349
26797
|
if (!installedAgent && (requiresAgentReplacement(unavailable.code) || unavailable.code === "acp_incompatible")) {
|
|
26350
26798
|
agent = await recipe.install({
|
|
26351
26799
|
audit: this.#audit,
|
|
26800
|
+
environment: this.#environment,
|
|
26352
26801
|
report,
|
|
26353
26802
|
requestId,
|
|
26354
26803
|
signal,
|
|
@@ -26412,8 +26861,8 @@ import { homedir as homedir2 } from "node:os";
|
|
|
26412
26861
|
import {
|
|
26413
26862
|
basename as basename2,
|
|
26414
26863
|
dirname as dirname4,
|
|
26415
|
-
isAbsolute as
|
|
26416
|
-
join as
|
|
26864
|
+
isAbsolute as isAbsolute3,
|
|
26865
|
+
join as join10,
|
|
26417
26866
|
normalize,
|
|
26418
26867
|
relative as relative2
|
|
26419
26868
|
} from "node:path";
|
|
@@ -26465,20 +26914,20 @@ var WorkspaceDirectoryService = class {
|
|
|
26465
26914
|
if (id === "home") return homedir2();
|
|
26466
26915
|
if (id.startsWith("path-")) {
|
|
26467
26916
|
const path2 = decodePath(id, "path-");
|
|
26468
|
-
if (
|
|
26917
|
+
if (isAbsolute3(path2)) return path2;
|
|
26469
26918
|
}
|
|
26470
26919
|
throw new LocalAuthorizationError("The directory identifier is invalid");
|
|
26471
26920
|
};
|
|
26472
26921
|
resolvePath = async (requested, signal) => {
|
|
26473
26922
|
signal.throwIfAborted();
|
|
26474
|
-
if (!
|
|
26923
|
+
if (!isAbsolute3(requested) || requested.includes("\0") || normalize(requested) !== requested)
|
|
26475
26924
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
26476
26925
|
try {
|
|
26477
26926
|
const target = await realpath4(requested);
|
|
26478
26927
|
signal.throwIfAborted();
|
|
26479
26928
|
const metadata = await stat4(target);
|
|
26480
26929
|
signal.throwIfAborted();
|
|
26481
|
-
if (!
|
|
26930
|
+
if (!isAbsolute3(target) || normalize(target) !== target || !metadata.isDirectory())
|
|
26482
26931
|
throw new LocalAuthorizationError(
|
|
26483
26932
|
"The selected location is not a directory"
|
|
26484
26933
|
);
|
|
@@ -26494,7 +26943,7 @@ var WorkspaceDirectoryService = class {
|
|
|
26494
26943
|
};
|
|
26495
26944
|
label = (path2) => {
|
|
26496
26945
|
const suffix = relative2(homedir2(), path2);
|
|
26497
|
-
return suffix === "" ? "~" : !
|
|
26946
|
+
return suffix === "" ? "~" : !isAbsolute3(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
|
|
26498
26947
|
};
|
|
26499
26948
|
identify = async (bindingId, requestedPath, signal) => {
|
|
26500
26949
|
this.authorizeMachine(bindingId);
|
|
@@ -26522,7 +26971,7 @@ var WorkspaceDirectoryService = class {
|
|
|
26522
26971
|
continue;
|
|
26523
26972
|
}
|
|
26524
26973
|
try {
|
|
26525
|
-
const path2 = await this.resolvePath(
|
|
26974
|
+
const path2 = await this.resolvePath(join10(target, child.name), signal);
|
|
26526
26975
|
entries.push({ directoryId: encodePath(path2), name: child.name });
|
|
26527
26976
|
} catch (cause) {
|
|
26528
26977
|
signal.throwIfAborted();
|