agentbox-sdk 0.1.316 → 0.1.318
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
|
@@ -2571,6 +2571,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2571
2571
|
};
|
|
2572
2572
|
|
|
2573
2573
|
// src/agents/providers/codex.ts
|
|
2574
|
+
import crypto from "crypto";
|
|
2574
2575
|
import path9 from "path";
|
|
2575
2576
|
|
|
2576
2577
|
// src/agents/transports/app-server.ts
|
|
@@ -2797,6 +2798,61 @@ function codexConfigDir(options) {
|
|
|
2797
2798
|
}
|
|
2798
2799
|
var REMOTE_CODEX_APP_SERVER_PORT = 43181;
|
|
2799
2800
|
var REMOTE_CODEX_APP_SERVER_ID = "shared-app-server";
|
|
2801
|
+
var CODEX_APP_SERVER_TOKEN_FILENAME = "codex-app-server-token";
|
|
2802
|
+
function defaultRemoteCodexTokenPath() {
|
|
2803
|
+
return path9.posix.join(
|
|
2804
|
+
agentboxRoot(AgentProvider.Codex, true),
|
|
2805
|
+
CODEX_APP_SERVER_TOKEN_FILENAME
|
|
2806
|
+
);
|
|
2807
|
+
}
|
|
2808
|
+
var codexAppServerTokenCache = /* @__PURE__ */ new WeakMap();
|
|
2809
|
+
async function readCodexAppServerTokenFile(sandbox, tokenFilePath) {
|
|
2810
|
+
const result = await sandbox.run(
|
|
2811
|
+
`if [ -f ${shellQuote(tokenFilePath)} ]; then cat ${shellQuote(tokenFilePath)}; fi`
|
|
2812
|
+
);
|
|
2813
|
+
if (result.exitCode !== 0) {
|
|
2814
|
+
return void 0;
|
|
2815
|
+
}
|
|
2816
|
+
const value = result.stdout.trim();
|
|
2817
|
+
return value.length > 0 ? value : void 0;
|
|
2818
|
+
}
|
|
2819
|
+
function resolveCodexAppServerToken(sandbox, tokenFilePath, create) {
|
|
2820
|
+
let cached = codexAppServerTokenCache.get(sandbox);
|
|
2821
|
+
if (!cached) {
|
|
2822
|
+
cached = (async () => {
|
|
2823
|
+
const existing = await readCodexAppServerTokenFile(
|
|
2824
|
+
sandbox,
|
|
2825
|
+
tokenFilePath
|
|
2826
|
+
);
|
|
2827
|
+
if (existing) {
|
|
2828
|
+
return existing;
|
|
2829
|
+
}
|
|
2830
|
+
if (create) {
|
|
2831
|
+
return crypto.randomBytes(32).toString("hex");
|
|
2832
|
+
}
|
|
2833
|
+
throw new Error(
|
|
2834
|
+
`Codex app-server token file is missing at ${tokenFilePath}. setup() must run before connecting to the codex app-server.`
|
|
2835
|
+
);
|
|
2836
|
+
})().catch((error) => {
|
|
2837
|
+
codexAppServerTokenCache.delete(sandbox);
|
|
2838
|
+
throw error;
|
|
2839
|
+
});
|
|
2840
|
+
codexAppServerTokenCache.set(sandbox, cached);
|
|
2841
|
+
}
|
|
2842
|
+
return cached;
|
|
2843
|
+
}
|
|
2844
|
+
function ensureCodexAppServerToken(sandbox, tokenFilePath) {
|
|
2845
|
+
return resolveCodexAppServerToken(sandbox, tokenFilePath, true);
|
|
2846
|
+
}
|
|
2847
|
+
function getCodexAppServerToken(sandbox, tokenFilePath = defaultRemoteCodexTokenPath()) {
|
|
2848
|
+
return resolveCodexAppServerToken(sandbox, tokenFilePath, false);
|
|
2849
|
+
}
|
|
2850
|
+
function withCodexAppServerAuthHeaders(base, token) {
|
|
2851
|
+
return {
|
|
2852
|
+
...base,
|
|
2853
|
+
Authorization: `Bearer ${token}`
|
|
2854
|
+
};
|
|
2855
|
+
}
|
|
2800
2856
|
function compactEnv(values) {
|
|
2801
2857
|
return Object.fromEntries(
|
|
2802
2858
|
Object.entries(values).filter(([, value]) => value !== void 0)
|
|
@@ -3131,9 +3187,10 @@ async function withCodexAppServer(request, body) {
|
|
|
3131
3187
|
);
|
|
3132
3188
|
}
|
|
3133
3189
|
const previewUrl = await sandbox.getPreviewLink(REMOTE_CODEX_APP_SERVER_PORT);
|
|
3190
|
+
const token = await getCodexAppServerToken(sandbox);
|
|
3134
3191
|
const transport = await connectJsonRpcWebSocket(
|
|
3135
3192
|
toRemoteCodexWebSocketUrl(previewUrl),
|
|
3136
|
-
{ headers: sandbox.previewHeaders }
|
|
3193
|
+
{ headers: withCodexAppServerAuthHeaders(sandbox.previewHeaders, token) }
|
|
3137
3194
|
);
|
|
3138
3195
|
const client = new JsonRpcLineClient(
|
|
3139
3196
|
transport.source,
|
|
@@ -3219,7 +3276,19 @@ async function setupCodex(request) {
|
|
|
3219
3276
|
...sharedTarget.env,
|
|
3220
3277
|
...options.provider?.env ?? {}
|
|
3221
3278
|
});
|
|
3222
|
-
const
|
|
3279
|
+
const tokenFilePath = path9.posix.join(
|
|
3280
|
+
sharedTarget.layout.rootDir,
|
|
3281
|
+
CODEX_APP_SERVER_TOKEN_FILENAME
|
|
3282
|
+
);
|
|
3283
|
+
const appServerToken = await ensureCodexAppServerToken(
|
|
3284
|
+
sandbox,
|
|
3285
|
+
tokenFilePath
|
|
3286
|
+
);
|
|
3287
|
+
const { artifacts: baseServerArtifacts } = buildArtifactsFor(sharedTarget);
|
|
3288
|
+
const serverArtifacts = [
|
|
3289
|
+
...baseServerArtifacts,
|
|
3290
|
+
{ path: tokenFilePath, content: appServerToken }
|
|
3291
|
+
];
|
|
3223
3292
|
const { artifacts: skillArtifacts2, installCommands: installCommands2 } = await prepareSkillArtifacts(provider, options.skills, target2.layout);
|
|
3224
3293
|
const enableRtk2 = options.enableRtk === true;
|
|
3225
3294
|
const daemonInfo = {
|
|
@@ -3260,6 +3329,7 @@ async function setupCodex(request) {
|
|
|
3260
3329
|
`mkdir -p ${shellQuote(sharedTarget.layout.rootDir)}`,
|
|
3261
3330
|
`if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then exit 0; fi`,
|
|
3262
3331
|
`if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" >/dev/null 2>&1 || true; rm -f ${shellQuote(pidFilePath)}; fi`,
|
|
3332
|
+
`chmod 600 ${shellQuote(tokenFilePath)}`,
|
|
3263
3333
|
`(${[
|
|
3264
3334
|
`nohup ${[
|
|
3265
3335
|
"env",
|
|
@@ -3268,7 +3338,15 @@ async function setupCodex(request) {
|
|
|
3268
3338
|
[
|
|
3269
3339
|
"app-server",
|
|
3270
3340
|
"--listen",
|
|
3271
|
-
`ws://0.0.0.0:${REMOTE_CODEX_APP_SERVER_PORT}
|
|
3341
|
+
`ws://0.0.0.0:${REMOTE_CODEX_APP_SERVER_PORT}`,
|
|
3342
|
+
// Auth on non-loopback listeners is opt-in in codex; without
|
|
3343
|
+
// these flags the 0.0.0.0 app-server accepts unauthenticated
|
|
3344
|
+
// clients. Requires codex >= 0.133 (`--ws-auth` flag); older
|
|
3345
|
+
// pinned binaries will fail to launch on the unknown arg.
|
|
3346
|
+
"--ws-auth",
|
|
3347
|
+
"capability-token",
|
|
3348
|
+
"--ws-token-file",
|
|
3349
|
+
tokenFilePath
|
|
3272
3350
|
],
|
|
3273
3351
|
options
|
|
3274
3352
|
)
|
|
@@ -3343,9 +3421,10 @@ async function createRuntime(request, inputParts) {
|
|
|
3343
3421
|
"getPreviewLink app-server",
|
|
3344
3422
|
() => sandbox.getPreviewLink(REMOTE_CODEX_APP_SERVER_PORT)
|
|
3345
3423
|
);
|
|
3424
|
+
const token = await getCodexAppServerToken(sandbox);
|
|
3346
3425
|
const transport = await connectRemoteCodexAppServer(
|
|
3347
3426
|
toRemoteCodexWebSocketUrl(previewUrl),
|
|
3348
|
-
sandbox.previewHeaders
|
|
3427
|
+
withCodexAppServerAuthHeaders(sandbox.previewHeaders, token)
|
|
3349
3428
|
);
|
|
3350
3429
|
debugCodex("\u2605 codex transport established");
|
|
3351
3430
|
return {
|
|
@@ -3790,12 +3869,74 @@ var CodexAgentAdapter = class {
|
|
|
3790
3869
|
};
|
|
3791
3870
|
|
|
3792
3871
|
// src/agents/providers/opencode.ts
|
|
3872
|
+
import { createHash as createHash2 } from "crypto";
|
|
3793
3873
|
import path10 from "path";
|
|
3794
3874
|
var SANDBOX_OPENCODE_PORT = 4096;
|
|
3795
3875
|
var LOCAL_OPENCODE_PORT = 4096;
|
|
3796
3876
|
var SANDBOX_OPENCODE_READY_TIMEOUT_MS = 9e4;
|
|
3797
3877
|
var LOCAL_OPENCODE_READY_TIMEOUT_MS = 2e4;
|
|
3798
3878
|
var SHARED_OPENCODE_TARGET_ID = "shared-opencode-server";
|
|
3879
|
+
var LLM_API_KEY_ENV_VARS = [
|
|
3880
|
+
"OPENROUTER_API_KEY",
|
|
3881
|
+
"OPENAI_API_KEY",
|
|
3882
|
+
"ANTHROPIC_API_KEY",
|
|
3883
|
+
"GOOGLE_GENERATIVE_AI_API_KEY",
|
|
3884
|
+
"GEMINI_API_KEY"
|
|
3885
|
+
];
|
|
3886
|
+
function hashLlmApiKeys(env) {
|
|
3887
|
+
const hasher = createHash2("sha256");
|
|
3888
|
+
for (const key of LLM_API_KEY_ENV_VARS) {
|
|
3889
|
+
if (env?.[key] !== void 0) {
|
|
3890
|
+
hasher.update(`${key}=${env[key]}
|
|
3891
|
+
`);
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
return hasher.digest("hex");
|
|
3895
|
+
}
|
|
3896
|
+
async function killLocalOpenCodeServer() {
|
|
3897
|
+
await time(debugOpencode, "kill local opencode server", async () => {
|
|
3898
|
+
const killer = spawnCommand({
|
|
3899
|
+
command: "sh",
|
|
3900
|
+
args: [
|
|
3901
|
+
"-c",
|
|
3902
|
+
`lsof -ti tcp:${LOCAL_OPENCODE_PORT} | xargs kill 2>/dev/null || true`
|
|
3903
|
+
]
|
|
3904
|
+
});
|
|
3905
|
+
await killer.wait().catch(() => void 0);
|
|
3906
|
+
await waitFor(
|
|
3907
|
+
async () => {
|
|
3908
|
+
try {
|
|
3909
|
+
const res = await fetch(
|
|
3910
|
+
`http://127.0.0.1:${LOCAL_OPENCODE_PORT}/global/health`
|
|
3911
|
+
);
|
|
3912
|
+
return !res.ok;
|
|
3913
|
+
} catch {
|
|
3914
|
+
return true;
|
|
3915
|
+
}
|
|
3916
|
+
},
|
|
3917
|
+
{ timeoutMs: 5e3, intervalMs: 200 }
|
|
3918
|
+
).catch(() => void 0);
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
async function killSandboxOpenCodeServer(sandbox, pidFilePath, cwd, port) {
|
|
3922
|
+
await time(debugOpencode, "kill sandbox opencode server", async () => {
|
|
3923
|
+
await sandbox.run(
|
|
3924
|
+
`kill -- -"$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || kill "$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || true`,
|
|
3925
|
+
{ cwd, timeoutMs: 5e3 }
|
|
3926
|
+
).catch(() => void 0);
|
|
3927
|
+
const deadline = Date.now() + 5e3;
|
|
3928
|
+
while (Date.now() < deadline) {
|
|
3929
|
+
const probe = await sandbox.run(
|
|
3930
|
+
`curl -fsS --max-time 2 http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
|
|
3931
|
+
{ cwd, timeoutMs: 5e3 }
|
|
3932
|
+
);
|
|
3933
|
+
if (probe.exitCode !== 0) {
|
|
3934
|
+
return;
|
|
3935
|
+
}
|
|
3936
|
+
await sleep(200);
|
|
3937
|
+
}
|
|
3938
|
+
});
|
|
3939
|
+
}
|
|
3799
3940
|
function toRawEvent3(runId, payload, type) {
|
|
3800
3941
|
return {
|
|
3801
3942
|
provider: AgentProvider.OpenCode,
|
|
@@ -3891,6 +4032,10 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
3891
4032
|
const googleBaseUrl = options.env?.GOOGLE_BASE_URL;
|
|
3892
4033
|
const openRouterBaseUrl = options.env?.OPENROUTER_BASE_URL;
|
|
3893
4034
|
const openRouterPlugins = options.openRouterPlugins && options.openRouterPlugins.length > 0 ? options.openRouterPlugins : void 0;
|
|
4035
|
+
const openRouterExtraBody = {
|
|
4036
|
+
transforms: ["middle-out"],
|
|
4037
|
+
...openRouterPlugins ? { plugins: openRouterPlugins } : {}
|
|
4038
|
+
};
|
|
3894
4039
|
return {
|
|
3895
4040
|
$schema: "https://opencode.ai/config.json",
|
|
3896
4041
|
...mcpConfig ? { mcp: mcpConfig } : {},
|
|
@@ -3899,7 +4044,7 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
3899
4044
|
openrouter: {
|
|
3900
4045
|
options: {
|
|
3901
4046
|
baseURL: openRouterBaseUrl || "https://openrouter.ai/api/v1",
|
|
3902
|
-
|
|
4047
|
+
extraBody: openRouterExtraBody
|
|
3903
4048
|
}
|
|
3904
4049
|
},
|
|
3905
4050
|
...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl } } } : {}
|
|
@@ -3949,7 +4094,10 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
3949
4094
|
artifacts: allArtifacts,
|
|
3950
4095
|
installCommands,
|
|
3951
4096
|
daemon: daemonInfo,
|
|
3952
|
-
extras: [
|
|
4097
|
+
extras: [
|
|
4098
|
+
`enableRtk:${enableRtk}`,
|
|
4099
|
+
`apiKeys:${hashLlmApiKeys(options.env)}`
|
|
4100
|
+
]
|
|
3953
4101
|
});
|
|
3954
4102
|
if (await preflightSetup(target, setupId, daemonInfo)) {
|
|
3955
4103
|
debugOpencode("opencode setup() preflight hit \u2014 skipping");
|
|
@@ -3990,13 +4138,14 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
3990
4138
|
`disown 2>/dev/null || true`
|
|
3991
4139
|
].join(" ")})`
|
|
3992
4140
|
].join(" && ");
|
|
4141
|
+
await killSandboxOpenCodeServer(sandbox, pidFilePath, options.cwd, port);
|
|
3993
4142
|
const launchResult = await time(
|
|
3994
4143
|
debugOpencode,
|
|
3995
4144
|
"spawn opencode serve",
|
|
3996
4145
|
() => sandbox.run(launchCommand, {
|
|
3997
4146
|
cwd: options.cwd,
|
|
3998
4147
|
env: serveEnv,
|
|
3999
|
-
timeoutMs:
|
|
4148
|
+
timeoutMs: 2e4
|
|
4000
4149
|
})
|
|
4001
4150
|
);
|
|
4002
4151
|
if (launchResult.exitCode !== 0) {
|
|
@@ -4030,16 +4179,6 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4030
4179
|
}
|
|
4031
4180
|
async function ensureLocalOpenCodeServer(request) {
|
|
4032
4181
|
const options = request.options;
|
|
4033
|
-
try {
|
|
4034
|
-
await waitForHttpReady(
|
|
4035
|
-
`http://127.0.0.1:${LOCAL_OPENCODE_PORT}/global/health`,
|
|
4036
|
-
{ timeoutMs: 1e3 }
|
|
4037
|
-
);
|
|
4038
|
-
debugOpencode("local opencode server already running \u2014 reusing");
|
|
4039
|
-
return;
|
|
4040
|
-
} catch {
|
|
4041
|
-
debugOpencode("local opencode server not running \u2014 cold-spawning");
|
|
4042
|
-
}
|
|
4043
4182
|
const plugins = assertHooksSupported(request.provider, options);
|
|
4044
4183
|
assertCommandsSupported(request.provider, options.commands);
|
|
4045
4184
|
const interactiveApproval = isInteractiveApproval(options);
|
|
@@ -4072,14 +4211,23 @@ async function ensureLocalOpenCodeServer(request) {
|
|
|
4072
4211
|
content: JSON.stringify(openCodeConfig, null, 2)
|
|
4073
4212
|
}
|
|
4074
4213
|
];
|
|
4214
|
+
const daemonInfo = {
|
|
4215
|
+
port: LOCAL_OPENCODE_PORT,
|
|
4216
|
+
healthPath: "/global/health"
|
|
4217
|
+
};
|
|
4075
4218
|
const setupId = computeSetupId({
|
|
4076
4219
|
artifacts: allArtifacts,
|
|
4077
|
-
installCommands
|
|
4220
|
+
installCommands,
|
|
4221
|
+
daemon: daemonInfo,
|
|
4222
|
+
extras: [`apiKeys:${hashLlmApiKeys(options.env)}`]
|
|
4078
4223
|
});
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4224
|
+
if (await preflightSetup(target, setupId, daemonInfo)) {
|
|
4225
|
+
debugOpencode("local opencode server up-to-date \u2014 reusing");
|
|
4226
|
+
return;
|
|
4082
4227
|
}
|
|
4228
|
+
debugOpencode("local opencode server drifted/absent \u2014 (re)spawning");
|
|
4229
|
+
await applyDifferentialSetup(target, allArtifacts, installCommands);
|
|
4230
|
+
await killLocalOpenCodeServer();
|
|
4083
4231
|
spawnCommand({
|
|
4084
4232
|
command: options.provider?.binary ?? "opencode",
|
|
4085
4233
|
args: [
|
package/dist/index.js
CHANGED