agentbox-sdk 0.1.317 → 0.1.319
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
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
createNormalizedEvent,
|
|
3
3
|
normalizeRawAgentEvent,
|
|
4
4
|
toAISDKStream
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-775FIGGL.js";
|
|
6
6
|
import {
|
|
7
7
|
AgentBoxError,
|
|
8
8
|
AsyncQueue,
|
|
@@ -2328,6 +2328,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2328
2328
|
)
|
|
2329
2329
|
);
|
|
2330
2330
|
let accumulatedText = "";
|
|
2331
|
+
let streamedThinkingChars = 0;
|
|
2331
2332
|
let pendingMessages = 1;
|
|
2332
2333
|
let firstStreamEventLogged = false;
|
|
2333
2334
|
let firstTextDeltaLogged = false;
|
|
@@ -2399,8 +2400,15 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2399
2400
|
);
|
|
2400
2401
|
}
|
|
2401
2402
|
const partial = message;
|
|
2403
|
+
if (partial.parent_tool_use_id) continue;
|
|
2404
|
+
const streamType = partial.event?.type;
|
|
2405
|
+
if (streamType === "message_start") {
|
|
2406
|
+
accumulatedText = "";
|
|
2407
|
+
streamedThinkingChars = 0;
|
|
2408
|
+
}
|
|
2402
2409
|
const { text, thinking } = extractStreamDeltas(partial);
|
|
2403
2410
|
if (thinking) {
|
|
2411
|
+
streamedThinkingChars += thinking.length;
|
|
2404
2412
|
sink.emitEvent(
|
|
2405
2413
|
createNormalizedEvent(
|
|
2406
2414
|
"reasoning.delta",
|
|
@@ -2430,8 +2438,9 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2430
2438
|
}
|
|
2431
2439
|
if (message.type === "assistant") {
|
|
2432
2440
|
const asst = message;
|
|
2441
|
+
if (asst.parent_tool_use_id) continue;
|
|
2433
2442
|
const thinking = extractAssistantThinking(asst);
|
|
2434
|
-
if (thinking) {
|
|
2443
|
+
if (thinking && streamedThinkingChars === 0) {
|
|
2435
2444
|
sink.emitEvent(
|
|
2436
2445
|
createNormalizedEvent(
|
|
2437
2446
|
"reasoning.delta",
|
|
@@ -2571,6 +2580,7 @@ var ClaudeCodeAgentAdapter = class {
|
|
|
2571
2580
|
};
|
|
2572
2581
|
|
|
2573
2582
|
// src/agents/providers/codex.ts
|
|
2583
|
+
import crypto from "crypto";
|
|
2574
2584
|
import path9 from "path";
|
|
2575
2585
|
|
|
2576
2586
|
// src/agents/transports/app-server.ts
|
|
@@ -2797,6 +2807,61 @@ function codexConfigDir(options) {
|
|
|
2797
2807
|
}
|
|
2798
2808
|
var REMOTE_CODEX_APP_SERVER_PORT = 43181;
|
|
2799
2809
|
var REMOTE_CODEX_APP_SERVER_ID = "shared-app-server";
|
|
2810
|
+
var CODEX_APP_SERVER_TOKEN_FILENAME = "codex-app-server-token";
|
|
2811
|
+
function defaultRemoteCodexTokenPath() {
|
|
2812
|
+
return path9.posix.join(
|
|
2813
|
+
agentboxRoot(AgentProvider.Codex, true),
|
|
2814
|
+
CODEX_APP_SERVER_TOKEN_FILENAME
|
|
2815
|
+
);
|
|
2816
|
+
}
|
|
2817
|
+
var codexAppServerTokenCache = /* @__PURE__ */ new WeakMap();
|
|
2818
|
+
async function readCodexAppServerTokenFile(sandbox, tokenFilePath) {
|
|
2819
|
+
const result = await sandbox.run(
|
|
2820
|
+
`if [ -f ${shellQuote(tokenFilePath)} ]; then cat ${shellQuote(tokenFilePath)}; fi`
|
|
2821
|
+
);
|
|
2822
|
+
if (result.exitCode !== 0) {
|
|
2823
|
+
return void 0;
|
|
2824
|
+
}
|
|
2825
|
+
const value = result.stdout.trim();
|
|
2826
|
+
return value.length > 0 ? value : void 0;
|
|
2827
|
+
}
|
|
2828
|
+
function resolveCodexAppServerToken(sandbox, tokenFilePath, create) {
|
|
2829
|
+
let cached = codexAppServerTokenCache.get(sandbox);
|
|
2830
|
+
if (!cached) {
|
|
2831
|
+
cached = (async () => {
|
|
2832
|
+
const existing = await readCodexAppServerTokenFile(
|
|
2833
|
+
sandbox,
|
|
2834
|
+
tokenFilePath
|
|
2835
|
+
);
|
|
2836
|
+
if (existing) {
|
|
2837
|
+
return existing;
|
|
2838
|
+
}
|
|
2839
|
+
if (create) {
|
|
2840
|
+
return crypto.randomBytes(32).toString("hex");
|
|
2841
|
+
}
|
|
2842
|
+
throw new Error(
|
|
2843
|
+
`Codex app-server token file is missing at ${tokenFilePath}. setup() must run before connecting to the codex app-server.`
|
|
2844
|
+
);
|
|
2845
|
+
})().catch((error) => {
|
|
2846
|
+
codexAppServerTokenCache.delete(sandbox);
|
|
2847
|
+
throw error;
|
|
2848
|
+
});
|
|
2849
|
+
codexAppServerTokenCache.set(sandbox, cached);
|
|
2850
|
+
}
|
|
2851
|
+
return cached;
|
|
2852
|
+
}
|
|
2853
|
+
function ensureCodexAppServerToken(sandbox, tokenFilePath) {
|
|
2854
|
+
return resolveCodexAppServerToken(sandbox, tokenFilePath, true);
|
|
2855
|
+
}
|
|
2856
|
+
function getCodexAppServerToken(sandbox, tokenFilePath = defaultRemoteCodexTokenPath()) {
|
|
2857
|
+
return resolveCodexAppServerToken(sandbox, tokenFilePath, false);
|
|
2858
|
+
}
|
|
2859
|
+
function withCodexAppServerAuthHeaders(base, token) {
|
|
2860
|
+
return {
|
|
2861
|
+
...base,
|
|
2862
|
+
Authorization: `Bearer ${token}`
|
|
2863
|
+
};
|
|
2864
|
+
}
|
|
2800
2865
|
function compactEnv(values) {
|
|
2801
2866
|
return Object.fromEntries(
|
|
2802
2867
|
Object.entries(values).filter(([, value]) => value !== void 0)
|
|
@@ -3131,9 +3196,10 @@ async function withCodexAppServer(request, body) {
|
|
|
3131
3196
|
);
|
|
3132
3197
|
}
|
|
3133
3198
|
const previewUrl = await sandbox.getPreviewLink(REMOTE_CODEX_APP_SERVER_PORT);
|
|
3199
|
+
const token = await getCodexAppServerToken(sandbox);
|
|
3134
3200
|
const transport = await connectJsonRpcWebSocket(
|
|
3135
3201
|
toRemoteCodexWebSocketUrl(previewUrl),
|
|
3136
|
-
{ headers: sandbox.previewHeaders }
|
|
3202
|
+
{ headers: withCodexAppServerAuthHeaders(sandbox.previewHeaders, token) }
|
|
3137
3203
|
);
|
|
3138
3204
|
const client = new JsonRpcLineClient(
|
|
3139
3205
|
transport.source,
|
|
@@ -3219,7 +3285,19 @@ async function setupCodex(request) {
|
|
|
3219
3285
|
...sharedTarget.env,
|
|
3220
3286
|
...options.provider?.env ?? {}
|
|
3221
3287
|
});
|
|
3222
|
-
const
|
|
3288
|
+
const tokenFilePath = path9.posix.join(
|
|
3289
|
+
sharedTarget.layout.rootDir,
|
|
3290
|
+
CODEX_APP_SERVER_TOKEN_FILENAME
|
|
3291
|
+
);
|
|
3292
|
+
const appServerToken = await ensureCodexAppServerToken(
|
|
3293
|
+
sandbox,
|
|
3294
|
+
tokenFilePath
|
|
3295
|
+
);
|
|
3296
|
+
const { artifacts: baseServerArtifacts } = buildArtifactsFor(sharedTarget);
|
|
3297
|
+
const serverArtifacts = [
|
|
3298
|
+
...baseServerArtifacts,
|
|
3299
|
+
{ path: tokenFilePath, content: appServerToken }
|
|
3300
|
+
];
|
|
3223
3301
|
const { artifacts: skillArtifacts2, installCommands: installCommands2 } = await prepareSkillArtifacts(provider, options.skills, target2.layout);
|
|
3224
3302
|
const enableRtk2 = options.enableRtk === true;
|
|
3225
3303
|
const daemonInfo = {
|
|
@@ -3260,6 +3338,7 @@ async function setupCodex(request) {
|
|
|
3260
3338
|
`mkdir -p ${shellQuote(sharedTarget.layout.rootDir)}`,
|
|
3261
3339
|
`if curl -fsS http://127.0.0.1:${REMOTE_CODEX_APP_SERVER_PORT}/readyz >/dev/null 2>&1; then exit 0; fi`,
|
|
3262
3340
|
`if [ -f ${shellQuote(pidFilePath)} ]; then kill "$(cat ${shellQuote(pidFilePath)})" >/dev/null 2>&1 || true; rm -f ${shellQuote(pidFilePath)}; fi`,
|
|
3341
|
+
`chmod 600 ${shellQuote(tokenFilePath)}`,
|
|
3263
3342
|
`(${[
|
|
3264
3343
|
`nohup ${[
|
|
3265
3344
|
"env",
|
|
@@ -3268,7 +3347,15 @@ async function setupCodex(request) {
|
|
|
3268
3347
|
[
|
|
3269
3348
|
"app-server",
|
|
3270
3349
|
"--listen",
|
|
3271
|
-
`ws://0.0.0.0:${REMOTE_CODEX_APP_SERVER_PORT}
|
|
3350
|
+
`ws://0.0.0.0:${REMOTE_CODEX_APP_SERVER_PORT}`,
|
|
3351
|
+
// Auth on non-loopback listeners is opt-in in codex; without
|
|
3352
|
+
// these flags the 0.0.0.0 app-server accepts unauthenticated
|
|
3353
|
+
// clients. Requires codex >= 0.133 (`--ws-auth` flag); older
|
|
3354
|
+
// pinned binaries will fail to launch on the unknown arg.
|
|
3355
|
+
"--ws-auth",
|
|
3356
|
+
"capability-token",
|
|
3357
|
+
"--ws-token-file",
|
|
3358
|
+
tokenFilePath
|
|
3272
3359
|
],
|
|
3273
3360
|
options
|
|
3274
3361
|
)
|
|
@@ -3343,9 +3430,10 @@ async function createRuntime(request, inputParts) {
|
|
|
3343
3430
|
"getPreviewLink app-server",
|
|
3344
3431
|
() => sandbox.getPreviewLink(REMOTE_CODEX_APP_SERVER_PORT)
|
|
3345
3432
|
);
|
|
3433
|
+
const token = await getCodexAppServerToken(sandbox);
|
|
3346
3434
|
const transport = await connectRemoteCodexAppServer(
|
|
3347
3435
|
toRemoteCodexWebSocketUrl(previewUrl),
|
|
3348
|
-
sandbox.previewHeaders
|
|
3436
|
+
withCodexAppServerAuthHeaders(sandbox.previewHeaders, token)
|
|
3349
3437
|
);
|
|
3350
3438
|
debugCodex("\u2605 codex transport established");
|
|
3351
3439
|
return {
|
|
@@ -3790,12 +3878,74 @@ var CodexAgentAdapter = class {
|
|
|
3790
3878
|
};
|
|
3791
3879
|
|
|
3792
3880
|
// src/agents/providers/opencode.ts
|
|
3881
|
+
import { createHash as createHash2 } from "crypto";
|
|
3793
3882
|
import path10 from "path";
|
|
3794
3883
|
var SANDBOX_OPENCODE_PORT = 4096;
|
|
3795
3884
|
var LOCAL_OPENCODE_PORT = 4096;
|
|
3796
3885
|
var SANDBOX_OPENCODE_READY_TIMEOUT_MS = 9e4;
|
|
3797
3886
|
var LOCAL_OPENCODE_READY_TIMEOUT_MS = 2e4;
|
|
3798
3887
|
var SHARED_OPENCODE_TARGET_ID = "shared-opencode-server";
|
|
3888
|
+
var LLM_API_KEY_ENV_VARS = [
|
|
3889
|
+
"OPENROUTER_API_KEY",
|
|
3890
|
+
"OPENAI_API_KEY",
|
|
3891
|
+
"ANTHROPIC_API_KEY",
|
|
3892
|
+
"GOOGLE_GENERATIVE_AI_API_KEY",
|
|
3893
|
+
"GEMINI_API_KEY"
|
|
3894
|
+
];
|
|
3895
|
+
function hashLlmApiKeys(env) {
|
|
3896
|
+
const hasher = createHash2("sha256");
|
|
3897
|
+
for (const key of LLM_API_KEY_ENV_VARS) {
|
|
3898
|
+
if (env?.[key] !== void 0) {
|
|
3899
|
+
hasher.update(`${key}=${env[key]}
|
|
3900
|
+
`);
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
return hasher.digest("hex");
|
|
3904
|
+
}
|
|
3905
|
+
async function killLocalOpenCodeServer() {
|
|
3906
|
+
await time(debugOpencode, "kill local opencode server", async () => {
|
|
3907
|
+
const killer = spawnCommand({
|
|
3908
|
+
command: "sh",
|
|
3909
|
+
args: [
|
|
3910
|
+
"-c",
|
|
3911
|
+
`lsof -ti tcp:${LOCAL_OPENCODE_PORT} | xargs kill 2>/dev/null || true`
|
|
3912
|
+
]
|
|
3913
|
+
});
|
|
3914
|
+
await killer.wait().catch(() => void 0);
|
|
3915
|
+
await waitFor(
|
|
3916
|
+
async () => {
|
|
3917
|
+
try {
|
|
3918
|
+
const res = await fetch(
|
|
3919
|
+
`http://127.0.0.1:${LOCAL_OPENCODE_PORT}/global/health`
|
|
3920
|
+
);
|
|
3921
|
+
return !res.ok;
|
|
3922
|
+
} catch {
|
|
3923
|
+
return true;
|
|
3924
|
+
}
|
|
3925
|
+
},
|
|
3926
|
+
{ timeoutMs: 5e3, intervalMs: 200 }
|
|
3927
|
+
).catch(() => void 0);
|
|
3928
|
+
});
|
|
3929
|
+
}
|
|
3930
|
+
async function killSandboxOpenCodeServer(sandbox, pidFilePath, cwd, port) {
|
|
3931
|
+
await time(debugOpencode, "kill sandbox opencode server", async () => {
|
|
3932
|
+
await sandbox.run(
|
|
3933
|
+
`kill -- -"$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || kill "$(cat ${shellQuote(pidFilePath)})" 2>/dev/null || true`,
|
|
3934
|
+
{ cwd, timeoutMs: 5e3 }
|
|
3935
|
+
).catch(() => void 0);
|
|
3936
|
+
const deadline = Date.now() + 5e3;
|
|
3937
|
+
while (Date.now() < deadline) {
|
|
3938
|
+
const probe = await sandbox.run(
|
|
3939
|
+
`curl -fsS --max-time 2 http://127.0.0.1:${port}/global/health >/dev/null 2>&1`,
|
|
3940
|
+
{ cwd, timeoutMs: 5e3 }
|
|
3941
|
+
);
|
|
3942
|
+
if (probe.exitCode !== 0) {
|
|
3943
|
+
return;
|
|
3944
|
+
}
|
|
3945
|
+
await sleep(200);
|
|
3946
|
+
}
|
|
3947
|
+
});
|
|
3948
|
+
}
|
|
3799
3949
|
function toRawEvent3(runId, payload, type) {
|
|
3800
3950
|
return {
|
|
3801
3951
|
provider: AgentProvider.OpenCode,
|
|
@@ -3891,6 +4041,10 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
3891
4041
|
const googleBaseUrl = options.env?.GOOGLE_BASE_URL;
|
|
3892
4042
|
const openRouterBaseUrl = options.env?.OPENROUTER_BASE_URL;
|
|
3893
4043
|
const openRouterPlugins = options.openRouterPlugins && options.openRouterPlugins.length > 0 ? options.openRouterPlugins : void 0;
|
|
4044
|
+
const openRouterExtraBody = {
|
|
4045
|
+
transforms: ["middle-out"],
|
|
4046
|
+
...openRouterPlugins ? { plugins: openRouterPlugins } : {}
|
|
4047
|
+
};
|
|
3894
4048
|
return {
|
|
3895
4049
|
$schema: "https://opencode.ai/config.json",
|
|
3896
4050
|
...mcpConfig ? { mcp: mcpConfig } : {},
|
|
@@ -3899,7 +4053,7 @@ function buildOpenCodeConfig(options, interactiveApproval) {
|
|
|
3899
4053
|
openrouter: {
|
|
3900
4054
|
options: {
|
|
3901
4055
|
baseURL: openRouterBaseUrl || "https://openrouter.ai/api/v1",
|
|
3902
|
-
|
|
4056
|
+
extraBody: openRouterExtraBody
|
|
3903
4057
|
}
|
|
3904
4058
|
},
|
|
3905
4059
|
...googleBaseUrl ? { google: { options: { baseURL: googleBaseUrl } } } : {}
|
|
@@ -3949,7 +4103,10 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
3949
4103
|
artifacts: allArtifacts,
|
|
3950
4104
|
installCommands,
|
|
3951
4105
|
daemon: daemonInfo,
|
|
3952
|
-
extras: [
|
|
4106
|
+
extras: [
|
|
4107
|
+
`enableRtk:${enableRtk}`,
|
|
4108
|
+
`apiKeys:${hashLlmApiKeys(options.env)}`
|
|
4109
|
+
]
|
|
3953
4110
|
});
|
|
3954
4111
|
if (await preflightSetup(target, setupId, daemonInfo)) {
|
|
3955
4112
|
debugOpencode("opencode setup() preflight hit \u2014 skipping");
|
|
@@ -3990,6 +4147,7 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
3990
4147
|
`disown 2>/dev/null || true`
|
|
3991
4148
|
].join(" ")})`
|
|
3992
4149
|
].join(" && ");
|
|
4150
|
+
await killSandboxOpenCodeServer(sandbox, pidFilePath, options.cwd, port);
|
|
3993
4151
|
const launchResult = await time(
|
|
3994
4152
|
debugOpencode,
|
|
3995
4153
|
"spawn opencode serve",
|
|
@@ -4030,16 +4188,6 @@ async function ensureSandboxOpenCodeServer(request) {
|
|
|
4030
4188
|
}
|
|
4031
4189
|
async function ensureLocalOpenCodeServer(request) {
|
|
4032
4190
|
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
4191
|
const plugins = assertHooksSupported(request.provider, options);
|
|
4044
4192
|
assertCommandsSupported(request.provider, options.commands);
|
|
4045
4193
|
const interactiveApproval = isInteractiveApproval(options);
|
|
@@ -4072,14 +4220,23 @@ async function ensureLocalOpenCodeServer(request) {
|
|
|
4072
4220
|
content: JSON.stringify(openCodeConfig, null, 2)
|
|
4073
4221
|
}
|
|
4074
4222
|
];
|
|
4223
|
+
const daemonInfo = {
|
|
4224
|
+
port: LOCAL_OPENCODE_PORT,
|
|
4225
|
+
healthPath: "/global/health"
|
|
4226
|
+
};
|
|
4075
4227
|
const setupId = computeSetupId({
|
|
4076
4228
|
artifacts: allArtifacts,
|
|
4077
|
-
installCommands
|
|
4229
|
+
installCommands,
|
|
4230
|
+
daemon: daemonInfo,
|
|
4231
|
+
extras: [`apiKeys:${hashLlmApiKeys(options.env)}`]
|
|
4078
4232
|
});
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4233
|
+
if (await preflightSetup(target, setupId, daemonInfo)) {
|
|
4234
|
+
debugOpencode("local opencode server up-to-date \u2014 reusing");
|
|
4235
|
+
return;
|
|
4082
4236
|
}
|
|
4237
|
+
debugOpencode("local opencode server drifted/absent \u2014 (re)spawning");
|
|
4238
|
+
await applyDifferentialSetup(target, allArtifacts, installCommands);
|
|
4239
|
+
await killLocalOpenCodeServer();
|
|
4083
4240
|
spawnCommand({
|
|
4084
4241
|
command: options.provider?.binary ?? "opencode",
|
|
4085
4242
|
args: [
|
|
@@ -189,9 +189,35 @@ function isRecord(value) {
|
|
|
189
189
|
function clone(value) {
|
|
190
190
|
return JSON.parse(JSON.stringify(value));
|
|
191
191
|
}
|
|
192
|
+
function isCodexNoiseEvent(method) {
|
|
193
|
+
if (!method) return false;
|
|
194
|
+
if (method.startsWith("mcpServer/")) return true;
|
|
195
|
+
return method.toLowerCase().includes("delta");
|
|
196
|
+
}
|
|
192
197
|
var CodexLogAssembler = class {
|
|
193
198
|
byItemId = /* @__PURE__ */ new Map();
|
|
194
199
|
textByItemId = /* @__PURE__ */ new Map();
|
|
200
|
+
// Non-item events (turn/completed usage, error notifications, thread
|
|
201
|
+
// responses). Returned by `process()` for the live channel; tracked here so
|
|
202
|
+
// `getSnapshots()` — the end-of-run persistence source — keeps them too.
|
|
203
|
+
passThroughSnapshots = [];
|
|
204
|
+
// First-seen chronological order across items and passthroughs.
|
|
205
|
+
snapshotOrder = [];
|
|
206
|
+
trackItem(itemId, snapshot) {
|
|
207
|
+
if (!this.byItemId.has(itemId)) {
|
|
208
|
+
this.snapshotOrder.push({ kind: "item", id: itemId });
|
|
209
|
+
}
|
|
210
|
+
this.byItemId.set(itemId, snapshot);
|
|
211
|
+
}
|
|
212
|
+
pushPassThrough(event) {
|
|
213
|
+
const passthrough = clone(event);
|
|
214
|
+
this.snapshotOrder.push({
|
|
215
|
+
kind: "passthrough",
|
|
216
|
+
index: this.passThroughSnapshots.length
|
|
217
|
+
});
|
|
218
|
+
this.passThroughSnapshots.push(passthrough);
|
|
219
|
+
return clone(passthrough);
|
|
220
|
+
}
|
|
195
221
|
process(event) {
|
|
196
222
|
if (!isRecord(event)) {
|
|
197
223
|
return [];
|
|
@@ -201,7 +227,7 @@ var CodexLogAssembler = class {
|
|
|
201
227
|
const item = isRecord(params.item) ? clone(params.item) : null;
|
|
202
228
|
if (method === "item/started" || method === "item/updated" || method === "item/completed") {
|
|
203
229
|
if (item && typeof item.id === "string") {
|
|
204
|
-
this.
|
|
230
|
+
this.trackItem(item.id, clone(event));
|
|
205
231
|
const text = typeof item.text === "string" ? item.text : void 0;
|
|
206
232
|
if (text !== void 0) {
|
|
207
233
|
this.textByItemId.set(item.id, text);
|
|
@@ -247,7 +273,8 @@ var CodexLogAssembler = class {
|
|
|
247
273
|
})
|
|
248
274
|
];
|
|
249
275
|
}
|
|
250
|
-
return [
|
|
276
|
+
if (isCodexNoiseEvent(method)) return [];
|
|
277
|
+
return [this.pushPassThrough(event)];
|
|
251
278
|
}
|
|
252
279
|
/**
|
|
253
280
|
* Repopulate state from a sequence of previously-assembled snapshots so the
|
|
@@ -256,12 +283,24 @@ var CodexLogAssembler = class {
|
|
|
256
283
|
seed(snapshots) {
|
|
257
284
|
this.byItemId.clear();
|
|
258
285
|
this.textByItemId.clear();
|
|
286
|
+
this.passThroughSnapshots.length = 0;
|
|
287
|
+
this.snapshotOrder.length = 0;
|
|
259
288
|
for (const snapshot of snapshots) {
|
|
260
289
|
if (!isRecord(snapshot)) continue;
|
|
261
290
|
const params = isRecord(snapshot.params) ? snapshot.params : {};
|
|
262
291
|
const item = isRecord(params.item) ? params.item : null;
|
|
263
|
-
if (!item || typeof item.id !== "string")
|
|
264
|
-
|
|
292
|
+
if (!item || typeof item.id !== "string") {
|
|
293
|
+
const method = typeof snapshot.method === "string" ? snapshot.method : void 0;
|
|
294
|
+
if (!isCodexNoiseEvent(method)) {
|
|
295
|
+
this.snapshotOrder.push({
|
|
296
|
+
kind: "passthrough",
|
|
297
|
+
index: this.passThroughSnapshots.length
|
|
298
|
+
});
|
|
299
|
+
this.passThroughSnapshots.push(clone(snapshot));
|
|
300
|
+
}
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
this.trackItem(item.id, clone(snapshot));
|
|
265
304
|
const text = typeof item.text === "string" ? item.text : void 0;
|
|
266
305
|
if (text !== void 0) {
|
|
267
306
|
this.textByItemId.set(item.id, text);
|
|
@@ -288,11 +327,16 @@ var CodexLogAssembler = class {
|
|
|
288
327
|
}
|
|
289
328
|
}
|
|
290
329
|
};
|
|
291
|
-
this.
|
|
330
|
+
this.trackItem(itemId, next);
|
|
292
331
|
return clone(next);
|
|
293
332
|
}
|
|
294
333
|
getSnapshots() {
|
|
295
|
-
|
|
334
|
+
const out = [];
|
|
335
|
+
for (const entry of this.snapshotOrder) {
|
|
336
|
+
const snapshot = entry.kind === "item" ? this.byItemId.get(entry.id) : this.passThroughSnapshots[entry.index];
|
|
337
|
+
if (snapshot) out.push(clone(snapshot));
|
|
338
|
+
}
|
|
339
|
+
return out;
|
|
296
340
|
}
|
|
297
341
|
};
|
|
298
342
|
var OpenCodeLogAssembler = class {
|
|
@@ -314,6 +358,39 @@ var OpenCodeLogAssembler = class {
|
|
|
314
358
|
childSessionToTaskCallId = /* @__PURE__ */ new Map();
|
|
315
359
|
childMessageIdToTaskCallId = /* @__PURE__ */ new Map();
|
|
316
360
|
messageIdToSessionId = /* @__PURE__ */ new Map();
|
|
361
|
+
// Part-less events (user `message.updated`, session lifecycle, errors).
|
|
362
|
+
// Returned by `process()` for the live channel; tracked here so
|
|
363
|
+
// `getSnapshots()` — the end-of-run persistence source — keeps them too.
|
|
364
|
+
// `message.updated` events are keyed by info.id (they re-emit on metadata
|
|
365
|
+
// updates, latest wins); everything else appends.
|
|
366
|
+
keyedPassThrough = /* @__PURE__ */ new Map();
|
|
367
|
+
passThroughSnapshots = [];
|
|
368
|
+
// First-seen chronological order across parts and passthroughs.
|
|
369
|
+
snapshotOrder = [];
|
|
370
|
+
trackPart(partId, snapshot) {
|
|
371
|
+
if (!this.byPartId.has(partId)) {
|
|
372
|
+
this.snapshotOrder.push({ kind: "part", id: partId });
|
|
373
|
+
}
|
|
374
|
+
this.byPartId.set(partId, snapshot);
|
|
375
|
+
}
|
|
376
|
+
pushPassThrough(event) {
|
|
377
|
+
const passthrough = clone(event);
|
|
378
|
+
const info = isRecord(event.properties) ? isRecord(event.properties.info) ? event.properties.info : null : null;
|
|
379
|
+
if (event.type === "message.updated" && info && typeof info.id === "string") {
|
|
380
|
+
const key = `message:${info.id}`;
|
|
381
|
+
if (!this.keyedPassThrough.has(key)) {
|
|
382
|
+
this.snapshotOrder.push({ kind: "keyed", key });
|
|
383
|
+
}
|
|
384
|
+
this.keyedPassThrough.set(key, passthrough);
|
|
385
|
+
return clone(passthrough);
|
|
386
|
+
}
|
|
387
|
+
this.snapshotOrder.push({
|
|
388
|
+
kind: "passthrough",
|
|
389
|
+
index: this.passThroughSnapshots.length
|
|
390
|
+
});
|
|
391
|
+
this.passThroughSnapshots.push(passthrough);
|
|
392
|
+
return clone(passthrough);
|
|
393
|
+
}
|
|
317
394
|
process(event) {
|
|
318
395
|
if (!isRecord(event)) {
|
|
319
396
|
return [];
|
|
@@ -356,7 +433,7 @@ var OpenCodeLogAssembler = class {
|
|
|
356
433
|
}
|
|
357
434
|
if (type === "message.updated" && typeof info?.id === "string" && info.role === "user") {
|
|
358
435
|
this.userMessageIds.add(info.id);
|
|
359
|
-
return [
|
|
436
|
+
return [this.pushPassThrough(event)];
|
|
360
437
|
}
|
|
361
438
|
const parentTaskCallId = this.resolveParentTaskCallId(
|
|
362
439
|
effectiveSid,
|
|
@@ -412,10 +489,10 @@ var OpenCodeLogAssembler = class {
|
|
|
412
489
|
);
|
|
413
490
|
}
|
|
414
491
|
}
|
|
415
|
-
this.
|
|
492
|
+
this.trackPart(eventPart.id, enriched);
|
|
416
493
|
return [clone(enriched)];
|
|
417
494
|
}
|
|
418
|
-
return [
|
|
495
|
+
return [this.pushPassThrough(event)];
|
|
419
496
|
}
|
|
420
497
|
seed(snapshots) {
|
|
421
498
|
this.userMessageIds.clear();
|
|
@@ -426,6 +503,9 @@ var OpenCodeLogAssembler = class {
|
|
|
426
503
|
this.childSessionToTaskCallId.clear();
|
|
427
504
|
this.childMessageIdToTaskCallId.clear();
|
|
428
505
|
this.messageIdToSessionId.clear();
|
|
506
|
+
this.keyedPassThrough.clear();
|
|
507
|
+
this.passThroughSnapshots.length = 0;
|
|
508
|
+
this.snapshotOrder.length = 0;
|
|
429
509
|
for (const snapshot of snapshots) {
|
|
430
510
|
if (!isRecord(snapshot)) continue;
|
|
431
511
|
const type = typeof snapshot.type === "string" ? snapshot.type : "";
|
|
@@ -440,11 +520,16 @@ var OpenCodeLogAssembler = class {
|
|
|
440
520
|
}
|
|
441
521
|
if (type === "message.updated" && typeof info?.id === "string" && info.role === "user") {
|
|
442
522
|
this.userMessageIds.add(info.id);
|
|
523
|
+
this.pushPassThrough(snapshot);
|
|
443
524
|
continue;
|
|
444
525
|
}
|
|
445
526
|
const part = isRecord(properties.part) ? properties.part : isRecord(snapshot.part) ? snapshot.part : null;
|
|
527
|
+
if (!part || typeof part.id !== "string") {
|
|
528
|
+
this.pushPassThrough(snapshot);
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
446
531
|
if (part && typeof part.id === "string") {
|
|
447
|
-
this.
|
|
532
|
+
this.trackPart(part.id, clone(snapshot));
|
|
448
533
|
if (typeof part.text === "string") {
|
|
449
534
|
this.textByPartId.set(part.id, part.text);
|
|
450
535
|
}
|
|
@@ -538,13 +623,27 @@ var OpenCodeLogAssembler = class {
|
|
|
538
623
|
part
|
|
539
624
|
}
|
|
540
625
|
};
|
|
541
|
-
this.
|
|
626
|
+
this.trackPart(partId, next);
|
|
542
627
|
return clone(next);
|
|
543
628
|
}
|
|
544
629
|
getSnapshots() {
|
|
545
|
-
|
|
630
|
+
const out = [];
|
|
631
|
+
for (const entry of this.snapshotOrder) {
|
|
632
|
+
const snapshot = entry.kind === "part" ? this.byPartId.get(entry.id) : entry.kind === "keyed" ? this.keyedPassThrough.get(entry.key) : this.passThroughSnapshots[entry.index];
|
|
633
|
+
if (snapshot) out.push(clone(snapshot));
|
|
634
|
+
}
|
|
635
|
+
return out;
|
|
546
636
|
}
|
|
547
637
|
};
|
|
638
|
+
function isClaudeNoiseEvent(event) {
|
|
639
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
640
|
+
if (type === "rate_limit_event" || type === "tool_progress") return true;
|
|
641
|
+
if (type === "system") {
|
|
642
|
+
const sub = typeof event.subtype === "string" ? event.subtype : "";
|
|
643
|
+
return sub === "status" || sub === "hook_started" || sub === "hook_response" || sub === "hook_progress" || sub === "api_retry" || sub === "auth_status";
|
|
644
|
+
}
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
548
647
|
var ClaudeCodeLogAssembler = class {
|
|
549
648
|
currentMessageId = null;
|
|
550
649
|
textByMessageId = /* @__PURE__ */ new Map();
|
|
@@ -565,6 +664,12 @@ var ClaudeCodeLogAssembler = class {
|
|
|
565
664
|
// insertion order so `getSnapshots()` returns the full trace, not just the
|
|
566
665
|
// deduped assistant messages.
|
|
567
666
|
passThroughSnapshots = [];
|
|
667
|
+
// First-seen chronological order of everything `getSnapshots()` returns:
|
|
668
|
+
// messages anchor at the position of their first event (message_start or
|
|
669
|
+
// first assistant block) and passthroughs at arrival. Without this the
|
|
670
|
+
// persisted trace would list every message first and every tool_result /
|
|
671
|
+
// system event after, scrambling replay order for sequential consumers.
|
|
672
|
+
snapshotOrder = [];
|
|
568
673
|
process(event) {
|
|
569
674
|
if (!isRecord(event)) return [];
|
|
570
675
|
const type = typeof event.type === "string" ? event.type : "";
|
|
@@ -606,24 +711,32 @@ var ClaudeCodeLogAssembler = class {
|
|
|
606
711
|
const message = isRecord(event.message) ? event.message : null;
|
|
607
712
|
const id = message && typeof message.id === "string" ? message.id : null;
|
|
608
713
|
if (!id || !message) {
|
|
609
|
-
|
|
610
|
-
this.passThroughSnapshots.push(passthrough2);
|
|
611
|
-
return [clone(passthrough2)];
|
|
714
|
+
return [this.pushPassThrough(event)];
|
|
612
715
|
}
|
|
613
716
|
this.setParentToolUseId(id, event);
|
|
614
717
|
const final = extractClaudeAssistantContent(message);
|
|
615
|
-
this.textByMessageId.
|
|
616
|
-
if (final.
|
|
718
|
+
const streamedText = this.textByMessageId.get(id) ?? "";
|
|
719
|
+
if (final.text.length > streamedText.length) {
|
|
720
|
+
this.textByMessageId.set(id, final.text);
|
|
721
|
+
}
|
|
722
|
+
const streamedThinking = this.thinkingByMessageId.get(id) ?? "";
|
|
723
|
+
if (final.thinking.length > streamedThinking.length) {
|
|
617
724
|
this.thinkingByMessageId.set(id, final.thinking);
|
|
618
725
|
}
|
|
619
726
|
this.mergeExtraBlocks(id, final.extraBlocks);
|
|
620
|
-
|
|
621
|
-
this.currentMessageId = null;
|
|
622
|
-
return [snapshot];
|
|
727
|
+
return [this.upsertMessage(id)];
|
|
623
728
|
}
|
|
729
|
+
if (isClaudeNoiseEvent(event)) return [];
|
|
730
|
+
return [this.pushPassThrough(event)];
|
|
731
|
+
}
|
|
732
|
+
pushPassThrough(event) {
|
|
624
733
|
const passthrough = clone(event);
|
|
734
|
+
this.snapshotOrder.push({
|
|
735
|
+
kind: "passthrough",
|
|
736
|
+
index: this.passThroughSnapshots.length
|
|
737
|
+
});
|
|
625
738
|
this.passThroughSnapshots.push(passthrough);
|
|
626
|
-
return
|
|
739
|
+
return clone(passthrough);
|
|
627
740
|
}
|
|
628
741
|
seed(snapshots) {
|
|
629
742
|
this.currentMessageId = null;
|
|
@@ -633,15 +746,26 @@ var ClaudeCodeLogAssembler = class {
|
|
|
633
746
|
this.byMessageId.clear();
|
|
634
747
|
this.extraBlocksByMessageId.clear();
|
|
635
748
|
this.passThroughSnapshots.length = 0;
|
|
749
|
+
this.snapshotOrder.length = 0;
|
|
636
750
|
for (const snapshot of snapshots) {
|
|
637
751
|
if (!isRecord(snapshot)) continue;
|
|
638
752
|
if (snapshot.type !== "message.updated") {
|
|
639
|
-
|
|
753
|
+
if (!isClaudeNoiseEvent(snapshot)) {
|
|
754
|
+
this.snapshotOrder.push({
|
|
755
|
+
kind: "passthrough",
|
|
756
|
+
index: this.passThroughSnapshots.length
|
|
757
|
+
});
|
|
758
|
+
this.passThroughSnapshots.push(clone(snapshot));
|
|
759
|
+
}
|
|
640
760
|
continue;
|
|
641
761
|
}
|
|
642
762
|
const messageId = typeof snapshot.messageId === "string" ? snapshot.messageId : null;
|
|
643
763
|
if (!messageId) continue;
|
|
764
|
+
if (!this.byMessageId.has(messageId)) {
|
|
765
|
+
this.snapshotOrder.push({ kind: "message", id: messageId });
|
|
766
|
+
}
|
|
644
767
|
this.byMessageId.set(messageId, clone(snapshot));
|
|
768
|
+
this.currentMessageId = messageId;
|
|
645
769
|
const parentToolUseId = typeof snapshot.parent_tool_use_id === "string" ? snapshot.parent_tool_use_id : null;
|
|
646
770
|
this.parentToolUseIdByMessageId.set(messageId, parentToolUseId);
|
|
647
771
|
const message = isRecord(snapshot.message) ? snapshot.message : null;
|
|
@@ -707,13 +831,18 @@ var ClaudeCodeLogAssembler = class {
|
|
|
707
831
|
content
|
|
708
832
|
}
|
|
709
833
|
};
|
|
834
|
+
if (!this.byMessageId.has(messageId)) {
|
|
835
|
+
this.snapshotOrder.push({ kind: "message", id: messageId });
|
|
836
|
+
}
|
|
710
837
|
this.byMessageId.set(messageId, next);
|
|
711
838
|
return clone(next);
|
|
712
839
|
}
|
|
713
840
|
getSnapshots() {
|
|
714
841
|
const out = [];
|
|
715
|
-
for (const
|
|
716
|
-
|
|
842
|
+
for (const entry of this.snapshotOrder) {
|
|
843
|
+
const snapshot = entry.kind === "message" ? this.byMessageId.get(entry.id) : this.passThroughSnapshots[entry.index];
|
|
844
|
+
if (snapshot) out.push(clone(snapshot));
|
|
845
|
+
}
|
|
717
846
|
return out;
|
|
718
847
|
}
|
|
719
848
|
};
|
package/dist/events/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
Agent,
|
|
3
3
|
agentboxRoot,
|
|
4
4
|
getAgentLayout
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2IHQY3WC.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderLogAssembler,
|
|
8
8
|
createNormalizedEvent,
|
|
9
9
|
normalizeRawAgentEvent,
|
|
10
10
|
toAISDKEvent,
|
|
11
11
|
toAISDKStream
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-775FIGGL.js";
|
|
13
13
|
import {
|
|
14
14
|
Sandbox,
|
|
15
15
|
SandboxAdapter,
|