agentbox-sdk 0.1.322 → 0.1.400

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.
@@ -1,5 +1,5 @@
1
- import { o as AgentProviderName, h as AgentOptions, t as AgentRunConfig, s as AgentRun, r as AgentResult, a3 as RawAgentEvent, b as AgentAttachRequest, y as AttachedRun, aa as SetupLayout } from '../types-DG4J_zMT.js';
2
- export { a as AgentApprovalMode, c as AgentCommandConfig, d as AgentCostData, e as AgentExecutionRequest, f as AgentLocalMcpConfig, g as AgentMcpConfig, i as AgentOptionsBase, j as AgentOptionsMap, k as AgentPermissionDecision, l as AgentPermissionKind, m as AgentPermissionResponse, n as AgentProviderAdapter, p as AgentReasoningEffort, q as AgentRemoteMcpConfig, u as AgentRunSink, v as AgentSetupRequest, w as AgentSkillConfig, x as AgentSubAgentConfig, C as ClaudeCodeAgentOptions, z as ClaudeCodeHookConfig, B as ClaudeCodeHookEvent, D as ClaudeCodeHookHandler, E as ClaudeCodeHookMatcherGroup, F as ClaudeCodeHooksConfig, G as ClaudeCodeProviderOptions, H as CodexAgentOptions, I as CodexCommandHook, J as CodexHookEvent, K as CodexHookMatcherGroup, L as CodexHooksConfig, M as CodexProviderOptions, N as DataContent, O as EmbeddedSkillConfig, P as FilePart, Q as ImagePart, X as OpenCodeAgentOptions, Y as OpenCodePluginConfig, Z as OpenCodePluginEvent, _ as OpenCodePluginHookConfig, $ as OpenCodeProviderOptions, a0 as OpenRouterPlugin, a5 as RepoSkillConfig, ac as TextPart, ag as UserContent, ah as UserContentPart } from '../types-DG4J_zMT.js';
1
+ import { o as AgentProviderName, h as AgentOptions, t as AgentRunConfig, s as AgentRun, r as AgentResult, a3 as RawAgentEvent, b as AgentAttachRequest, y as AttachedRun, aa as SetupLayout } from '../types-vOsvzkcO.js';
2
+ export { a as AgentApprovalMode, c as AgentCommandConfig, d as AgentCostData, e as AgentExecutionRequest, f as AgentLocalMcpConfig, g as AgentMcpConfig, i as AgentOptionsBase, j as AgentOptionsMap, k as AgentPermissionDecision, l as AgentPermissionKind, m as AgentPermissionResponse, n as AgentProviderAdapter, p as AgentReasoningEffort, q as AgentRemoteMcpConfig, u as AgentRunSink, v as AgentSetupRequest, w as AgentSkillConfig, x as AgentSubAgentConfig, C as ClaudeCodeAgentOptions, z as ClaudeCodeHookConfig, B as ClaudeCodeHookEvent, D as ClaudeCodeHookHandler, E as ClaudeCodeHookMatcherGroup, F as ClaudeCodeHooksConfig, G as ClaudeCodeProviderOptions, H as CodexAgentOptions, I as CodexCommandHook, J as CodexHookEvent, K as CodexHookMatcherGroup, L as CodexHooksConfig, M as CodexProviderOptions, N as DataContent, O as EmbeddedSkillConfig, P as FilePart, Q as ImagePart, X as OpenCodeAgentOptions, Y as OpenCodePluginConfig, Z as OpenCodePluginEvent, _ as OpenCodePluginHookConfig, $ as OpenCodeProviderOptions, a0 as OpenRouterPlugin, a5 as RepoSkillConfig, ac as TextPart, ag as UserContent, ah as UserContentPart } from '../types-vOsvzkcO.js';
3
3
  import { S as Sandbox } from '../Sandbox-DcKAU-E3.js';
4
4
  export { AgentProvider } from '../enums.js';
5
5
  import 'e2b';
@@ -42,6 +42,23 @@ declare class Agent<P extends AgentProviderName = AgentProviderName> {
42
42
  * work.
43
43
  */
44
44
  setup(): Promise<void>;
45
+ /**
46
+ * Stop the long-lived provider CLI server booted by {@link Agent.setup}
47
+ * (claude-code relay daemon, codex app-server, opencode `serve`).
48
+ *
49
+ * agentbox NEVER kills a running server on its own — not on run
50
+ * completion, not on `abort()`, and not when {@link Agent.setup} detects
51
+ * a changed config/credential set. This method is the single, explicit,
52
+ * developer-driven teardown. Call it to free a server's resources, or to
53
+ * apply a changed config: after `killServer()` the next {@link setup}
54
+ * cold-starts a fresh server with the new configuration.
55
+ *
56
+ * Best-effort and idempotent: a no-op when no server is running, or when
57
+ * the provider has no shared server for the current mode (host-mode
58
+ * claude-code runs the SDK in-process; local codex spawns a fresh
59
+ * app-server per run, torn down with the run).
60
+ */
61
+ killServer(): Promise<void>;
45
62
  stream(runConfig: AgentRunConfig): AgentRun;
46
63
  run(runConfig: AgentRunConfig): Promise<AgentResult>;
47
64
  rawEvents(runConfig: AgentRunConfig): AsyncIterable<RawAgentEvent>;
@@ -2,7 +2,7 @@ import {
2
2
  Agent,
3
3
  agentboxRoot,
4
4
  getAgentLayout
5
- } from "../chunk-ZK5PDWOI.js";
5
+ } from "../chunk-KFMFNBVC.js";
6
6
  import "../chunk-775FIGGL.js";
7
7
  import {
8
8
  AGENT_RESERVED_PORTS,
@@ -583,6 +583,9 @@ function buildClaudeHookSettings(hooks) {
583
583
  }
584
584
  return { hooks };
585
585
  }
586
+ function buildClaudeWorkflowSettings(ultracode) {
587
+ return ultracode ? { enableWorkflows: true, ultracode: true } : {};
588
+ }
586
589
  function buildCodexHooksFile(hooks) {
587
590
  if (!hasHookEntries(hooks)) {
588
591
  return void 0;
@@ -1228,13 +1231,14 @@ async function preflightSetup(target, setupId, daemon) {
1228
1231
  ];
1229
1232
  if (daemon) {
1230
1233
  const url = `http://127.0.0.1:${daemon.port}${daemon.healthPath}`;
1234
+ const auth = daemon.curlAuthArg ? `${daemon.curlAuthArg} ` : "";
1231
1235
  if (daemon.expectedVersionMatch) {
1232
1236
  checks.push(
1233
- `curl -fsS --max-time 2 ${shellQuote(url)} 2>/dev/null | grep -q ${shellQuote(daemon.expectedVersionMatch)}`
1237
+ `curl -fsS --max-time 2 ${auth}${shellQuote(url)} 2>/dev/null | grep -q ${shellQuote(daemon.expectedVersionMatch)}`
1234
1238
  );
1235
1239
  } else {
1236
1240
  checks.push(
1237
- `curl -fsS --max-time 2 ${shellQuote(url)} >/dev/null 2>&1`
1241
+ `curl -fsS --max-time 2 ${auth}${shellQuote(url)} >/dev/null 2>&1`
1238
1242
  );
1239
1243
  }
1240
1244
  }
@@ -1513,6 +1517,46 @@ function buildCodexSubagentArtifacts(subAgents, layout) {
1513
1517
  };
1514
1518
  }
1515
1519
 
1520
+ // src/agents/config/capability-token.ts
1521
+ import crypto from "crypto";
1522
+ var tokenCache = /* @__PURE__ */ new WeakMap();
1523
+ async function readCapabilityTokenFile(sandbox, tokenFilePath) {
1524
+ const result = await sandbox.run(
1525
+ `if [ -f ${shellQuote(tokenFilePath)} ]; then cat ${shellQuote(tokenFilePath)}; fi`
1526
+ );
1527
+ if (result.exitCode !== 0) return void 0;
1528
+ const value = result.stdout.trim();
1529
+ return value.length > 0 ? value : void 0;
1530
+ }
1531
+ function resolveCapabilityToken(sandbox, tokenFilePath, create) {
1532
+ let byPath = tokenCache.get(sandbox);
1533
+ if (!byPath) {
1534
+ byPath = /* @__PURE__ */ new Map();
1535
+ tokenCache.set(sandbox, byPath);
1536
+ }
1537
+ const map = byPath;
1538
+ let cached = map.get(tokenFilePath);
1539
+ if (!cached) {
1540
+ const pending = (async () => {
1541
+ const existing = await readCapabilityTokenFile(sandbox, tokenFilePath);
1542
+ if (existing) return existing;
1543
+ if (create) return crypto.randomBytes(32).toString("hex");
1544
+ throw new Error(
1545
+ `Capability token file is missing at ${tokenFilePath}. setup() must run before connecting to this sandbox server.`
1546
+ );
1547
+ })().catch((error) => {
1548
+ map.delete(tokenFilePath);
1549
+ throw error;
1550
+ });
1551
+ map.set(tokenFilePath, pending);
1552
+ cached = pending;
1553
+ }
1554
+ return cached;
1555
+ }
1556
+ function withBearerToken(base, token) {
1557
+ return { ...base, Authorization: `Bearer ${token}` };
1558
+ }
1559
+
1516
1560
  // src/agents/cost.ts
1517
1561
  function addIfNumber(target, key, value) {
1518
1562
  if (typeof value !== "number" || !Number.isFinite(value)) {
@@ -1643,11 +1687,12 @@ function extractOpenCodeCostData(events) {
1643
1687
  }
1644
1688
 
1645
1689
  // src/agents/providers/claude-code.ts
1646
- var DAEMON_PROTOCOL_VERSION = "2";
1690
+ var DAEMON_PROTOCOL_VERSION = "3";
1647
1691
  var DAEMON_PORT = 43180;
1648
1692
  var DAEMON_PATH = "/tmp/agentbox/claude-code/daemon.mjs";
1649
1693
  var DAEMON_LOG_PATH = "/tmp/agentbox/claude-code/daemon.log";
1650
1694
  var DAEMON_PID_PATH = "/tmp/agentbox/claude-code/daemon.pid";
1695
+ var DAEMON_TOKEN_PATH = "/tmp/agentbox/claude-code/daemon-token";
1651
1696
  var DAEMON_READY_TIMEOUT_MS = 3e4;
1652
1697
  var DAEMON_READY_POLL_INTERVAL_MS = 250;
1653
1698
  function claudeConfigDir(options) {
@@ -1672,6 +1717,7 @@ function buildClaudeQueryOptions(params) {
1672
1717
  extraArgs["append-system-prompt"] = run.systemPrompt;
1673
1718
  }
1674
1719
  const includeHookEvents = provider?.includeHookEvents ?? false;
1720
+ const effort = provider?.ultracode ? "xhigh" : run.reasoning;
1675
1721
  return {
1676
1722
  cwd: params.cwd ?? params.request.options.cwd,
1677
1723
  env: params.env,
@@ -1684,7 +1730,7 @@ function buildClaudeQueryOptions(params) {
1684
1730
  thinking: { type: "adaptive", display: "summarized" },
1685
1731
  ...provider?.additionalDirectories?.length ? { additionalDirectories: provider.additionalDirectories } : {},
1686
1732
  ...run.model ? { model: run.model } : {},
1687
- ...run.reasoning ? { effort: run.reasoning } : {},
1733
+ ...effort ? { effort } : {},
1688
1734
  ...provider?.permissionMode ? { permissionMode: provider.permissionMode } : {},
1689
1735
  ...provider?.permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {},
1690
1736
  ...provider?.allowedTools?.length ? { allowedTools: provider.allowedTools } : {},
@@ -1741,11 +1787,30 @@ function createClaudeCodeDaemonScript() {
1741
1787
  const version = JSON.stringify(DAEMON_PROTOCOL_VERSION);
1742
1788
  return `import http from "node:http";
1743
1789
  import { execSync } from "node:child_process";
1744
- import { existsSync } from "node:fs";
1790
+ import { existsSync, readFileSync } from "node:fs";
1791
+ import { timingSafeEqual } from "node:crypto";
1745
1792
  import { query, getSessionInfo } from "@anthropic-ai/claude-agent-sdk";
1746
1793
 
1747
1794
  const VERSION = ${version};
1748
1795
  const port = Number(process.argv[2] ?? "${DAEMON_PORT}");
1796
+ // Capability token: every route except the loopback /__version probe
1797
+ // requires \`Authorization: Bearer <token>\`. Loaded once at boot from the
1798
+ // 0600 file the host writes alongside this script. Fails closed (rejects
1799
+ // all run-control requests) when the file is missing or empty.
1800
+ const tokenFilePath = process.argv[3] ?? "";
1801
+ let AUTH_TOKEN = "";
1802
+ try { if (tokenFilePath) AUTH_TOKEN = readFileSync(tokenFilePath, "utf8").trim(); } catch {}
1803
+
1804
+ function isAuthorized(req) {
1805
+ if (!AUTH_TOKEN) return false;
1806
+ const header = req.headers["authorization"] || "";
1807
+ const presented = header.startsWith("Bearer ") ? header.slice(7) : "";
1808
+ if (!presented) return false;
1809
+ const a = Buffer.from(presented);
1810
+ const b = Buffer.from(AUTH_TOKEN);
1811
+ return a.length === b.length && timingSafeEqual(a, b);
1812
+ }
1813
+
1749
1814
  const liveRuns = new Map();
1750
1815
 
1751
1816
  // The SDK's default spawn does \`existsSync(pathToClaudeCodeExecutable)\`
@@ -1982,6 +2047,14 @@ const server = http.createServer((req, res) => {
1982
2047
  res.end(VERSION);
1983
2048
  return;
1984
2049
  }
2050
+ // Capability-token gate for every run-control route. The /__version probe
2051
+ // above stays open: it carries no secret and the host probes it over
2052
+ // loopback (no bearer) to detect daemon liveness/version.
2053
+ if (!isAuthorized(req)) {
2054
+ res.writeHead(401, { "content-type": "text/plain" });
2055
+ res.end("unauthorized");
2056
+ return;
2057
+ }
1985
2058
  const url = req.url ?? "";
1986
2059
  let m;
1987
2060
  if (req.method === "POST" && (m = url.match(/^\\/runs\\/([^/]+)\\/start$/))) {
@@ -2052,6 +2125,11 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
2052
2125
  );
2053
2126
  return;
2054
2127
  }
2128
+ const daemonToken = await resolveCapabilityToken(
2129
+ sandbox,
2130
+ DAEMON_TOKEN_PATH,
2131
+ true
2132
+ );
2055
2133
  const daemonDir = path8.posix.dirname(DAEMON_PATH);
2056
2134
  const daemonNodeModules = `${daemonDir}/node_modules/@anthropic-ai`;
2057
2135
  const launchCommand = [
@@ -2059,13 +2137,18 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
2059
2137
  `if [ -z "$NPM_ROOT" ] || [ ! -d "$NPM_ROOT/@anthropic-ai/claude-agent-sdk" ]; then echo "claude-code daemon launch: @anthropic-ai/claude-agent-sdk not found under $NPM_ROOT" >&2; exit 1; fi`,
2060
2138
  `mkdir -p ${shellQuote(daemonNodeModules)}`,
2061
2139
  `ln -sfn "$NPM_ROOT/@anthropic-ai/claude-agent-sdk" ${shellQuote(daemonNodeModules + "/claude-agent-sdk")}`,
2140
+ // The base uploadAndRun only chmods execute-bit artifacts, so the 0600
2141
+ // tarball mode is dropped on Daytona (and other non-Modal providers).
2142
+ // Tighten the just-written token file explicitly — matching codex —
2143
+ // so the bearer is never group/world-readable inside the sandbox.
2144
+ `chmod 600 ${shellQuote(DAEMON_TOKEN_PATH)}`,
2062
2145
  `if [ -f ${shellQuote(DAEMON_PID_PATH)} ]; then kill -TERM "$(cat ${shellQuote(DAEMON_PID_PATH)})" 2>/dev/null || true; fi`,
2063
2146
  `(fuser -k -n tcp ${DAEMON_PORT} 2>/dev/null || true)`,
2064
2147
  // Brief grace so the kernel releases the port before the new
2065
2148
  // daemon's listen() — only matters on warm-sandbox respawns;
2066
2149
  // adds 200ms otherwise.
2067
2150
  `sleep 0.2`,
2068
- `(nohup node ${shellQuote(DAEMON_PATH)} ${DAEMON_PORT} > ${shellQuote(DAEMON_LOG_PATH)} 2>&1 & echo $! > ${shellQuote(DAEMON_PID_PATH)})`
2151
+ `(nohup node ${shellQuote(DAEMON_PATH)} ${DAEMON_PORT} ${shellQuote(DAEMON_TOKEN_PATH)} > ${shellQuote(DAEMON_LOG_PATH)} 2>&1 & echo $! > ${shellQuote(DAEMON_PID_PATH)})`
2069
2152
  ].join(" && ");
2070
2153
  const launch = await time(
2071
2154
  debugRelay,
@@ -2076,6 +2159,11 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
2076
2159
  path: DAEMON_PATH,
2077
2160
  content: createClaudeCodeDaemonScript(),
2078
2161
  mode: 420
2162
+ },
2163
+ {
2164
+ path: DAEMON_TOKEN_PATH,
2165
+ content: daemonToken,
2166
+ mode: 384
2079
2167
  }
2080
2168
  ],
2081
2169
  launchCommand,
@@ -2171,6 +2259,10 @@ async function daemonBaseUrl(sandbox) {
2171
2259
  const url = await sandbox.getPreviewLink(DAEMON_PORT);
2172
2260
  return url.replace(/\/$/, "");
2173
2261
  }
2262
+ async function daemonAuthHeaders(sandbox) {
2263
+ const token = await resolveCapabilityToken(sandbox, DAEMON_TOKEN_PATH, false);
2264
+ return withBearerToken(sandbox.previewHeaders, token);
2265
+ }
2174
2266
  var ClaudeCodeAgentAdapter = class {
2175
2267
  /**
2176
2268
  * Sandbox-side preparation. Uploads `.claude/` artifacts and ensures
@@ -2181,6 +2273,24 @@ var ClaudeCodeAgentAdapter = class {
2181
2273
  * match what we'd produce, we skip the artifact upload AND the daemon
2182
2274
  * boot entirely.
2183
2275
  */
2276
+ /**
2277
+ * Explicit, developer-invoked teardown of the in-sandbox claude-code
2278
+ * relay daemon (see {@link AgentProviderAdapter.killServer}). agentbox
2279
+ * never calls this on its own. Best-effort and idempotent: a no-op when
2280
+ * the daemon isn't running or no sandbox is configured. After it returns
2281
+ * the next `setup()` re-spawns the daemon (its `/__version` probe fails).
2282
+ */
2283
+ async killServer(request) {
2284
+ const sandbox = request.options.sandbox;
2285
+ if (!sandbox) return;
2286
+ await sandbox.run(
2287
+ [
2288
+ `if [ -f ${shellQuote(DAEMON_PID_PATH)} ]; then kill -TERM "$(cat ${shellQuote(DAEMON_PID_PATH)})" 2>/dev/null || true; rm -f ${shellQuote(DAEMON_PID_PATH)}; fi`,
2289
+ `fuser -k -n tcp ${DAEMON_PORT} 2>/dev/null || true`
2290
+ ].join("; "),
2291
+ { cwd: request.options.cwd, timeoutMs: 1e4 }
2292
+ ).catch(() => void 0);
2293
+ }
2184
2294
  async setup(request) {
2185
2295
  await time(debugClaude, "claude-code setup()", async () => {
2186
2296
  const options = request.options;
@@ -2205,12 +2315,19 @@ var ClaudeCodeAgentAdapter = class {
2205
2315
  () => prepareSkillArtifacts(provider, options.skills, target.layout)
2206
2316
  );
2207
2317
  const hookSettings = buildClaudeHookSettings(hooks) ?? {};
2318
+ const workflowSettings = buildClaudeWorkflowSettings(
2319
+ options.provider?.ultracode
2320
+ );
2321
+ const claudeSettings = { ...hookSettings, ...workflowSettings };
2208
2322
  const mcpConfigJson = buildClaudeMcpConfig(options.mcps) ?? JSON.stringify({ mcpServers: {} }, null, 2);
2209
2323
  const artifacts = [
2210
2324
  ...skillArtifacts,
2211
2325
  ...buildClaudeCommandArtifacts(options.commands, target.layout),
2212
2326
  ...buildClaudeSubagentArtifacts(options.subAgents, target.layout),
2213
- { path: settingsPath, content: JSON.stringify(hookSettings, null, 2) },
2327
+ {
2328
+ path: settingsPath,
2329
+ content: JSON.stringify(claudeSettings, null, 2)
2330
+ },
2214
2331
  { path: mcpConfigPath, content: mcpConfigJson }
2215
2332
  ];
2216
2333
  const enableRtk = options.enableRtk === true;
@@ -2279,6 +2396,7 @@ var ClaudeCodeAgentAdapter = class {
2279
2396
  "getPreviewLink daemon",
2280
2397
  () => daemonBaseUrl(sandbox)
2281
2398
  );
2399
+ const authHeaders = await daemonAuthHeaders(sandbox);
2282
2400
  const startUrl = `${baseUrl}/runs/${encodeURIComponent(request.runId)}/start`;
2283
2401
  const sdkOptions = buildClaudeQueryOptions({
2284
2402
  request,
@@ -2310,7 +2428,7 @@ var ClaudeCodeAgentAdapter = class {
2310
2428
  try {
2311
2429
  await fetch(
2312
2430
  `${baseUrl}/runs/${encodeURIComponent(request.runId)}/abort`,
2313
- { method: "POST", headers: sandbox.previewHeaders }
2431
+ { method: "POST", headers: authHeaders }
2314
2432
  );
2315
2433
  } catch {
2316
2434
  }
@@ -2327,7 +2445,7 @@ var ClaudeCodeAgentAdapter = class {
2327
2445
  method: "POST",
2328
2446
  headers: {
2329
2447
  "content-type": "application/json",
2330
- ...sandbox.previewHeaders
2448
+ ...authHeaders
2331
2449
  },
2332
2450
  body: JSON.stringify({ content: mapped })
2333
2451
  }
@@ -2342,7 +2460,7 @@ var ClaudeCodeAgentAdapter = class {
2342
2460
  signal: fetchAbort.signal,
2343
2461
  headers: {
2344
2462
  "content-type": "application/json",
2345
- ...sandbox.previewHeaders
2463
+ ...authHeaders
2346
2464
  },
2347
2465
  body: JSON.stringify(requestBody)
2348
2466
  })
@@ -2570,6 +2688,7 @@ var ClaudeCodeAgentAdapter = class {
2570
2688
  */
2571
2689
  async attachAbort(request) {
2572
2690
  const baseUrl = await daemonBaseUrl(request.sandbox);
2691
+ const authHeaders = await daemonAuthHeaders(request.sandbox);
2573
2692
  const controller = new AbortController();
2574
2693
  const timeout = setTimeout(() => controller.abort(), 3e3);
2575
2694
  try {
@@ -2578,7 +2697,7 @@ var ClaudeCodeAgentAdapter = class {
2578
2697
  {
2579
2698
  method: "POST",
2580
2699
  signal: controller.signal,
2581
- headers: request.sandbox.previewHeaders
2700
+ headers: authHeaders
2582
2701
  }
2583
2702
  ).catch((error) => {
2584
2703
  debugClaude("attachAbort POST failed: %o", error);
@@ -2595,6 +2714,7 @@ var ClaudeCodeAgentAdapter = class {
2595
2714
  */
2596
2715
  async attachSendMessage(request, content) {
2597
2716
  const baseUrl = await daemonBaseUrl(request.sandbox);
2717
+ const authHeaders = await daemonAuthHeaders(request.sandbox);
2598
2718
  const inputParts = await validateProviderUserInput(
2599
2719
  AgentProvider.ClaudeCode,
2600
2720
  content
@@ -2606,7 +2726,7 @@ var ClaudeCodeAgentAdapter = class {
2606
2726
  method: "POST",
2607
2727
  headers: {
2608
2728
  "content-type": "application/json",
2609
- ...request.sandbox.previewHeaders
2729
+ ...authHeaders
2610
2730
  },
2611
2731
  body: JSON.stringify({ content: mapped })
2612
2732
  }
@@ -2620,7 +2740,7 @@ var ClaudeCodeAgentAdapter = class {
2620
2740
  };
2621
2741
 
2622
2742
  // src/agents/providers/codex.ts
2623
- import crypto from "crypto";
2743
+ import crypto2 from "crypto";
2624
2744
  import path9 from "path";
2625
2745
 
2626
2746
  // src/agents/transports/app-server.ts
@@ -2877,7 +2997,7 @@ function resolveCodexAppServerToken(sandbox, tokenFilePath, create) {
2877
2997
  return existing;
2878
2998
  }
2879
2999
  if (create) {
2880
- return crypto.randomBytes(32).toString("hex");
3000
+ return crypto2.randomBytes(32).toString("hex");
2881
3001
  }
2882
3002
  throw new Error(
2883
3003
  `Codex app-server token file is missing at ${tokenFilePath}. setup() must run before connecting to the codex app-server.`
@@ -3573,10 +3693,34 @@ async function buildCodexInputItems(options, inputParts) {
3573
3693
  );
3574
3694
  return inputItems;
3575
3695
  }
3696
+ async function killCodexAppServer(request) {
3697
+ const { options } = request;
3698
+ const sandbox = options.sandbox;
3699
+ if (!sandbox) return;
3700
+ const sharedTarget = await createSetupTarget(
3701
+ request.provider,
3702
+ REMOTE_CODEX_APP_SERVER_ID,
3703
+ options
3704
+ );
3705
+ const pidFilePath = path9.posix.join(
3706
+ sharedTarget.layout.rootDir,
3707
+ "codex-app-server.pid"
3708
+ );
3709
+ await sandbox.run(
3710
+ [
3711
+ `if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || true; rm -f ${shellQuote(pidFilePath)}; fi`,
3712
+ `fuser -k -n tcp ${REMOTE_CODEX_APP_SERVER_PORT} 2>/dev/null || true`
3713
+ ].join("; "),
3714
+ { cwd: options.cwd, timeoutMs: 1e4 }
3715
+ ).catch(() => void 0);
3716
+ }
3576
3717
  var CodexAgentAdapter = class {
3577
3718
  async setup(request) {
3578
3719
  await setupCodex(request);
3579
3720
  }
3721
+ async killServer(request) {
3722
+ await killCodexAppServer(request);
3723
+ }
3580
3724
  async execute(request, sink) {
3581
3725
  const executeStartedAt = Date.now();
3582
3726
  debugCodex("execute() start runId=%s", request.runId);
@@ -3925,6 +4069,37 @@ var LOCAL_OPENCODE_PORT = 4096;
3925
4069
  var SANDBOX_OPENCODE_READY_TIMEOUT_MS = 9e4;
3926
4070
  var LOCAL_OPENCODE_READY_TIMEOUT_MS = 2e4;
3927
4071
  var SHARED_OPENCODE_TARGET_ID = "shared-opencode-server";
4072
+ var OPENCODE_AUTH_USERNAME = "opencode";
4073
+ function opencodeServerTokenPath() {
4074
+ return path10.posix.join(
4075
+ agentboxRoot(AgentProvider.OpenCode, true),
4076
+ "opencode-auth-token"
4077
+ );
4078
+ }
4079
+ function opencodeCurlAuthArg() {
4080
+ return `-u "opencode:$(cat ${shellQuote(opencodeServerTokenPath())} 2>/dev/null)"`;
4081
+ }
4082
+ function opencodeHealthCurl(port) {
4083
+ return `curl -fsS --max-time 2 ${opencodeCurlAuthArg()} http://127.0.0.1:${port}/global/health >/dev/null 2>&1`;
4084
+ }
4085
+ async function isSandboxOpenCodeServerAuthEnforced(sandbox, cwd, port) {
4086
+ const probe = await sandbox.run(
4087
+ `test "$(curl -s -o /dev/null -w '%{http_code}' --max-time 2 http://127.0.0.1:${port}/global/health)" = "401"`,
4088
+ { cwd, timeoutMs: 5e3 }
4089
+ ).catch(() => void 0);
4090
+ return probe?.exitCode === 0;
4091
+ }
4092
+ async function opencodeAuthHeaders(sandbox) {
4093
+ const token = await resolveCapabilityToken(
4094
+ sandbox,
4095
+ opencodeServerTokenPath(),
4096
+ false
4097
+ );
4098
+ const basic = Buffer.from(`${OPENCODE_AUTH_USERNAME}:${token}`).toString(
4099
+ "base64"
4100
+ );
4101
+ return { ...sandbox.previewHeaders, Authorization: `Basic ${basic}` };
4102
+ }
3928
4103
  var LLM_API_KEY_ENV_VARS = [
3929
4104
  "OPENROUTER_API_KEY",
3930
4105
  "OPENAI_API_KEY",
@@ -3975,10 +4150,10 @@ async function killSandboxOpenCodeServer(sandbox, pidFilePath, cwd, port) {
3975
4150
  ).catch(() => void 0);
3976
4151
  const deadline = Date.now() + 5e3;
3977
4152
  while (Date.now() < deadline) {
3978
- const probe = await sandbox.run(
3979
- `curl -fsS --max-time 2 http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
3980
- { cwd, timeoutMs: 5e3 }
3981
- );
4153
+ const probe = await sandbox.run(opencodeHealthCurl(port), {
4154
+ cwd,
4155
+ timeoutMs: 5e3
4156
+ });
3982
4157
  if (probe.exitCode !== 0) {
3983
4158
  return;
3984
4159
  }
@@ -4118,6 +4293,12 @@ async function ensureSandboxOpenCodeServer(request) {
4118
4293
  SHARED_OPENCODE_TARGET_ID,
4119
4294
  options
4120
4295
  );
4296
+ const serverTokenPath = opencodeServerTokenPath();
4297
+ const serverToken = await resolveCapabilityToken(
4298
+ sandbox,
4299
+ serverTokenPath,
4300
+ true
4301
+ );
4121
4302
  const { artifacts: skillArtifacts, installCommands } = await prepareSkillArtifacts(
4122
4303
  request.provider,
4123
4304
  options.skills,
@@ -4135,10 +4316,18 @@ async function ensureSandboxOpenCodeServer(request) {
4135
4316
  {
4136
4317
  path: configPath,
4137
4318
  content: JSON.stringify(openCodeConfig, null, 2)
4319
+ },
4320
+ {
4321
+ path: serverTokenPath,
4322
+ content: serverToken
4138
4323
  }
4139
4324
  ];
4140
4325
  const enableRtk = options.enableRtk === true;
4141
- const daemonInfo = { port, healthPath: "/global/health" };
4326
+ const daemonInfo = {
4327
+ port,
4328
+ healthPath: "/global/health",
4329
+ curlAuthArg: opencodeCurlAuthArg()
4330
+ };
4142
4331
  const setupId = computeSetupId({
4143
4332
  artifacts: allArtifacts,
4144
4333
  installCommands,
@@ -4152,6 +4341,17 @@ async function ensureSandboxOpenCodeServer(request) {
4152
4341
  debugOpencode("opencode setup() preflight hit \u2014 skipping");
4153
4342
  return;
4154
4343
  }
4344
+ if (await isSandboxOpenCodeServerHealthy(sandbox, options.cwd, port)) {
4345
+ if (await isSandboxOpenCodeServerAuthEnforced(sandbox, options.cwd, port)) {
4346
+ debugOpencode(
4347
+ "opencode server already running but setup drifted \u2014 reusing it without restart; call agent.killServer() to apply the new config"
4348
+ );
4349
+ return;
4350
+ }
4351
+ debugOpencode(
4352
+ "opencode server running without capability auth \u2014 restarting to enforce it"
4353
+ );
4354
+ }
4155
4355
  const commonEnv = {
4156
4356
  OPENCODE_CONFIG: configPath,
4157
4357
  OPENCODE_CONFIG_DIR: target.layout.opencodeDir,
@@ -4170,9 +4370,18 @@ async function ensureSandboxOpenCodeServer(request) {
4170
4370
  target.layout.rootDir,
4171
4371
  "opencode-serve.log"
4172
4372
  );
4173
- const serveEnv = { ...options.env ?? {}, ...commonEnv };
4373
+ const serveEnv = {
4374
+ ...options.env ?? {},
4375
+ ...commonEnv,
4376
+ // Native opencode HTTP basic auth. The host presents this token on
4377
+ // every request (see opencodeAuthHeaders); the in-sandbox health probes
4378
+ // present it too (see opencodeHealthCurl).
4379
+ OPENCODE_SERVER_USERNAME: OPENCODE_AUTH_USERNAME,
4380
+ OPENCODE_SERVER_PASSWORD: serverToken
4381
+ };
4174
4382
  const launchCommand = [
4175
4383
  `mkdir -p ${shellQuote(target.layout.rootDir)}`,
4384
+ `chmod 600 ${shellQuote(serverTokenPath)} 2>/dev/null || true`,
4176
4385
  `(${[
4177
4386
  `setsid nohup ${[
4178
4387
  binary,
@@ -4215,10 +4424,10 @@ async function ensureSandboxOpenCodeServer(request) {
4215
4424
  );
4216
4425
  }
4217
4426
  while (Date.now() < readyDeadline) {
4218
- const probe = await sandbox.run(
4219
- `curl -fsS http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
4220
- { cwd: options.cwd, timeoutMs: 5e3 }
4221
- );
4427
+ const probe = await sandbox.run(opencodeHealthCurl(port), {
4428
+ cwd: options.cwd,
4429
+ timeoutMs: 5e3
4430
+ });
4222
4431
  if (probe.exitCode === 0) {
4223
4432
  debugOpencode("ready on attempt %d", attempt);
4224
4433
  return true;
@@ -4260,6 +4469,18 @@ opencode log:
4260
4469
  ${lastLog}` : "")
4261
4470
  );
4262
4471
  }
4472
+ if (!await isSandboxOpenCodeServerAuthEnforced(sandbox, options.cwd, port)) {
4473
+ await killSandboxOpenCodeServer(
4474
+ sandbox,
4475
+ pidFilePath,
4476
+ options.cwd,
4477
+ port
4478
+ ).catch(() => void 0);
4479
+ await target.cleanup().catch(() => void 0);
4480
+ throw new Error(
4481
+ "OpenCode server started but is not enforcing the capability token (OPENCODE_SERVER_PASSWORD ignored). Upgrade opencode-ai to a version that supports server authentication."
4482
+ );
4483
+ }
4263
4484
  await markSetupComplete(target, setupId);
4264
4485
  });
4265
4486
  }
@@ -4311,7 +4532,13 @@ async function ensureLocalOpenCodeServer(request) {
4311
4532
  debugOpencode("local opencode server up-to-date \u2014 reusing");
4312
4533
  return;
4313
4534
  }
4314
- debugOpencode("local opencode server drifted/absent \u2014 (re)spawning");
4535
+ if (await isLocalOpenCodeServerHealthy()) {
4536
+ debugOpencode(
4537
+ "local opencode server already running but setup drifted \u2014 reusing it without restart; call agent.killServer() to apply the new config"
4538
+ );
4539
+ return;
4540
+ }
4541
+ debugOpencode("local opencode server absent \u2014 spawning");
4315
4542
  await applyDifferentialSetup(target, allArtifacts, installCommands);
4316
4543
  await killLocalOpenCodeServer();
4317
4544
  spawnCommand({
@@ -4344,13 +4571,49 @@ async function setupOpenCode(request) {
4344
4571
  }
4345
4572
  await ensureLocalOpenCodeServer(request);
4346
4573
  }
4574
+ async function isSandboxOpenCodeServerHealthy(sandbox, cwd, port) {
4575
+ const probe = await sandbox.run(opencodeHealthCurl(port), { cwd, timeoutMs: 5e3 }).catch(() => void 0);
4576
+ return probe?.exitCode === 0;
4577
+ }
4578
+ async function isLocalOpenCodeServerHealthy() {
4579
+ try {
4580
+ const res = await fetch(
4581
+ `http://127.0.0.1:${LOCAL_OPENCODE_PORT}/global/health`
4582
+ );
4583
+ return res.ok;
4584
+ } catch {
4585
+ return false;
4586
+ }
4587
+ }
4588
+ async function killOpenCodeServer(request) {
4589
+ const { options } = request;
4590
+ if (options.sandbox) {
4591
+ const target = await createSetupTarget(
4592
+ request.provider,
4593
+ SHARED_OPENCODE_TARGET_ID,
4594
+ options
4595
+ );
4596
+ const pidFilePath = path10.posix.join(
4597
+ target.layout.rootDir,
4598
+ "opencode-serve.pid"
4599
+ );
4600
+ await killSandboxOpenCodeServer(
4601
+ options.sandbox,
4602
+ pidFilePath,
4603
+ options.cwd,
4604
+ SANDBOX_OPENCODE_PORT
4605
+ );
4606
+ return;
4607
+ }
4608
+ await killLocalOpenCodeServer();
4609
+ }
4347
4610
  async function buildOpenCodeRuntime(options) {
4348
4611
  if (options.sandbox) {
4349
4612
  const sandbox = options.sandbox;
4350
4613
  const baseUrl2 = (await sandbox.getPreviewLink(SANDBOX_OPENCODE_PORT)).replace(/\/$/, "");
4351
4614
  return {
4352
4615
  baseUrl: baseUrl2,
4353
- previewHeaders: sandbox.previewHeaders,
4616
+ previewHeaders: await opencodeAuthHeaders(sandbox),
4354
4617
  raw: { baseUrl: baseUrl2, port: SANDBOX_OPENCODE_PORT }
4355
4618
  };
4356
4619
  }
@@ -4365,6 +4628,9 @@ var OpenCodeAgentAdapter = class {
4365
4628
  async setup(request) {
4366
4629
  await setupOpenCode(request);
4367
4630
  }
4631
+ async killServer(request) {
4632
+ await killOpenCodeServer(request);
4633
+ }
4368
4634
  async execute(request, sink) {
4369
4635
  const executeStartedAt = Date.now();
4370
4636
  debugOpencode("execute() start runId=%s", request.runId);
@@ -4881,6 +5147,7 @@ var OpenCodeAgentAdapter = class {
4881
5147
  );
4882
5148
  }
4883
5149
  const baseUrl = (await request.sandbox.getPreviewLink(SANDBOX_OPENCODE_PORT)).replace(/\/$/, "");
5150
+ const authHeaders = await opencodeAuthHeaders(request.sandbox);
4884
5151
  const controller = new AbortController();
4885
5152
  const timeout = setTimeout(() => controller.abort(), 3e3);
4886
5153
  try {
@@ -4889,7 +5156,7 @@ var OpenCodeAgentAdapter = class {
4889
5156
  signal: controller.signal,
4890
5157
  headers: {
4891
5158
  "content-type": "application/json",
4892
- ...request.sandbox.previewHeaders
5159
+ ...authHeaders
4893
5160
  }
4894
5161
  }).catch((error) => {
4895
5162
  debugOpencode(
@@ -4920,12 +5187,13 @@ var OpenCodeAgentAdapter = class {
4920
5187
  content
4921
5188
  );
4922
5189
  const parts = mapToOpenCodeParts(inputParts);
5190
+ const authHeaders = await opencodeAuthHeaders(request.sandbox);
4923
5191
  const url = `${baseUrl}/session/${request.sessionId}/prompt_async`;
4924
5192
  const response = await fetch(url, {
4925
5193
  method: "POST",
4926
5194
  headers: {
4927
5195
  "content-type": "application/json",
4928
- ...request.sandbox.previewHeaders
5196
+ ...authHeaders
4929
5197
  },
4930
5198
  body: JSON.stringify({
4931
5199
  agent: openCodeAgentSlug(void 0),
@@ -5353,6 +5621,30 @@ var Agent = class {
5353
5621
  throw error;
5354
5622
  }
5355
5623
  }
5624
+ /**
5625
+ * Stop the long-lived provider CLI server booted by {@link Agent.setup}
5626
+ * (claude-code relay daemon, codex app-server, opencode `serve`).
5627
+ *
5628
+ * agentbox NEVER kills a running server on its own — not on run
5629
+ * completion, not on `abort()`, and not when {@link Agent.setup} detects
5630
+ * a changed config/credential set. This method is the single, explicit,
5631
+ * developer-driven teardown. Call it to free a server's resources, or to
5632
+ * apply a changed config: after `killServer()` the next {@link setup}
5633
+ * cold-starts a fresh server with the new configuration.
5634
+ *
5635
+ * Best-effort and idempotent: a no-op when no server is running, or when
5636
+ * the provider has no shared server for the current mode (host-mode
5637
+ * claude-code runs the SDK in-process; local codex spawns a fresh
5638
+ * app-server per run, torn down with the run).
5639
+ */
5640
+ async killServer() {
5641
+ debugAgent("killServer() provider=%s", this.provider);
5642
+ await this.adapter.killServer({
5643
+ provider: this.provider,
5644
+ options: this.options
5645
+ });
5646
+ this.setupPromise = void 0;
5647
+ }
5356
5648
  stream(runConfig) {
5357
5649
  if (runConfig.resumeSessionId && runConfig.forkSessionId) {
5358
5650
  throw new Error(
@@ -251,6 +251,20 @@ function resolveSandboxResources(resources) {
251
251
  }
252
252
 
253
253
  // src/sandboxes/providers/daytona.ts
254
+ var STARTABLE_STATES = /* @__PURE__ */ new Set(["stopped", "archived"]);
255
+ var TERMINAL_STATES = /* @__PURE__ */ new Set([
256
+ "error",
257
+ "build_failed",
258
+ "destroyed",
259
+ "destroying"
260
+ ]);
261
+ var ATTACH_SETTLE_TIMEOUT_MS = 12e4;
262
+ var ATTACH_POLL_INTERVAL_MS = 2e3;
263
+ function isStateChangeInProgressError(err) {
264
+ const e = err;
265
+ if (!e) return false;
266
+ return e.statusCode === 409 || e.name === "DaytonaConflictError" || /state change in progress/i.test(e.message ?? "");
267
+ }
254
268
  var DaytonaSandboxAdapter = class extends SandboxAdapter {
255
269
  client;
256
270
  sandbox;
@@ -292,20 +306,54 @@ var DaytonaSandboxAdapter = class extends SandboxAdapter {
292
306
  throw new Error(`Daytona sandbox ${id} not found`);
293
307
  }
294
308
  this.sandbox = existing;
295
- const state = existing.state ?? "unknown";
296
- const isWarm = state === "started";
297
- if (!isWarm) {
298
- await existing.start();
309
+ this.isWarmFlag = existing.state === "started";
310
+ await this.ensureStarted(existing);
311
+ }
312
+ /**
313
+ * Bring a sandbox to the `started` state, tolerating in-flight transitions.
314
+ *
315
+ * `start()` only works from a resting state (`stopped`/`archived`); calling
316
+ * it while the sandbox is creating/starting/restoring/snapshotting/etc. — or
317
+ * racing another caller that's already starting it — makes Daytona 409 with
318
+ * "Sandbox state change in progress". So we poll: start from a resting
319
+ * state, wait out a transition, fail fast on a terminal state, and treat a
320
+ * 409 as "someone else is mid-transition" and keep waiting.
321
+ */
322
+ async ensureStarted(sandbox) {
323
+ let current = sandbox;
324
+ const deadline = Date.now() + ATTACH_SETTLE_TIMEOUT_MS;
325
+ for (; ; ) {
326
+ const state = current.state ?? "unknown";
327
+ if (state === "started") return;
328
+ if (TERMINAL_STATES.has(state)) {
329
+ throw new Error(
330
+ `Daytona sandbox ${current.id} is in a terminal state: ${state}`
331
+ );
332
+ }
333
+ if (STARTABLE_STATES.has(state)) {
334
+ try {
335
+ await current.start();
336
+ return;
337
+ } catch (err) {
338
+ if (!isStateChangeInProgressError(err)) throw err;
339
+ }
340
+ }
341
+ if (Date.now() >= deadline) {
342
+ throw new Error(
343
+ `Timed out waiting for Daytona sandbox ${current.id} to start (state=${state})`
344
+ );
345
+ }
346
+ await sleep(ATTACH_POLL_INTERVAL_MS);
347
+ current = await this.client.get(current.id);
348
+ this.sandbox = current;
299
349
  }
300
- this.isWarmFlag = isWarm;
301
350
  }
302
351
  async provision() {
303
352
  const existing = await this.findMatchingSandbox();
304
353
  if (existing) {
305
354
  this.sandbox = existing;
306
- const isWarm = existing.state === "started";
307
- await existing.start();
308
- this.isWarmFlag = isWarm;
355
+ this.isWarmFlag = existing.state === "started";
356
+ await this.ensureStarted(existing);
309
357
  return;
310
358
  }
311
359
  const labels = this.getLabels();
@@ -1,4 +1,4 @@
1
- export { A as AISDKEvent, R as MessageCompletedEvent, S as MessageInjectedEvent, T as MessageStartedEvent, U as NormalizedAgentEvent, V as NormalizedAgentEventBase, W as NormalizedAgentEventType, a1 as PermissionRequestedEvent, a2 as PermissionResolvedEvent, a3 as RawAgentEvent, a4 as ReasoningDeltaEvent, a6 as RunCancelledEvent, a7 as RunCompletedEvent, a8 as RunErrorEvent, a9 as RunStartedEvent, ab as TextDeltaEvent, ad as ToolCallCompletedEvent, ae as ToolCallDeltaEvent, af as ToolCallStartedEvent, ai as createNormalizedEvent, aj as normalizeRawAgentEvent, ak as toAISDKEvent, al as toAISDKStream } from '../types-DG4J_zMT.js';
1
+ export { A as AISDKEvent, R as MessageCompletedEvent, S as MessageInjectedEvent, T as MessageStartedEvent, U as NormalizedAgentEvent, V as NormalizedAgentEventBase, W as NormalizedAgentEventType, a1 as PermissionRequestedEvent, a2 as PermissionResolvedEvent, a3 as RawAgentEvent, a4 as ReasoningDeltaEvent, a6 as RunCancelledEvent, a7 as RunCompletedEvent, a8 as RunErrorEvent, a9 as RunStartedEvent, ab as TextDeltaEvent, ad as ToolCallCompletedEvent, ae as ToolCallDeltaEvent, af as ToolCallStartedEvent, ai as createNormalizedEvent, aj as normalizeRawAgentEvent, ak as toAISDKEvent, al as toAISDKStream } from '../types-vOsvzkcO.js';
2
2
  import { AgentProvider } from '../enums.js';
3
3
  import '../Sandbox-DcKAU-E3.js';
4
4
  import 'e2b';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AISDKEvent, a as AgentApprovalMode, b as AgentAttachRequest, c as AgentCommandConfig, d as AgentCostData, e as AgentExecutionRequest, f as AgentLocalMcpConfig, g as AgentMcpConfig, h as AgentOptions, i as AgentOptionsBase, j as AgentOptionsMap, k as AgentPermissionDecision, l as AgentPermissionKind, m as AgentPermissionResponse, n as AgentProviderAdapter, o as AgentProviderName, p as AgentReasoningEffort, q as AgentRemoteMcpConfig, r as AgentResult, s as AgentRun, t as AgentRunConfig, u as AgentRunSink, v as AgentSetupRequest, w as AgentSkillConfig, x as AgentSubAgentConfig, y as AttachedRun, C as ClaudeCodeAgentOptions, z as ClaudeCodeHookConfig, B as ClaudeCodeHookEvent, D as ClaudeCodeHookHandler, E as ClaudeCodeHookMatcherGroup, F as ClaudeCodeHooksConfig, G as ClaudeCodeProviderOptions, H as CodexAgentOptions, I as CodexCommandHook, J as CodexHookEvent, K as CodexHookMatcherGroup, L as CodexHooksConfig, M as CodexProviderOptions, N as DataContent, O as EmbeddedSkillConfig, P as FilePart, Q as ImagePart, R as MessageCompletedEvent, S as MessageInjectedEvent, T as MessageStartedEvent, U as NormalizedAgentEvent, V as NormalizedAgentEventBase, W as NormalizedAgentEventType, X as OpenCodeAgentOptions, Y as OpenCodePluginConfig, Z as OpenCodePluginEvent, _ as OpenCodePluginHookConfig, $ as OpenCodeProviderOptions, a0 as OpenRouterPlugin, a1 as PermissionRequestedEvent, a2 as PermissionResolvedEvent, a3 as RawAgentEvent, a4 as ReasoningDeltaEvent, a5 as RepoSkillConfig, a6 as RunCancelledEvent, a7 as RunCompletedEvent, a8 as RunErrorEvent, a9 as RunStartedEvent, aa as SetupLayout, ab as TextDeltaEvent, ac as TextPart, ad as ToolCallCompletedEvent, ae as ToolCallDeltaEvent, af as ToolCallStartedEvent, ag as UserContent, ah as UserContentPart, ai as createNormalizedEvent, aj as normalizeRawAgentEvent, ak as toAISDKEvent, al as toAISDKStream } from './types-DG4J_zMT.js';
1
+ export { A as AISDKEvent, a as AgentApprovalMode, b as AgentAttachRequest, c as AgentCommandConfig, d as AgentCostData, e as AgentExecutionRequest, f as AgentLocalMcpConfig, g as AgentMcpConfig, h as AgentOptions, i as AgentOptionsBase, j as AgentOptionsMap, k as AgentPermissionDecision, l as AgentPermissionKind, m as AgentPermissionResponse, n as AgentProviderAdapter, o as AgentProviderName, p as AgentReasoningEffort, q as AgentRemoteMcpConfig, r as AgentResult, s as AgentRun, t as AgentRunConfig, u as AgentRunSink, v as AgentSetupRequest, w as AgentSkillConfig, x as AgentSubAgentConfig, y as AttachedRun, C as ClaudeCodeAgentOptions, z as ClaudeCodeHookConfig, B as ClaudeCodeHookEvent, D as ClaudeCodeHookHandler, E as ClaudeCodeHookMatcherGroup, F as ClaudeCodeHooksConfig, G as ClaudeCodeProviderOptions, H as CodexAgentOptions, I as CodexCommandHook, J as CodexHookEvent, K as CodexHookMatcherGroup, L as CodexHooksConfig, M as CodexProviderOptions, N as DataContent, O as EmbeddedSkillConfig, P as FilePart, Q as ImagePart, R as MessageCompletedEvent, S as MessageInjectedEvent, T as MessageStartedEvent, U as NormalizedAgentEvent, V as NormalizedAgentEventBase, W as NormalizedAgentEventType, X as OpenCodeAgentOptions, Y as OpenCodePluginConfig, Z as OpenCodePluginEvent, _ as OpenCodePluginHookConfig, $ as OpenCodeProviderOptions, a0 as OpenRouterPlugin, a1 as PermissionRequestedEvent, a2 as PermissionResolvedEvent, a3 as RawAgentEvent, a4 as ReasoningDeltaEvent, a5 as RepoSkillConfig, a6 as RunCancelledEvent, a7 as RunCompletedEvent, a8 as RunErrorEvent, a9 as RunStartedEvent, aa as SetupLayout, ab as TextDeltaEvent, ac as TextPart, ad as ToolCallCompletedEvent, ae as ToolCallDeltaEvent, af as ToolCallStartedEvent, ag as UserContent, ah as UserContentPart, ai as createNormalizedEvent, aj as normalizeRawAgentEvent, ak as toAISDKEvent, al as toAISDKStream } from './types-vOsvzkcO.js';
2
2
  export { AGENT_RESERVED_PORTS, Agent, agentboxRoot, collectAllAgentReservedPorts, getAgentLayout } from './agents/index.js';
3
3
  export { A as AsyncCommandHandle, C as CommandEvent, a as CommandOptions, b as CommandResult, D as DaytonaProviderOptions, c as DaytonaSandboxOptions, E as E2bProviderOptions, d as E2bSandboxOptions, G as GitCloneOptions, L as LocalDockerProviderOptions, e as LocalDockerSandboxOptions, M as ModalProviderOptions, f as ModalSandboxOptions, S as Sandbox, g as SandboxDescriptor, h as SandboxListOptions, i as SandboxOptions, j as SandboxOptionsBase, k as SandboxOptionsMap, l as SandboxProviderName, m as SandboxRaw, n as SandboxRawMap, o as SandboxResourceSpec, T as TarballEntry, V as VercelGitSource, p as VercelProviderOptions, q as VercelSandboxOptions } from './Sandbox-DcKAU-E3.js';
4
4
  export { SandboxAdapter, buildGitCloneCommand } from './sandboxes/index.js';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  Agent,
3
3
  agentboxRoot,
4
4
  getAgentLayout
5
- } from "./chunk-ZK5PDWOI.js";
5
+ } from "./chunk-KFMFNBVC.js";
6
6
  import {
7
7
  ProviderLogAssembler,
8
8
  createNormalizedEvent,
@@ -14,7 +14,7 @@ import {
14
14
  Sandbox,
15
15
  SandboxAdapter,
16
16
  buildGitCloneCommand
17
- } from "./chunk-T4AS2WEF.js";
17
+ } from "./chunk-TUBBWIOM.js";
18
18
  import {
19
19
  AGENT_RESERVED_PORTS,
20
20
  collectAllAgentReservedPorts
@@ -2,7 +2,7 @@ import {
2
2
  Sandbox,
3
3
  SandboxAdapter,
4
4
  buildGitCloneCommand
5
- } from "../chunk-T4AS2WEF.js";
5
+ } from "../chunk-TUBBWIOM.js";
6
6
  import "../chunk-AVXJMCBC.js";
7
7
  import "../chunk-NSJM57Z4.js";
8
8
  import {
@@ -418,6 +418,18 @@ interface ClaudeCodeProviderOptions {
418
418
  * silence them when hook noise drowns out the rest of the event stream.
419
419
  */
420
420
  includeHookEvents?: boolean;
421
+ /**
422
+ * Enable "ultracode" for claude-code runs: xhigh reasoning effort plus
423
+ * standing dynamic-workflow orchestration (the built-in `Workflow` tool).
424
+ *
425
+ * When `true`, agentbox writes `enableWorkflows: true` + `ultracode: true`
426
+ * into the managed `settings.json` and forces `effort: "xhigh"` on the query.
427
+ *
428
+ * Requires an xhigh-capable model (e.g. Opus) and a recent runtime — the
429
+ * Workflows feature shipped around Claude Code 2.1.154 / Agent SDK 0.3.149.
430
+ * On older CLIs the settings keys are simply ignored.
431
+ */
432
+ ultracode?: boolean;
421
433
  }
422
434
  interface CodexAgentOptions extends AgentOptionsBase {
423
435
  provider?: CodexProviderOptions;
@@ -599,6 +611,22 @@ interface AgentProviderAdapter<P extends AgentProviderName = AgentProviderName>
599
611
  * is already listening.
600
612
  */
601
613
  setup(request: AgentSetupRequest<P>): Promise<void>;
614
+ /**
615
+ * Stop the long-lived provider CLI server that {@link setup} boots
616
+ * (claude-code relay daemon, codex app-server, opencode `serve`).
617
+ *
618
+ * agentbox NEVER calls this on its own — not on run completion, not on
619
+ * abort, and not when {@link setup} sees a changed config/credential
620
+ * set. It exists purely so a developer can explicitly tear a server
621
+ * down (to reclaim resources, or to force the changed config to apply
622
+ * on the next cold {@link setup}).
623
+ *
624
+ * Best-effort and idempotent: a no-op when nothing is running, or when
625
+ * the provider has no shared server for the current mode (host-mode
626
+ * claude-code runs the SDK in-process; local codex spawns a fresh
627
+ * app-server per run).
628
+ */
629
+ killServer(request: AgentSetupRequest<P>): Promise<void>;
602
630
  execute(request: AgentExecutionRequest<P>, sink: AgentRunSink): Promise<() => Promise<void> | void>;
603
631
  /**
604
632
  * Stateless abort. Dial the in-sandbox provider server, issue the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbox-sdk",
3
- "version": "0.1.322",
3
+ "version": "0.1.400",
4
4
  "description": "Swappable coding agents and sandbox providers for Bun and TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {