@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.
Files changed (38) hide show
  1. package/dist/acp/session-manager.d.ts.map +1 -1
  2. package/dist/acp/session-manager.js +11 -2
  3. package/dist/acp/session-manager.js.map +1 -1
  4. package/dist/agent-catalog/agent-diagnostics.d.ts.map +1 -1
  5. package/dist/agent-catalog/agent-diagnostics.js +6 -2
  6. package/dist/agent-catalog/agent-diagnostics.js.map +1 -1
  7. package/dist/agent-catalog/discover-local-agents.d.ts +35 -7
  8. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  9. package/dist/agent-catalog/discover-local-agents.js +137 -26
  10. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  11. package/dist/agent-catalog/local-agent.d.ts +2 -1
  12. package/dist/agent-catalog/local-agent.d.ts.map +1 -1
  13. package/dist/agent-catalog/local-agent.js +7 -1
  14. package/dist/agent-catalog/local-agent.js.map +1 -1
  15. package/dist/agent-installation/fixed-agent-install-recipes.d.ts +1 -0
  16. package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -1
  17. package/dist/agent-installation/fixed-agent-install-recipes.js +48 -0
  18. package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -1
  19. package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
  20. package/dist/agent-installation/fixed-installation-executor.js +2 -0
  21. package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
  22. package/dist/agent-installation/managed-adapter-installer.d.ts +3 -2
  23. package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -1
  24. package/dist/agent-installation/managed-adapter-installer.js +25 -126
  25. package/dist/agent-installation/managed-adapter-installer.js.map +1 -1
  26. package/dist/agent-installation/managed-npm-package.d.ts +24 -0
  27. package/dist/agent-installation/managed-npm-package.d.ts.map +1 -0
  28. package/dist/agent-installation/managed-npm-package.js +227 -0
  29. package/dist/agent-installation/managed-npm-package.js.map +1 -0
  30. package/dist/agent-installation/pi-managed-packages.d.ts +4 -0
  31. package/dist/agent-installation/pi-managed-packages.d.ts.map +1 -0
  32. package/dist/agent-installation/pi-managed-packages.js +4 -0
  33. package/dist/agent-installation/pi-managed-packages.js.map +1 -0
  34. package/dist/cli.js +610 -159
  35. package/dist/cli.js.map +4 -4
  36. package/dist/index.js +601 -152
  37. package/dist/index.js.map +4 -4
  38. 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
- constructor(id, label, command, arguments_, environment = {}, adapterVersion = "", agentVersion = "", adapterIdentity = readTrustedIdentity(command), agentIdentity = adapterIdentity) {
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(options);
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(options);
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 join7, resolve as resolve3 } from "node:path";
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 join6 } from "node:path";
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 ADAPTER_INSTALL_TIMEOUT_MILLISECONDS = 2 * 60 * 1e3;
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 ManagedAdapterInstallError = class extends Error {
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 = "ManagedAdapterInstallError";
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
- async function readPackageJson(path2) {
24004
- const handle = await open3(path2, "r");
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 metadata = await handle.stat();
24007
- if (!metadata.isFile() || metadata.size > PACKAGE_METADATA_LIMIT_BYTES) {
24008
- throw new ManagedAdapterInstallError(
24009
- "adapter_verification_failed",
24010
- "The managed adapter package metadata is invalid"
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
- const value = JSON.parse(
24014
- await handle.readFile({ encoding: "utf8" })
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
- return value;
24023
- } finally {
24024
- await handle.close();
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 ManagedAdapterInstallError(
24036
- "adapter_verification_failed",
24037
- "The managed adapter executable declaration is invalid"
24095
+ throw new ManagedNpmPackageError(
24096
+ "managed_package_verification_failed",
24097
+ "The managed npm package executable declaration is invalid"
24038
24098
  );
24039
24099
  }
24040
- async function validateManagedAdapter(root, specification) {
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, specification.adapterPackage)
24148
+ packagePath(rootPath, definition.packageName)
24044
24149
  );
24045
- const packageDifference = relative(rootPath, packageRoot);
24046
- if (packageDifference.startsWith("..") || packageDifference.length === 0) {
24047
- throw new ManagedAdapterInstallError(
24048
- "adapter_verification_failed",
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 readPackageJson(join5(packageRoot, "package.json"));
24053
- if (metadata["name"] !== specification.adapterPackage || metadata["version"] !== specification.adapterVersion) {
24054
- throw new ManagedAdapterInstallError(
24055
- "adapter_verification_failed",
24056
- "The managed adapter package identity is invalid"
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
- const declaredBin = readBinPath(metadata, specification.adapterExecutable);
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 ManagedAdapterInstallError(
24065
- "adapter_verification_failed",
24066
- "The managed adapter executable is invalid"
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 ManagedAdapterInstaller = class {
24079
- #environment;
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(published);
24191
+ const metadata = await stat2(root);
24091
24192
  if (metadata.isDirectory()) {
24092
- return await validateManagedAdapter(published, specification);
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
- await mkdir(agentCache, { mode: 448, recursive: true });
24200
+ const parent = dirname3(root);
24201
+ await mkdir(parent, { mode: 448, recursive: true });
24100
24202
  const staging = await mkdtemp(
24101
- join5(agentCache, `.${specification.adapterVersion}.staging-`)
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
- this.#environment
24208
+ environment
24107
24209
  );
24108
24210
  if (npm === null) {
24109
- throw new ManagedAdapterInstallError(
24211
+ throw new ManagedNpmPackageError(
24110
24212
  "package_manager_not_found",
24111
- "A supported npm executable is required to install the ACP adapter"
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=false",
24124
- "--save=false",
24225
+ "--package-lock=true",
24226
+ "--save-exact",
24125
24227
  "--registry=https://registry.npmjs.org/",
24126
- `${specification.adapterPackage}@${specification.adapterVersion}`
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: ADAPTER_INSTALL_TIMEOUT_MILLISECONDS
24245
+ timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS
24142
24246
  });
24143
- await validateManagedAdapter(staging, specification);
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, published);
24253
+ await rename(staging, root);
24146
24254
  } catch (error61) {
24147
24255
  try {
24148
- return await validateManagedAdapter(published, specification);
24256
+ return await validateManagedNpmPackage(root, definition);
24149
24257
  } catch {
24150
- throw new ManagedAdapterInstallError(
24151
- "adapter_publish_failed",
24152
- "The managed adapter could not be published",
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 validateManagedAdapter(published, specification);
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 ManagedAdapterInstallError) {
24270
+ if (error61 instanceof ManagedNpmPackageError) {
24163
24271
  throw error61;
24164
24272
  }
24165
- throw new ManagedAdapterInstallError(
24166
- "adapter_install_failed",
24167
- "The pinned ACP adapter could not be installed",
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 LocalAgentSpecification {
24422
+ var CodexAgentSpecification = class extends BridgedAcpAgentDefinition {
24185
24423
  adapterEnvironmentVariable = "CODEX_PATH";
24186
- adapterExecutable = "codex-acp";
24187
24424
  adapterOverrideVariable = "MOBIUS_CODEX_ACP_PATH";
24188
- adapterPackage = "@agentclientprotocol/codex-acp";
24189
- adapterVersion = "1.8.0";
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 LocalAgentSpecification {
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
- adapterPackage = "@agentclientprotocol/claude-agent-acp";
24211
- adapterVersion = "0.73.0";
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(platform, architecture)
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(managedExecutablePath, options) {
24340
- return await resolveExecutablePath(
24341
- join6(readStateDirectory(options.environment), ...managedExecutablePath),
24342
- options.platform
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
- join6(
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 || !isAbsolute(override)) {
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: ["--version"],
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
- }, ACP_PROBE_TIMEOUT_MILLISECONDS);
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
- adapterVersion = await probeVersion(
24660
- adapter,
24661
- {
24662
- ...options.environment,
24663
- [specification.adapterEnvironmentVariable]: agent.path
24664
- },
24665
- options.defaultWorkspace,
24666
- options.signal
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
- return new AvailableAgent(specification, definition);
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 = join7(readStateDirectory(), "connections");
25358
+ const connectionsDirectory = join8(readStateDirectory(), "connections");
24984
25359
  await mkdir2(connectionsDirectory, { mode: 448, recursive: true });
24985
- const connectionPath = join7(connectionsDirectory, `${channelId}.json`);
24986
- const temporaryPath = join7(
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 = join7(
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 = join7(
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 = join7(
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 join8 } from "node:path";
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 = join8(options.stateDirectory, "agents", this.id);
25995
- const temporaryRoot = join8(options.stateDirectory, "temporary");
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
- join8(temporaryRoot, ".codex-install-")
26376
+ join9(temporaryRoot, ".codex-install-")
26002
26377
  );
26003
- const installerPath = join8(temporaryDirectory, "install.sh");
26004
- const installDirectory = join8(root, "bin");
26005
- const codexHome = join8(root, "home");
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
- join8(installDirectory, "codex")
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 = join8(options.stateDirectory, "agents", this.id);
26074
- const managedHome = join8(root, "home");
26075
- const temporaryRoot = join8(options.stateDirectory, "temporary");
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
- join8(temporaryRoot, ".claude-install-")
26456
+ join9(temporaryRoot, ".claude-install-")
26082
26457
  );
26083
- const installerPath = join8(temporaryDirectory, "install.sh");
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
- join8(managedHome, ".local", "bin", "claude")
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 isAbsolute2,
26416
- join as join9,
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 (isAbsolute2(path2)) return path2;
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 (!isAbsolute2(requested) || requested.includes("\0") || normalize(requested) !== requested)
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 (!isAbsolute2(target) || normalize(target) !== target || !metadata.isDirectory())
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 === "" ? "~" : !isAbsolute2(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
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(join9(target, child.name), signal);
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();