agentbox-sdk 0.1.319 → 0.1.322
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.js
CHANGED
|
@@ -254,6 +254,16 @@ function resolveSandboxResources(resources) {
|
|
|
254
254
|
var DaytonaSandboxAdapter = class extends SandboxAdapter {
|
|
255
255
|
client;
|
|
256
256
|
sandbox;
|
|
257
|
+
/**
|
|
258
|
+
* Per-sandbox preview access token, captured from `getPreviewLink`.
|
|
259
|
+
* Daytona's preview proxy now requires this token to reach a sandbox's
|
|
260
|
+
* ports: unauthenticated requests get 307-redirected to an Auth0 login
|
|
261
|
+
* (which surfaces as a 307 on WebSocket upgrades and a 404 on plain GETs).
|
|
262
|
+
* The token is sandbox-level and stable across ports, so caching the most
|
|
263
|
+
* recent one is sufficient — every consumer calls `getPreviewLink` to build
|
|
264
|
+
* the URL right before reading `previewHeaders`. See {@link previewHeaders}.
|
|
265
|
+
*/
|
|
266
|
+
previewToken;
|
|
257
267
|
constructor(options) {
|
|
258
268
|
super(options);
|
|
259
269
|
this.client = new Daytona({
|
|
@@ -494,12 +504,26 @@ var DaytonaSandboxAdapter = class extends SandboxAdapter {
|
|
|
494
504
|
}
|
|
495
505
|
async openPort(port) {
|
|
496
506
|
this.requireProvisioned();
|
|
497
|
-
await this.requireSandbox().getPreviewLink(port);
|
|
507
|
+
const preview = await this.requireSandbox().getPreviewLink(port);
|
|
508
|
+
this.previewToken = preview.token;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Headers callers must attach to HTTP/WebSocket requests against this
|
|
512
|
+
* sandbox's preview URLs. Daytona private sandboxes gate their preview
|
|
513
|
+
* proxy behind `x-daytona-preview-token`; without it the proxy 307-redirects
|
|
514
|
+
* to Auth0, which breaks every provider (claude-code `/start` 404, codex WS
|
|
515
|
+
* "307", opencode `/session` 404). The token is captured lazily from
|
|
516
|
+
* `getPreviewLink`/`openPort`, both of which every consumer calls to build
|
|
517
|
+
* the URL immediately before reading these headers.
|
|
518
|
+
*/
|
|
519
|
+
get previewHeaders() {
|
|
520
|
+
return this.previewToken ? { "x-daytona-preview-token": this.previewToken } : {};
|
|
498
521
|
}
|
|
499
522
|
async getPreviewLink(port) {
|
|
500
523
|
this.requireProvisioned();
|
|
501
524
|
const sandbox = this.requireSandbox();
|
|
502
525
|
const preview = await sandbox.getPreviewLink(port);
|
|
526
|
+
this.previewToken = preview.token;
|
|
503
527
|
return preview.url;
|
|
504
528
|
}
|
|
505
529
|
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) {
|
|
@@ -4147,42 +4187,79 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4147
4187
|
`disown 2>/dev/null || true`
|
|
4148
4188
|
].join(" ")})`
|
|
4149
4189
|
].join(" && ");
|
|
4150
|
-
|
|
4151
|
-
const
|
|
4190
|
+
const OPENCODE_MAX_LAUNCH_ATTEMPTS = 4;
|
|
4191
|
+
const OPENCODE_RELAUNCH_BACKOFF_MS = 1e3;
|
|
4192
|
+
const readyDeadline = Date.now() + SANDBOX_OPENCODE_READY_TIMEOUT_MS;
|
|
4193
|
+
const pidAlive = `kill -0 "$(cat ${shellQuote(pidFilePath)} 2>/dev/null)" 2>/dev/null`;
|
|
4194
|
+
let lastLog = "";
|
|
4195
|
+
const becameReady = await time(
|
|
4152
4196
|
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
|
-
|
|
4197
|
+
"launch + poll opencode until ready",
|
|
4198
|
+
async () => {
|
|
4199
|
+
for (let attempt = 1; attempt <= OPENCODE_MAX_LAUNCH_ATTEMPTS && Date.now() < readyDeadline; attempt++) {
|
|
4200
|
+
await killSandboxOpenCodeServer(
|
|
4201
|
+
sandbox,
|
|
4202
|
+
pidFilePath,
|
|
4203
|
+
options.cwd,
|
|
4204
|
+
port
|
|
4205
|
+
);
|
|
4206
|
+
const launchResult = await sandbox.run(launchCommand, {
|
|
4207
|
+
cwd: options.cwd,
|
|
4208
|
+
env: serveEnv,
|
|
4209
|
+
timeoutMs: 4e4
|
|
4210
|
+
});
|
|
4211
|
+
if (launchResult.exitCode !== 0) {
|
|
4212
|
+
await target.cleanup().catch(() => void 0);
|
|
4213
|
+
throw new Error(
|
|
4214
|
+
`Could not start OpenCode server: ${launchResult.combinedOutput || launchResult.stderr}`
|
|
4215
|
+
);
|
|
4216
|
+
}
|
|
4217
|
+
while (Date.now() < readyDeadline) {
|
|
4218
|
+
const probe = await sandbox.run(
|
|
4219
|
+
`curl -fsS http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
|
|
4220
|
+
{ cwd: options.cwd, timeoutMs: 5e3 }
|
|
4221
|
+
);
|
|
4222
|
+
if (probe.exitCode === 0) {
|
|
4223
|
+
debugOpencode("ready on attempt %d", attempt);
|
|
4224
|
+
return true;
|
|
4225
|
+
}
|
|
4226
|
+
const alive = await sandbox.run(pidAlive, {
|
|
4227
|
+
cwd: options.cwd,
|
|
4228
|
+
timeoutMs: 5e3
|
|
4229
|
+
});
|
|
4230
|
+
if (alive.exitCode !== 0) {
|
|
4231
|
+
lastLog = (await sandbox.run(`tail -n 40 ${shellQuote(logFilePath)} 2>/dev/null`, {
|
|
4232
|
+
cwd: options.cwd
|
|
4233
|
+
}).catch(() => void 0))?.combinedOutput?.trim() ?? lastLog;
|
|
4234
|
+
debugOpencode(
|
|
4235
|
+
"opencode died on attempt %d/%d; relaunching. log:\n%s",
|
|
4236
|
+
attempt,
|
|
4237
|
+
OPENCODE_MAX_LAUNCH_ATTEMPTS,
|
|
4238
|
+
lastLog
|
|
4239
|
+
);
|
|
4240
|
+
break;
|
|
4241
|
+
}
|
|
4242
|
+
await sleep(500);
|
|
4243
|
+
}
|
|
4244
|
+
if (Date.now() >= readyDeadline) break;
|
|
4245
|
+
await sleep(OPENCODE_RELAUNCH_BACKOFF_MS);
|
|
4178
4246
|
}
|
|
4179
|
-
|
|
4247
|
+
return false;
|
|
4248
|
+
}
|
|
4249
|
+
);
|
|
4250
|
+
if (!becameReady) {
|
|
4251
|
+
if (!lastLog) {
|
|
4252
|
+
lastLog = (await sandbox.run(`tail -n 40 ${shellQuote(logFilePath)} 2>/dev/null`, {
|
|
4253
|
+
cwd: options.cwd
|
|
4254
|
+
}).catch(() => void 0))?.combinedOutput?.trim() ?? "";
|
|
4180
4255
|
}
|
|
4181
4256
|
await target.cleanup().catch(() => void 0);
|
|
4182
4257
|
throw new Error(
|
|
4183
|
-
`OpenCode server did not become ready within ${SANDBOX_OPENCODE_READY_TIMEOUT_MS}ms.`
|
|
4258
|
+
`OpenCode server did not become ready within ${SANDBOX_OPENCODE_READY_TIMEOUT_MS}ms.` + (lastLog ? `
|
|
4259
|
+
opencode log:
|
|
4260
|
+
${lastLog}` : "")
|
|
4184
4261
|
);
|
|
4185
|
-
}
|
|
4262
|
+
}
|
|
4186
4263
|
await markSetupComplete(target, setupId);
|
|
4187
4264
|
});
|
|
4188
4265
|
}
|
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-ZK5PDWOI.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-T4AS2WEF.js";
|
|
18
18
|
import {
|
|
19
19
|
AGENT_RESERVED_PORTS,
|
|
20
20
|
collectAllAgentReservedPorts
|
package/dist/sandboxes/index.js
CHANGED