@agentproto/driver-agent-cli 2.5.0 → 2.6.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,9 +2,9 @@ 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, mkdtempSync } from 'fs';
5
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync, rmdirSync, realpathSync, mkdtempSync } from 'fs';
6
6
  import { createInterface } from 'readline';
7
- import { join, delimiter, dirname, basename } from 'path';
7
+ import { join, resolve, delimiter, dirname, basename } from 'path';
8
8
  import { tmpdir, homedir } from 'os';
9
9
  import { loadAdapterSpawnSandboxConfig, resolveCommandSandbox } from '@agentproto/command-sandbox';
10
10
  import { randomUUID, createHash } from 'crypto';
@@ -701,15 +701,15 @@ function isAlive(pid) {
701
701
  }
702
702
  }
703
703
  function listProcesses() {
704
- return new Promise((resolve) => {
704
+ return new Promise((resolve2) => {
705
705
  execFile("ps", ["-axo", "pid=,ppid="], { maxBuffer: 32 * 1024 * 1024 }, (err, stdout) => {
706
- if (err) return resolve([]);
706
+ if (err) return resolve2([]);
707
707
  const out = [];
708
708
  for (const line of stdout.split("\n")) {
709
709
  const m = line.match(/^\s*(\d+)\s+(\d+)\s*$/);
710
710
  if (m) out.push({ pid: Number(m[1]), ppid: Number(m[2]) });
711
711
  }
712
- resolve(out);
712
+ resolve2(out);
713
713
  });
714
714
  });
715
715
  }
@@ -743,8 +743,13 @@ function defaultToolchainReadPaths() {
743
743
  }
744
744
  async function wrapAgentCliSpawn(bin, args, opts) {
745
745
  const cfg = await loadAdapterSpawnSandboxConfig(opts.cwd);
746
- const mode = opts.mode ?? cfg.mode;
746
+ const mode = opts.zones ? opts.mode ?? "workspace" : opts.mode ?? cfg.mode;
747
747
  if (mode === void 0) return [bin, args];
748
+ if (mode === "off" && opts.zones) {
749
+ throw new Error(
750
+ `agent-cli '${opts.label}': filesystem zones (an app boundary) cannot be combined with commandSandbox "off" \u2014 the zones are only enforceable through the OS sandbox. Refusing to spawn.`
751
+ );
752
+ }
748
753
  if (mode === "off") {
749
754
  console.error(
750
755
  `[agent-cli] \u26A0 spawning '${opts.label}' UNCONFINED \u2014 no OS-level sandbox is active (commandSandbox mode is "off").`
@@ -757,18 +762,20 @@ async function wrapAgentCliSpawn(bin, args, opts) {
757
762
  `agent-cli '${opts.label}': commandSandbox mode="${mode}" is configured but no sandbox backend is available on ${process.platform} (macOS needs sandbox-exec, Linux needs bwrap installed). Refusing to spawn unconfined \u2014 pass commandSandbox: "off" to explicitly accept unconfined execution, or install the missing backend.`
758
763
  );
759
764
  }
765
+ const fileCfg = opts.zones ? void 0 : cfg;
760
766
  const policy = {
761
767
  workspace: opts.cwd,
762
768
  extraReadPaths: [
763
769
  ...defaultToolchainReadPaths(),
764
- ...cfg.extraReadPaths,
770
+ ...fileCfg?.extraReadPaths ?? [],
765
771
  ...opts.extraReadPaths ?? []
766
772
  ],
767
773
  extraWritePaths: [
768
774
  ...defaultToolchainWritePaths(),
769
- ...cfg.extraWritePaths,
775
+ ...fileCfg?.extraWritePaths ?? [],
770
776
  ...opts.extraWritePaths ?? []
771
777
  ],
778
+ ...opts.zones ? { zones: opts.zones } : {},
772
779
  network: mode === "strict" || cfg.network === "deny" ? "deny" : "allow"
773
780
  };
774
781
  const wrapped = backend.wrap([bin, ...args], policy);
@@ -822,6 +829,7 @@ function createPrintSession(opts) {
822
829
  cwd: opts.cwd,
823
830
  ...opts.extraWritePaths ? { extraWritePaths: opts.extraWritePaths } : {},
824
831
  ...opts.extraReadPaths ? { extraReadPaths: opts.extraReadPaths } : {},
832
+ ...opts.fsZones ? { zones: opts.fsZones } : {},
825
833
  label: "print-arm"
826
834
  });
827
835
  const child = spawn(execBin, execArgs, {
@@ -831,11 +839,11 @@ function createPrintSession(opts) {
831
839
  });
832
840
  activeChild = child;
833
841
  let spawnFailure;
834
- await new Promise((resolve) => {
835
- child.once("spawn", () => resolve());
842
+ await new Promise((resolve2) => {
843
+ child.once("spawn", () => resolve2());
836
844
  child.once("error", (err) => {
837
845
  spawnFailure = err;
838
- resolve();
846
+ resolve2();
839
847
  });
840
848
  });
841
849
  if (spawnFailure) {
@@ -1033,14 +1041,26 @@ function setupMcpConfigFile(opts, eventSchema) {
1033
1041
  }
1034
1042
  function extractPromptText(message) {
1035
1043
  if (typeof message === "string") return message;
1036
- if (message !== null && typeof message === "object") {
1037
- const m = message;
1038
- if (typeof m.text === "string") return m.text;
1039
- if (Array.isArray(message)) {
1040
- return message.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
1044
+ const blocks = Array.isArray(message) ? message : [message];
1045
+ const texts = [];
1046
+ for (const block of blocks) {
1047
+ if (block !== null && typeof block === "object") {
1048
+ const b = block;
1049
+ if (b.type === "text" && typeof b.text === "string") {
1050
+ texts.push(b.text);
1051
+ continue;
1052
+ }
1053
+ if (b.type === void 0 && typeof b.text === "string") {
1054
+ texts.push(b.text);
1055
+ continue;
1056
+ }
1041
1057
  }
1058
+ const kind = block !== null && typeof block === "object" && typeof block.type === "string" ? block.type : typeof block;
1059
+ throw new Error(
1060
+ `this adapter has no multimodal input (capabilities.multimodal: false) \u2014 got a "${kind}" content block it can't send. Upload the file via POST /files/upload and reference its path in the prompt text instead.`
1061
+ );
1042
1062
  }
1043
- return JSON.stringify(message);
1063
+ return texts.join("\n");
1044
1064
  }
1045
1065
  function captureSessionId(evt, schema) {
1046
1066
  switch (schema) {
@@ -1442,16 +1462,16 @@ var EventQueue = class {
1442
1462
  `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.`
1443
1463
  );
1444
1464
  }
1445
- const resolve = this.resolveNext;
1465
+ const resolve2 = this.resolveNext;
1446
1466
  this.resolveNext = null;
1447
- resolve?.();
1467
+ resolve2?.();
1448
1468
  }
1449
1469
  /** Signal that no further events will be pushed. */
1450
1470
  end() {
1451
1471
  this.ended = true;
1452
- const resolve = this.resolveNext;
1472
+ const resolve2 = this.resolveNext;
1453
1473
  this.resolveNext = null;
1454
- resolve?.();
1474
+ resolve2?.();
1455
1475
  }
1456
1476
  async *[Symbol.asyncIterator]() {
1457
1477
  for (; ; ) {
@@ -1461,8 +1481,8 @@ var EventQueue = class {
1461
1481
  continue;
1462
1482
  }
1463
1483
  if (this.ended) return;
1464
- await new Promise((resolve) => {
1465
- this.resolveNext = resolve;
1484
+ await new Promise((resolve2) => {
1485
+ this.resolveNext = resolve2;
1466
1486
  });
1467
1487
  }
1468
1488
  }
@@ -1481,9 +1501,9 @@ function mapMastraFinishReason(raw) {
1481
1501
  }
1482
1502
  }
1483
1503
  function waitForExit(child) {
1484
- return new Promise((resolve) => {
1485
- child.once("exit", (code) => resolve(code));
1486
- child.once("error", () => resolve(null));
1504
+ return new Promise((resolve2) => {
1505
+ child.once("exit", (code) => resolve2(code));
1506
+ child.once("error", () => resolve2(null));
1487
1507
  });
1488
1508
  }
1489
1509
 
@@ -1732,6 +1752,42 @@ function interpolateEnv(env, value) {
1732
1752
  }
1733
1753
  return out;
1734
1754
  }
1755
+ function agentCliSupportsHostContextIsolation(adapterId) {
1756
+ return adapterId === "claude-code";
1757
+ }
1758
+ function escapeGlob(p) {
1759
+ return p.replace(/[\\*?[\]{}()!+@]/g, "\\$&");
1760
+ }
1761
+ function ancestors(dir) {
1762
+ const out = [];
1763
+ let cur = dirname(dir);
1764
+ for (; ; ) {
1765
+ out.push(cur);
1766
+ const parent = dirname(cur);
1767
+ if (parent === cur) return out;
1768
+ cur = parent;
1769
+ }
1770
+ }
1771
+ function hostContextExcludes(cwd) {
1772
+ const abs = resolve(cwd);
1773
+ let real = abs;
1774
+ try {
1775
+ real = realpathSync(abs);
1776
+ } catch {
1777
+ }
1778
+ const dirs = /* @__PURE__ */ new Set([...ancestors(abs), ...ancestors(real)]);
1779
+ const out = [];
1780
+ for (const d of dirs) {
1781
+ const base = d === "/" ? "" : escapeGlob(d);
1782
+ out.push(
1783
+ `${base}/CLAUDE.md`,
1784
+ `${base}/CLAUDE.local.md`,
1785
+ `${base}/.claude/CLAUDE.md`,
1786
+ `${base}/.claude/rules/**`
1787
+ );
1788
+ }
1789
+ return out;
1790
+ }
1735
1791
  function createArmSessionControls(arm, definition) {
1736
1792
  const modelApply = definition.models?.apply ?? "config";
1737
1793
  return {
@@ -2021,8 +2077,16 @@ function createAgentCliRuntime(definition) {
2021
2077
  const isolatedSettings = {
2022
2078
  attribution: { commit: "", pr: "", sessionUrl: false }
2023
2079
  };
2024
- if (permissionMode) {
2025
- isolatedSettings.permissions = { defaultMode: permissionMode };
2080
+ const isolatedPermissions = {};
2081
+ if (permissionMode) isolatedPermissions.defaultMode = permissionMode;
2082
+ if (opts?.fsZones?.writable.length) {
2083
+ isolatedPermissions.additionalDirectories = opts.fsZones.writable;
2084
+ }
2085
+ if (Object.keys(isolatedPermissions).length > 0) {
2086
+ isolatedSettings.permissions = isolatedPermissions;
2087
+ }
2088
+ if (opts?.isolateHostContext) {
2089
+ isolatedSettings.claudeMdExcludes = hostContextExcludes(cwd);
2026
2090
  }
2027
2091
  writeFileSync(
2028
2092
  join(claudeConfigDir, "settings.json"),
@@ -2041,6 +2105,7 @@ function createAgentCliRuntime(definition) {
2041
2105
  ...opts?.mcpServers ? { mcpServers: opts.mcpServers } : {},
2042
2106
  printConfig: definition.print,
2043
2107
  commandSandbox: opts?.commandSandbox,
2108
+ ...opts?.fsZones ? { fsZones: opts.fsZones } : {},
2044
2109
  ...claudeConfigDir ? { extraWritePaths: [claudeConfigDir] } : {},
2045
2110
  // Exact-file read grant — see the ACP arm's wrapAgentCliSpawn call.
2046
2111
  ...opts?.additionalReadPaths?.length ? { extraReadPaths: opts.additionalReadPaths } : {},
@@ -2056,6 +2121,7 @@ function createAgentCliRuntime(definition) {
2056
2121
  {
2057
2122
  mode: opts?.commandSandbox,
2058
2123
  cwd,
2124
+ ...opts?.fsZones ? { zones: opts.fsZones } : {},
2059
2125
  ...claudeConfigDir ? { extraWritePaths: [claudeConfigDir] } : {},
2060
2126
  // Exact-file read grant (see additionalReadPaths above):
2061
2127
  // READ-only exceptions to the confinement boundary, never writes.
@@ -2071,11 +2137,11 @@ function createAgentCliRuntime(definition) {
2071
2137
  });
2072
2138
  child = spawned;
2073
2139
  let spawnFailure;
2074
- await new Promise((resolve) => {
2075
- spawned.once("spawn", () => resolve());
2140
+ await new Promise((resolve2) => {
2141
+ spawned.once("spawn", () => resolve2());
2076
2142
  spawned.once("error", (err) => {
2077
2143
  spawnFailure = err;
2078
- resolve();
2144
+ resolve2();
2079
2145
  });
2080
2146
  });
2081
2147
  if (spawnFailure) {
@@ -2284,6 +2350,6 @@ function derivedModelRefusalError(definition, requested, reason) {
2284
2350
  );
2285
2351
  }
2286
2352
 
2287
- export { LEGACY_GATEWAY_MODE_IDS, LEGACY_POSTURE_MODE_IDS, RuntimeConfigError, agentCliFrontmatterSchema, applyModelCommand, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createArmSessionControls, createJcodeMapperState, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, inferLegacyModeKind, isLegacyExtractedModeId, isModelSwitchAcknowledgement, mapJcodeEvent, mapMastraEvent, parseModelSwitchCommand, planModePermissionHandler, promptTurn, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
2288
- //# sourceMappingURL=chunk-JPL6CMLQ.mjs.map
2289
- //# sourceMappingURL=chunk-JPL6CMLQ.mjs.map
2353
+ 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 };
2354
+ //# sourceMappingURL=chunk-SCR7UF3T.mjs.map
2355
+ //# sourceMappingURL=chunk-SCR7UF3T.mjs.map