agentbox-sdk 0.1.400 → 0.1.501

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.
package/README.md CHANGED
@@ -145,6 +145,62 @@ await agent.run({
145
145
 
146
146
  `xhigh` requires a model that supports it (e.g. Claude Opus 4.7+, Codex `gpt-5.4`).
147
147
 
148
+ ### Open-source & custom models (OpenRouter, OSS)
149
+
150
+ Codex isn't limited to OpenAI models — it can route through any
151
+ OpenAI-compatible endpoint (OpenRouter, a local Ollama/LM Studio/vLLM
152
+ server, a proxy). Just like the opencode provider lights up OpenRouter
153
+ from `OPENROUTER_API_KEY`, the codex provider does too: set the key in the
154
+ agent env and pass an OpenRouter model slug.
155
+
156
+ ```ts
157
+ const agent = new Agent("codex", {
158
+ sandbox,
159
+ cwd: "/workspace",
160
+ approvalMode: "auto",
161
+ env: { OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY! },
162
+ });
163
+
164
+ await agent.run({
165
+ model: "openai/gpt-5.3-codex", // any OpenRouter model slug
166
+ input: "Explain the project structure.",
167
+ });
168
+ ```
169
+
170
+ When `OPENROUTER_API_KEY` is present (and `OPENAI_API_KEY` is not), AgentBox
171
+ auto-registers an `openrouter` model provider pointing at
172
+ `https://openrouter.ai/api/v1` and selects it. Override the endpoint with
173
+ `OPENROUTER_BASE_URL`.
174
+
175
+ For any other OpenAI-compatible endpoint, declare providers explicitly via
176
+ `provider.modelProviders` and pick one with `provider.modelProvider`:
177
+
178
+ ```ts
179
+ new Agent("codex", {
180
+ sandbox,
181
+ cwd: "/workspace",
182
+ env: { TOGETHER_API_KEY: process.env.TOGETHER_API_KEY! },
183
+ provider: {
184
+ modelProvider: "together",
185
+ modelProviders: {
186
+ together: {
187
+ name: "Together",
188
+ baseUrl: "https://api.together.xyz/v1",
189
+ envKey: "TOGETHER_API_KEY",
190
+ wireApi: "responses", // codex removed the "chat" wire API
191
+ },
192
+ },
193
+ },
194
+ });
195
+ ```
196
+
197
+ These are written into Codex's `config.toml` as `[model_providers.*]`
198
+ blocks, which the codex app-server reads via `CODEX_HOME`. The model slug
199
+ stays a per-run value; the provider is agent-level config. Note that codex
200
+ dropped the Chat Completions wire API in early 2026 — providers must speak
201
+ the Responses API (`wire_api = "responses"`), which OpenRouter and LM
202
+ Studio support; chat-only backends need a responses→chat proxy.
203
+
148
204
  ## Sandboxes
149
205
 
150
206
  Five sandbox providers are supported. Each gives you an isolated environment with the same interface:
@@ -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-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';
1
+ import { o as AgentProviderName, h as AgentOptions, t as AgentRunConfig, s as AgentRun, r as AgentResult, a4 as RawAgentEvent, b as AgentAttachRequest, y as AttachedRun, ab as SetupLayout } from '../types-1seasIwq.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 CodexModelProviderConfig, N as CodexProviderOptions, O as DataContent, P as EmbeddedSkillConfig, Q as FilePart, R as ImagePart, Y as OpenCodeAgentOptions, Z as OpenCodePluginConfig, _ as OpenCodePluginEvent, $ as OpenCodePluginHookConfig, a0 as OpenCodeProviderOptions, a1 as OpenRouterPlugin, a6 as RepoSkillConfig, ad as TextPart, ah as UserContent, ai as UserContentPart } from '../types-1seasIwq.js';
3
3
  import { S as Sandbox } from '../Sandbox-DcKAU-E3.js';
4
4
  export { AgentProvider } from '../enums.js';
5
5
  import 'e2b';
@@ -2,7 +2,7 @@ import {
2
2
  Agent,
3
3
  agentboxRoot,
4
4
  getAgentLayout
5
- } from "../chunk-KFMFNBVC.js";
5
+ } from "../chunk-2FCUUUXG.js";
6
6
  import "../chunk-775FIGGL.js";
7
7
  import {
8
8
  AGENT_RESERVED_PORTS,
@@ -705,6 +705,47 @@ function tomlString(value) {
705
705
  function tomlStringArray(values) {
706
706
  return `[${values.map(tomlString).join(", ")}]`;
707
707
  }
708
+ function tomlInlineTable(values) {
709
+ const entries = Object.entries(values).map(
710
+ ([key, value]) => `${tomlString(key)} = ${tomlString(value)}`
711
+ );
712
+ return `{ ${entries.join(", ")} }`;
713
+ }
714
+ function appendCodexModelProviderBlock(blocks, id, cfg) {
715
+ assertSafeTomlKey(id, "Model provider");
716
+ blocks.push(`[model_providers.${id}]`);
717
+ blocks.push(`name = ${tomlString(cfg.name ?? id)}`);
718
+ if (cfg.baseUrl) {
719
+ blocks.push(`base_url = ${tomlString(cfg.baseUrl)}`);
720
+ }
721
+ if (cfg.envKey) {
722
+ blocks.push(`env_key = ${tomlString(cfg.envKey)}`);
723
+ }
724
+ if (cfg.wireApi) {
725
+ blocks.push(`wire_api = ${tomlString(cfg.wireApi)}`);
726
+ }
727
+ if (cfg.queryParams && Object.keys(cfg.queryParams).length > 0) {
728
+ blocks.push(`query_params = ${tomlInlineTable(cfg.queryParams)}`);
729
+ }
730
+ if (cfg.httpHeaders && Object.keys(cfg.httpHeaders).length > 0) {
731
+ blocks.push(`http_headers = ${tomlInlineTable(cfg.httpHeaders)}`);
732
+ }
733
+ if (cfg.envHttpHeaders && Object.keys(cfg.envHttpHeaders).length > 0) {
734
+ blocks.push(`env_http_headers = ${tomlInlineTable(cfg.envHttpHeaders)}`);
735
+ }
736
+ if (cfg.requestMaxRetries !== void 0) {
737
+ blocks.push(`request_max_retries = ${Math.trunc(cfg.requestMaxRetries)}`);
738
+ }
739
+ if (cfg.streamMaxRetries !== void 0) {
740
+ blocks.push(`stream_max_retries = ${Math.trunc(cfg.streamMaxRetries)}`);
741
+ }
742
+ if (cfg.streamIdleTimeoutMs !== void 0) {
743
+ blocks.push(
744
+ `stream_idle_timeout_ms = ${Math.trunc(cfg.streamIdleTimeoutMs)}`
745
+ );
746
+ }
747
+ blocks.push("");
748
+ }
708
749
  function buildClaudeMcpConfig(mcps) {
709
750
  if (!mcps || mcps.length === 0) {
710
751
  return void 0;
@@ -780,13 +821,27 @@ function buildCodexConfigToml(opts = {}) {
780
821
  enableHooks = false,
781
822
  enableSkills = false,
782
823
  enableMultiAgent = false,
783
- openAiBaseUrl
824
+ openAiBaseUrl,
825
+ model,
826
+ modelProvider,
827
+ modelProviders
784
828
  } = opts;
785
829
  const blocks = [];
786
830
  if (openAiBaseUrl) {
787
831
  blocks.push(`openai_base_url = ${tomlString(openAiBaseUrl)}`);
788
832
  blocks.push("");
789
833
  }
834
+ if (model) {
835
+ blocks.push(`model = ${tomlString(model)}`);
836
+ blocks.push("");
837
+ }
838
+ if (modelProvider) {
839
+ blocks.push(`model_provider = ${tomlString(modelProvider)}`);
840
+ blocks.push("");
841
+ }
842
+ for (const [id, cfg] of Object.entries(modelProviders ?? {})) {
843
+ appendCodexModelProviderBlock(blocks, id, cfg);
844
+ }
790
845
  for (const mcp of mcps ?? []) {
791
846
  if (mcp.enabled === false) {
792
847
  continue;
@@ -1463,7 +1518,7 @@ function mapOpenCodeTools(tools) {
1463
1518
  }
1464
1519
  return Object.fromEntries(tools.map((tool) => [tool, true]));
1465
1520
  }
1466
- function buildOpenCodeSubagentConfig(subAgents) {
1521
+ function buildOpenCodeSubagentConfig(subAgents, permission) {
1467
1522
  return Object.fromEntries(
1468
1523
  (subAgents ?? []).map((subAgent) => [
1469
1524
  subAgent.name,
@@ -1471,12 +1526,19 @@ function buildOpenCodeSubagentConfig(subAgents) {
1471
1526
  mode: "subagent",
1472
1527
  description: subAgent.description,
1473
1528
  prompt: subAgent.instructions,
1529
+ ...permission ? { permission } : {},
1530
+ // opencode reads a per-agent `model` as a "<providerID>/<modelID>"
1531
+ // string (e.g. "openrouter/deepseek/deepseek-v4-flash"). Without it,
1532
+ // the sub-agent silently inherits the orchestrator's model instead of
1533
+ // the one it was configured with — unlike claude-code (frontmatter
1534
+ // `model`) and codex (TOML `model`), which both carry it through.
1535
+ ...subAgent.model ? { model: subAgent.model } : {},
1474
1536
  ...mapOpenCodeTools(subAgent.tools) ? { tools: mapOpenCodeTools(subAgent.tools) } : {}
1475
1537
  }
1476
1538
  ])
1477
1539
  );
1478
1540
  }
1479
- function buildCodexSubagentArtifacts(subAgents, layout) {
1541
+ function buildCodexSubagentArtifacts(subAgents, layout, defaultModel) {
1480
1542
  const artifacts = [];
1481
1543
  const agentSections = [];
1482
1544
  for (const subAgent of subAgents ?? []) {
@@ -1489,8 +1551,9 @@ function buildCodexSubagentArtifacts(subAgents, layout) {
1489
1551
  const tomlLines = [
1490
1552
  `model_instructions_file = ${tomlString2(roleConfigPromptPath)}`
1491
1553
  ];
1492
- if (subAgent.model) {
1493
- tomlLines.push(`model = ${tomlString2(subAgent.model)}`);
1554
+ const model = subAgent.model ?? defaultModel;
1555
+ if (model) {
1556
+ tomlLines.push(`model = ${tomlString2(model)}`);
1494
1557
  }
1495
1558
  tomlLines.push(
1496
1559
  `model_reasoning_effort = ${tomlString2("medium")}`,
@@ -2382,6 +2445,12 @@ var ClaudeCodeAgentAdapter = class {
2382
2445
  // user inside our images.
2383
2446
  IS_SANDBOX: "1"
2384
2447
  };
2448
+ const customHeaders = request.options.customHeaders;
2449
+ if (customHeaders && Object.keys(customHeaders).length > 0) {
2450
+ const serialized = Object.entries(customHeaders).map(([name, value]) => `${name}: ${value}`).join("\n");
2451
+ env.ANTHROPIC_CUSTOM_HEADERS = env.ANTHROPIC_CUSTOM_HEADERS ? `${env.ANTHROPIC_CUSTOM_HEADERS}
2452
+ ${serialized}` : serialized;
2453
+ }
2385
2454
  const inputParts = await time(
2386
2455
  debugClaude,
2387
2456
  "validateProviderUserInput",
@@ -3318,6 +3387,45 @@ async function materializeCodexImage(options, part, index) {
3318
3387
  function resolveCodexOpenAiBaseUrlFromOptions(options) {
3319
3388
  return options.env?.OPENAI_BASE_URL ?? options.provider?.env?.OPENAI_BASE_URL;
3320
3389
  }
3390
+ function codexCredentialEnv(options) {
3391
+ return { ...options.env ?? {}, ...options.provider?.env ?? {} };
3392
+ }
3393
+ function resolveCodexModelProviders(options) {
3394
+ const modelProviders = {
3395
+ ...options.provider?.modelProviders ?? {}
3396
+ };
3397
+ const modelProvider = options.provider?.modelProvider;
3398
+ const customHeaders = options.customHeaders;
3399
+ if (customHeaders && Object.keys(customHeaders).length > 0) {
3400
+ for (const [id, cfg] of Object.entries(modelProviders)) {
3401
+ modelProviders[id] = {
3402
+ ...cfg,
3403
+ httpHeaders: { ...cfg.httpHeaders ?? {}, ...customHeaders }
3404
+ };
3405
+ }
3406
+ }
3407
+ return { modelProviders, modelProvider };
3408
+ }
3409
+ function hashCodexProviderCredentials(options, modelProviders) {
3410
+ const env = codexCredentialEnv(options);
3411
+ const envKeyNames = /* @__PURE__ */ new Set(["OPENAI_API_KEY"]);
3412
+ for (const cfg of Object.values(modelProviders)) {
3413
+ if (cfg.envKey) {
3414
+ envKeyNames.add(cfg.envKey);
3415
+ }
3416
+ for (const envVar of Object.values(cfg.envHttpHeaders ?? {})) {
3417
+ envKeyNames.add(envVar);
3418
+ }
3419
+ }
3420
+ const hasher = crypto2.createHash("sha256");
3421
+ for (const name of [...envKeyNames].sort()) {
3422
+ if (env[name] !== void 0) {
3423
+ hasher.update(`${name}=${env[name]}
3424
+ `);
3425
+ }
3426
+ }
3427
+ return hasher.digest("hex");
3428
+ }
3321
3429
  async function ensureCodexLoginViaConfig(request, target) {
3322
3430
  const options = request.options;
3323
3431
  const openAiApiKey = options.env?.OPENAI_API_KEY ?? options.provider?.env?.OPENAI_API_KEY;
@@ -3402,9 +3510,19 @@ async function setupCodex(request) {
3402
3510
  const provider = request.provider;
3403
3511
  const hooks = assertHooksSupported(provider, options);
3404
3512
  assertCommandsSupported(provider, options.commands);
3513
+ const { modelProviders, modelProvider } = resolveCodexModelProviders(options);
3514
+ const providerCredHash = hashCodexProviderCredentials(
3515
+ options,
3516
+ modelProviders
3517
+ );
3405
3518
  const usesRemoteWebSocket = options.sandbox && options.sandbox.provider !== SandboxProvider.LocalDocker;
3406
3519
  function buildArtifactsFor(layoutTarget) {
3407
- const { artifacts: subAgentArtifacts, agentSections } = buildCodexSubagentArtifacts(options.subAgents, layoutTarget.layout);
3520
+ const defaultModel = options.provider?.defaultModel;
3521
+ const { artifacts: subAgentArtifacts, agentSections } = buildCodexSubagentArtifacts(
3522
+ options.subAgents,
3523
+ layoutTarget.layout,
3524
+ defaultModel
3525
+ );
3408
3526
  const hooksFile = buildCodexHooksFile(hooks);
3409
3527
  const enableMultiAgent = (options.subAgents?.length ?? 0) > 0;
3410
3528
  const enableSkills = (options.skills?.length ?? 0) > 0;
@@ -3415,7 +3533,10 @@ async function setupCodex(request) {
3415
3533
  enableHooks: Boolean(hooksFile),
3416
3534
  enableSkills,
3417
3535
  enableMultiAgent,
3418
- openAiBaseUrl
3536
+ openAiBaseUrl,
3537
+ model: defaultModel,
3538
+ modelProvider,
3539
+ modelProviders
3419
3540
  });
3420
3541
  const artifacts = [...subAgentArtifacts];
3421
3542
  if (configToml) {
@@ -3468,7 +3589,7 @@ async function setupCodex(request) {
3468
3589
  artifacts: [...serverArtifacts, ...skillArtifacts2],
3469
3590
  installCommands: installCommands2,
3470
3591
  daemon: daemonInfo,
3471
- extras: [`enableRtk:${enableRtk2}`]
3592
+ extras: [`enableRtk:${enableRtk2}`, `providerCreds:${providerCredHash}`]
3472
3593
  });
3473
3594
  if (await preflightSetup(sharedTarget, setupId2, daemonInfo)) {
3474
3595
  debugCodex("codex remote setup() preflight hit \u2014 skipping");
@@ -3492,12 +3613,18 @@ async function setupCodex(request) {
3492
3613
  const serverCwd = sharedTarget.layout.rootDir;
3493
3614
  const launchResult = await time(
3494
3615
  debugCodex,
3495
- "launch app-server (probe + spawn-if-cold)",
3616
+ "restart app-server after setup miss",
3496
3617
  () => sandbox.run(
3497
3618
  [
3498
3619
  `mkdir -p ${shellQuote(sharedTarget.layout.rootDir)}`,
3499
- `if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then exit 0; fi`,
3500
- `if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" >/dev/null 2>&1 || true; rm -f ${shellQuote(pidFilePath)}; fi`,
3620
+ [
3621
+ `if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then`,
3622
+ ` if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" >/dev/null 2>&1 || true; else fuser -k -n tcp ${REMOTE_CODEX_APP_SERVER_PORT} >/dev/null 2>&1 || true; fi`,
3623
+ ` for i in 1 2 3 4 5; do if ! curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then break; fi; sleep 0.2; done`,
3624
+ ` if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then if [ -f ${shellQuote(pidFilePath)} ]; then kill -9 "$(cat ${shellQuote(pidFilePath)})" >/dev/null 2>&1 || true; else fuser -k -n tcp ${REMOTE_CODEX_APP_SERVER_PORT} >/dev/null 2>&1 || true; fi; fi`,
3625
+ ` rm -f ${shellQuote(pidFilePath)}`,
3626
+ `fi`
3627
+ ].join("\n"),
3501
3628
  `chmod 600 ${shellQuote(tokenFilePath)}`,
3502
3629
  `(${[
3503
3630
  `nohup ${[
@@ -3554,7 +3681,7 @@ async function setupCodex(request) {
3554
3681
  const setupId = computeSetupId({
3555
3682
  artifacts: allArtifacts,
3556
3683
  installCommands,
3557
- extras: [`enableRtk:${enableRtk}`]
3684
+ extras: [`enableRtk:${enableRtk}`, `providerCreds:${providerCredHash}`]
3558
3685
  });
3559
3686
  if (await preflightSetup(target, setupId)) {
3560
3687
  debugCodex("codex local setup() preflight hit \u2014 skipping");
@@ -4260,6 +4387,8 @@ function buildOpenCodeConfig(options, interactiveApproval) {
4260
4387
  transforms: ["middle-out"],
4261
4388
  ...openRouterPlugins ? { plugins: openRouterPlugins } : {}
4262
4389
  };
4390
+ const customHeaders = options.customHeaders && Object.keys(options.customHeaders).length > 0 ? options.customHeaders : void 0;
4391
+ const headerOpts = customHeaders ? { headers: customHeaders } : {};
4263
4392
  return {
4264
4393
  $schema: "https://opencode.ai/config.json",
4265
4394
  ...mcpConfig ? { mcp: mcpConfig } : {},
@@ -4268,15 +4397,20 @@ function buildOpenCodeConfig(options, interactiveApproval) {
4268
4397
  openrouter: {
4269
4398
  options: {
4270
4399
  baseURL: openRouterBaseUrl || "https://openrouter.ai/api/v1",
4271
- extraBody: openRouterExtraBody
4400
+ extraBody: openRouterExtraBody,
4401
+ ...headerOpts
4272
4402
  }
4273
4403
  },
4274
- ...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl } } } : {}
4404
+ ...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl, ...headerOpts } } } : {},
4405
+ ...customHeaders ? { anthropic: { options: { ...headerOpts } } } : {}
4275
4406
  },
4276
4407
  agent: {
4277
4408
  agentbox: baseAgent,
4278
4409
  ...reasoningVariants,
4279
- ...buildOpenCodeSubagentConfig(options.subAgents)
4410
+ ...buildOpenCodeSubagentConfig(
4411
+ options.subAgents,
4412
+ buildOpenCodePermissionConfig(interactiveApproval)
4413
+ )
4280
4414
  }
4281
4415
  };
4282
4416
  }
@@ -4757,6 +4891,33 @@ var OpenCodeAgentAdapter = class {
4757
4891
  }
4758
4892
  const announcedUserMessageIds = /* @__PURE__ */ new Set();
4759
4893
  const foreignMessageIds = /* @__PURE__ */ new Set();
4894
+ const runSessionIds = /* @__PURE__ */ new Set([sessionId]);
4895
+ const resolveRunSession = async (candidate) => {
4896
+ if (runSessionIds.has(candidate)) return true;
4897
+ try {
4898
+ const sessions = await fetchJson(`${runtime.baseUrl}/session`, {
4899
+ headers: runtime.previewHeaders
4900
+ });
4901
+ if (!Array.isArray(sessions)) return false;
4902
+ const parentById = /* @__PURE__ */ new Map();
4903
+ for (const session of sessions) {
4904
+ if (typeof session?.id === "string" && typeof session?.parentID === "string") {
4905
+ parentById.set(session.id, session.parentID);
4906
+ }
4907
+ }
4908
+ const lineage = [];
4909
+ let cursor = candidate;
4910
+ while (cursor && !runSessionIds.has(cursor) && lineage.length < 16) {
4911
+ lineage.push(cursor);
4912
+ cursor = parentById.get(cursor);
4913
+ }
4914
+ if (!cursor || !runSessionIds.has(cursor)) return false;
4915
+ for (const id of lineage) runSessionIds.add(id);
4916
+ return true;
4917
+ } catch {
4918
+ return false;
4919
+ }
4920
+ };
4760
4921
  sseTask = (async () => {
4761
4922
  try {
4762
4923
  for await (const event of streamSseResilient(
@@ -4790,6 +4951,13 @@ var OpenCodeAgentAdapter = class {
4790
4951
  }
4791
4952
  sink.emitRaw(raw);
4792
4953
  const eventType = typeof payload?.type === "string" ? String(payload.type) : event.event;
4954
+ if (eventType === "session.created" || eventType === "session.updated") {
4955
+ const properties = payload.properties;
4956
+ const info = properties?.info;
4957
+ if (info && typeof info.id === "string" && typeof info.parentID === "string" && runSessionIds.has(info.parentID)) {
4958
+ runSessionIds.add(info.id);
4959
+ }
4960
+ }
4793
4961
  if (eventType === "message.updated") {
4794
4962
  const properties = payload.properties;
4795
4963
  const info = properties?.info;
@@ -4830,7 +4998,8 @@ var OpenCodeAgentAdapter = class {
4830
4998
  }
4831
4999
  if (eventType === "permission.asked") {
4832
5000
  const properties = payload.properties;
4833
- if (properties && typeof properties.sessionID === "string" && properties.sessionID === sessionId) {
5001
+ if (properties && typeof properties.sessionID === "string" && await resolveRunSession(properties.sessionID)) {
5002
+ const askingSessionId = properties.sessionID;
4834
5003
  const permissionEvent = createOpenCodePermissionEvent(
4835
5004
  request,
4836
5005
  raw,
@@ -4841,7 +5010,7 @@ var OpenCodeAgentAdapter = class {
4841
5010
  decision: "allow"
4842
5011
  };
4843
5012
  await fetchJson(
4844
- `${runtime.baseUrl}/session/${sessionId}/permissions/${permissionEvent.requestId}`,
5013
+ `${runtime.baseUrl}/session/${askingSessionId}/permissions/${permissionEvent.requestId}`,
4845
5014
  {
4846
5015
  method: "POST",
4847
5016
  headers: {
@@ -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-vOsvzkcO.js';
1
+ export { A as AISDKEvent, S as MessageCompletedEvent, T as MessageInjectedEvent, U as MessageStartedEvent, V as NormalizedAgentEvent, W as NormalizedAgentEventBase, X as NormalizedAgentEventType, a2 as PermissionRequestedEvent, a3 as PermissionResolvedEvent, a4 as RawAgentEvent, a5 as ReasoningDeltaEvent, a7 as RunCancelledEvent, a8 as RunCompletedEvent, a9 as RunErrorEvent, aa as RunStartedEvent, ac as TextDeltaEvent, ae as ToolCallCompletedEvent, af as ToolCallDeltaEvent, ag as ToolCallStartedEvent, aj as createNormalizedEvent, ak as normalizeRawAgentEvent, al as toAISDKEvent, am as toAISDKStream } from '../types-1seasIwq.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-vOsvzkcO.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 CodexModelProviderConfig, N as CodexProviderOptions, O as DataContent, P as EmbeddedSkillConfig, Q as FilePart, R as ImagePart, S as MessageCompletedEvent, T as MessageInjectedEvent, U as MessageStartedEvent, V as NormalizedAgentEvent, W as NormalizedAgentEventBase, X as NormalizedAgentEventType, Y as OpenCodeAgentOptions, Z as OpenCodePluginConfig, _ as OpenCodePluginEvent, $ as OpenCodePluginHookConfig, a0 as OpenCodeProviderOptions, a1 as OpenRouterPlugin, a2 as PermissionRequestedEvent, a3 as PermissionResolvedEvent, a4 as RawAgentEvent, a5 as ReasoningDeltaEvent, a6 as RepoSkillConfig, a7 as RunCancelledEvent, a8 as RunCompletedEvent, a9 as RunErrorEvent, aa as RunStartedEvent, ab as SetupLayout, ac as TextDeltaEvent, ad as TextPart, ae as ToolCallCompletedEvent, af as ToolCallDeltaEvent, ag as ToolCallStartedEvent, ah as UserContent, ai as UserContentPart, aj as createNormalizedEvent, ak as normalizeRawAgentEvent, al as toAISDKEvent, am as toAISDKStream } from './types-1seasIwq.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-KFMFNBVC.js";
5
+ } from "./chunk-2FCUUUXG.js";
6
6
  import {
7
7
  ProviderLogAssembler,
8
8
  createNormalizedEvent,
@@ -264,6 +264,48 @@ interface CodexHookMatcherGroup {
264
264
  hooks: CodexCommandHook[];
265
265
  }
266
266
  type CodexHooksConfig = Partial<Record<CodexHookEvent, CodexHookMatcherGroup[]>>;
267
+ /**
268
+ * One OpenAI-compatible model provider for Codex, serialized into a
269
+ * `[model_providers.<id>]` block in config.toml. Mirrors codex's
270
+ * `ModelProviderInfo` (which uses snake_case keys and
271
+ * `deny_unknown_fields`) but with the camelCase field names AgentBox
272
+ * exposes publicly. Use it to point Codex at a local Ollama/LM Studio/vLLM
273
+ * server or any other OpenAI-compatible endpoint.
274
+ */
275
+ interface CodexModelProviderConfig {
276
+ /** Friendly display name. Defaults to the provider id when omitted. */
277
+ name?: string;
278
+ /** Base URL of the OpenAI-compatible API (e.g. `http://localhost:8000/v1`). */
279
+ baseUrl?: string;
280
+ /**
281
+ * Name of the environment variable holding the API key. The variable
282
+ * must be present in the agent env (`options.env` / `provider.env`) so
283
+ * the codex process can read it — AgentBox never writes the secret into
284
+ * config.toml.
285
+ */
286
+ envKey?: string;
287
+ /**
288
+ * Wire protocol the endpoint speaks. Codex removed the `"chat"` (Chat
289
+ * Completions) wire API in Feb 2026 and now rejects it at config load,
290
+ * so prefer `"responses"` (the Responses API) — what LM Studio and modern
291
+ * Ollama expose. Omit to use codex's default
292
+ * (`"responses"`). `"chat"` remains in the type only for older codex
293
+ * builds / chat→responses proxies.
294
+ */
295
+ wireApi?: "chat" | "responses" | "responses_websocket";
296
+ /** Extra query-string params appended to every request. */
297
+ queryParams?: Record<string, string>;
298
+ /** Static HTTP headers added to every request. */
299
+ httpHeaders?: Record<string, string>;
300
+ /** HTTP headers whose values come from env vars (header name -> env var name). */
301
+ envHttpHeaders?: Record<string, string>;
302
+ /** Maximum number of times to retry a failed request. */
303
+ requestMaxRetries?: number;
304
+ /** Maximum number of reconnect attempts for a dropped stream. */
305
+ streamMaxRetries?: number;
306
+ /** Idle timeout (ms) before a stalled stream is treated as lost. */
307
+ streamIdleTimeoutMs?: number;
308
+ }
267
309
  type OpenCodePluginEvent = "command.executed" | "file.edited" | "file.watcher.updated" | "installation.updated" | "lsp.client.diagnostics" | "lsp.updated" | "message.part.removed" | "message.part.updated" | "message.removed" | "message.updated" | "permission.asked" | "permission.replied" | "server.connected" | "session.created" | "session.compacted" | "session.deleted" | "session.diff" | "session.error" | "session.idle" | "session.status" | "session.updated" | "todo.updated" | "shell.env" | "tool.execute.after" | "tool.execute.before" | "tui.prompt.append" | "tui.command.execute" | "tui.toast.show" | "experimental.session.compacting";
268
310
  interface OpenCodePluginHookConfig {
269
311
  event: OpenCodePluginEvent;
@@ -367,6 +409,22 @@ interface AgentOptionsBase {
367
409
  * is a no-op when already active. Toggle invalidates the setup cache.
368
410
  */
369
411
  enableRtk?: boolean;
412
+ /**
413
+ * Custom HTTP headers to attach to the agent's outbound LLM API requests.
414
+ *
415
+ * Forwarded per provider via whatever native mechanism each CLI exposes:
416
+ * - claude-code: `ANTHROPIC_CUSTOM_HEADERS` (applies to all Anthropic calls)
417
+ * - codex: `http_headers` on the active `[model_providers.*]` block in
418
+ * config.toml. When Codex falls back to its built-in `openai` provider,
419
+ * there is no provider block to carry headers, so headers are ignored.
420
+ * - open-code: `provider.<id>.options.headers` in the opencode config
421
+ *
422
+ * Typical use: spend-tracking / routing tags for an LLM gateway, e.g.
423
+ * `{ "x-litellm-tags": "task:123" }`. Whether a header actually reaches the
424
+ * upstream depends on the CLI and provider; open-code's config-level headers
425
+ * in particular are subject to upstream support.
426
+ */
427
+ customHeaders?: Record<string, string>;
370
428
  approvalMode?: AgentApprovalMode;
371
429
  mcps?: AgentMcpConfig[];
372
430
  skills?: AgentSkillConfig[];
@@ -379,6 +437,37 @@ interface CodexProviderOptions {
379
437
  brokerEndpoint?: string;
380
438
  useBroker?: boolean;
381
439
  hooks?: CodexHooksConfig;
440
+ /**
441
+ * Extra OpenAI-compatible model providers, written as
442
+ * `[model_providers.<id>]` blocks in Codex's config.toml. Lets Codex
443
+ * talk to a local Ollama/LM Studio/vLLM server or another
444
+ * OpenAI-compatible endpoint.
445
+ */
446
+ modelProviders?: Record<string, CodexModelProviderConfig>;
447
+ /**
448
+ * Top-level `model_provider` written into Codex's config.toml — selects
449
+ * which {@link modelProviders} table Codex routes every run through (the
450
+ * per-run {@link AgentRunConfig.model} stays a plain model slug).
451
+ *
452
+ * When omitted, Codex falls back to its built-in `openai` provider.
453
+ */
454
+ modelProvider?: string;
455
+ /**
456
+ * Default model slug written as the top-level `model` in Codex's
457
+ * config.toml and used as the fallback `model` for any sub-agent
458
+ * ({@link AgentSubAgentConfig}) that does not set its own.
459
+ *
460
+ * Why this exists: when Codex spawns a *named* sub-agent it reloads the
461
+ * child config from the on-disk config-layer stack (config.toml + the
462
+ * role's TOML) and drops the parent turn's runtime model. If neither
463
+ * layer carries a `model`, the child's model resolves to `None` and
464
+ * `spawn_agent` fails service-tier validation with "could not resolve the
465
+ * child model". Setting this guarantees a resolvable model is always on
466
+ * disk. The per-run {@link AgentRunConfig.model} still overrides it for
467
+ * the root turn via `thread/start`; this only backstops role spawns and
468
+ * runs that omit a model.
469
+ */
470
+ defaultModel?: string;
382
471
  /**
383
472
  * When `false`, writes `supports_websockets = false` into Codex's
384
473
  * config.toml. Useful in environments where outbound WebSocket
@@ -641,4 +730,4 @@ interface AgentProviderAdapter<P extends AgentProviderName = AgentProviderName>
641
730
  attachSendMessage(request: AgentAttachRequest<P>, content: UserContent): Promise<void>;
642
731
  }
643
732
 
644
- export { type OpenCodeProviderOptions as $, type AISDKEvent as A, type ClaudeCodeHookEvent as B, type ClaudeCodeAgentOptions as C, type ClaudeCodeHookHandler as D, type ClaudeCodeHookMatcherGroup as E, type ClaudeCodeHooksConfig as F, type ClaudeCodeProviderOptions as G, type CodexAgentOptions as H, type CodexCommandHook as I, type CodexHookEvent as J, type CodexHookMatcherGroup as K, type CodexHooksConfig as L, type CodexProviderOptions as M, type DataContent as N, type EmbeddedSkillConfig as O, type FilePart as P, type ImagePart as Q, type MessageCompletedEvent as R, type MessageInjectedEvent as S, type MessageStartedEvent as T, type NormalizedAgentEvent as U, type NormalizedAgentEventBase as V, type NormalizedAgentEventType as W, type OpenCodeAgentOptions as X, type OpenCodePluginConfig as Y, type OpenCodePluginEvent as Z, type OpenCodePluginHookConfig as _, type AgentApprovalMode as a, type OpenRouterPlugin as a0, type PermissionRequestedEvent as a1, type PermissionResolvedEvent as a2, type RawAgentEvent as a3, type ReasoningDeltaEvent as a4, type RepoSkillConfig as a5, type RunCancelledEvent as a6, type RunCompletedEvent as a7, type RunErrorEvent as a8, type RunStartedEvent as a9, type SetupLayout as aa, type TextDeltaEvent as ab, type TextPart as ac, type ToolCallCompletedEvent as ad, type ToolCallDeltaEvent as ae, type ToolCallStartedEvent as af, type UserContent as ag, type UserContentPart as ah, createNormalizedEvent as ai, normalizeRawAgentEvent as aj, toAISDKEvent as ak, toAISDKStream as al, type AgentAttachRequest as b, type AgentCommandConfig as c, type AgentCostData as d, type AgentExecutionRequest as e, type AgentLocalMcpConfig as f, type AgentMcpConfig as g, type AgentOptions as h, type AgentOptionsBase as i, type AgentOptionsMap as j, type AgentPermissionDecision as k, type AgentPermissionKind as l, type AgentPermissionResponse as m, type AgentProviderAdapter as n, type AgentProviderName as o, type AgentReasoningEffort as p, type AgentRemoteMcpConfig as q, type AgentResult as r, type AgentRun as s, type AgentRunConfig as t, type AgentRunSink as u, type AgentSetupRequest as v, type AgentSkillConfig as w, type AgentSubAgentConfig as x, type AttachedRun as y, type ClaudeCodeHookConfig as z };
733
+ export { type OpenCodePluginHookConfig as $, type AISDKEvent as A, type ClaudeCodeHookEvent as B, type ClaudeCodeAgentOptions as C, type ClaudeCodeHookHandler as D, type ClaudeCodeHookMatcherGroup as E, type ClaudeCodeHooksConfig as F, type ClaudeCodeProviderOptions as G, type CodexAgentOptions as H, type CodexCommandHook as I, type CodexHookEvent as J, type CodexHookMatcherGroup as K, type CodexHooksConfig as L, type CodexModelProviderConfig as M, type CodexProviderOptions as N, type DataContent as O, type EmbeddedSkillConfig as P, type FilePart as Q, type ImagePart as R, type MessageCompletedEvent as S, type MessageInjectedEvent as T, type MessageStartedEvent as U, type NormalizedAgentEvent as V, type NormalizedAgentEventBase as W, type NormalizedAgentEventType as X, type OpenCodeAgentOptions as Y, type OpenCodePluginConfig as Z, type OpenCodePluginEvent as _, type AgentApprovalMode as a, type OpenCodeProviderOptions as a0, type OpenRouterPlugin as a1, type PermissionRequestedEvent as a2, type PermissionResolvedEvent as a3, type RawAgentEvent as a4, type ReasoningDeltaEvent as a5, type RepoSkillConfig as a6, type RunCancelledEvent as a7, type RunCompletedEvent as a8, type RunErrorEvent as a9, type RunStartedEvent as aa, type SetupLayout as ab, type TextDeltaEvent as ac, type TextPart as ad, type ToolCallCompletedEvent as ae, type ToolCallDeltaEvent as af, type ToolCallStartedEvent as ag, type UserContent as ah, type UserContentPart as ai, createNormalizedEvent as aj, normalizeRawAgentEvent as ak, toAISDKEvent as al, toAISDKStream as am, type AgentAttachRequest as b, type AgentCommandConfig as c, type AgentCostData as d, type AgentExecutionRequest as e, type AgentLocalMcpConfig as f, type AgentMcpConfig as g, type AgentOptions as h, type AgentOptionsBase as i, type AgentOptionsMap as j, type AgentPermissionDecision as k, type AgentPermissionKind as l, type AgentPermissionResponse as m, type AgentProviderAdapter as n, type AgentProviderName as o, type AgentReasoningEffort as p, type AgentRemoteMcpConfig as q, type AgentResult as r, type AgentRun as s, type AgentRunConfig as t, type AgentRunSink as u, type AgentSetupRequest as v, type AgentSkillConfig as w, type AgentSubAgentConfig as x, type AttachedRun as y, type ClaudeCodeHookConfig as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbox-sdk",
3
- "version": "0.1.400",
3
+ "version": "0.1.501",
4
4
  "description": "Swappable coding agents and sandbox providers for Bun and TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {