agentbox-sdk 0.1.319 → 0.1.323
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/dist/agents/index.d.ts +19 -2
- package/dist/agents/index.js +1 -1
- package/dist/{chunk-HYHLKO3L.js → chunk-TUBBWIOM.js} +81 -9
- package/dist/{chunk-2IHQY3WC.js → chunk-XONT46YC.js} +239 -42
- package/dist/events/index.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/sandboxes/index.js +1 -1
- package/dist/{types-DG4J_zMT.d.ts → types-t01PuLUJ.d.ts} +16 -0
- package/package.json +1 -1
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, a3 as RawAgentEvent, b as AgentAttachRequest, y as AttachedRun, aa as SetupLayout } from '../types-
|
|
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-
|
|
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-t01PuLUJ.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-t01PuLUJ.js';
|
|
3
3
|
import { S as Sandbox } from '../Sandbox-DcKAU-E3.js';
|
|
4
4
|
export { AgentProvider } from '../enums.js';
|
|
5
5
|
import 'e2b';
|
|
@@ -42,6 +42,23 @@ declare class Agent<P extends AgentProviderName = AgentProviderName> {
|
|
|
42
42
|
* work.
|
|
43
43
|
*/
|
|
44
44
|
setup(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Stop the long-lived provider CLI server booted by {@link Agent.setup}
|
|
47
|
+
* (claude-code relay daemon, codex app-server, opencode `serve`).
|
|
48
|
+
*
|
|
49
|
+
* agentbox NEVER kills a running server on its own — not on run
|
|
50
|
+
* completion, not on `abort()`, and not when {@link Agent.setup} detects
|
|
51
|
+
* a changed config/credential set. This method is the single, explicit,
|
|
52
|
+
* developer-driven teardown. Call it to free a server's resources, or to
|
|
53
|
+
* apply a changed config: after `killServer()` the next {@link setup}
|
|
54
|
+
* cold-starts a fresh server with the new configuration.
|
|
55
|
+
*
|
|
56
|
+
* Best-effort and idempotent: a no-op when no server is running, or when
|
|
57
|
+
* the provider has no shared server for the current mode (host-mode
|
|
58
|
+
* claude-code runs the SDK in-process; local codex spawns a fresh
|
|
59
|
+
* app-server per run, torn down with the run).
|
|
60
|
+
*/
|
|
61
|
+
killServer(): Promise<void>;
|
|
45
62
|
stream(runConfig: AgentRunConfig): AgentRun;
|
|
46
63
|
run(runConfig: AgentRunConfig): Promise<AgentResult>;
|
|
47
64
|
rawEvents(runConfig: AgentRunConfig): AsyncIterable<RawAgentEvent>;
|
package/dist/agents/index.js
CHANGED
|
@@ -251,9 +251,33 @@ function resolveSandboxResources(resources) {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// src/sandboxes/providers/daytona.ts
|
|
254
|
+
var STARTABLE_STATES = /* @__PURE__ */ new Set(["stopped", "archived"]);
|
|
255
|
+
var TERMINAL_STATES = /* @__PURE__ */ new Set([
|
|
256
|
+
"error",
|
|
257
|
+
"build_failed",
|
|
258
|
+
"destroyed",
|
|
259
|
+
"destroying"
|
|
260
|
+
]);
|
|
261
|
+
var ATTACH_SETTLE_TIMEOUT_MS = 12e4;
|
|
262
|
+
var ATTACH_POLL_INTERVAL_MS = 2e3;
|
|
263
|
+
function isStateChangeInProgressError(err) {
|
|
264
|
+
const e = err;
|
|
265
|
+
if (!e) return false;
|
|
266
|
+
return e.statusCode === 409 || e.name === "DaytonaConflictError" || /state change in progress/i.test(e.message ?? "");
|
|
267
|
+
}
|
|
254
268
|
var DaytonaSandboxAdapter = class extends SandboxAdapter {
|
|
255
269
|
client;
|
|
256
270
|
sandbox;
|
|
271
|
+
/**
|
|
272
|
+
* Per-sandbox preview access token, captured from `getPreviewLink`.
|
|
273
|
+
* Daytona's preview proxy now requires this token to reach a sandbox's
|
|
274
|
+
* ports: unauthenticated requests get 307-redirected to an Auth0 login
|
|
275
|
+
* (which surfaces as a 307 on WebSocket upgrades and a 404 on plain GETs).
|
|
276
|
+
* The token is sandbox-level and stable across ports, so caching the most
|
|
277
|
+
* recent one is sufficient — every consumer calls `getPreviewLink` to build
|
|
278
|
+
* the URL right before reading `previewHeaders`. See {@link previewHeaders}.
|
|
279
|
+
*/
|
|
280
|
+
previewToken;
|
|
257
281
|
constructor(options) {
|
|
258
282
|
super(options);
|
|
259
283
|
this.client = new Daytona({
|
|
@@ -282,20 +306,54 @@ var DaytonaSandboxAdapter = class extends SandboxAdapter {
|
|
|
282
306
|
throw new Error(`Daytona sandbox ${id} not found`);
|
|
283
307
|
}
|
|
284
308
|
this.sandbox = existing;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
309
|
+
this.isWarmFlag = existing.state === "started";
|
|
310
|
+
await this.ensureStarted(existing);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Bring a sandbox to the `started` state, tolerating in-flight transitions.
|
|
314
|
+
*
|
|
315
|
+
* `start()` only works from a resting state (`stopped`/`archived`); calling
|
|
316
|
+
* it while the sandbox is creating/starting/restoring/snapshotting/etc. — or
|
|
317
|
+
* racing another caller that's already starting it — makes Daytona 409 with
|
|
318
|
+
* "Sandbox state change in progress". So we poll: start from a resting
|
|
319
|
+
* state, wait out a transition, fail fast on a terminal state, and treat a
|
|
320
|
+
* 409 as "someone else is mid-transition" and keep waiting.
|
|
321
|
+
*/
|
|
322
|
+
async ensureStarted(sandbox) {
|
|
323
|
+
let current = sandbox;
|
|
324
|
+
const deadline = Date.now() + ATTACH_SETTLE_TIMEOUT_MS;
|
|
325
|
+
for (; ; ) {
|
|
326
|
+
const state = current.state ?? "unknown";
|
|
327
|
+
if (state === "started") return;
|
|
328
|
+
if (TERMINAL_STATES.has(state)) {
|
|
329
|
+
throw new Error(
|
|
330
|
+
`Daytona sandbox ${current.id} is in a terminal state: ${state}`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (STARTABLE_STATES.has(state)) {
|
|
334
|
+
try {
|
|
335
|
+
await current.start();
|
|
336
|
+
return;
|
|
337
|
+
} catch (err) {
|
|
338
|
+
if (!isStateChangeInProgressError(err)) throw err;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (Date.now() >= deadline) {
|
|
342
|
+
throw new Error(
|
|
343
|
+
`Timed out waiting for Daytona sandbox ${current.id} to start (state=${state})`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
await sleep(ATTACH_POLL_INTERVAL_MS);
|
|
347
|
+
current = await this.client.get(current.id);
|
|
348
|
+
this.sandbox = current;
|
|
289
349
|
}
|
|
290
|
-
this.isWarmFlag = isWarm;
|
|
291
350
|
}
|
|
292
351
|
async provision() {
|
|
293
352
|
const existing = await this.findMatchingSandbox();
|
|
294
353
|
if (existing) {
|
|
295
354
|
this.sandbox = existing;
|
|
296
|
-
|
|
297
|
-
await
|
|
298
|
-
this.isWarmFlag = isWarm;
|
|
355
|
+
this.isWarmFlag = existing.state === "started";
|
|
356
|
+
await this.ensureStarted(existing);
|
|
299
357
|
return;
|
|
300
358
|
}
|
|
301
359
|
const labels = this.getLabels();
|
|
@@ -494,12 +552,26 @@ var DaytonaSandboxAdapter = class extends SandboxAdapter {
|
|
|
494
552
|
}
|
|
495
553
|
async openPort(port) {
|
|
496
554
|
this.requireProvisioned();
|
|
497
|
-
await this.requireSandbox().getPreviewLink(port);
|
|
555
|
+
const preview = await this.requireSandbox().getPreviewLink(port);
|
|
556
|
+
this.previewToken = preview.token;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Headers callers must attach to HTTP/WebSocket requests against this
|
|
560
|
+
* sandbox's preview URLs. Daytona private sandboxes gate their preview
|
|
561
|
+
* proxy behind `x-daytona-preview-token`; without it the proxy 307-redirects
|
|
562
|
+
* to Auth0, which breaks every provider (claude-code `/start` 404, codex WS
|
|
563
|
+
* "307", opencode `/session` 404). The token is captured lazily from
|
|
564
|
+
* `getPreviewLink`/`openPort`, both of which every consumer calls to build
|
|
565
|
+
* the URL immediately before reading these headers.
|
|
566
|
+
*/
|
|
567
|
+
get previewHeaders() {
|
|
568
|
+
return this.previewToken ? { "x-daytona-preview-token": this.previewToken } : {};
|
|
498
569
|
}
|
|
499
570
|
async getPreviewLink(port) {
|
|
500
571
|
this.requireProvisioned();
|
|
501
572
|
const sandbox = this.requireSandbox();
|
|
502
573
|
const preview = await sandbox.getPreviewLink(port);
|
|
574
|
+
this.previewToken = preview.token;
|
|
503
575
|
return preview.url;
|
|
504
576
|
}
|
|
505
577
|
async uploadFile(content, targetPath) {
|
|
@@ -1244,16 +1244,23 @@ async function preflightSetup(target, setupId, daemon) {
|
|
|
1244
1244
|
);
|
|
1245
1245
|
}
|
|
1246
1246
|
async function markSetupComplete(target, setupId) {
|
|
1247
|
-
await time(
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
)
|
|
1256
|
-
|
|
1247
|
+
await time(debugSetup, `markSetupComplete ${target.provider}`, async () => {
|
|
1248
|
+
const setupIdFile = path5.posix.join(
|
|
1249
|
+
target.layout.rootDir,
|
|
1250
|
+
SETUP_ID_FILENAME
|
|
1251
|
+
);
|
|
1252
|
+
const result = await target.uploadAndRun(
|
|
1253
|
+
[{ path: setupIdFile, content: setupId }],
|
|
1254
|
+
"true"
|
|
1255
|
+
);
|
|
1256
|
+
if (result.exitCode !== 0) {
|
|
1257
|
+
const detail = result.combinedOutput?.trim();
|
|
1258
|
+
throw new Error(
|
|
1259
|
+
`markSetupComplete failed (${result.exitCode})${detail ? `
|
|
1260
|
+
${detail}` : ""}`
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1257
1264
|
}
|
|
1258
1265
|
function buildInstallScript(rootDir, installCommandsByKey) {
|
|
1259
1266
|
const commandsB64 = Buffer.from(
|
|
@@ -1641,6 +1648,8 @@ var DAEMON_PORT = 43180;
|
|
|
1641
1648
|
var DAEMON_PATH = "/tmp/agentbox/claude-code/daemon.mjs";
|
|
1642
1649
|
var DAEMON_LOG_PATH = "/tmp/agentbox/claude-code/daemon.log";
|
|
1643
1650
|
var DAEMON_PID_PATH = "/tmp/agentbox/claude-code/daemon.pid";
|
|
1651
|
+
var DAEMON_READY_TIMEOUT_MS = 3e4;
|
|
1652
|
+
var DAEMON_READY_POLL_INTERVAL_MS = 250;
|
|
1644
1653
|
function claudeConfigDir(options) {
|
|
1645
1654
|
return path8.join(
|
|
1646
1655
|
agentboxRoot(AgentProvider.ClaudeCode, Boolean(options.sandbox)),
|
|
@@ -2078,16 +2087,44 @@ async function ensureClaudeCodeDaemonUncached(options, env) {
|
|
|
2078
2087
|
`Could not start claude-code daemon: ${launch.stderr || launch.combinedOutput || "(no output)"}`
|
|
2079
2088
|
);
|
|
2080
2089
|
}
|
|
2090
|
+
const deadline = Date.now() + DAEMON_READY_TIMEOUT_MS;
|
|
2091
|
+
let lastProbe = "";
|
|
2092
|
+
while (Date.now() < deadline) {
|
|
2093
|
+
const ready = await sandbox.run(
|
|
2094
|
+
`curl -fsS --max-time 1 http://127.0.0.1:${DAEMON_PORT}/__version 2>/dev/null`,
|
|
2095
|
+
{ cwd: options.cwd, timeoutMs: 1e4 }
|
|
2096
|
+
);
|
|
2097
|
+
lastProbe = ready.combinedOutput.trim();
|
|
2098
|
+
if (ready.exitCode === 0 && lastProbe === DAEMON_PROTOCOL_VERSION) {
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
await sleep(DAEMON_READY_POLL_INTERVAL_MS);
|
|
2102
|
+
}
|
|
2103
|
+
const logTail = await sandbox.run(`tail -n 20 ${shellQuote(DAEMON_LOG_PATH)} 2>/dev/null`, {
|
|
2104
|
+
cwd: options.cwd
|
|
2105
|
+
}).catch(() => void 0);
|
|
2106
|
+
throw new Error(
|
|
2107
|
+
`claude-code daemon did not become ready within ${DAEMON_READY_TIMEOUT_MS}ms` + (lastProbe ? ` (last /__version response: ${lastProbe})` : "") + (logTail?.combinedOutput ? `
|
|
2108
|
+
${logTail.combinedOutput}` : "")
|
|
2109
|
+
);
|
|
2081
2110
|
});
|
|
2082
2111
|
}
|
|
2083
2112
|
var DAEMON_FIRST_REQUEST_RETRY_BUDGET_MS = 3e4;
|
|
2084
2113
|
var DAEMON_FIRST_REQUEST_RETRY_INTERVAL_MS = 250;
|
|
2114
|
+
var TRANSIENT_PROXY_STATUSES = /* @__PURE__ */ new Set([404, 502, 503, 504]);
|
|
2085
2115
|
async function fetchWithDaemonRetry(input, init) {
|
|
2086
2116
|
const deadline = Date.now() + DAEMON_FIRST_REQUEST_RETRY_BUDGET_MS;
|
|
2087
2117
|
let lastError;
|
|
2118
|
+
let lastResponse;
|
|
2088
2119
|
while (Date.now() < deadline) {
|
|
2089
2120
|
try {
|
|
2090
|
-
|
|
2121
|
+
const response = await fetch(input, init);
|
|
2122
|
+
if (TRANSIENT_PROXY_STATUSES.has(response.status)) {
|
|
2123
|
+
lastResponse = response;
|
|
2124
|
+
await sleep(DAEMON_FIRST_REQUEST_RETRY_INTERVAL_MS);
|
|
2125
|
+
continue;
|
|
2126
|
+
}
|
|
2127
|
+
return response;
|
|
2091
2128
|
} catch (error) {
|
|
2092
2129
|
lastError = error;
|
|
2093
2130
|
const aborted = error?.name === "AbortError";
|
|
@@ -2097,6 +2134,9 @@ async function fetchWithDaemonRetry(input, init) {
|
|
|
2097
2134
|
await sleep(DAEMON_FIRST_REQUEST_RETRY_INTERVAL_MS);
|
|
2098
2135
|
}
|
|
2099
2136
|
}
|
|
2137
|
+
if (lastResponse) {
|
|
2138
|
+
return lastResponse;
|
|
2139
|
+
}
|
|
2100
2140
|
throw lastError ?? new Error("claude-code daemon request timed out");
|
|
2101
2141
|
}
|
|
2102
2142
|
async function* parseNdjsonStream(body) {
|
|
@@ -2141,6 +2181,24 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2141
2181
|
* match what we'd produce, we skip the artifact upload AND the daemon
|
|
2142
2182
|
* boot entirely.
|
|
2143
2183
|
*/
|
|
2184
|
+
/**
|
|
2185
|
+
* Explicit, developer-invoked teardown of the in-sandbox claude-code
|
|
2186
|
+
* relay daemon (see {@link AgentProviderAdapter.killServer}). agentbox
|
|
2187
|
+
* never calls this on its own. Best-effort and idempotent: a no-op when
|
|
2188
|
+
* the daemon isn't running or no sandbox is configured. After it returns
|
|
2189
|
+
* the next `setup()` re-spawns the daemon (its `/__version` probe fails).
|
|
2190
|
+
*/
|
|
2191
|
+
async killServer(request) {
|
|
2192
|
+
const sandbox = request.options.sandbox;
|
|
2193
|
+
if (!sandbox) return;
|
|
2194
|
+
await sandbox.run(
|
|
2195
|
+
[
|
|
2196
|
+
`if [ -f ${shellQuote(DAEMON_PID_PATH)} ]; then kill -TERM "$(cat ${shellQuote(DAEMON_PID_PATH)})" 2>/dev/null || true; rm -f ${shellQuote(DAEMON_PID_PATH)}; fi`,
|
|
2197
|
+
`fuser -k -n tcp ${DAEMON_PORT} 2>/dev/null || true`
|
|
2198
|
+
].join("; "),
|
|
2199
|
+
{ cwd: request.options.cwd, timeoutMs: 1e4 }
|
|
2200
|
+
).catch(() => void 0);
|
|
2201
|
+
}
|
|
2144
2202
|
async setup(request) {
|
|
2145
2203
|
await time(debugClaude, "claude-code setup()", async () => {
|
|
2146
2204
|
const options = request.options;
|
|
@@ -3533,10 +3591,34 @@ async function buildCodexInputItems(options, inputParts) {
|
|
|
3533
3591
|
);
|
|
3534
3592
|
return inputItems;
|
|
3535
3593
|
}
|
|
3594
|
+
async function killCodexAppServer(request) {
|
|
3595
|
+
const { options } = request;
|
|
3596
|
+
const sandbox = options.sandbox;
|
|
3597
|
+
if (!sandbox) return;
|
|
3598
|
+
const sharedTarget = await createSetupTarget(
|
|
3599
|
+
request.provider,
|
|
3600
|
+
REMOTE_CODEX_APP_SERVER_ID,
|
|
3601
|
+
options
|
|
3602
|
+
);
|
|
3603
|
+
const pidFilePath = path9.posix.join(
|
|
3604
|
+
sharedTarget.layout.rootDir,
|
|
3605
|
+
"codex-app-server.pid"
|
|
3606
|
+
);
|
|
3607
|
+
await sandbox.run(
|
|
3608
|
+
[
|
|
3609
|
+
`if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || true; rm -f ${shellQuote(pidFilePath)}; fi`,
|
|
3610
|
+
`fuser -k -n tcp ${REMOTE_CODEX_APP_SERVER_PORT} 2>/dev/null || true`
|
|
3611
|
+
].join("; "),
|
|
3612
|
+
{ cwd: options.cwd, timeoutMs: 1e4 }
|
|
3613
|
+
).catch(() => void 0);
|
|
3614
|
+
}
|
|
3536
3615
|
var CodexAgentAdapter = class {
|
|
3537
3616
|
async setup(request) {
|
|
3538
3617
|
await setupCodex(request);
|
|
3539
3618
|
}
|
|
3619
|
+
async killServer(request) {
|
|
3620
|
+
await killCodexAppServer(request);
|
|
3621
|
+
}
|
|
3540
3622
|
async execute(request, sink) {
|
|
3541
3623
|
const executeStartedAt = Date.now();
|
|
3542
3624
|
debugCodex("execute() start runId=%s", request.runId);
|
|
@@ -4112,6 +4194,12 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4112
4194
|
debugOpencode("opencode setup() preflight hit \u2014 skipping");
|
|
4113
4195
|
return;
|
|
4114
4196
|
}
|
|
4197
|
+
if (await isSandboxOpenCodeServerHealthy(sandbox, options.cwd, port)) {
|
|
4198
|
+
debugOpencode(
|
|
4199
|
+
"opencode server already running but setup drifted \u2014 reusing it without restart; call agent.killServer() to apply the new config"
|
|
4200
|
+
);
|
|
4201
|
+
return;
|
|
4202
|
+
}
|
|
4115
4203
|
const commonEnv = {
|
|
4116
4204
|
OPENCODE_CONFIG: configPath,
|
|
4117
4205
|
OPENCODE_CONFIG_DIR: target.layout.opencodeDir,
|
|
@@ -4147,42 +4235,79 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4147
4235
|
`disown 2>/dev/null || true`
|
|
4148
4236
|
].join(" ")})`
|
|
4149
4237
|
].join(" && ");
|
|
4150
|
-
|
|
4151
|
-
const
|
|
4238
|
+
const OPENCODE_MAX_LAUNCH_ATTEMPTS = 4;
|
|
4239
|
+
const OPENCODE_RELAUNCH_BACKOFF_MS = 1e3;
|
|
4240
|
+
const readyDeadline = Date.now() + SANDBOX_OPENCODE_READY_TIMEOUT_MS;
|
|
4241
|
+
const pidAlive = `kill -0 "$(cat ${shellQuote(pidFilePath)} 2>/dev/null)" 2>/dev/null`;
|
|
4242
|
+
let lastLog = "";
|
|
4243
|
+
const becameReady = await time(
|
|
4152
4244
|
debugOpencode,
|
|
4153
|
-
"
|
|
4154
|
-
() =>
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4245
|
+
"launch + poll opencode until ready",
|
|
4246
|
+
async () => {
|
|
4247
|
+
for (let attempt = 1; attempt <= OPENCODE_MAX_LAUNCH_ATTEMPTS && Date.now() < readyDeadline; attempt++) {
|
|
4248
|
+
await killSandboxOpenCodeServer(
|
|
4249
|
+
sandbox,
|
|
4250
|
+
pidFilePath,
|
|
4251
|
+
options.cwd,
|
|
4252
|
+
port
|
|
4253
|
+
);
|
|
4254
|
+
const launchResult = await sandbox.run(launchCommand, {
|
|
4255
|
+
cwd: options.cwd,
|
|
4256
|
+
env: serveEnv,
|
|
4257
|
+
timeoutMs: 4e4
|
|
4258
|
+
});
|
|
4259
|
+
if (launchResult.exitCode !== 0) {
|
|
4260
|
+
await target.cleanup().catch(() => void 0);
|
|
4261
|
+
throw new Error(
|
|
4262
|
+
`Could not start OpenCode server: ${launchResult.combinedOutput || launchResult.stderr}`
|
|
4263
|
+
);
|
|
4264
|
+
}
|
|
4265
|
+
while (Date.now() < readyDeadline) {
|
|
4266
|
+
const probe = await sandbox.run(
|
|
4267
|
+
`curl -fsS http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
|
|
4268
|
+
{ cwd: options.cwd, timeoutMs: 5e3 }
|
|
4269
|
+
);
|
|
4270
|
+
if (probe.exitCode === 0) {
|
|
4271
|
+
debugOpencode("ready on attempt %d", attempt);
|
|
4272
|
+
return true;
|
|
4273
|
+
}
|
|
4274
|
+
const alive = await sandbox.run(pidAlive, {
|
|
4275
|
+
cwd: options.cwd,
|
|
4276
|
+
timeoutMs: 5e3
|
|
4277
|
+
});
|
|
4278
|
+
if (alive.exitCode !== 0) {
|
|
4279
|
+
lastLog = (await sandbox.run(`tail -n 40 ${shellQuote(logFilePath)} 2>/dev/null`, {
|
|
4280
|
+
cwd: options.cwd
|
|
4281
|
+
}).catch(() => void 0))?.combinedOutput?.trim() ?? lastLog;
|
|
4282
|
+
debugOpencode(
|
|
4283
|
+
"opencode died on attempt %d/%d; relaunching. log:\n%s",
|
|
4284
|
+
attempt,
|
|
4285
|
+
OPENCODE_MAX_LAUNCH_ATTEMPTS,
|
|
4286
|
+
lastLog
|
|
4287
|
+
);
|
|
4288
|
+
break;
|
|
4289
|
+
}
|
|
4290
|
+
await sleep(500);
|
|
4291
|
+
}
|
|
4292
|
+
if (Date.now() >= readyDeadline) break;
|
|
4293
|
+
await sleep(OPENCODE_RELAUNCH_BACKOFF_MS);
|
|
4178
4294
|
}
|
|
4179
|
-
|
|
4295
|
+
return false;
|
|
4296
|
+
}
|
|
4297
|
+
);
|
|
4298
|
+
if (!becameReady) {
|
|
4299
|
+
if (!lastLog) {
|
|
4300
|
+
lastLog = (await sandbox.run(`tail -n 40 ${shellQuote(logFilePath)} 2>/dev/null`, {
|
|
4301
|
+
cwd: options.cwd
|
|
4302
|
+
}).catch(() => void 0))?.combinedOutput?.trim() ?? "";
|
|
4180
4303
|
}
|
|
4181
4304
|
await target.cleanup().catch(() => void 0);
|
|
4182
4305
|
throw new Error(
|
|
4183
|
-
`OpenCode server did not become ready within ${SANDBOX_OPENCODE_READY_TIMEOUT_MS}ms.`
|
|
4306
|
+
`OpenCode server did not become ready within ${SANDBOX_OPENCODE_READY_TIMEOUT_MS}ms.` + (lastLog ? `
|
|
4307
|
+
opencode log:
|
|
4308
|
+
${lastLog}` : "")
|
|
4184
4309
|
);
|
|
4185
|
-
}
|
|
4310
|
+
}
|
|
4186
4311
|
await markSetupComplete(target, setupId);
|
|
4187
4312
|
});
|
|
4188
4313
|
}
|
|
@@ -4234,7 +4359,13 @@ async function ensureLocalOpenCodeServer(request) {
|
|
|
4234
4359
|
debugOpencode("local opencode server up-to-date \u2014 reusing");
|
|
4235
4360
|
return;
|
|
4236
4361
|
}
|
|
4237
|
-
|
|
4362
|
+
if (await isLocalOpenCodeServerHealthy()) {
|
|
4363
|
+
debugOpencode(
|
|
4364
|
+
"local opencode server already running but setup drifted \u2014 reusing it without restart; call agent.killServer() to apply the new config"
|
|
4365
|
+
);
|
|
4366
|
+
return;
|
|
4367
|
+
}
|
|
4368
|
+
debugOpencode("local opencode server absent \u2014 spawning");
|
|
4238
4369
|
await applyDifferentialSetup(target, allArtifacts, installCommands);
|
|
4239
4370
|
await killLocalOpenCodeServer();
|
|
4240
4371
|
spawnCommand({
|
|
@@ -4267,6 +4398,45 @@ async function setupOpenCode(request) {
|
|
|
4267
4398
|
}
|
|
4268
4399
|
await ensureLocalOpenCodeServer(request);
|
|
4269
4400
|
}
|
|
4401
|
+
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);
|
|
4406
|
+
return probe?.exitCode === 0;
|
|
4407
|
+
}
|
|
4408
|
+
async function isLocalOpenCodeServerHealthy() {
|
|
4409
|
+
try {
|
|
4410
|
+
const res = await fetch(
|
|
4411
|
+
`http://127.0.0.1:${LOCAL_OPENCODE_PORT}/global/health`
|
|
4412
|
+
);
|
|
4413
|
+
return res.ok;
|
|
4414
|
+
} catch {
|
|
4415
|
+
return false;
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
async function killOpenCodeServer(request) {
|
|
4419
|
+
const { options } = request;
|
|
4420
|
+
if (options.sandbox) {
|
|
4421
|
+
const target = await createSetupTarget(
|
|
4422
|
+
request.provider,
|
|
4423
|
+
SHARED_OPENCODE_TARGET_ID,
|
|
4424
|
+
options
|
|
4425
|
+
);
|
|
4426
|
+
const pidFilePath = path10.posix.join(
|
|
4427
|
+
target.layout.rootDir,
|
|
4428
|
+
"opencode-serve.pid"
|
|
4429
|
+
);
|
|
4430
|
+
await killSandboxOpenCodeServer(
|
|
4431
|
+
options.sandbox,
|
|
4432
|
+
pidFilePath,
|
|
4433
|
+
options.cwd,
|
|
4434
|
+
SANDBOX_OPENCODE_PORT
|
|
4435
|
+
);
|
|
4436
|
+
return;
|
|
4437
|
+
}
|
|
4438
|
+
await killLocalOpenCodeServer();
|
|
4439
|
+
}
|
|
4270
4440
|
async function buildOpenCodeRuntime(options) {
|
|
4271
4441
|
if (options.sandbox) {
|
|
4272
4442
|
const sandbox = options.sandbox;
|
|
@@ -4288,6 +4458,9 @@ var OpenCodeAgentAdapter = class {
|
|
|
4288
4458
|
async setup(request) {
|
|
4289
4459
|
await setupOpenCode(request);
|
|
4290
4460
|
}
|
|
4461
|
+
async killServer(request) {
|
|
4462
|
+
await killOpenCodeServer(request);
|
|
4463
|
+
}
|
|
4291
4464
|
async execute(request, sink) {
|
|
4292
4465
|
const executeStartedAt = Date.now();
|
|
4293
4466
|
debugOpencode("execute() start runId=%s", request.runId);
|
|
@@ -5276,6 +5449,30 @@ var Agent = class {
|
|
|
5276
5449
|
throw error;
|
|
5277
5450
|
}
|
|
5278
5451
|
}
|
|
5452
|
+
/**
|
|
5453
|
+
* Stop the long-lived provider CLI server booted by {@link Agent.setup}
|
|
5454
|
+
* (claude-code relay daemon, codex app-server, opencode `serve`).
|
|
5455
|
+
*
|
|
5456
|
+
* agentbox NEVER kills a running server on its own — not on run
|
|
5457
|
+
* completion, not on `abort()`, and not when {@link Agent.setup} detects
|
|
5458
|
+
* a changed config/credential set. This method is the single, explicit,
|
|
5459
|
+
* developer-driven teardown. Call it to free a server's resources, or to
|
|
5460
|
+
* apply a changed config: after `killServer()` the next {@link setup}
|
|
5461
|
+
* cold-starts a fresh server with the new configuration.
|
|
5462
|
+
*
|
|
5463
|
+
* Best-effort and idempotent: a no-op when no server is running, or when
|
|
5464
|
+
* the provider has no shared server for the current mode (host-mode
|
|
5465
|
+
* claude-code runs the SDK in-process; local codex spawns a fresh
|
|
5466
|
+
* app-server per run, torn down with the run).
|
|
5467
|
+
*/
|
|
5468
|
+
async killServer() {
|
|
5469
|
+
debugAgent("killServer() provider=%s", this.provider);
|
|
5470
|
+
await this.adapter.killServer({
|
|
5471
|
+
provider: this.provider,
|
|
5472
|
+
options: this.options
|
|
5473
|
+
});
|
|
5474
|
+
this.setupPromise = void 0;
|
|
5475
|
+
}
|
|
5279
5476
|
stream(runConfig) {
|
|
5280
5477
|
if (runConfig.resumeSessionId && runConfig.forkSessionId) {
|
|
5281
5478
|
throw new Error(
|
package/dist/events/index.d.ts
CHANGED
|
@@ -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-
|
|
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-t01PuLUJ.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-
|
|
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-t01PuLUJ.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-
|
|
5
|
+
} from "./chunk-XONT46YC.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderLogAssembler,
|
|
8
8
|
createNormalizedEvent,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
Sandbox,
|
|
15
15
|
SandboxAdapter,
|
|
16
16
|
buildGitCloneCommand
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TUBBWIOM.js";
|
|
18
18
|
import {
|
|
19
19
|
AGENT_RESERVED_PORTS,
|
|
20
20
|
collectAllAgentReservedPorts
|
package/dist/sandboxes/index.js
CHANGED
|
@@ -599,6 +599,22 @@ interface AgentProviderAdapter<P extends AgentProviderName = AgentProviderName>
|
|
|
599
599
|
* is already listening.
|
|
600
600
|
*/
|
|
601
601
|
setup(request: AgentSetupRequest<P>): Promise<void>;
|
|
602
|
+
/**
|
|
603
|
+
* Stop the long-lived provider CLI server that {@link setup} boots
|
|
604
|
+
* (claude-code relay daemon, codex app-server, opencode `serve`).
|
|
605
|
+
*
|
|
606
|
+
* agentbox NEVER calls this on its own — not on run completion, not on
|
|
607
|
+
* abort, and not when {@link setup} sees a changed config/credential
|
|
608
|
+
* set. It exists purely so a developer can explicitly tear a server
|
|
609
|
+
* down (to reclaim resources, or to force the changed config to apply
|
|
610
|
+
* on the next cold {@link setup}).
|
|
611
|
+
*
|
|
612
|
+
* Best-effort and idempotent: a no-op when nothing is running, or when
|
|
613
|
+
* the provider has no shared server for the current mode (host-mode
|
|
614
|
+
* claude-code runs the SDK in-process; local codex spawns a fresh
|
|
615
|
+
* app-server per run).
|
|
616
|
+
*/
|
|
617
|
+
killServer(request: AgentSetupRequest<P>): Promise<void>;
|
|
602
618
|
execute(request: AgentExecutionRequest<P>, sink: AgentRunSink): Promise<() => Promise<void> | void>;
|
|
603
619
|
/**
|
|
604
620
|
* Stateless abort. Dial the in-sandbox provider server, issue the
|