agentbox-sdk 0.1.323 → 0.1.500
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 +56 -0
- package/dist/agents/index.d.ts +2 -2
- package/dist/agents/index.js +1 -1
- package/dist/{chunk-XONT46YC.js → chunk-JYI7MRGO.js} +348 -46
- package/dist/events/index.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{types-t01PuLUJ.d.ts → types-1seasIwq.d.ts} +102 -1
- package/package.json +1 -1
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:
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { o as AgentProviderName, h as AgentOptions, t as AgentRunConfig, s as AgentRun, r as AgentResult,
|
|
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
|
|
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';
|
package/dist/agents/index.js
CHANGED
|
@@ -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;
|
|
@@ -702,6 +705,47 @@ function tomlString(value) {
|
|
|
702
705
|
function tomlStringArray(values) {
|
|
703
706
|
return `[${values.map(tomlString).join(", ")}]`;
|
|
704
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
|
+
}
|
|
705
749
|
function buildClaudeMcpConfig(mcps) {
|
|
706
750
|
if (!mcps || mcps.length === 0) {
|
|
707
751
|
return void 0;
|
|
@@ -777,13 +821,27 @@ function buildCodexConfigToml(opts = {}) {
|
|
|
777
821
|
enableHooks = false,
|
|
778
822
|
enableSkills = false,
|
|
779
823
|
enableMultiAgent = false,
|
|
780
|
-
openAiBaseUrl
|
|
824
|
+
openAiBaseUrl,
|
|
825
|
+
model,
|
|
826
|
+
modelProvider,
|
|
827
|
+
modelProviders
|
|
781
828
|
} = opts;
|
|
782
829
|
const blocks = [];
|
|
783
830
|
if (openAiBaseUrl) {
|
|
784
831
|
blocks.push(`openai_base_url = ${tomlString(openAiBaseUrl)}`);
|
|
785
832
|
blocks.push("");
|
|
786
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
|
+
}
|
|
787
845
|
for (const mcp of mcps ?? []) {
|
|
788
846
|
if (mcp.enabled === false) {
|
|
789
847
|
continue;
|
|
@@ -1228,13 +1286,14 @@ async function preflightSetup(target, setupId, daemon) {
|
|
|
1228
1286
|
];
|
|
1229
1287
|
if (daemon) {
|
|
1230
1288
|
const url = `http://127.0.0.1:${daemon.port}${daemon.healthPath}`;
|
|
1289
|
+
const auth = daemon.curlAuthArg ? `${daemon.curlAuthArg} ` : "";
|
|
1231
1290
|
if (daemon.expectedVersionMatch) {
|
|
1232
1291
|
checks.push(
|
|
1233
|
-
`curl -fsS --max-time 2 ${shellQuote(url)} 2>/dev/null | grep -q ${shellQuote(daemon.expectedVersionMatch)}`
|
|
1292
|
+
`curl -fsS --max-time 2 ${auth}${shellQuote(url)} 2>/dev/null | grep -q ${shellQuote(daemon.expectedVersionMatch)}`
|
|
1234
1293
|
);
|
|
1235
1294
|
} else {
|
|
1236
1295
|
checks.push(
|
|
1237
|
-
`curl -fsS --max-time 2 ${shellQuote(url)} >/dev/null 2>&1`
|
|
1296
|
+
`curl -fsS --max-time 2 ${auth}${shellQuote(url)} >/dev/null 2>&1`
|
|
1238
1297
|
);
|
|
1239
1298
|
}
|
|
1240
1299
|
}
|
|
@@ -1467,12 +1526,18 @@ function buildOpenCodeSubagentConfig(subAgents) {
|
|
|
1467
1526
|
mode: "subagent",
|
|
1468
1527
|
description: subAgent.description,
|
|
1469
1528
|
prompt: subAgent.instructions,
|
|
1529
|
+
// opencode reads a per-agent `model` as a "<providerID>/<modelID>"
|
|
1530
|
+
// string (e.g. "openrouter/deepseek/deepseek-v4-flash"). Without it,
|
|
1531
|
+
// the sub-agent silently inherits the orchestrator's model instead of
|
|
1532
|
+
// the one it was configured with — unlike claude-code (frontmatter
|
|
1533
|
+
// `model`) and codex (TOML `model`), which both carry it through.
|
|
1534
|
+
...subAgent.model ? { model: subAgent.model } : {},
|
|
1470
1535
|
...mapOpenCodeTools(subAgent.tools) ? { tools: mapOpenCodeTools(subAgent.tools) } : {}
|
|
1471
1536
|
}
|
|
1472
1537
|
])
|
|
1473
1538
|
);
|
|
1474
1539
|
}
|
|
1475
|
-
function buildCodexSubagentArtifacts(subAgents, layout) {
|
|
1540
|
+
function buildCodexSubagentArtifacts(subAgents, layout, defaultModel) {
|
|
1476
1541
|
const artifacts = [];
|
|
1477
1542
|
const agentSections = [];
|
|
1478
1543
|
for (const subAgent of subAgents ?? []) {
|
|
@@ -1485,8 +1550,9 @@ function buildCodexSubagentArtifacts(subAgents, layout) {
|
|
|
1485
1550
|
const tomlLines = [
|
|
1486
1551
|
`model_instructions_file = ${tomlString2(roleConfigPromptPath)}`
|
|
1487
1552
|
];
|
|
1488
|
-
|
|
1489
|
-
|
|
1553
|
+
const model = subAgent.model ?? defaultModel;
|
|
1554
|
+
if (model) {
|
|
1555
|
+
tomlLines.push(`model = ${tomlString2(model)}`);
|
|
1490
1556
|
}
|
|
1491
1557
|
tomlLines.push(
|
|
1492
1558
|
`model_reasoning_effort = ${tomlString2("medium")}`,
|
|
@@ -1513,6 +1579,46 @@ function buildCodexSubagentArtifacts(subAgents, layout) {
|
|
|
1513
1579
|
};
|
|
1514
1580
|
}
|
|
1515
1581
|
|
|
1582
|
+
// src/agents/config/capability-token.ts
|
|
1583
|
+
import crypto from "crypto";
|
|
1584
|
+
var tokenCache = /* @__PURE__ */ new WeakMap();
|
|
1585
|
+
async function readCapabilityTokenFile(sandbox, tokenFilePath) {
|
|
1586
|
+
const result = await sandbox.run(
|
|
1587
|
+
`if [ -f ${shellQuote(tokenFilePath)} ]; then cat ${shellQuote(tokenFilePath)}; fi`
|
|
1588
|
+
);
|
|
1589
|
+
if (result.exitCode !== 0) return void 0;
|
|
1590
|
+
const value = result.stdout.trim();
|
|
1591
|
+
return value.length > 0 ? value : void 0;
|
|
1592
|
+
}
|
|
1593
|
+
function resolveCapabilityToken(sandbox, tokenFilePath, create) {
|
|
1594
|
+
let byPath = tokenCache.get(sandbox);
|
|
1595
|
+
if (!byPath) {
|
|
1596
|
+
byPath = /* @__PURE__ */ new Map();
|
|
1597
|
+
tokenCache.set(sandbox, byPath);
|
|
1598
|
+
}
|
|
1599
|
+
const map = byPath;
|
|
1600
|
+
let cached = map.get(tokenFilePath);
|
|
1601
|
+
if (!cached) {
|
|
1602
|
+
const pending = (async () => {
|
|
1603
|
+
const existing = await readCapabilityTokenFile(sandbox, tokenFilePath);
|
|
1604
|
+
if (existing) return existing;
|
|
1605
|
+
if (create) return crypto.randomBytes(32).toString("hex");
|
|
1606
|
+
throw new Error(
|
|
1607
|
+
`Capability token file is missing at ${tokenFilePath}. setup() must run before connecting to this sandbox server.`
|
|
1608
|
+
);
|
|
1609
|
+
})().catch((error) => {
|
|
1610
|
+
map.delete(tokenFilePath);
|
|
1611
|
+
throw error;
|
|
1612
|
+
});
|
|
1613
|
+
map.set(tokenFilePath, pending);
|
|
1614
|
+
cached = pending;
|
|
1615
|
+
}
|
|
1616
|
+
return cached;
|
|
1617
|
+
}
|
|
1618
|
+
function withBearerToken(base, token) {
|
|
1619
|
+
return { ...base, Authorization: `Bearer ${token}` };
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1516
1622
|
// src/agents/cost.ts
|
|
1517
1623
|
function addIfNumber(target, key, value) {
|
|
1518
1624
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
@@ -1643,11 +1749,12 @@ function extractOpenCodeCostData(events) {
|
|
|
1643
1749
|
}
|
|
1644
1750
|
|
|
1645
1751
|
// src/agents/providers/claude-code.ts
|
|
1646
|
-
var DAEMON_PROTOCOL_VERSION = "
|
|
1752
|
+
var DAEMON_PROTOCOL_VERSION = "3";
|
|
1647
1753
|
var DAEMON_PORT = 43180;
|
|
1648
1754
|
var DAEMON_PATH = "/tmp/agentbox/claude-code/daemon.mjs";
|
|
1649
1755
|
var DAEMON_LOG_PATH = "/tmp/agentbox/claude-code/daemon.log";
|
|
1650
1756
|
var DAEMON_PID_PATH = "/tmp/agentbox/claude-code/daemon.pid";
|
|
1757
|
+
var DAEMON_TOKEN_PATH = "/tmp/agentbox/claude-code/daemon-token";
|
|
1651
1758
|
var DAEMON_READY_TIMEOUT_MS = 3e4;
|
|
1652
1759
|
var DAEMON_READY_POLL_INTERVAL_MS = 250;
|
|
1653
1760
|
function claudeConfigDir(options) {
|
|
@@ -1672,6 +1779,7 @@ function buildClaudeQueryOptions(params) {
|
|
|
1672
1779
|
extraArgs["append-system-prompt"] = run.systemPrompt;
|
|
1673
1780
|
}
|
|
1674
1781
|
const includeHookEvents = provider?.includeHookEvents ?? false;
|
|
1782
|
+
const effort = provider?.ultracode ? "xhigh" : run.reasoning;
|
|
1675
1783
|
return {
|
|
1676
1784
|
cwd: params.cwd ?? params.request.options.cwd,
|
|
1677
1785
|
env: params.env,
|
|
@@ -1684,7 +1792,7 @@ function buildClaudeQueryOptions(params) {
|
|
|
1684
1792
|
thinking: { type: "adaptive", display: "summarized" },
|
|
1685
1793
|
...provider?.additionalDirectories?.length ? { additionalDirectories: provider.additionalDirectories } : {},
|
|
1686
1794
|
...run.model ? { model: run.model } : {},
|
|
1687
|
-
...
|
|
1795
|
+
...effort ? { effort } : {},
|
|
1688
1796
|
...provider?.permissionMode ? { permissionMode: provider.permissionMode } : {},
|
|
1689
1797
|
...provider?.permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {},
|
|
1690
1798
|
...provider?.allowedTools?.length ? { allowedTools: provider.allowedTools } : {},
|
|
@@ -1741,11 +1849,30 @@ function createClaudeCodeDaemonScript() {
|
|
|
1741
1849
|
const version = JSON.stringify(DAEMON_PROTOCOL_VERSION);
|
|
1742
1850
|
return `import http from "node:http";
|
|
1743
1851
|
import { execSync } from "node:child_process";
|
|
1744
|
-
import { existsSync } from "node:fs";
|
|
1852
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1853
|
+
import { timingSafeEqual } from "node:crypto";
|
|
1745
1854
|
import { query, getSessionInfo } from "@anthropic-ai/claude-agent-sdk";
|
|
1746
1855
|
|
|
1747
1856
|
const VERSION = ${version};
|
|
1748
1857
|
const port = Number(process.argv[2] ?? "${DAEMON_PORT}");
|
|
1858
|
+
// Capability token: every route except the loopback /__version probe
|
|
1859
|
+
// requires \`Authorization: Bearer <token>\`. Loaded once at boot from the
|
|
1860
|
+
// 0600 file the host writes alongside this script. Fails closed (rejects
|
|
1861
|
+
// all run-control requests) when the file is missing or empty.
|
|
1862
|
+
const tokenFilePath = process.argv[3] ?? "";
|
|
1863
|
+
let AUTH_TOKEN = "";
|
|
1864
|
+
try { if (tokenFilePath) AUTH_TOKEN = readFileSync(tokenFilePath, "utf8").trim(); } catch {}
|
|
1865
|
+
|
|
1866
|
+
function isAuthorized(req) {
|
|
1867
|
+
if (!AUTH_TOKEN) return false;
|
|
1868
|
+
const header = req.headers["authorization"] || "";
|
|
1869
|
+
const presented = header.startsWith("Bearer ") ? header.slice(7) : "";
|
|
1870
|
+
if (!presented) return false;
|
|
1871
|
+
const a = Buffer.from(presented);
|
|
1872
|
+
const b = Buffer.from(AUTH_TOKEN);
|
|
1873
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1749
1876
|
const liveRuns = new Map();
|
|
1750
1877
|
|
|
1751
1878
|
// The SDK's default spawn does \`existsSync(pathToClaudeCodeExecutable)\`
|
|
@@ -1982,6 +2109,14 @@ const server = http.createServer((req, res) => {
|
|
|
1982
2109
|
res.end(VERSION);
|
|
1983
2110
|
return;
|
|
1984
2111
|
}
|
|
2112
|
+
// Capability-token gate for every run-control route. The /__version probe
|
|
2113
|
+
// above stays open: it carries no secret and the host probes it over
|
|
2114
|
+
// loopback (no bearer) to detect daemon liveness/version.
|
|
2115
|
+
if (!isAuthorized(req)) {
|
|
2116
|
+
res.writeHead(401, { "content-type": "text/plain" });
|
|
2117
|
+
res.end("unauthorized");
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
1985
2120
|
const url = req.url ?? "";
|
|
1986
2121
|
let m;
|
|
1987
2122
|
if (req.method === "POST" && (m = url.match(/^\\/runs\\/([^/]+)\\/start$/))) {
|
|
@@ -2052,6 +2187,11 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
|
|
|
2052
2187
|
);
|
|
2053
2188
|
return;
|
|
2054
2189
|
}
|
|
2190
|
+
const daemonToken = await resolveCapabilityToken(
|
|
2191
|
+
sandbox,
|
|
2192
|
+
DAEMON_TOKEN_PATH,
|
|
2193
|
+
true
|
|
2194
|
+
);
|
|
2055
2195
|
const daemonDir = path8.posix.dirname(DAEMON_PATH);
|
|
2056
2196
|
const daemonNodeModules = `${daemonDir}/node_modules/@anthropic-ai`;
|
|
2057
2197
|
const launchCommand = [
|
|
@@ -2059,13 +2199,18 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
|
|
|
2059
2199
|
`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
2200
|
`mkdir -p ${shellQuote(daemonNodeModules)}`,
|
|
2061
2201
|
`ln -sfn "$NPM_ROOT/@anthropic-ai/claude-agent-sdk" ${shellQuote(daemonNodeModules + "/claude-agent-sdk")}`,
|
|
2202
|
+
// The base uploadAndRun only chmods execute-bit artifacts, so the 0600
|
|
2203
|
+
// tarball mode is dropped on Daytona (and other non-Modal providers).
|
|
2204
|
+
// Tighten the just-written token file explicitly — matching codex —
|
|
2205
|
+
// so the bearer is never group/world-readable inside the sandbox.
|
|
2206
|
+
`chmod 600 ${shellQuote(DAEMON_TOKEN_PATH)}`,
|
|
2062
2207
|
`if [ -f ${shellQuote(DAEMON_PID_PATH)} ]; then kill -TERM "$(cat ${shellQuote(DAEMON_PID_PATH)})" 2>/dev/null || true; fi`,
|
|
2063
2208
|
`(fuser -k -n tcp ${DAEMON_PORT} 2>/dev/null || true)`,
|
|
2064
2209
|
// Brief grace so the kernel releases the port before the new
|
|
2065
2210
|
// daemon's listen() — only matters on warm-sandbox respawns;
|
|
2066
2211
|
// adds 200ms otherwise.
|
|
2067
2212
|
`sleep 0.2`,
|
|
2068
|
-
`(nohup node ${shellQuote(DAEMON_PATH)} ${DAEMON_PORT} > ${shellQuote(DAEMON_LOG_PATH)} 2>&1 & echo $! > ${shellQuote(DAEMON_PID_PATH)})`
|
|
2213
|
+
`(nohup node ${shellQuote(DAEMON_PATH)} ${DAEMON_PORT} ${shellQuote(DAEMON_TOKEN_PATH)} > ${shellQuote(DAEMON_LOG_PATH)} 2>&1 & echo $! > ${shellQuote(DAEMON_PID_PATH)})`
|
|
2069
2214
|
].join(" && ");
|
|
2070
2215
|
const launch = await time(
|
|
2071
2216
|
debugRelay,
|
|
@@ -2076,6 +2221,11 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
|
|
|
2076
2221
|
path: DAEMON_PATH,
|
|
2077
2222
|
content: createClaudeCodeDaemonScript(),
|
|
2078
2223
|
mode: 420
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
path: DAEMON_TOKEN_PATH,
|
|
2227
|
+
content: daemonToken,
|
|
2228
|
+
mode: 384
|
|
2079
2229
|
}
|
|
2080
2230
|
],
|
|
2081
2231
|
launchCommand,
|
|
@@ -2171,6 +2321,10 @@ async function daemonBaseUrl(sandbox) {
|
|
|
2171
2321
|
const url = await sandbox.getPreviewLink(DAEMON_PORT);
|
|
2172
2322
|
return url.replace(/\/$/, "");
|
|
2173
2323
|
}
|
|
2324
|
+
async function daemonAuthHeaders(sandbox) {
|
|
2325
|
+
const token = await resolveCapabilityToken(sandbox, DAEMON_TOKEN_PATH, false);
|
|
2326
|
+
return withBearerToken(sandbox.previewHeaders, token);
|
|
2327
|
+
}
|
|
2174
2328
|
var ClaudeCodeAgentAdapter = class {
|
|
2175
2329
|
/**
|
|
2176
2330
|
* Sandbox-side preparation. Uploads `.claude/` artifacts and ensures
|
|
@@ -2223,12 +2377,19 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2223
2377
|
() => prepareSkillArtifacts(provider, options.skills, target.layout)
|
|
2224
2378
|
);
|
|
2225
2379
|
const hookSettings = buildClaudeHookSettings(hooks) ?? {};
|
|
2380
|
+
const workflowSettings = buildClaudeWorkflowSettings(
|
|
2381
|
+
options.provider?.ultracode
|
|
2382
|
+
);
|
|
2383
|
+
const claudeSettings = { ...hookSettings, ...workflowSettings };
|
|
2226
2384
|
const mcpConfigJson = buildClaudeMcpConfig(options.mcps) ?? JSON.stringify({ mcpServers: {} }, null, 2);
|
|
2227
2385
|
const artifacts = [
|
|
2228
2386
|
...skillArtifacts,
|
|
2229
2387
|
...buildClaudeCommandArtifacts(options.commands, target.layout),
|
|
2230
2388
|
...buildClaudeSubagentArtifacts(options.subAgents, target.layout),
|
|
2231
|
-
{
|
|
2389
|
+
{
|
|
2390
|
+
path: settingsPath,
|
|
2391
|
+
content: JSON.stringify(claudeSettings, null, 2)
|
|
2392
|
+
},
|
|
2232
2393
|
{ path: mcpConfigPath, content: mcpConfigJson }
|
|
2233
2394
|
];
|
|
2234
2395
|
const enableRtk = options.enableRtk === true;
|
|
@@ -2283,6 +2444,12 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2283
2444
|
// user inside our images.
|
|
2284
2445
|
IS_SANDBOX: "1"
|
|
2285
2446
|
};
|
|
2447
|
+
const customHeaders = request.options.customHeaders;
|
|
2448
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
2449
|
+
const serialized = Object.entries(customHeaders).map(([name, value]) => `${name}: ${value}`).join("\n");
|
|
2450
|
+
env.ANTHROPIC_CUSTOM_HEADERS = env.ANTHROPIC_CUSTOM_HEADERS ? `${env.ANTHROPIC_CUSTOM_HEADERS}
|
|
2451
|
+
${serialized}` : serialized;
|
|
2452
|
+
}
|
|
2286
2453
|
const inputParts = await time(
|
|
2287
2454
|
debugClaude,
|
|
2288
2455
|
"validateProviderUserInput",
|
|
@@ -2297,6 +2464,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2297
2464
|
"getPreviewLink daemon",
|
|
2298
2465
|
() => daemonBaseUrl(sandbox)
|
|
2299
2466
|
);
|
|
2467
|
+
const authHeaders = await daemonAuthHeaders(sandbox);
|
|
2300
2468
|
const startUrl = `${baseUrl}/runs/${encodeURIComponent(request.runId)}/start`;
|
|
2301
2469
|
const sdkOptions = buildClaudeQueryOptions({
|
|
2302
2470
|
request,
|
|
@@ -2328,7 +2496,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2328
2496
|
try {
|
|
2329
2497
|
await fetch(
|
|
2330
2498
|
`${baseUrl}/runs/${encodeURIComponent(request.runId)}/abort`,
|
|
2331
|
-
{ method: "POST", headers:
|
|
2499
|
+
{ method: "POST", headers: authHeaders }
|
|
2332
2500
|
);
|
|
2333
2501
|
} catch {
|
|
2334
2502
|
}
|
|
@@ -2345,7 +2513,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2345
2513
|
method: "POST",
|
|
2346
2514
|
headers: {
|
|
2347
2515
|
"content-type": "application/json",
|
|
2348
|
-
...
|
|
2516
|
+
...authHeaders
|
|
2349
2517
|
},
|
|
2350
2518
|
body: JSON.stringify({ content: mapped })
|
|
2351
2519
|
}
|
|
@@ -2360,7 +2528,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2360
2528
|
signal: fetchAbort.signal,
|
|
2361
2529
|
headers: {
|
|
2362
2530
|
"content-type": "application/json",
|
|
2363
|
-
...
|
|
2531
|
+
...authHeaders
|
|
2364
2532
|
},
|
|
2365
2533
|
body: JSON.stringify(requestBody)
|
|
2366
2534
|
})
|
|
@@ -2588,6 +2756,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2588
2756
|
*/
|
|
2589
2757
|
async attachAbort(request) {
|
|
2590
2758
|
const baseUrl = await daemonBaseUrl(request.sandbox);
|
|
2759
|
+
const authHeaders = await daemonAuthHeaders(request.sandbox);
|
|
2591
2760
|
const controller = new AbortController();
|
|
2592
2761
|
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
2593
2762
|
try {
|
|
@@ -2596,7 +2765,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2596
2765
|
{
|
|
2597
2766
|
method: "POST",
|
|
2598
2767
|
signal: controller.signal,
|
|
2599
|
-
headers:
|
|
2768
|
+
headers: authHeaders
|
|
2600
2769
|
}
|
|
2601
2770
|
).catch((error) => {
|
|
2602
2771
|
debugClaude("attachAbort POST failed: %o", error);
|
|
@@ -2613,6 +2782,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2613
2782
|
*/
|
|
2614
2783
|
async attachSendMessage(request, content) {
|
|
2615
2784
|
const baseUrl = await daemonBaseUrl(request.sandbox);
|
|
2785
|
+
const authHeaders = await daemonAuthHeaders(request.sandbox);
|
|
2616
2786
|
const inputParts = await validateProviderUserInput(
|
|
2617
2787
|
AgentProvider.ClaudeCode,
|
|
2618
2788
|
content
|
|
@@ -2624,7 +2794,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2624
2794
|
method: "POST",
|
|
2625
2795
|
headers: {
|
|
2626
2796
|
"content-type": "application/json",
|
|
2627
|
-
...
|
|
2797
|
+
...authHeaders
|
|
2628
2798
|
},
|
|
2629
2799
|
body: JSON.stringify({ content: mapped })
|
|
2630
2800
|
}
|
|
@@ -2638,7 +2808,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2638
2808
|
};
|
|
2639
2809
|
|
|
2640
2810
|
// src/agents/providers/codex.ts
|
|
2641
|
-
import
|
|
2811
|
+
import crypto2 from "crypto";
|
|
2642
2812
|
import path9 from "path";
|
|
2643
2813
|
|
|
2644
2814
|
// src/agents/transports/app-server.ts
|
|
@@ -2895,7 +3065,7 @@ function resolveCodexAppServerToken(sandbox, tokenFilePath, create) {
|
|
|
2895
3065
|
return existing;
|
|
2896
3066
|
}
|
|
2897
3067
|
if (create) {
|
|
2898
|
-
return
|
|
3068
|
+
return crypto2.randomBytes(32).toString("hex");
|
|
2899
3069
|
}
|
|
2900
3070
|
throw new Error(
|
|
2901
3071
|
`Codex app-server token file is missing at ${tokenFilePath}. setup() must run before connecting to the codex app-server.`
|
|
@@ -3216,6 +3386,45 @@ async function materializeCodexImage(options, part, index) {
|
|
|
3216
3386
|
function resolveCodexOpenAiBaseUrlFromOptions(options) {
|
|
3217
3387
|
return options.env?.OPENAI_BASE_URL ?? options.provider?.env?.OPENAI_BASE_URL;
|
|
3218
3388
|
}
|
|
3389
|
+
function codexCredentialEnv(options) {
|
|
3390
|
+
return { ...options.env ?? {}, ...options.provider?.env ?? {} };
|
|
3391
|
+
}
|
|
3392
|
+
function resolveCodexModelProviders(options) {
|
|
3393
|
+
const modelProviders = {
|
|
3394
|
+
...options.provider?.modelProviders ?? {}
|
|
3395
|
+
};
|
|
3396
|
+
const modelProvider = options.provider?.modelProvider;
|
|
3397
|
+
const customHeaders = options.customHeaders;
|
|
3398
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
3399
|
+
for (const [id, cfg] of Object.entries(modelProviders)) {
|
|
3400
|
+
modelProviders[id] = {
|
|
3401
|
+
...cfg,
|
|
3402
|
+
httpHeaders: { ...cfg.httpHeaders ?? {}, ...customHeaders }
|
|
3403
|
+
};
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
return { modelProviders, modelProvider };
|
|
3407
|
+
}
|
|
3408
|
+
function hashCodexProviderCredentials(options, modelProviders) {
|
|
3409
|
+
const env = codexCredentialEnv(options);
|
|
3410
|
+
const envKeyNames = /* @__PURE__ */ new Set(["OPENAI_API_KEY"]);
|
|
3411
|
+
for (const cfg of Object.values(modelProviders)) {
|
|
3412
|
+
if (cfg.envKey) {
|
|
3413
|
+
envKeyNames.add(cfg.envKey);
|
|
3414
|
+
}
|
|
3415
|
+
for (const envVar of Object.values(cfg.envHttpHeaders ?? {})) {
|
|
3416
|
+
envKeyNames.add(envVar);
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
const hasher = crypto2.createHash("sha256");
|
|
3420
|
+
for (const name of [...envKeyNames].sort()) {
|
|
3421
|
+
if (env[name] !== void 0) {
|
|
3422
|
+
hasher.update(`${name}=${env[name]}
|
|
3423
|
+
`);
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
return hasher.digest("hex");
|
|
3427
|
+
}
|
|
3219
3428
|
async function ensureCodexLoginViaConfig(request, target) {
|
|
3220
3429
|
const options = request.options;
|
|
3221
3430
|
const openAiApiKey = options.env?.OPENAI_API_KEY ?? options.provider?.env?.OPENAI_API_KEY;
|
|
@@ -3300,9 +3509,19 @@ async function setupCodex(request) {
|
|
|
3300
3509
|
const provider = request.provider;
|
|
3301
3510
|
const hooks = assertHooksSupported(provider, options);
|
|
3302
3511
|
assertCommandsSupported(provider, options.commands);
|
|
3512
|
+
const { modelProviders, modelProvider } = resolveCodexModelProviders(options);
|
|
3513
|
+
const providerCredHash = hashCodexProviderCredentials(
|
|
3514
|
+
options,
|
|
3515
|
+
modelProviders
|
|
3516
|
+
);
|
|
3303
3517
|
const usesRemoteWebSocket = options.sandbox && options.sandbox.provider !== SandboxProvider.LocalDocker;
|
|
3304
3518
|
function buildArtifactsFor(layoutTarget) {
|
|
3305
|
-
const
|
|
3519
|
+
const defaultModel = options.provider?.defaultModel;
|
|
3520
|
+
const { artifacts: subAgentArtifacts, agentSections } = buildCodexSubagentArtifacts(
|
|
3521
|
+
options.subAgents,
|
|
3522
|
+
layoutTarget.layout,
|
|
3523
|
+
defaultModel
|
|
3524
|
+
);
|
|
3306
3525
|
const hooksFile = buildCodexHooksFile(hooks);
|
|
3307
3526
|
const enableMultiAgent = (options.subAgents?.length ?? 0) > 0;
|
|
3308
3527
|
const enableSkills = (options.skills?.length ?? 0) > 0;
|
|
@@ -3313,7 +3532,10 @@ async function setupCodex(request) {
|
|
|
3313
3532
|
enableHooks: Boolean(hooksFile),
|
|
3314
3533
|
enableSkills,
|
|
3315
3534
|
enableMultiAgent,
|
|
3316
|
-
openAiBaseUrl
|
|
3535
|
+
openAiBaseUrl,
|
|
3536
|
+
model: defaultModel,
|
|
3537
|
+
modelProvider,
|
|
3538
|
+
modelProviders
|
|
3317
3539
|
});
|
|
3318
3540
|
const artifacts = [...subAgentArtifacts];
|
|
3319
3541
|
if (configToml) {
|
|
@@ -3366,7 +3588,7 @@ async function setupCodex(request) {
|
|
|
3366
3588
|
artifacts: [...serverArtifacts, ...skillArtifacts2],
|
|
3367
3589
|
installCommands: installCommands2,
|
|
3368
3590
|
daemon: daemonInfo,
|
|
3369
|
-
extras: [`enableRtk:${enableRtk2}`]
|
|
3591
|
+
extras: [`enableRtk:${enableRtk2}`, `providerCreds:${providerCredHash}`]
|
|
3370
3592
|
});
|
|
3371
3593
|
if (await preflightSetup(sharedTarget, setupId2, daemonInfo)) {
|
|
3372
3594
|
debugCodex("codex remote setup() preflight hit \u2014 skipping");
|
|
@@ -3390,12 +3612,18 @@ async function setupCodex(request) {
|
|
|
3390
3612
|
const serverCwd = sharedTarget.layout.rootDir;
|
|
3391
3613
|
const launchResult = await time(
|
|
3392
3614
|
debugCodex,
|
|
3393
|
-
"
|
|
3615
|
+
"restart app-server after setup miss",
|
|
3394
3616
|
() => sandbox.run(
|
|
3395
3617
|
[
|
|
3396
3618
|
`mkdir -p ${shellQuote(sharedTarget.layout.rootDir)}`,
|
|
3397
|
-
|
|
3398
|
-
|
|
3619
|
+
[
|
|
3620
|
+
`if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then`,
|
|
3621
|
+
` 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`,
|
|
3622
|
+
` 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`,
|
|
3623
|
+
` 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`,
|
|
3624
|
+
` rm -f ${shellQuote(pidFilePath)}`,
|
|
3625
|
+
`fi`
|
|
3626
|
+
].join("\n"),
|
|
3399
3627
|
`chmod 600 ${shellQuote(tokenFilePath)}`,
|
|
3400
3628
|
`(${[
|
|
3401
3629
|
`nohup ${[
|
|
@@ -3452,7 +3680,7 @@ async function setupCodex(request) {
|
|
|
3452
3680
|
const setupId = computeSetupId({
|
|
3453
3681
|
artifacts: allArtifacts,
|
|
3454
3682
|
installCommands,
|
|
3455
|
-
extras: [`enableRtk:${enableRtk}`]
|
|
3683
|
+
extras: [`enableRtk:${enableRtk}`, `providerCreds:${providerCredHash}`]
|
|
3456
3684
|
});
|
|
3457
3685
|
if (await preflightSetup(target, setupId)) {
|
|
3458
3686
|
debugCodex("codex local setup() preflight hit \u2014 skipping");
|
|
@@ -3967,6 +4195,37 @@ var LOCAL_OPENCODE_PORT = 4096;
|
|
|
3967
4195
|
var SANDBOX_OPENCODE_READY_TIMEOUT_MS = 9e4;
|
|
3968
4196
|
var LOCAL_OPENCODE_READY_TIMEOUT_MS = 2e4;
|
|
3969
4197
|
var SHARED_OPENCODE_TARGET_ID = "shared-opencode-server";
|
|
4198
|
+
var OPENCODE_AUTH_USERNAME = "opencode";
|
|
4199
|
+
function opencodeServerTokenPath() {
|
|
4200
|
+
return path10.posix.join(
|
|
4201
|
+
agentboxRoot(AgentProvider.OpenCode, true),
|
|
4202
|
+
"opencode-auth-token"
|
|
4203
|
+
);
|
|
4204
|
+
}
|
|
4205
|
+
function opencodeCurlAuthArg() {
|
|
4206
|
+
return `-u "opencode:$(cat ${shellQuote(opencodeServerTokenPath())} 2>/dev/null)"`;
|
|
4207
|
+
}
|
|
4208
|
+
function opencodeHealthCurl(port) {
|
|
4209
|
+
return `curl -fsS --max-time 2 ${opencodeCurlAuthArg()} http://127.0.0.1:${port}/global/health >/dev/null 2>&1`;
|
|
4210
|
+
}
|
|
4211
|
+
async function isSandboxOpenCodeServerAuthEnforced(sandbox, cwd, port) {
|
|
4212
|
+
const probe = await sandbox.run(
|
|
4213
|
+
`test "$(curl -s -o /dev/null -w '%{http_code}' --max-time 2 http://127.0.0.1:${port}/global/health)" = "401"`,
|
|
4214
|
+
{ cwd, timeoutMs: 5e3 }
|
|
4215
|
+
).catch(() => void 0);
|
|
4216
|
+
return probe?.exitCode === 0;
|
|
4217
|
+
}
|
|
4218
|
+
async function opencodeAuthHeaders(sandbox) {
|
|
4219
|
+
const token = await resolveCapabilityToken(
|
|
4220
|
+
sandbox,
|
|
4221
|
+
opencodeServerTokenPath(),
|
|
4222
|
+
false
|
|
4223
|
+
);
|
|
4224
|
+
const basic = Buffer.from(`${OPENCODE_AUTH_USERNAME}:${token}`).toString(
|
|
4225
|
+
"base64"
|
|
4226
|
+
);
|
|
4227
|
+
return { ...sandbox.previewHeaders, Authorization: `Basic ${basic}` };
|
|
4228
|
+
}
|
|
3970
4229
|
var LLM_API_KEY_ENV_VARS = [
|
|
3971
4230
|
"OPENROUTER_API_KEY",
|
|
3972
4231
|
"OPENAI_API_KEY",
|
|
@@ -4017,10 +4276,10 @@ async function killSandboxOpenCodeServer(sandbox, pidFilePath, cwd, port) {
|
|
|
4017
4276
|
).catch(() => void 0);
|
|
4018
4277
|
const deadline = Date.now() + 5e3;
|
|
4019
4278
|
while (Date.now() < deadline) {
|
|
4020
|
-
const probe = await sandbox.run(
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
);
|
|
4279
|
+
const probe = await sandbox.run(opencodeHealthCurl(port), {
|
|
4280
|
+
cwd,
|
|
4281
|
+
timeoutMs: 5e3
|
|
4282
|
+
});
|
|
4024
4283
|
if (probe.exitCode !== 0) {
|
|
4025
4284
|
return;
|
|
4026
4285
|
}
|
|
@@ -4127,6 +4386,8 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
4127
4386
|
transforms: ["middle-out"],
|
|
4128
4387
|
...openRouterPlugins ? { plugins: openRouterPlugins } : {}
|
|
4129
4388
|
};
|
|
4389
|
+
const customHeaders = options.customHeaders && Object.keys(options.customHeaders).length > 0 ? options.customHeaders : void 0;
|
|
4390
|
+
const headerOpts = customHeaders ? { headers: customHeaders } : {};
|
|
4130
4391
|
return {
|
|
4131
4392
|
$schema: "https://opencode.ai/config.json",
|
|
4132
4393
|
...mcpConfig ? { mcp: mcpConfig } : {},
|
|
@@ -4135,10 +4396,12 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
4135
4396
|
openrouter: {
|
|
4136
4397
|
options: {
|
|
4137
4398
|
baseURL: openRouterBaseUrl || "https://openrouter.ai/api/v1",
|
|
4138
|
-
extraBody: openRouterExtraBody
|
|
4399
|
+
extraBody: openRouterExtraBody,
|
|
4400
|
+
...headerOpts
|
|
4139
4401
|
}
|
|
4140
4402
|
},
|
|
4141
|
-
...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl } } } : {}
|
|
4403
|
+
...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl, ...headerOpts } } } : {},
|
|
4404
|
+
...customHeaders ? { anthropic: { options: { ...headerOpts } } } : {}
|
|
4142
4405
|
},
|
|
4143
4406
|
agent: {
|
|
4144
4407
|
agentbox: baseAgent,
|
|
@@ -4160,6 +4423,12 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4160
4423
|
SHARED_OPENCODE_TARGET_ID,
|
|
4161
4424
|
options
|
|
4162
4425
|
);
|
|
4426
|
+
const serverTokenPath = opencodeServerTokenPath();
|
|
4427
|
+
const serverToken = await resolveCapabilityToken(
|
|
4428
|
+
sandbox,
|
|
4429
|
+
serverTokenPath,
|
|
4430
|
+
true
|
|
4431
|
+
);
|
|
4163
4432
|
const { artifacts: skillArtifacts, installCommands } = await prepareSkillArtifacts(
|
|
4164
4433
|
request.provider,
|
|
4165
4434
|
options.skills,
|
|
@@ -4177,10 +4446,18 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4177
4446
|
{
|
|
4178
4447
|
path: configPath,
|
|
4179
4448
|
content: JSON.stringify(openCodeConfig, null, 2)
|
|
4449
|
+
},
|
|
4450
|
+
{
|
|
4451
|
+
path: serverTokenPath,
|
|
4452
|
+
content: serverToken
|
|
4180
4453
|
}
|
|
4181
4454
|
];
|
|
4182
4455
|
const enableRtk = options.enableRtk === true;
|
|
4183
|
-
const daemonInfo = {
|
|
4456
|
+
const daemonInfo = {
|
|
4457
|
+
port,
|
|
4458
|
+
healthPath: "/global/health",
|
|
4459
|
+
curlAuthArg: opencodeCurlAuthArg()
|
|
4460
|
+
};
|
|
4184
4461
|
const setupId = computeSetupId({
|
|
4185
4462
|
artifacts: allArtifacts,
|
|
4186
4463
|
installCommands,
|
|
@@ -4195,10 +4472,15 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4195
4472
|
return;
|
|
4196
4473
|
}
|
|
4197
4474
|
if (await isSandboxOpenCodeServerHealthy(sandbox, options.cwd, port)) {
|
|
4475
|
+
if (await isSandboxOpenCodeServerAuthEnforced(sandbox, options.cwd, port)) {
|
|
4476
|
+
debugOpencode(
|
|
4477
|
+
"opencode server already running but setup drifted \u2014 reusing it without restart; call agent.killServer() to apply the new config"
|
|
4478
|
+
);
|
|
4479
|
+
return;
|
|
4480
|
+
}
|
|
4198
4481
|
debugOpencode(
|
|
4199
|
-
"opencode server
|
|
4482
|
+
"opencode server running without capability auth \u2014 restarting to enforce it"
|
|
4200
4483
|
);
|
|
4201
|
-
return;
|
|
4202
4484
|
}
|
|
4203
4485
|
const commonEnv = {
|
|
4204
4486
|
OPENCODE_CONFIG: configPath,
|
|
@@ -4218,9 +4500,18 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4218
4500
|
target.layout.rootDir,
|
|
4219
4501
|
"opencode-serve.log"
|
|
4220
4502
|
);
|
|
4221
|
-
const serveEnv = {
|
|
4503
|
+
const serveEnv = {
|
|
4504
|
+
...options.env ?? {},
|
|
4505
|
+
...commonEnv,
|
|
4506
|
+
// Native opencode HTTP basic auth. The host presents this token on
|
|
4507
|
+
// every request (see opencodeAuthHeaders); the in-sandbox health probes
|
|
4508
|
+
// present it too (see opencodeHealthCurl).
|
|
4509
|
+
OPENCODE_SERVER_USERNAME: OPENCODE_AUTH_USERNAME,
|
|
4510
|
+
OPENCODE_SERVER_PASSWORD: serverToken
|
|
4511
|
+
};
|
|
4222
4512
|
const launchCommand = [
|
|
4223
4513
|
`mkdir -p ${shellQuote(target.layout.rootDir)}`,
|
|
4514
|
+
`chmod 600 ${shellQuote(serverTokenPath)} 2>/dev/null || true`,
|
|
4224
4515
|
`(${[
|
|
4225
4516
|
`setsid nohup ${[
|
|
4226
4517
|
binary,
|
|
@@ -4263,10 +4554,10 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4263
4554
|
);
|
|
4264
4555
|
}
|
|
4265
4556
|
while (Date.now() < readyDeadline) {
|
|
4266
|
-
const probe = await sandbox.run(
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
);
|
|
4557
|
+
const probe = await sandbox.run(opencodeHealthCurl(port), {
|
|
4558
|
+
cwd: options.cwd,
|
|
4559
|
+
timeoutMs: 5e3
|
|
4560
|
+
});
|
|
4270
4561
|
if (probe.exitCode === 0) {
|
|
4271
4562
|
debugOpencode("ready on attempt %d", attempt);
|
|
4272
4563
|
return true;
|
|
@@ -4308,6 +4599,18 @@ opencode log:
|
|
|
4308
4599
|
${lastLog}` : "")
|
|
4309
4600
|
);
|
|
4310
4601
|
}
|
|
4602
|
+
if (!await isSandboxOpenCodeServerAuthEnforced(sandbox, options.cwd, port)) {
|
|
4603
|
+
await killSandboxOpenCodeServer(
|
|
4604
|
+
sandbox,
|
|
4605
|
+
pidFilePath,
|
|
4606
|
+
options.cwd,
|
|
4607
|
+
port
|
|
4608
|
+
).catch(() => void 0);
|
|
4609
|
+
await target.cleanup().catch(() => void 0);
|
|
4610
|
+
throw new Error(
|
|
4611
|
+
"OpenCode server started but is not enforcing the capability token (OPENCODE_SERVER_PASSWORD ignored). Upgrade opencode-ai to a version that supports server authentication."
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4311
4614
|
await markSetupComplete(target, setupId);
|
|
4312
4615
|
});
|
|
4313
4616
|
}
|
|
@@ -4399,10 +4702,7 @@ async function setupOpenCode(request) {
|
|
|
4399
4702
|
await ensureLocalOpenCodeServer(request);
|
|
4400
4703
|
}
|
|
4401
4704
|
async function isSandboxOpenCodeServerHealthy(sandbox, cwd, port) {
|
|
4402
|
-
const probe = await sandbox.run(
|
|
4403
|
-
`curl -fsS --max-time 2 http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
|
|
4404
|
-
{ cwd, timeoutMs: 5e3 }
|
|
4405
|
-
).catch(() => void 0);
|
|
4705
|
+
const probe = await sandbox.run(opencodeHealthCurl(port), { cwd, timeoutMs: 5e3 }).catch(() => void 0);
|
|
4406
4706
|
return probe?.exitCode === 0;
|
|
4407
4707
|
}
|
|
4408
4708
|
async function isLocalOpenCodeServerHealthy() {
|
|
@@ -4443,7 +4743,7 @@ async function buildOpenCodeRuntime(options) {
|
|
|
4443
4743
|
const baseUrl2 = (await sandbox.getPreviewLink(SANDBOX_OPENCODE_PORT)).replace(/\/$/, "");
|
|
4444
4744
|
return {
|
|
4445
4745
|
baseUrl: baseUrl2,
|
|
4446
|
-
previewHeaders: sandbox
|
|
4746
|
+
previewHeaders: await opencodeAuthHeaders(sandbox),
|
|
4447
4747
|
raw: { baseUrl: baseUrl2, port: SANDBOX_OPENCODE_PORT }
|
|
4448
4748
|
};
|
|
4449
4749
|
}
|
|
@@ -4977,6 +5277,7 @@ var OpenCodeAgentAdapter = class {
|
|
|
4977
5277
|
);
|
|
4978
5278
|
}
|
|
4979
5279
|
const baseUrl = (await request.sandbox.getPreviewLink(SANDBOX_OPENCODE_PORT)).replace(/\/$/, "");
|
|
5280
|
+
const authHeaders = await opencodeAuthHeaders(request.sandbox);
|
|
4980
5281
|
const controller = new AbortController();
|
|
4981
5282
|
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
4982
5283
|
try {
|
|
@@ -4985,7 +5286,7 @@ var OpenCodeAgentAdapter = class {
|
|
|
4985
5286
|
signal: controller.signal,
|
|
4986
5287
|
headers: {
|
|
4987
5288
|
"content-type": "application/json",
|
|
4988
|
-
...
|
|
5289
|
+
...authHeaders
|
|
4989
5290
|
}
|
|
4990
5291
|
}).catch((error) => {
|
|
4991
5292
|
debugOpencode(
|
|
@@ -5016,12 +5317,13 @@ var OpenCodeAgentAdapter = class {
|
|
|
5016
5317
|
content
|
|
5017
5318
|
);
|
|
5018
5319
|
const parts = mapToOpenCodeParts(inputParts);
|
|
5320
|
+
const authHeaders = await opencodeAuthHeaders(request.sandbox);
|
|
5019
5321
|
const url = `${baseUrl}/session/${request.sessionId}/prompt_async`;
|
|
5020
5322
|
const response = await fetch(url, {
|
|
5021
5323
|
method: "POST",
|
|
5022
5324
|
headers: {
|
|
5023
5325
|
"content-type": "application/json",
|
|
5024
|
-
...
|
|
5326
|
+
...authHeaders
|
|
5025
5327
|
},
|
|
5026
5328
|
body: JSON.stringify({
|
|
5027
5329
|
agent: openCodeAgentSlug(void 0),
|
package/dist/events/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as AISDKEvent,
|
|
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
|
|
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
|
@@ -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
|
|
@@ -418,6 +507,18 @@ interface ClaudeCodeProviderOptions {
|
|
|
418
507
|
* silence them when hook noise drowns out the rest of the event stream.
|
|
419
508
|
*/
|
|
420
509
|
includeHookEvents?: boolean;
|
|
510
|
+
/**
|
|
511
|
+
* Enable "ultracode" for claude-code runs: xhigh reasoning effort plus
|
|
512
|
+
* standing dynamic-workflow orchestration (the built-in `Workflow` tool).
|
|
513
|
+
*
|
|
514
|
+
* When `true`, agentbox writes `enableWorkflows: true` + `ultracode: true`
|
|
515
|
+
* into the managed `settings.json` and forces `effort: "xhigh"` on the query.
|
|
516
|
+
*
|
|
517
|
+
* Requires an xhigh-capable model (e.g. Opus) and a recent runtime — the
|
|
518
|
+
* Workflows feature shipped around Claude Code 2.1.154 / Agent SDK 0.3.149.
|
|
519
|
+
* On older CLIs the settings keys are simply ignored.
|
|
520
|
+
*/
|
|
521
|
+
ultracode?: boolean;
|
|
421
522
|
}
|
|
422
523
|
interface CodexAgentOptions extends AgentOptionsBase {
|
|
423
524
|
provider?: CodexProviderOptions;
|
|
@@ -629,4 +730,4 @@ interface AgentProviderAdapter<P extends AgentProviderName = AgentProviderName>
|
|
|
629
730
|
attachSendMessage(request: AgentAttachRequest<P>, content: UserContent): Promise<void>;
|
|
630
731
|
}
|
|
631
732
|
|
|
632
|
-
export { type
|
|
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 };
|