agentbox-sdk 0.1.600 → 0.1.602

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, al as RawAgentEvent, b as AgentAttachRequest, B as AttachedRun, as as SetupLayout, ay as UserContent } from '../types-ChkpU7Lf.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, y as AgentUserAnswer, z as AgentUserQuestion, E as ClaudeCodeAgentOptions, F as ClaudeCodeHookConfig, G as ClaudeCodeHookEvent, H as ClaudeCodeHookHandler, I as ClaudeCodeHookMatcherGroup, J as ClaudeCodeHooksConfig, K as ClaudeCodeProviderOptions, L as CodexAgentOptions, M as CodexCommandHook, N as CodexHookEvent, O as CodexHookMatcherGroup, P as CodexHooksConfig, Q as CodexModelProviderConfig, R as CodexProviderOptions, S as CodexSkillEntry, T as DataContent, U as EmbeddedSkillConfig, V as FilePart, W as HarnessCommandDescriptor, X as HarnessCommandInvocation, Y as HarnessCommandSource, _ as ImagePart, $ as MAX_HARNESS_COMMANDS, a0 as MAX_HARNESS_COMMAND_ARGUMENT_HINT, a1 as MAX_HARNESS_COMMAND_DESCRIPTION, a2 as MAX_HARNESS_COMMAND_NAME, a6 as NativeParkBackgroundWork, ab as OpenCodeAgentOptions, ac as OpenCodeCommandEntry, ad as OpenCodePluginConfig, ae as OpenCodePluginEvent, af as OpenCodePluginHookConfig, ag as OpenCodeProviderOptions, ah as OpenCodeSkillEntry, ai as OpenRouterPlugin, an as RepoSkillConfig, au as TextPart, az as UserContentPart, aA as builtinHarnessCommands, aB as claudeHarnessCommands, aC as codexHarnessCommands, aD as codexSkillMention, aG as openCodeHarnessCommands, aH as parseHarnessCommandInvocation, aI as skillDirective } from '../types-ChkpU7Lf.js';
1
+ import { o as AgentProviderName, h as AgentOptions, t as AgentRunConfig, s as AgentRun, r as AgentResult, al as RawAgentEvent, b as AgentAttachRequest, B as AttachedRun, as as SetupLayout, ay as UserContent } from '../types-B_oR4A4a.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, y as AgentUserAnswer, z as AgentUserQuestion, E as ClaudeCodeAgentOptions, F as ClaudeCodeHookConfig, G as ClaudeCodeHookEvent, H as ClaudeCodeHookHandler, I as ClaudeCodeHookMatcherGroup, J as ClaudeCodeHooksConfig, K as ClaudeCodeProviderOptions, L as CodexAgentOptions, M as CodexCommandHook, N as CodexHookEvent, O as CodexHookMatcherGroup, P as CodexHooksConfig, Q as CodexModelProviderConfig, R as CodexProviderOptions, S as CodexSkillEntry, T as DataContent, U as EmbeddedSkillConfig, V as FilePart, W as HarnessCommandDescriptor, X as HarnessCommandInvocation, Y as HarnessCommandSource, _ as ImagePart, $ as MAX_HARNESS_COMMANDS, a0 as MAX_HARNESS_COMMAND_ARGUMENT_HINT, a1 as MAX_HARNESS_COMMAND_DESCRIPTION, a2 as MAX_HARNESS_COMMAND_NAME, a6 as NativeParkBackgroundWork, ab as OpenCodeAgentOptions, ac as OpenCodeCommandEntry, ad as OpenCodePluginConfig, ae as OpenCodePluginEvent, af as OpenCodePluginHookConfig, ag as OpenCodeProviderOptions, ah as OpenCodeSkillEntry, ai as OpenRouterPlugin, an as RepoSkillConfig, au as TextPart, az as UserContentPart, aA as builtinHarnessCommands, aB as claudeHarnessCommands, aC as codexHarnessCommands, aD as codexSkillMention, aG as openCodeHarnessCommands, aH as parseHarnessCommandInvocation, aI as skillDirective } from '../types-B_oR4A4a.js';
3
3
  import { S as Sandbox } from '../Sandbox-DcKAU-E3.js';
4
4
  export { AgentProvider } from '../enums.js';
5
5
  import 'e2b';
@@ -15,7 +15,7 @@ import {
15
15
  parseHarnessCommandInvocation,
16
16
  resolveHarnessCommand,
17
17
  skillDirective
18
- } from "../chunk-RSURGSVM.js";
18
+ } from "../chunk-UE4LQEL5.js";
19
19
  import "../chunk-AE2FQ6YU.js";
20
20
  import {
21
21
  AGENT_RESERVED_PORTS,
@@ -30,11 +30,11 @@ import {
30
30
  } from "./chunk-GOFJNFAD.js";
31
31
 
32
32
  // src/agents/Agent.ts
33
- import { randomUUID as randomUUID3 } from "crypto";
33
+ import { randomUUID as randomUUID4 } from "crypto";
34
34
  import path12 from "path";
35
35
 
36
36
  // src/agents/providers/claude-code.ts
37
- import { randomUUID } from "crypto";
37
+ import { randomUUID as randomUUID2 } from "crypto";
38
38
 
39
39
  // src/agents/transports/spawn.ts
40
40
  import { execFile, spawn } from "child_process";
@@ -1585,13 +1585,13 @@ async function activateRtk(target) {
1585
1585
  }
1586
1586
 
1587
1587
  // src/agents/config/setup-manifest.ts
1588
- import { createHash } from "crypto";
1588
+ import { createHash, randomUUID } from "crypto";
1589
1589
  import path6 from "path";
1590
1590
  var MANIFEST_FILENAME = "setup-manifest.json";
1591
- var TARGET_MANIFEST_FILENAME = "setup-target.json";
1592
- var INSTALL_SCRIPT_FILENAME = "install.sh";
1591
+ var TARGET_MANIFEST_PREFIX = "setup-target.";
1592
+ var INSTALL_SCRIPT_PREFIX = "install.";
1593
1593
  var SETUP_ID_FILENAME = "setup.id";
1594
- var MANIFEST_VERSION = 1;
1594
+ var MANIFEST_VERSION = 2;
1595
1595
  function hashArtifact(artifact) {
1596
1596
  const hasher = createHash("sha256");
1597
1597
  hasher.update(artifact.executable ? "1" : "0");
@@ -1685,7 +1685,7 @@ ${detail}` : ""}`
1685
1685
  }
1686
1686
  });
1687
1687
  }
1688
- function buildInstallScript(rootDir, installCommandsByKey) {
1688
+ function buildInstallScript(rootDir, targetManifestPath, installCommandsByKey) {
1689
1689
  const commandsB64 = Buffer.from(
1690
1690
  JSON.stringify(installCommandsByKey),
1691
1691
  "utf8"
@@ -1693,7 +1693,7 @@ function buildInstallScript(rootDir, installCommandsByKey) {
1693
1693
  return `#!/usr/bin/env bash
1694
1694
  set -e
1695
1695
  ROOT_DIR=${shellQuote(rootDir)}
1696
- TARGET_MANIFEST="$ROOT_DIR/${TARGET_MANIFEST_FILENAME}"
1696
+ TARGET_MANIFEST=${shellQuote(targetManifestPath)}
1697
1697
  EXISTING_MANIFEST="$ROOT_DIR/${MANIFEST_FILENAME}"
1698
1698
  export TARGET_MANIFEST EXISTING_MANIFEST
1699
1699
 
@@ -1702,7 +1702,8 @@ export TARGET_MANIFEST EXISTING_MANIFEST
1702
1702
  # emits the commands themselves, NUL-separated, so bash never has to
1703
1703
  # deserialize JSON.
1704
1704
  STALE_CMDS_FILE="$(mktemp)"
1705
- trap 'rm -f "$STALE_CMDS_FILE"' EXIT
1705
+ # This run's target manifest and script are per-run files; remove them.
1706
+ trap 'rm -f "$STALE_CMDS_FILE" "$TARGET_MANIFEST" "$0"' EXIT
1706
1707
  COMMANDS_B64=${shellQuote(commandsB64)} \\
1707
1708
  MANIFEST_VERSION=${MANIFEST_VERSION} \\
1708
1709
  python3 - <<'PY' > "$STALE_CMDS_FILE"
@@ -1728,15 +1729,36 @@ stale = [
1728
1729
  for key, hashed in target_cmds.items()
1729
1730
  if commands.get(key) is not None and existing_cmds.get(key) != hashed
1730
1731
  ]
1731
- sys.stdout.write("\\0".join(stale))
1732
+ # Terminate every entry: \`read -d ''\` drops a last entry with no NUL.
1733
+ sys.stdout.write("".join(cmd + "\\0" for cmd in stale))
1732
1734
  PY
1733
1735
 
1736
+ # Run stale commands in parallel, then retry failures one at a time: parallel
1737
+ # \`npx\` calls race on a cold npx cache, and the cache is warm by the retry.
1738
+ FAILED=0
1734
1739
  if [ -s "$STALE_CMDS_FILE" ]; then
1740
+ CMDS=()
1741
+ PIDS=()
1735
1742
  while IFS= read -r -d '' CMD; do
1736
1743
  [ -z "$CMD" ] && continue
1737
1744
  bash -c "$CMD" &
1745
+ CMDS+=("$CMD")
1746
+ PIDS+=("$!")
1738
1747
  done < "$STALE_CMDS_FILE"
1739
- wait
1748
+ for i in "\${!PIDS[@]}"; do
1749
+ if ! wait "\${PIDS[$i]}"; then
1750
+ echo "agentbox install failed, retrying: \${CMDS[$i]}" >&2
1751
+ if ! bash -c "\${CMDS[$i]}"; then
1752
+ echo "agentbox install failed: \${CMDS[$i]}" >&2
1753
+ FAILED=1
1754
+ fi
1755
+ fi
1756
+ done
1757
+ fi
1758
+
1759
+ # Keep the old manifest when an install failed so the next run retries it.
1760
+ if [ "$FAILED" -ne 0 ]; then
1761
+ exit 1
1740
1762
  fi
1741
1763
 
1742
1764
  # Persist target manifest as the new manifest atomically. Doing this last
@@ -1745,7 +1767,7 @@ mv "$TARGET_MANIFEST" "$EXISTING_MANIFEST"
1745
1767
  `;
1746
1768
  }
1747
1769
  async function applyDifferentialSetup(target, artifacts, installCommands) {
1748
- await time(
1770
+ return time(
1749
1771
  debugSetup,
1750
1772
  `applyDifferentialSetup ${target.provider}`,
1751
1773
  async () => {
@@ -1763,7 +1785,16 @@ async function applyDifferentialSetup(target, artifacts, installCommands) {
1763
1785
  ])
1764
1786
  )
1765
1787
  };
1788
+ const runId = randomUUID();
1766
1789
  const rootDir = target.layout.rootDir;
1790
+ const targetManifestPath = path6.posix.join(
1791
+ rootDir,
1792
+ `${TARGET_MANIFEST_PREFIX}${runId}.json`
1793
+ );
1794
+ const installScriptPath = path6.posix.join(
1795
+ rootDir,
1796
+ `${INSTALL_SCRIPT_PREFIX}${runId}.sh`
1797
+ );
1767
1798
  const tarballEntries = [
1768
1799
  ...artifacts.map((artifact) => ({
1769
1800
  path: artifact.path,
@@ -1771,22 +1802,36 @@ async function applyDifferentialSetup(target, artifacts, installCommands) {
1771
1802
  mode: artifact.executable ? 493 : 420
1772
1803
  })),
1773
1804
  {
1774
- path: path6.posix.join(rootDir, TARGET_MANIFEST_FILENAME),
1805
+ path: targetManifestPath,
1775
1806
  content: JSON.stringify(targetForSandbox),
1776
1807
  mode: 420
1777
1808
  },
1778
1809
  {
1779
- path: path6.posix.join(rootDir, INSTALL_SCRIPT_FILENAME),
1780
- content: buildInstallScript(rootDir, installCommandsByKey),
1810
+ path: installScriptPath,
1811
+ content: buildInstallScript(
1812
+ rootDir,
1813
+ targetManifestPath,
1814
+ installCommandsByKey
1815
+ ),
1781
1816
  mode: 493
1782
1817
  }
1783
1818
  ];
1784
- await target.uploadAndRun(
1819
+ const result = await target.uploadAndRun(
1785
1820
  tarballEntries,
1786
- `bash ${shellQuote(path6.posix.join(rootDir, INSTALL_SCRIPT_FILENAME))}`
1821
+ `bash ${shellQuote(installScriptPath)}`
1787
1822
  );
1823
+ if (result.exitCode !== 0) {
1824
+ const output = result.combinedOutput?.trim();
1825
+ console.warn(
1826
+ `[agentbox] ${target.provider} setup install failed (exit ${result.exitCode}); it will be retried on the next setup${output ? `:
1827
+ ${output.slice(-2e3)}` : ""}`
1828
+ );
1829
+ return false;
1830
+ }
1831
+ return true;
1788
1832
  },
1789
- () => ({
1833
+ (ok) => ({
1834
+ ok,
1790
1835
  artifacts: artifacts.length,
1791
1836
  installCommands: installCommands.length
1792
1837
  })
@@ -2148,6 +2193,11 @@ function asArray(value) {
2148
2193
  }
2149
2194
  var SCHEDULE_TOOLS = /* @__PURE__ */ new Set(["CronCreate", "ScheduleWakeup"]);
2150
2195
  var DONE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "killed"]);
2196
+ var SUBAGENT_TASK_TYPES = /* @__PURE__ */ new Set(["local_agent", "local_workflow", "subagent"]);
2197
+ var SUBAGENT_RESULT_GRACE_MS = 6e4;
2198
+ function holdsBackgroundCeiling(tasks, exemptSubagents) {
2199
+ return exemptSubagents === true && tasks.some((task) => SUBAGENT_TASK_TYPES.has(task.type));
2200
+ }
2151
2201
  var BackgroundTaskTracker = class {
2152
2202
  tasks = /* @__PURE__ */ new Map();
2153
2203
  wakeups = /* @__PURE__ */ new Map();
@@ -2326,21 +2376,42 @@ function withTimeout(promise, ms) {
2326
2376
  return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
2327
2377
  }
2328
2378
  var BackgroundWait = class {
2329
- constructor(graceMs, ceilingMs) {
2379
+ constructor(graceMs, ceilingMs, held = false) {
2330
2380
  this.graceMs = graceMs;
2381
+ this.ceilingMs = ceilingMs;
2331
2382
  this.expired = new Promise((resolve) => {
2332
2383
  this.expire = resolve;
2333
2384
  });
2334
- if (Number.isFinite(ceilingMs)) {
2335
- this.ceiling = setTimeout(() => this.expire("ceiling"), Math.min(ceilingMs, MAX_TIMER_MS));
2336
- }
2385
+ if (held) this.heldSince = this.startedAt;
2386
+ else this.armCeiling();
2337
2387
  }
2338
2388
  graceMs;
2389
+ ceilingMs;
2339
2390
  expired;
2340
2391
  expire;
2341
2392
  grace;
2342
2393
  ceiling;
2343
2394
  startedAt = Date.now();
2395
+ heldMs = 0;
2396
+ heldSince;
2397
+ /** Stop the ceiling while a subagent is live; resume it with what is left once none is. */
2398
+ hold(held) {
2399
+ if (held === (this.heldSince !== void 0)) return;
2400
+ if (held) {
2401
+ clearTimeout(this.ceiling);
2402
+ this.ceiling = void 0;
2403
+ this.heldSince = Date.now();
2404
+ return;
2405
+ }
2406
+ this.heldMs += Date.now() - this.heldSince;
2407
+ this.heldSince = void 0;
2408
+ this.armCeiling(SUBAGENT_RESULT_GRACE_MS);
2409
+ }
2410
+ armCeiling(floorMs = 0) {
2411
+ if (!Number.isFinite(this.ceilingMs)) return;
2412
+ const leftMs = Math.max(floorMs, this.ceilingMs - this.elapsedMs());
2413
+ this.ceiling = setTimeout(() => this.expire("ceiling"), Math.min(leftMs, MAX_TIMER_MS));
2414
+ }
2344
2415
  /** Arm the grace timer while nothing is live; disarm it once a task appears. */
2345
2416
  setIdle(idle) {
2346
2417
  if (!idle) {
@@ -2354,8 +2425,11 @@ var BackgroundWait = class {
2354
2425
  finish() {
2355
2426
  this.expire("finished");
2356
2427
  }
2428
+ /** Time counted against the budget: held time excluded. */
2357
2429
  elapsedMs() {
2358
- return Date.now() - this.startedAt;
2430
+ const now = Date.now();
2431
+ const held = this.heldMs + (this.heldSince === void 0 ? 0 : now - this.heldSince);
2432
+ return now - this.startedAt - held;
2359
2433
  }
2360
2434
  clear() {
2361
2435
  clearTimeout(this.grace);
@@ -2408,9 +2482,14 @@ var NativeClaudeSession = class {
2408
2482
  iterator;
2409
2483
  handlers;
2410
2484
  parked;
2411
- // Absolute end of the background budget, carried across parks so a CLI
2412
- // that is adopted and parked again cannot extend its own ceiling.
2413
- parkDeadline = Infinity;
2485
+ // The background budget, carried across parks so a CLI that is adopted and
2486
+ // parked again cannot extend its own ceiling: what was left of it at
2487
+ // `budgetSince`, and it runs from then on. Unset while a subagent holds it.
2488
+ budgetLeftMs = Infinity;
2489
+ budgetSince = Date.now();
2490
+ exemptSubagents = false;
2491
+ // What is live in the CLI, from every message it produces.
2492
+ tasks = new BackgroundTaskTracker();
2414
2493
  buffer = [];
2415
2494
  bufferedBytes = 0;
2416
2495
  bufferedResults = 0;
@@ -2458,30 +2537,59 @@ var NativeClaudeSession = class {
2458
2537
  * Keep the CLI after the attached run settles. `inflight` is a read that
2459
2538
  * run started but never consumed; its message is buffered, not lost.
2460
2539
  */
2461
- park(tasks, ttlMs, parking, inflight) {
2540
+ park(tasks, ttlMs, parking, inflight, options = {}) {
2462
2541
  if (this.ending || !this.iterator) return false;
2463
2542
  this.handlers = void 0;
2464
- this.parkDeadline = Math.min(
2465
- this.parkDeadline,
2466
- Number.isFinite(ttlMs) ? Date.now() + Math.max(0, ttlMs) : Infinity
2543
+ this.budgetLeftMs = Math.min(
2544
+ this.budgetLeft(),
2545
+ Number.isFinite(ttlMs) ? Math.max(0, ttlMs) : Infinity
2467
2546
  );
2468
- const parked = { tasks, parking, waking: false, wokeAt: 0 };
2469
- if (Number.isFinite(this.parkDeadline)) {
2470
- parked.timer = setTimeout(
2471
- () => {
2472
- if (this.parked !== parked) return;
2473
- debugClaude("\u2605 parked CLI ran out of background budget; ending it");
2474
- void this.end();
2475
- },
2476
- Math.min(Math.max(0, this.parkDeadline - Date.now()), 2147483647)
2477
- );
2478
- parked.timer.unref?.();
2479
- }
2480
- this.parked = parked;
2547
+ if (this.budgetSince !== void 0) this.budgetSince = Date.now();
2548
+ this.exemptSubagents = options.exemptSubagents === true;
2549
+ this.parked = { tasks, parking, waking: false, wokeAt: 0 };
2481
2550
  parkedSessions.set(this.sessionId, this);
2551
+ this.updateBudget();
2552
+ this.armBudget();
2482
2553
  void this.pump(inflight);
2483
2554
  return true;
2484
2555
  }
2556
+ budgetLeft() {
2557
+ return this.budgetSince === void 0 ? this.budgetLeftMs : this.budgetLeftMs - (Date.now() - this.budgetSince);
2558
+ }
2559
+ /** Hold the budget while an exempt subagent is live. True when that changed. */
2560
+ updateBudget() {
2561
+ const held = holdsBackgroundCeiling(
2562
+ this.tasks.liveTasks(),
2563
+ this.exemptSubagents
2564
+ );
2565
+ if (held === (this.budgetSince === void 0)) return false;
2566
+ if (held) {
2567
+ this.budgetLeftMs = this.budgetLeft();
2568
+ this.budgetSince = void 0;
2569
+ } else {
2570
+ this.budgetLeftMs = Math.max(this.budgetLeftMs, SUBAGENT_RESULT_GRACE_MS);
2571
+ this.budgetSince = Date.now();
2572
+ }
2573
+ return true;
2574
+ }
2575
+ /** While parked, end the CLI once a running budget is spent. */
2576
+ armBudget() {
2577
+ const parked = this.parked;
2578
+ if (!parked) return;
2579
+ clearTimeout(parked.timer);
2580
+ parked.timer = void 0;
2581
+ if (this.budgetSince === void 0 || !Number.isFinite(this.budgetLeftMs))
2582
+ return;
2583
+ parked.timer = setTimeout(
2584
+ () => {
2585
+ if (this.parked !== parked) return;
2586
+ debugClaude("\u2605 parked CLI ran out of background budget; ending it");
2587
+ void this.end();
2588
+ },
2589
+ Math.min(Math.max(0, this.budgetLeft()), MAX_TIMER_MS)
2590
+ );
2591
+ parked.timer.unref?.();
2592
+ }
2485
2593
  /**
2486
2594
  * A later run takes the parked CLI over: it learns what was live and how
2487
2595
  * many results precede its own turn, then reads what was buffered. An
@@ -2495,7 +2603,8 @@ var NativeClaudeSession = class {
2495
2603
  clearTimeout(parked.timer);
2496
2604
  this.parked = void 0;
2497
2605
  parkedSessions.delete(this.sessionId);
2498
- const budgetLeftMs = Number.isFinite(this.parkDeadline) ? Math.max(0, this.parkDeadline - Date.now()) : null;
2606
+ const left = this.budgetLeft();
2607
+ const budgetLeftMs = Number.isFinite(left) ? Math.max(0, left) : null;
2499
2608
  const preamble = [
2500
2609
  { _parked: { tasks: parked.tasks, turns, budgetLeftMs } },
2501
2610
  ...this.buffer
@@ -2530,6 +2639,8 @@ var NativeClaudeSession = class {
2530
2639
  const { started, ended } = turnEdges(result.value);
2531
2640
  if (started) this.turnActive = true;
2532
2641
  if (ended) this.turnActive = false;
2642
+ this.tasks.ingest(result.value);
2643
+ if (this.updateBudget()) this.armBudget();
2533
2644
  }
2534
2645
  return result;
2535
2646
  });
@@ -3660,7 +3771,7 @@ var ClaudeCodeAgentAdapter = class {
3660
3771
  return;
3661
3772
  }
3662
3773
  const env = { ...options.env ?? {}, ...target.env };
3663
- await Promise.all([
3774
+ const [installed] = await Promise.all([
3664
3775
  time(
3665
3776
  debugClaude,
3666
3777
  "applyDifferentialSetup",
@@ -3671,7 +3782,7 @@ var ClaudeCodeAgentAdapter = class {
3671
3782
  if (enableRtk) {
3672
3783
  await time(debugClaude, "activateRtk", () => activateRtk(target));
3673
3784
  }
3674
- await markSetupComplete(target, setupId);
3785
+ if (installed) await markSetupComplete(target, setupId);
3675
3786
  });
3676
3787
  }
3677
3788
  async execute(request, sink) {
@@ -3709,8 +3820,8 @@ ${serialized}` : serialized;
3709
3820
  () => validateProviderUserInput(request.provider, request.run.input)
3710
3821
  );
3711
3822
  const userContent = mapToClaudeUserContent(inputParts);
3712
- const initialUuid = randomUUID();
3713
- const presetSessionId = request.run.resumeSessionId ?? randomUUID();
3823
+ const initialUuid = randomUUID2();
3824
+ const presetSessionId = request.run.resumeSessionId ?? randomUUID2();
3714
3825
  sink.setSessionId(presetSessionId);
3715
3826
  const baseUrl = await time(
3716
3827
  debugClaude,
@@ -3775,7 +3886,7 @@ ${serialized}` : serialized;
3775
3886
  sink.onMessage(async (content) => {
3776
3887
  const parts = await validateProviderUserInput(request.provider, content);
3777
3888
  const mapped = mapToClaudeUserContent(parts);
3778
- const messageUuid = randomUUID();
3889
+ const messageUuid = randomUUID2();
3779
3890
  await fetch(
3780
3891
  `${baseUrl}/runs/${encodeURIComponent(request.runId)}/sendMessage`,
3781
3892
  {
@@ -4000,6 +4111,10 @@ async function consumeClaudeMessages(request, sink, messages, executeStartedAt,
4000
4111
  const timeoutMs = resolveBackgroundTaskTimeoutMs(
4001
4112
  request.options.backgroundTaskTimeoutMs
4002
4113
  );
4114
+ const holdsCeiling = (live) => holdsBackgroundCeiling(
4115
+ live,
4116
+ request.options.exemptSubagentsFromBackgroundTimeout
4117
+ );
4003
4118
  const graceMs = wait.graceMs ?? BACKGROUND_TASK_GRACE_MS;
4004
4119
  let pendingWait;
4005
4120
  let waitedMs = 0;
@@ -4032,8 +4147,9 @@ async function consumeClaudeMessages(request, sink, messages, executeStartedAt,
4032
4147
  const tryPark = async (inflight) => {
4033
4148
  const live = tracker.liveTasks();
4034
4149
  const ttlMs = budgetLeftMs();
4035
- if (!wait.park || live.length === 0 || isAborted() || ttlMs <= 0)
4036
- return false;
4150
+ const held = holdsCeiling(live);
4151
+ if (!wait.park || live.length === 0 || isAborted()) return false;
4152
+ if (held ? !wait.parkHoldsSubagents : ttlMs <= 0) return false;
4037
4153
  parked = await wait.park(live, ttlMs, inflight).catch(() => false);
4038
4154
  if (parked)
4039
4155
  debugClaude(
@@ -4129,6 +4245,7 @@ async function consumeClaudeMessages(request, sink, messages, executeStartedAt,
4129
4245
  endWait();
4130
4246
  }
4131
4247
  emitTasks(tracker.liveTasks(), pendingWait !== void 0);
4248
+ pendingWait?.hold(holdsCeiling(tracker.liveTasks()));
4132
4249
  const sessionState = message.type === "system" && message.subtype === "session_state_changed" ? message.state : void 0;
4133
4250
  if (sessionState) sawSessionState = true;
4134
4251
  pendingWait?.setIdle(
@@ -4297,7 +4414,11 @@ async function consumeClaudeMessages(request, sink, messages, executeStartedAt,
4297
4414
  );
4298
4415
  endWait();
4299
4416
  pendingWait = finishWait.watch(
4300
- new BackgroundWait(graceMs, Math.max(0, timeoutMs - waitedMs))
4417
+ new BackgroundWait(
4418
+ graceMs,
4419
+ Math.max(0, timeoutMs - waitedMs),
4420
+ holdsCeiling(live)
4421
+ )
4301
4422
  );
4302
4423
  pendingWait.setIdle(!sawSessionState && live.length === 0);
4303
4424
  emitTasks(live, true);
@@ -4396,7 +4517,7 @@ async function executeNativeClaude(request, sink, wait = {}) {
4396
4517
  const input = attachOnly ? [] : await validateProviderUserInput(request.provider, request.run.input);
4397
4518
  const parkOption = request.options.provider?.parkBackgroundWork;
4398
4519
  const parking = parkOption && "onWake" in parkOption ? parkOption : void 0;
4399
- const sessionId = request.run.resumeSessionId ?? randomUUID();
4520
+ const sessionId = request.run.resumeSessionId ?? randomUUID2();
4400
4521
  if (request.run.forkSessionId)
4401
4522
  await findParkedNativeSession(request.run.forkSessionId)?.end();
4402
4523
  const adopting = request.run.resumeSessionId ? findParkedNativeSession(request.run.resumeSessionId) : void 0;
@@ -4413,7 +4534,7 @@ async function executeNativeClaude(request, sink, wait = {}) {
4413
4534
  await stop();
4414
4535
  });
4415
4536
  sink.setSessionId(sessionId);
4416
- const messageId = randomUUID();
4537
+ const messageId = randomUUID2();
4417
4538
  const userMessage = {
4418
4539
  type: "user",
4419
4540
  uuid: messageId,
@@ -4622,7 +4743,10 @@ async function executeNativeClaude(request, sink, wait = {}) {
4622
4743
  );
4623
4744
  },
4624
4745
  ...parking && owned ? {
4625
- park: async (tasks, ttlMs, inflight) => parked = owned.park(tasks, ttlMs, parking, inflight),
4746
+ park: async (tasks, ttlMs, inflight) => parked = owned.park(tasks, ttlMs, parking, inflight, {
4747
+ exemptSubagents: request.options.exemptSubagentsFromBackgroundTimeout
4748
+ }),
4749
+ parkHoldsSubagents: true,
4626
4750
  // The CLI lives on in the session; nothing to let go of.
4627
4751
  detach: async () => void 0
4628
4752
  } : {}
@@ -5631,8 +5755,13 @@ async function setupCodex(request) {
5631
5755
  `Could not start Codex app-server: ${launchResult.combinedOutput || launchResult.stderr}`
5632
5756
  );
5633
5757
  }
5758
+ let installed2;
5634
5759
  try {
5635
- await applyDifferentialSetup(target2, skillArtifacts2, installCommands2);
5760
+ installed2 = await applyDifferentialSetup(
5761
+ target2,
5762
+ skillArtifacts2,
5763
+ installCommands2
5764
+ );
5636
5765
  } catch (error) {
5637
5766
  await target2.cleanup().catch(() => void 0);
5638
5767
  throw error;
@@ -5640,7 +5769,7 @@ async function setupCodex(request) {
5640
5769
  if (enableRtk2) {
5641
5770
  await time(debugCodex, "activateRtk", () => activateRtk(sharedTarget));
5642
5771
  }
5643
- await markSetupComplete(sharedTarget, setupId2);
5772
+ if (installed2) await markSetupComplete(sharedTarget, setupId2);
5644
5773
  return;
5645
5774
  }
5646
5775
  const target = await createSetupTarget(provider, "shared-setup", options);
@@ -5663,11 +5792,15 @@ async function setupCodex(request) {
5663
5792
  await target.cleanup().catch(() => void 0);
5664
5793
  throw error;
5665
5794
  }
5666
- await applyDifferentialSetup(target, allArtifacts, installCommands);
5795
+ const installed = await applyDifferentialSetup(
5796
+ target,
5797
+ allArtifacts,
5798
+ installCommands
5799
+ );
5667
5800
  if (enableRtk) {
5668
5801
  await time(debugCodex, "activateRtk", () => activateRtk(target));
5669
5802
  }
5670
- await markSetupComplete(target, setupId);
5803
+ if (installed) await markSetupComplete(target, setupId);
5671
5804
  }
5672
5805
  async function createRuntime(request, inputParts) {
5673
5806
  const options = request.options;
@@ -6345,7 +6478,7 @@ var CodexAgentAdapter = class {
6345
6478
  };
6346
6479
 
6347
6480
  // src/agents/providers/opencode.ts
6348
- import { createHash as createHash2, randomBytes, randomUUID as randomUUID2 } from "crypto";
6481
+ import { createHash as createHash2, randomBytes, randomUUID as randomUUID3 } from "crypto";
6349
6482
  import os2 from "os";
6350
6483
  import path11 from "path";
6351
6484
  var SANDBOX_OPENCODE_PORT = 4096;
@@ -6690,7 +6823,11 @@ async function ensureSandboxOpenCodeServer(request) {
6690
6823
  OPENCODE_DISABLE_DEFAULT_PLUGINS: "true",
6691
6824
  OPENCODE_ENABLE_QUESTION_TOOL: hasInteractiveQuestions(options) ? "true" : "false"
6692
6825
  };
6693
- await applyDifferentialSetup(target, allArtifacts, installCommands);
6826
+ const installed = await applyDifferentialSetup(
6827
+ target,
6828
+ allArtifacts,
6829
+ installCommands
6830
+ );
6694
6831
  if (enableRtk) {
6695
6832
  await time(debugOpencode, "activateRtk", () => activateRtk(target));
6696
6833
  }
@@ -6814,14 +6951,14 @@ ${lastLog}` : "")
6814
6951
  "OpenCode server started but is not enforcing the capability token (OPENCODE_SERVER_PASSWORD ignored). Upgrade opencode-ai to a version that supports server authentication."
6815
6952
  );
6816
6953
  }
6817
- await markSetupComplete(target, setupId);
6954
+ if (installed) await markSetupComplete(target, setupId);
6818
6955
  });
6819
6956
  }
6820
6957
  async function startLocalOpenCodeServer(request) {
6821
6958
  const originalOptions = request.options;
6822
6959
  const options = {
6823
6960
  ...originalOptions,
6824
- stateDirectory: path11.join(originalOptions.stateDirectory ?? path11.join(os2.tmpdir(), "agentbox-native"), "instances", randomUUID2())
6961
+ stateDirectory: path11.join(originalOptions.stateDirectory ?? path11.join(os2.tmpdir(), "agentbox-native"), "instances", randomUUID3())
6825
6962
  };
6826
6963
  let generatedEnv = {};
6827
6964
  if (options.configuration !== "native") {
@@ -7139,7 +7276,9 @@ var OpenCodeAgentAdapter = class {
7139
7276
  );
7140
7277
  const wait = new BackgroundWait(
7141
7278
  BACKGROUND_TASK_GRACE_MS,
7142
- Math.max(0, backgroundTimeoutMs - waitedMs)
7279
+ Math.max(0, backgroundTimeoutMs - waitedMs),
7280
+ // Every child waited on here is a subagent.
7281
+ request.options.exemptSubagentsFromBackgroundTimeout === true
7143
7282
  );
7144
7283
  pendingWait = wait;
7145
7284
  void wait.expired.then((reason) => {
@@ -8317,7 +8456,7 @@ var Agent = class {
8317
8456
  throw new Error("AgentRunConfig.resumeParked requires resumeSessionId.");
8318
8457
  }
8319
8458
  }
8320
- const runId = runConfig.runId ?? randomUUID3();
8459
+ const runId = runConfig.runId ?? randomUUID4();
8321
8460
  const streamCalledAt = Date.now();
8322
8461
  debugAgent("stream() provider=%s runId=%s", this.provider, runId);
8323
8462
  const run = new AgentRunController(
@@ -1,4 +1,4 @@
1
- export { A as AISDKEvent, C as BackgroundTask, D as BackgroundTasksEvent, Z as HarnessCommandsEvent, a3 as MessageCompletedEvent, a4 as MessageInjectedEvent, a5 as MessageStartedEvent, a7 as NativePlanEvent, a8 as NormalizedAgentEvent, a9 as NormalizedAgentEventBase, aa as NormalizedAgentEventType, aj as PermissionRequestedEvent, ak as PermissionResolvedEvent, al as RawAgentEvent, am as ReasoningDeltaEvent, ao as RunCancelledEvent, ap as RunCompletedEvent, aq as RunErrorEvent, ar as RunStartedEvent, at as TextDeltaEvent, av as ToolCallCompletedEvent, aw as ToolCallDeltaEvent, ax as ToolCallStartedEvent, aE as createNormalizedEvent, aF as normalizeRawAgentEvent, aJ as toAISDKEvent, aK as toAISDKStream } from '../types-ChkpU7Lf.js';
1
+ export { A as AISDKEvent, C as BackgroundTask, D as BackgroundTasksEvent, Z as HarnessCommandsEvent, a3 as MessageCompletedEvent, a4 as MessageInjectedEvent, a5 as MessageStartedEvent, a7 as NativePlanEvent, a8 as NormalizedAgentEvent, a9 as NormalizedAgentEventBase, aa as NormalizedAgentEventType, aj as PermissionRequestedEvent, ak as PermissionResolvedEvent, al as RawAgentEvent, am as ReasoningDeltaEvent, ao as RunCancelledEvent, ap as RunCompletedEvent, aq as RunErrorEvent, ar as RunStartedEvent, at as TextDeltaEvent, av as ToolCallCompletedEvent, aw as ToolCallDeltaEvent, ax as ToolCallStartedEvent, aE as createNormalizedEvent, aF as normalizeRawAgentEvent, aJ as toAISDKEvent, aK as toAISDKStream } from '../types-B_oR4A4a.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 AgentUserAnswer, z as AgentUserQuestion, B as AttachedRun, C as BackgroundTask, D as BackgroundTasksEvent, E as ClaudeCodeAgentOptions, F as ClaudeCodeHookConfig, G as ClaudeCodeHookEvent, H as ClaudeCodeHookHandler, I as ClaudeCodeHookMatcherGroup, J as ClaudeCodeHooksConfig, K as ClaudeCodeProviderOptions, L as CodexAgentOptions, M as CodexCommandHook, N as CodexHookEvent, O as CodexHookMatcherGroup, P as CodexHooksConfig, Q as CodexModelProviderConfig, R as CodexProviderOptions, S as CodexSkillEntry, T as DataContent, U as EmbeddedSkillConfig, V as FilePart, W as HarnessCommandDescriptor, X as HarnessCommandInvocation, Y as HarnessCommandSource, Z as HarnessCommandsEvent, _ as ImagePart, $ as MAX_HARNESS_COMMANDS, a0 as MAX_HARNESS_COMMAND_ARGUMENT_HINT, a1 as MAX_HARNESS_COMMAND_DESCRIPTION, a2 as MAX_HARNESS_COMMAND_NAME, a3 as MessageCompletedEvent, a4 as MessageInjectedEvent, a5 as MessageStartedEvent, a6 as NativeParkBackgroundWork, a7 as NativePlanEvent, a8 as NormalizedAgentEvent, a9 as NormalizedAgentEventBase, aa as NormalizedAgentEventType, ab as OpenCodeAgentOptions, ac as OpenCodeCommandEntry, ad as OpenCodePluginConfig, ae as OpenCodePluginEvent, af as OpenCodePluginHookConfig, ag as OpenCodeProviderOptions, ah as OpenCodeSkillEntry, ai as OpenRouterPlugin, aj as PermissionRequestedEvent, ak as PermissionResolvedEvent, al as RawAgentEvent, am as ReasoningDeltaEvent, an as RepoSkillConfig, ao as RunCancelledEvent, ap as RunCompletedEvent, aq as RunErrorEvent, ar as RunStartedEvent, as as SetupLayout, at as TextDeltaEvent, au as TextPart, av as ToolCallCompletedEvent, aw as ToolCallDeltaEvent, ax as ToolCallStartedEvent, ay as UserContent, az as UserContentPart, aA as builtinHarnessCommands, aB as claudeHarnessCommands, aC as codexHarnessCommands, aD as codexSkillMention, aE as createNormalizedEvent, aF as normalizeRawAgentEvent, aG as openCodeHarnessCommands, aH as parseHarnessCommandInvocation, aI as skillDirective, aJ as toAISDKEvent, aK as toAISDKStream } from './types-ChkpU7Lf.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 AgentUserAnswer, z as AgentUserQuestion, B as AttachedRun, C as BackgroundTask, D as BackgroundTasksEvent, E as ClaudeCodeAgentOptions, F as ClaudeCodeHookConfig, G as ClaudeCodeHookEvent, H as ClaudeCodeHookHandler, I as ClaudeCodeHookMatcherGroup, J as ClaudeCodeHooksConfig, K as ClaudeCodeProviderOptions, L as CodexAgentOptions, M as CodexCommandHook, N as CodexHookEvent, O as CodexHookMatcherGroup, P as CodexHooksConfig, Q as CodexModelProviderConfig, R as CodexProviderOptions, S as CodexSkillEntry, T as DataContent, U as EmbeddedSkillConfig, V as FilePart, W as HarnessCommandDescriptor, X as HarnessCommandInvocation, Y as HarnessCommandSource, Z as HarnessCommandsEvent, _ as ImagePart, $ as MAX_HARNESS_COMMANDS, a0 as MAX_HARNESS_COMMAND_ARGUMENT_HINT, a1 as MAX_HARNESS_COMMAND_DESCRIPTION, a2 as MAX_HARNESS_COMMAND_NAME, a3 as MessageCompletedEvent, a4 as MessageInjectedEvent, a5 as MessageStartedEvent, a6 as NativeParkBackgroundWork, a7 as NativePlanEvent, a8 as NormalizedAgentEvent, a9 as NormalizedAgentEventBase, aa as NormalizedAgentEventType, ab as OpenCodeAgentOptions, ac as OpenCodeCommandEntry, ad as OpenCodePluginConfig, ae as OpenCodePluginEvent, af as OpenCodePluginHookConfig, ag as OpenCodeProviderOptions, ah as OpenCodeSkillEntry, ai as OpenRouterPlugin, aj as PermissionRequestedEvent, ak as PermissionResolvedEvent, al as RawAgentEvent, am as ReasoningDeltaEvent, an as RepoSkillConfig, ao as RunCancelledEvent, ap as RunCompletedEvent, aq as RunErrorEvent, ar as RunStartedEvent, as as SetupLayout, at as TextDeltaEvent, au as TextPart, av as ToolCallCompletedEvent, aw as ToolCallDeltaEvent, ax as ToolCallStartedEvent, ay as UserContent, az as UserContentPart, aA as builtinHarnessCommands, aB as claudeHarnessCommands, aC as codexHarnessCommands, aD as codexSkillMention, aE as createNormalizedEvent, aF as normalizeRawAgentEvent, aG as openCodeHarnessCommands, aH as parseHarnessCommandInvocation, aI as skillDirective, aJ as toAISDKEvent, aK as toAISDKStream } from './types-B_oR4A4a.js';
2
2
  export { AGENT_RESERVED_PORTS, Agent, HarnessCapabilities, HarnessCommand, agentboxRoot, collectAllAgentReservedPorts, getAgentLayout, harnessCapabilities, resolveHarnessCommand } 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
@@ -15,7 +15,7 @@ import {
15
15
  parseHarnessCommandInvocation,
16
16
  resolveHarnessCommand,
17
17
  skillDirective
18
- } from "./chunk-RSURGSVM.js";
18
+ } from "./chunk-UE4LQEL5.js";
19
19
  import {
20
20
  ProviderLogAssembler,
21
21
  createNormalizedEvent,
@@ -625,6 +625,17 @@ interface AgentOptionsBase {
625
625
  * settles immediately.
626
626
  */
627
627
  backgroundTaskTimeoutMs?: number;
628
+ /**
629
+ * Leave background subagents out of {@link backgroundTaskTimeoutMs}: while
630
+ * one is live (Claude Code background agents and workflows, OpenCode
631
+ * background children) the budget does not run, so the ceiling never stops
632
+ * a working subagent. Shells, monitors and scheduled wakeups are still
633
+ * bounded once no subagent is live. Covers the run's own waits and native
634
+ * Claude Code parks; a sandbox run keeps waiting instead of parking while a
635
+ * subagent is live, since the daemon's park TTL cannot be held. Default
636
+ * `false`. `backgroundTaskTimeoutMs: 0` still abandons everything.
637
+ */
638
+ exemptSubagentsFromBackgroundTimeout?: boolean;
628
639
  /**
629
640
  * Keep every normalized and raw event in memory for the life of the run so
630
641
  * {@link AgentResult.events} / {@link AgentResult.rawEvents} can replay it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbox-sdk",
3
- "version": "0.1.600",
3
+ "version": "0.1.602",
4
4
  "description": "Swappable coding agents and sandbox providers for Bun and TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {