@sagentlab/navarch-runtime 0.1.41 → 0.1.42

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.
@@ -4,6 +4,7 @@ exports.openCodeAdapter = void 0;
4
4
  exports.runOpenCodeAdapter = runOpenCodeAdapter;
5
5
  const node_child_process_1 = require("node:child_process");
6
6
  const node_fs_1 = require("node:fs");
7
+ const config_cjs_1 = require("../config.cjs");
7
8
  /**
8
9
  * Headless OpenCode adapter, fixture-pinned to the OpenCode 1.18 JSON/config
9
10
  * contract:
@@ -24,9 +25,7 @@ async function runOpenCodeAdapter(options) {
24
25
  timedOut: false,
25
26
  killedByLeaseLoss: false,
26
27
  stdout: "",
27
- stderr: "OpenCode cannot enforce Navarch's host worktree boundary for shell side effects. " +
28
- "Use NAVARCH_SANDBOX_MODE=docker, or explicitly set NAVARCH_WORKTREE_GUARD=off " +
29
- "only on an otherwise isolated machine.",
28
+ stderr: config_cjs_1.OPENCODE_HOST_GUARD_MESSAGE,
30
29
  };
31
30
  }
32
31
  const env = { ...options.env };
package/dist/cli.cjs CHANGED
@@ -274,7 +274,19 @@ async function superviseCommand(flags) {
274
274
  process.exitCode = exitCode;
275
275
  }
276
276
  async function doctorCommand(flags) {
277
- const config = configFromFlags(flags);
277
+ // doctor is the command an operator reaches for precisely when the config
278
+ // will not load — an OpenCode-only machine on a guarded host refuses to
279
+ // start (config.cts). Report that as the diagnosis instead of rethrowing it
280
+ // as a bare CLI error.
281
+ let config;
282
+ try {
283
+ config = configFromFlags(flags);
284
+ }
285
+ catch (err) {
286
+ console.log(`config: UNUSABLE — ${err instanceof Error ? err.message : String(err)}`);
287
+ process.exitCode = 1;
288
+ return;
289
+ }
278
290
  const dockerOk = await (0, sandbox_cjs_1.isDockerAvailable)();
279
291
  console.log(`api_base: ${config.apiBase}`);
280
292
  console.log(`config_dir: ${config.configDir}`);
@@ -282,6 +294,8 @@ async function doctorCommand(flags) {
282
294
  console.log(`max_sessions: ${config.maxSessions}`);
283
295
  console.log(`capabilities: ${config.capabilities.join(", ")}`);
284
296
  console.log(`sandbox_mode: ${config.sandboxMode}`);
297
+ console.log(`worktree_guard: ${config.worktreeGuard ? "on" : "off"}`);
298
+ console.log(`runtimes: ${config.runtimes?.join(", ") ?? config.agentType}`);
285
299
  console.log(`docker: ${dockerOk ? "available" : "NOT AVAILABLE (docker-backed sessions will fail)"}`);
286
300
  let identity;
287
301
  try {
package/dist/config.cjs CHANGED
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_SANDBOX_IMAGE = void 0;
6
+ exports.OPENCODE_HOST_GUARD_MESSAGE = exports.DEFAULT_SANDBOX_IMAGE = void 0;
7
7
  exports.isRuntimeAgentType = isRuntimeAgentType;
8
+ exports.opencodeBlockedOnHost = opencodeBlockedOnHost;
8
9
  exports.loadRuntimeConfig = loadRuntimeConfig;
9
10
  const node_path_1 = __importDefault(require("node:path"));
10
11
  const node_os_1 = __importDefault(require("node:os"));
@@ -44,6 +45,18 @@ function envList(env, name, fallback) {
44
45
  .map((s) => s.trim())
45
46
  .filter(Boolean);
46
47
  }
48
+ /**
49
+ * OpenCode is the one runtime Navarch cannot fence into a per-session worktree
50
+ * on the host: its CLI has no equivalent of Claude's PreToolUse hook or
51
+ * Codex's native permission profile. Docker mode supplies the boundary
52
+ * instead, and NAVARCH_WORKTREE_GUARD=off is the explicit opt-out.
53
+ */
54
+ function opencodeBlockedOnHost(sandboxMode, worktreeGuard) {
55
+ return sandboxMode === "host" && worktreeGuard;
56
+ }
57
+ exports.OPENCODE_HOST_GUARD_MESSAGE = "OpenCode cannot enforce Navarch's host worktree boundary for shell side effects. " +
58
+ "Use NAVARCH_SANDBOX_MODE=docker, or explicitly set NAVARCH_WORKTREE_GUARD=off " +
59
+ "only on an otherwise isolated machine.";
47
60
  /**
48
61
  * Loads runtime config from NAVARCH_* env vars, with sane defaults for a
49
62
  * fresh machine. Accepts an explicit env map (defaulting to process.env) so
@@ -57,8 +70,23 @@ function loadRuntimeConfig(env = process.env) {
57
70
  // prerequisite for claiming ordinary shell work.
58
71
  const sandboxMode = env.NAVARCH_SANDBOX_MODE === "docker" ? "docker" : "host";
59
72
  const defaultCapabilities = sandboxMode === "docker" ? ["docker-sandbox", "shell"] : ["shell", "browser-use"];
60
- const agentType = isRuntimeAgentType(env.NAVARCH_AGENT) ? env.NAVARCH_AGENT : "claude-code";
61
- const runtimes = envList(env, "NAVARCH_RUNTIMES", [agentType]).filter(isRuntimeAgentType);
73
+ const requestedAgentType = isRuntimeAgentType(env.NAVARCH_AGENT) ? env.NAVARCH_AGENT : "claude-code";
74
+ // Multiple sessions share one machine; keeping each agent inside its own
75
+ // worktree is the safe default, so disabling is the explicit opt-out.
76
+ const worktreeGuard = !["off", "false", "0"].includes(env.NAVARCH_WORKTREE_GUARD ?? "");
77
+ const requestedRuntimes = envList(env, "NAVARCH_RUNTIMES", [requestedAgentType]).filter(isRuntimeAgentType);
78
+ // OpenCode's CLI cannot express the host worktree boundary, so its adapter
79
+ // fails closed there (adapters/opencode.cts). Advertising it anyway meant
80
+ // the machine claimed OpenCode tasks it could only fail, one lease at a
81
+ // time; keep it out of the claim instead of discovering this per session.
82
+ const runnableRuntimes = requestedRuntimes.filter((runtime) => runtime !== "opencode" || !opencodeBlockedOnHost(sandboxMode, worktreeGuard));
83
+ if (requestedRuntimes.includes("opencode") && runnableRuntimes.length === 0) {
84
+ throw new Error(exports.OPENCODE_HOST_GUARD_MESSAGE);
85
+ }
86
+ const agentType = runnableRuntimes.includes(requestedAgentType) || runnableRuntimes.length === 0
87
+ ? requestedAgentType
88
+ : (runnableRuntimes[0] ?? requestedAgentType);
89
+ const runtimes = runnableRuntimes;
62
90
  return {
63
91
  apiBase: env.NAVARCH_API_BASE ?? "http://localhost:3000",
64
92
  workspaceRoot: env.NAVARCH_WORKSPACE_ROOT ?? node_path_1.default.join(configDir, "sandboxes"),
@@ -98,9 +126,7 @@ function loadRuntimeConfig(env = process.env) {
98
126
  : sandbox_profile_cjs_1.DEFAULT_SANDBOX_PROFILE_ID,
99
127
  sandboxEgressNetwork: env.NAVARCH_SANDBOX_EGRESS_NETWORK?.trim() || null,
100
128
  dockerImage: env.NAVARCH_DOCKER_IMAGE ?? exports.DEFAULT_SANDBOX_IMAGE,
101
- // Multiple sessions share one machine; keeping each agent inside its own
102
- // worktree is the safe default, so disabling is the explicit opt-out.
103
- worktreeGuard: !["off", "false", "0"].includes(env.NAVARCH_WORKTREE_GUARD ?? ""),
129
+ worktreeGuard,
104
130
  guardExtraRoots: (env.NAVARCH_GUARD_EXTRA_ROOTS ?? "")
105
131
  .split(node_path_1.default.delimiter)
106
132
  .map((s) => s.trim())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sagentlab/navarch-runtime",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "description": "Navarch machine-side session manager: claims delivery tasks and runs them through local coding agents.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",