@agentproto/driver-agent-cli 2.8.0 → 2.9.0

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.
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { Writable, Readable } from 'stream';
3
3
  import { createAcpClient } from '@agentproto/acp/client';
4
4
  import { spawn, execFile } from 'child_process';
5
- import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync, rmdirSync, realpathSync, mkdtempSync } from 'fs';
5
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync, rmdirSync, realpathSync, mkdtempSync, lstatSync, unlinkSync, symlinkSync } from 'fs';
6
6
  import { createInterface } from 'readline';
7
7
  import { join, isAbsolute, resolve, delimiter, dirname, basename } from 'path';
8
8
  import { tmpdir, homedir } from 'os';
@@ -392,6 +392,14 @@ var agentCliFrontmatterSchema = z.object({
392
392
  routeSelection: z.enum(["free", "derived-from-model"]).optional(),
393
393
  authEnforce: z.enum(["always", "when-configured"]).optional(),
394
394
  sandbox: z.union([z.string(), z.record(z.string(), z.unknown())]),
395
+ stateHome: z.object({
396
+ env: z.string().regex(/^[A-Z][A-Z0-9_]*$/),
397
+ defaultDir: z.string().min(1).refine((d) => !d.startsWith("/") && !d.split("/").includes(".."), {
398
+ message: "defaultDir must be relative to $HOME and stay inside it"
399
+ }),
400
+ share: z.array(z.string().regex(/^[^/]+$/)).optional(),
401
+ seed: z.record(z.string().regex(/^[^/]+$/).refine((n) => n !== "." && n !== "..", { message: "seed names a file of the home" }), z.string()).optional()
402
+ }).strict().optional(),
395
403
  runner: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
396
404
  protocol: z.enum(["acp", "mcp", "proprietary", "print"]),
397
405
  acp: z.string().optional(),
@@ -720,15 +728,15 @@ function isAlive(pid) {
720
728
  }
721
729
  }
722
730
  function listProcesses() {
723
- return new Promise((resolve2) => {
731
+ return new Promise((resolve3) => {
724
732
  execFile("ps", ["-axo", "pid=,ppid="], { maxBuffer: 32 * 1024 * 1024 }, (err, stdout) => {
725
- if (err) return resolve2([]);
733
+ if (err) return resolve3([]);
726
734
  const out = [];
727
735
  for (const line of stdout.split("\n")) {
728
736
  const m = line.match(/^\s*(\d+)\s+(\d+)\s*$/);
729
737
  if (m) out.push({ pid: Number(m[1]), ppid: Number(m[2]) });
730
738
  }
731
- resolve2(out);
739
+ resolve3(out);
732
740
  });
733
741
  });
734
742
  }
@@ -777,9 +785,17 @@ function defaultToolchainReadPaths() {
777
785
  // macOS Keychain DB — git/gh credential retrieval (read-only; see doc above)
778
786
  ];
779
787
  }
788
+ function effectiveSpawnSandboxMode(opts, configured) {
789
+ return opts.zones ? opts.mode ?? "workspace" : opts.mode ?? configured;
790
+ }
791
+ async function willConfineAgentCliSpawn(opts) {
792
+ const cfg = await loadAdapterSpawnSandboxConfig(opts.cwd);
793
+ const mode = effectiveSpawnSandboxMode(opts, cfg.mode);
794
+ return mode !== void 0 && mode !== "off";
795
+ }
780
796
  async function wrapAgentCliSpawn(bin, args, opts) {
781
797
  const cfg = await loadAdapterSpawnSandboxConfig(opts.cwd);
782
- const mode = opts.zones ? opts.mode ?? "workspace" : opts.mode ?? cfg.mode;
798
+ const mode = effectiveSpawnSandboxMode(opts, cfg.mode);
783
799
  if (mode === void 0) return [bin, args];
784
800
  if (mode === "off" && opts.zones) {
785
801
  throw new Error(
@@ -880,11 +896,11 @@ function createPrintSession(opts) {
880
896
  });
881
897
  activeChild = child;
882
898
  let spawnFailure;
883
- await new Promise((resolve2) => {
884
- child.once("spawn", () => resolve2());
899
+ await new Promise((resolve3) => {
900
+ child.once("spawn", () => resolve3());
885
901
  child.once("error", (err) => {
886
902
  spawnFailure = err;
887
- resolve2();
903
+ resolve3();
888
904
  });
889
905
  });
890
906
  if (spawnFailure) {
@@ -1503,16 +1519,16 @@ var EventQueue = class {
1503
1519
  `print-arm: event backlog exceeded ${QUEUE_HIGH_WATER_MARK} buffered events \u2014 downstream consumer is not keeping up. The child's stdout is still being drained (no ENOBUFS), but memory will grow until the consumer catches up.`
1504
1520
  );
1505
1521
  }
1506
- const resolve2 = this.resolveNext;
1522
+ const resolve3 = this.resolveNext;
1507
1523
  this.resolveNext = null;
1508
- resolve2?.();
1524
+ resolve3?.();
1509
1525
  }
1510
1526
  /** Signal that no further events will be pushed. */
1511
1527
  end() {
1512
1528
  this.ended = true;
1513
- const resolve2 = this.resolveNext;
1529
+ const resolve3 = this.resolveNext;
1514
1530
  this.resolveNext = null;
1515
- resolve2?.();
1531
+ resolve3?.();
1516
1532
  }
1517
1533
  async *[Symbol.asyncIterator]() {
1518
1534
  for (; ; ) {
@@ -1522,8 +1538,8 @@ var EventQueue = class {
1522
1538
  continue;
1523
1539
  }
1524
1540
  if (this.ended) return;
1525
- await new Promise((resolve2) => {
1526
- this.resolveNext = resolve2;
1541
+ await new Promise((resolve3) => {
1542
+ this.resolveNext = resolve3;
1527
1543
  });
1528
1544
  }
1529
1545
  }
@@ -1542,9 +1558,9 @@ function mapMastraFinishReason(raw) {
1542
1558
  }
1543
1559
  }
1544
1560
  function waitForExit(child) {
1545
- return new Promise((resolve2) => {
1546
- child.once("exit", (code) => resolve2(code));
1547
- child.once("error", () => resolve2(null));
1561
+ return new Promise((resolve3) => {
1562
+ child.once("exit", (code) => resolve3(code));
1563
+ child.once("error", () => resolve3(null));
1548
1564
  });
1549
1565
  }
1550
1566
  async function createProprietaryProtocolArm(options) {
@@ -1981,8 +1997,8 @@ async function* promptTurn(arm, turnId, message, stderrTurnError) {
1981
1997
  return;
1982
1998
  }
1983
1999
  const nextEvent = iterator.next();
1984
- const stderrArrived = new Promise((resolve2) => {
1985
- wake = resolve2;
2000
+ const stderrArrived = new Promise((resolve3) => {
2001
+ wake = resolve3;
1986
2002
  });
1987
2003
  const winner = await Promise.race([
1988
2004
  nextEvent.then((result) => ({ source: "event", result })),
@@ -2006,6 +2022,43 @@ async function* promptTurn(arm, turnId, message, stderrTurnError) {
2006
2022
  });
2007
2023
  }
2008
2024
  }
2025
+ function realStateHome(stateHome, env) {
2026
+ const fromEnv = env[stateHome.env];
2027
+ if (fromEnv && isAbsolute(fromEnv)) return fromEnv;
2028
+ return resolve(homedir(), stateHome.defaultDir);
2029
+ }
2030
+ function prepareIsolatedStateHome(stateHome, opts) {
2031
+ const real = realStateHome(stateHome, opts.env);
2032
+ let dir;
2033
+ if (opts.configDir) {
2034
+ dir = opts.configDir;
2035
+ mkdirSync(dir, { recursive: true });
2036
+ } else {
2037
+ dir = mkdtempSync(join(tmpdir(), `agentproto-${stateHome.env.toLowerCase()}-`));
2038
+ }
2039
+ const writePaths = [dir];
2040
+ for (const name of stateHome.share ?? []) {
2041
+ const target = join(real, name);
2042
+ const link = join(dir, name);
2043
+ try {
2044
+ lstatSync(link);
2045
+ unlinkSync(link);
2046
+ } catch {
2047
+ }
2048
+ if (!existsSync(target)) continue;
2049
+ symlinkSync(target, link);
2050
+ writePaths.push(realpathSync(target));
2051
+ }
2052
+ for (const [name, content] of Object.entries(stateHome.seed ?? {})) {
2053
+ const file = join(dir, name);
2054
+ try {
2055
+ unlinkSync(file);
2056
+ } catch {
2057
+ }
2058
+ writeFileSync(file, content);
2059
+ }
2060
+ return { dir, writePaths };
2061
+ }
2009
2062
  function npxCacheKey(packages) {
2010
2063
  return createHash("sha512").update([...packages].sort((a, b) => a.localeCompare(b, "en")).join("\n")).digest("hex").slice(0, 16);
2011
2064
  }
@@ -2212,6 +2265,15 @@ function createAgentCliRuntime(definition) {
2212
2265
  );
2213
2266
  env.CLAUDE_CONFIG_DIR = claudeConfigDir;
2214
2267
  }
2268
+ const extraWritePaths = claudeConfigDir ? [claudeConfigDir] : [];
2269
+ if (definition.stateHome && definition.protocol !== "proprietary" && await willConfineAgentCliSpawn({ mode: opts?.commandSandbox, cwd, zones: opts?.fsZones })) {
2270
+ const isolated = prepareIsolatedStateHome(definition.stateHome, {
2271
+ ...opts?.configDir ? { configDir: opts.configDir } : {},
2272
+ env
2273
+ });
2274
+ env[definition.stateHome.env] = isolated.dir;
2275
+ extraWritePaths.push(...isolated.writePaths);
2276
+ }
2215
2277
  if (definition.protocol === "print") {
2216
2278
  const printModel = config?.options?.model;
2217
2279
  return createPrintSession({
@@ -2224,7 +2286,7 @@ function createAgentCliRuntime(definition) {
2224
2286
  printConfig: definition.print,
2225
2287
  commandSandbox: opts?.commandSandbox,
2226
2288
  ...opts?.fsZones ? { fsZones: opts.fsZones } : {},
2227
- ...claudeConfigDir ? { extraWritePaths: [claudeConfigDir] } : {},
2289
+ ...extraWritePaths.length ? { extraWritePaths } : {},
2228
2290
  // Exact-file read grant — see the ACP arm's wrapAgentCliSpawn call.
2229
2291
  ...opts?.additionalReadPaths?.length ? { extraReadPaths: opts.additionalReadPaths } : {},
2230
2292
  ...definition.routeSelection === "derived-from-model" && printModel ? { expectedModel: String(printModel) } : {}
@@ -2241,7 +2303,7 @@ function createAgentCliRuntime(definition) {
2241
2303
  mode: opts?.commandSandbox,
2242
2304
  cwd,
2243
2305
  ...opts?.fsZones ? { zones: opts.fsZones } : {},
2244
- ...claudeConfigDir ? { extraWritePaths: [claudeConfigDir] } : {},
2306
+ ...extraWritePaths.length ? { extraWritePaths } : {},
2245
2307
  // Exact-file read grant (see additionalReadPaths above):
2246
2308
  // READ-only exceptions to the confinement boundary, never writes.
2247
2309
  ...opts?.additionalReadPaths?.length ? { extraReadPaths: opts.additionalReadPaths } : {},
@@ -2261,11 +2323,11 @@ function createAgentCliRuntime(definition) {
2261
2323
  });
2262
2324
  child = spawned;
2263
2325
  let spawnFailure;
2264
- await new Promise((resolve2) => {
2265
- spawned.once("spawn", () => resolve2());
2326
+ await new Promise((resolve3) => {
2327
+ spawned.once("spawn", () => resolve3());
2266
2328
  spawned.once("error", (err) => {
2267
2329
  spawnFailure = err;
2268
- resolve2();
2330
+ resolve3();
2269
2331
  });
2270
2332
  });
2271
2333
  if (spawnFailure) {
@@ -2487,5 +2549,5 @@ function derivedModelRefusalError(definition, requested, reason) {
2487
2549
  }
2488
2550
 
2489
2551
  export { LEGACY_GATEWAY_MODE_IDS, LEGACY_POSTURE_MODE_IDS, RuntimeConfigError, agentCliFrontmatterSchema, agentCliSupportsHostContextIsolation, applyModelCommand, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createArmSessionControls, createJcodeMapperState, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, hostContextExcludes, inferLegacyModeKind, isLegacyExtractedModeId, isModelSwitchAcknowledgement, mapJcodeEvent, mapMastraEvent, parseModelSwitchCommand, planModePermissionHandler, promptTurn, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
2490
- //# sourceMappingURL=chunk-E45SX7GU.mjs.map
2491
- //# sourceMappingURL=chunk-E45SX7GU.mjs.map
2552
+ //# sourceMappingURL=chunk-AN5G6ENG.mjs.map
2553
+ //# sourceMappingURL=chunk-AN5G6ENG.mjs.map