@posthog/agent 2.1.47 → 2.1.53
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/{agent-BJ7Uacyp.d.ts → agent-9gv5HohC.d.ts} +4 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +91 -132
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +288 -327
- package/dist/index.js.map +1 -1
- package/dist/server/agent-server.js +286 -325
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +293 -332
- package/dist/server/bin.cjs.map +1 -1
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/adapters/acp-connection.ts +1 -6
- package/src/adapters/claude/claude-agent.ts +39 -75
- package/src/agent.ts +1 -1
- package/src/session-log-writer.ts +50 -0
- package/src/types.ts +2 -0
|
@@ -44,6 +44,8 @@ interface SessionLogWriterOptions {
|
|
|
44
44
|
posthogAPI?: PostHogAPIClient;
|
|
45
45
|
/** Logger instance */
|
|
46
46
|
logger?: Logger;
|
|
47
|
+
/** Local cache path for instant log loading (e.g., ~/.twig) */
|
|
48
|
+
localCachePath?: string;
|
|
47
49
|
}
|
|
48
50
|
declare class SessionLogWriter {
|
|
49
51
|
private static readonly FLUSH_DEBOUNCE_MS;
|
|
@@ -58,6 +60,7 @@ declare class SessionLogWriter {
|
|
|
58
60
|
private sessions;
|
|
59
61
|
private messageCounts;
|
|
60
62
|
private logger;
|
|
63
|
+
private localCachePath?;
|
|
61
64
|
constructor(options?: SessionLogWriterOptions);
|
|
62
65
|
flushAll(): Promise<void>;
|
|
63
66
|
register(sessionId: string, context: SessionContext): void;
|
|
@@ -68,6 +71,7 @@ declare class SessionLogWriter {
|
|
|
68
71
|
private extractChunkText;
|
|
69
72
|
private emitCoalescedMessage;
|
|
70
73
|
private scheduleFlush;
|
|
74
|
+
private writeToLocalCache;
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
type StreamPair = {
|
|
@@ -94,8 +98,6 @@ type AcpConnectionConfig = {
|
|
|
94
98
|
/** Deployment environment - "local" for desktop, "cloud" for cloud sandbox */
|
|
95
99
|
deviceType?: "local" | "cloud";
|
|
96
100
|
logger?: Logger;
|
|
97
|
-
/** Enable dev-only instrumentation (timing, verbose logging) */
|
|
98
|
-
debug?: boolean;
|
|
99
101
|
processCallbacks?: ProcessSpawnedCallback;
|
|
100
102
|
codexOptions?: CodexProcessOptions;
|
|
101
103
|
allowedModelIds?: Set<string>;
|
package/dist/agent.d.ts
CHANGED
package/dist/agent.js
CHANGED
|
@@ -271,49 +271,12 @@ import {
|
|
|
271
271
|
import {
|
|
272
272
|
query
|
|
273
273
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
274
|
-
|
|
275
|
-
// ../shared/dist/index.js
|
|
276
|
-
var NOOP_COLLECTOR = {
|
|
277
|
-
time: (_label, fn) => fn(),
|
|
278
|
-
timeSync: (_label, fn) => fn(),
|
|
279
|
-
record: () => {
|
|
280
|
-
},
|
|
281
|
-
summarize: () => {
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
function createTimingCollector(enabled, log) {
|
|
285
|
-
if (!enabled) return NOOP_COLLECTOR;
|
|
286
|
-
const steps = {};
|
|
287
|
-
return {
|
|
288
|
-
async time(label, fn) {
|
|
289
|
-
const start = Date.now();
|
|
290
|
-
const result = await fn();
|
|
291
|
-
steps[label] = Date.now() - start;
|
|
292
|
-
return result;
|
|
293
|
-
},
|
|
294
|
-
timeSync(label, fn) {
|
|
295
|
-
const start = Date.now();
|
|
296
|
-
const result = fn();
|
|
297
|
-
steps[label] = Date.now() - start;
|
|
298
|
-
return result;
|
|
299
|
-
},
|
|
300
|
-
record(label, ms) {
|
|
301
|
-
steps[label] = ms;
|
|
302
|
-
},
|
|
303
|
-
summarize(label) {
|
|
304
|
-
const total = Object.values(steps).reduce((a, b) => a + b, 0);
|
|
305
|
-
log(`[timing] ${label}: ${total}ms`, steps);
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// src/adapters/claude/claude-agent.ts
|
|
311
274
|
import { v7 as uuidv7 } from "uuid";
|
|
312
275
|
|
|
313
276
|
// package.json
|
|
314
277
|
var package_default = {
|
|
315
278
|
name: "@posthog/agent",
|
|
316
|
-
version: "2.1.
|
|
279
|
+
version: "2.1.53",
|
|
317
280
|
repository: "https://github.com/PostHog/twig",
|
|
318
281
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
319
282
|
exports: {
|
|
@@ -727,8 +690,8 @@ var ToolContentBuilder = class {
|
|
|
727
690
|
this.items.push({ type: "content", content: image(data, mimeType, uri) });
|
|
728
691
|
return this;
|
|
729
692
|
}
|
|
730
|
-
diff(
|
|
731
|
-
this.items.push({ type: "diff", path:
|
|
693
|
+
diff(path5, oldText, newText) {
|
|
694
|
+
this.items.push({ type: "diff", path: path5, oldText, newText });
|
|
732
695
|
return this;
|
|
733
696
|
}
|
|
734
697
|
build() {
|
|
@@ -918,13 +881,13 @@ function toolInfoFromToolUse(toolUse, cachedFileContent, logger = new Logger({ d
|
|
|
918
881
|
locations: []
|
|
919
882
|
};
|
|
920
883
|
case "Edit": {
|
|
921
|
-
const
|
|
884
|
+
const path5 = input?.file_path ? String(input.file_path) : void 0;
|
|
922
885
|
let oldText = input?.old_string ? String(input.old_string) : null;
|
|
923
886
|
let newText = input?.new_string ? String(input.new_string) : "";
|
|
924
887
|
let affectedLines = [];
|
|
925
|
-
if (
|
|
888
|
+
if (path5 && oldText) {
|
|
926
889
|
try {
|
|
927
|
-
const oldContent = cachedFileContent[
|
|
890
|
+
const oldContent = cachedFileContent[path5] || "";
|
|
928
891
|
const newContent = replaceAndCalculateLocation(oldContent, [
|
|
929
892
|
{
|
|
930
893
|
oldText,
|
|
@@ -940,17 +903,17 @@ function toolInfoFromToolUse(toolUse, cachedFileContent, logger = new Logger({ d
|
|
|
940
903
|
}
|
|
941
904
|
}
|
|
942
905
|
return {
|
|
943
|
-
title:
|
|
906
|
+
title: path5 ? `Edit \`${path5}\`` : "Edit",
|
|
944
907
|
kind: "edit",
|
|
945
|
-
content: input &&
|
|
908
|
+
content: input && path5 ? [
|
|
946
909
|
{
|
|
947
910
|
type: "diff",
|
|
948
|
-
path:
|
|
911
|
+
path: path5,
|
|
949
912
|
oldText,
|
|
950
913
|
newText
|
|
951
914
|
}
|
|
952
915
|
] : [],
|
|
953
|
-
locations:
|
|
916
|
+
locations: path5 ? affectedLines.length > 0 ? affectedLines.map((line) => ({ line, path: path5 })) : [{ path: path5 }] : []
|
|
954
917
|
};
|
|
955
918
|
}
|
|
956
919
|
case "Write": {
|
|
@@ -2424,12 +2387,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2424
2387
|
logWriter;
|
|
2425
2388
|
options;
|
|
2426
2389
|
lastSentConfigOptions;
|
|
2427
|
-
debug;
|
|
2428
2390
|
constructor(client, logWriter, options) {
|
|
2429
2391
|
super(client);
|
|
2430
2392
|
this.logWriter = logWriter;
|
|
2431
2393
|
this.options = options;
|
|
2432
|
-
this.debug = options?.debug ?? false;
|
|
2433
2394
|
this.toolUseCache = {};
|
|
2434
2395
|
this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
|
|
2435
2396
|
}
|
|
@@ -2472,36 +2433,26 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2472
2433
|
}
|
|
2473
2434
|
async newSession(params) {
|
|
2474
2435
|
this.checkAuthStatus();
|
|
2475
|
-
const tc = createTimingCollector(
|
|
2476
|
-
this.debug,
|
|
2477
|
-
(msg, data) => this.logger.info(msg, data)
|
|
2478
|
-
);
|
|
2479
2436
|
const meta = params._meta;
|
|
2480
2437
|
const sessionId = uuidv7();
|
|
2481
2438
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
2482
|
-
const mcpServers =
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
isResume: false,
|
|
2498
|
-
onModeChange: this.createOnModeChange(sessionId),
|
|
2499
|
-
onProcessSpawned: this.options?.onProcessSpawned,
|
|
2500
|
-
onProcessExited: this.options?.onProcessExited
|
|
2501
|
-
})
|
|
2502
|
-
);
|
|
2439
|
+
const mcpServers = parseMcpServers(params);
|
|
2440
|
+
const options = buildSessionOptions({
|
|
2441
|
+
cwd: params.cwd,
|
|
2442
|
+
mcpServers,
|
|
2443
|
+
permissionMode,
|
|
2444
|
+
canUseTool: this.createCanUseTool(sessionId),
|
|
2445
|
+
logger: this.logger,
|
|
2446
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
2447
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
2448
|
+
sessionId,
|
|
2449
|
+
isResume: false,
|
|
2450
|
+
onModeChange: this.createOnModeChange(sessionId),
|
|
2451
|
+
onProcessSpawned: this.options?.onProcessSpawned,
|
|
2452
|
+
onProcessExited: this.options?.onProcessExited
|
|
2453
|
+
});
|
|
2503
2454
|
const input = new Pushable();
|
|
2504
|
-
const q =
|
|
2455
|
+
const q = query({ prompt: input, options });
|
|
2505
2456
|
const session = this.createSession(
|
|
2506
2457
|
sessionId,
|
|
2507
2458
|
q,
|
|
@@ -2513,27 +2464,17 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2513
2464
|
session.taskRunId = meta?.taskRunId;
|
|
2514
2465
|
this.registerPersistence(sessionId, meta);
|
|
2515
2466
|
if (meta?.taskRunId) {
|
|
2516
|
-
await
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
adapter: "claude"
|
|
2522
|
-
})
|
|
2523
|
-
);
|
|
2467
|
+
await this.client.extNotification("_posthog/sdk_session", {
|
|
2468
|
+
taskRunId: meta.taskRunId,
|
|
2469
|
+
sessionId,
|
|
2470
|
+
adapter: "claude"
|
|
2471
|
+
});
|
|
2524
2472
|
}
|
|
2525
|
-
const modelOptions = await
|
|
2526
|
-
|
|
2527
|
-
() => this.getModelConfigOptions()
|
|
2528
|
-
);
|
|
2529
|
-
this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
|
|
2473
|
+
const modelOptions = await this.getModelConfigOptions();
|
|
2474
|
+
this.deferBackgroundFetches(q, sessionId, mcpServers);
|
|
2530
2475
|
session.modelId = modelOptions.currentModelId;
|
|
2531
2476
|
await this.trySetModel(q, modelOptions.currentModelId);
|
|
2532
|
-
const configOptions = await
|
|
2533
|
-
"buildConfigOptions",
|
|
2534
|
-
() => this.buildConfigOptions(modelOptions)
|
|
2535
|
-
);
|
|
2536
|
-
tc.summarize("newSession");
|
|
2477
|
+
const configOptions = await this.buildConfigOptions(modelOptions);
|
|
2537
2478
|
return {
|
|
2538
2479
|
sessionId,
|
|
2539
2480
|
configOptions
|
|
@@ -2543,10 +2484,6 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2543
2484
|
return this.resumeSession(params);
|
|
2544
2485
|
}
|
|
2545
2486
|
async resumeSession(params) {
|
|
2546
|
-
const tc = createTimingCollector(
|
|
2547
|
-
this.debug,
|
|
2548
|
-
(msg, data) => this.logger.info(msg, data)
|
|
2549
|
-
);
|
|
2550
2487
|
const meta = params._meta;
|
|
2551
2488
|
const sessionId = meta?.sessionId;
|
|
2552
2489
|
if (!sessionId) {
|
|
@@ -2555,32 +2492,22 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2555
2492
|
if (this.sessionId === sessionId) {
|
|
2556
2493
|
return {};
|
|
2557
2494
|
}
|
|
2558
|
-
const mcpServers =
|
|
2559
|
-
"parseMcpServers",
|
|
2560
|
-
() => parseMcpServers(params)
|
|
2561
|
-
);
|
|
2495
|
+
const mcpServers = parseMcpServers(params);
|
|
2562
2496
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
2563
|
-
const { query: q, session } = await
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
|
|
2574
|
-
})
|
|
2575
|
-
);
|
|
2497
|
+
const { query: q, session } = await this.initializeQuery({
|
|
2498
|
+
cwd: params.cwd,
|
|
2499
|
+
permissionMode,
|
|
2500
|
+
mcpServers,
|
|
2501
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
2502
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
2503
|
+
sessionId,
|
|
2504
|
+
isResume: true,
|
|
2505
|
+
additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
|
|
2506
|
+
});
|
|
2576
2507
|
session.taskRunId = meta?.taskRunId;
|
|
2577
2508
|
this.registerPersistence(sessionId, meta);
|
|
2578
|
-
this.deferBackgroundFetches(
|
|
2579
|
-
const configOptions = await
|
|
2580
|
-
"buildConfigOptions",
|
|
2581
|
-
() => this.buildConfigOptions()
|
|
2582
|
-
);
|
|
2583
|
-
tc.summarize("resumeSession");
|
|
2509
|
+
this.deferBackgroundFetches(q, sessionId, mcpServers);
|
|
2510
|
+
const configOptions = await this.buildConfigOptions();
|
|
2584
2511
|
return { configOptions };
|
|
2585
2512
|
}
|
|
2586
2513
|
async prompt(params) {
|
|
@@ -2768,13 +2695,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
2768
2695
|
* Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
|
|
2769
2696
|
* Both populate caches used later — neither is needed to return configOptions.
|
|
2770
2697
|
*/
|
|
2771
|
-
deferBackgroundFetches(
|
|
2698
|
+
deferBackgroundFetches(q, sessionId, mcpServers) {
|
|
2772
2699
|
Promise.all([
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
"mcpMetadata",
|
|
2776
|
-
() => fetchMcpToolMetadata(mcpServers, this.logger)
|
|
2777
|
-
)
|
|
2700
|
+
getAvailableSlashCommands(q),
|
|
2701
|
+
fetchMcpToolMetadata(mcpServers, this.logger)
|
|
2778
2702
|
]).then(([slashCommands]) => {
|
|
2779
2703
|
this.sendAvailableCommandsUpdate(sessionId, slashCommands);
|
|
2780
2704
|
}).catch((err) => {
|
|
@@ -3068,10 +2992,7 @@ function createClaudeConnection(config) {
|
|
|
3068
2992
|
const agentStream = ndJsonStream(agentWritable, streams.agent.readable);
|
|
3069
2993
|
let agent = null;
|
|
3070
2994
|
const agentConnection = new AgentSideConnection((client) => {
|
|
3071
|
-
agent = new ClaudeAcpAgent(client, logWriter,
|
|
3072
|
-
...config.processCallbacks,
|
|
3073
|
-
debug: config.debug
|
|
3074
|
-
});
|
|
2995
|
+
agent = new ClaudeAcpAgent(client, logWriter, config.processCallbacks);
|
|
3075
2996
|
logger.info(`Created ${agent.adapterName} agent`);
|
|
3076
2997
|
return agent;
|
|
3077
2998
|
}, agentStream);
|
|
@@ -3486,6 +3407,8 @@ var PostHogAPIClient = class {
|
|
|
3486
3407
|
};
|
|
3487
3408
|
|
|
3488
3409
|
// src/session-log-writer.ts
|
|
3410
|
+
import fs3 from "fs";
|
|
3411
|
+
import path4 from "path";
|
|
3489
3412
|
var SessionLogWriter = class _SessionLogWriter {
|
|
3490
3413
|
static FLUSH_DEBOUNCE_MS = 500;
|
|
3491
3414
|
static FLUSH_MAX_INTERVAL_MS = 5e3;
|
|
@@ -3499,8 +3422,10 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
3499
3422
|
sessions = /* @__PURE__ */ new Map();
|
|
3500
3423
|
messageCounts = /* @__PURE__ */ new Map();
|
|
3501
3424
|
logger;
|
|
3425
|
+
localCachePath;
|
|
3502
3426
|
constructor(options = {}) {
|
|
3503
3427
|
this.posthogAPI = options.posthogAPI;
|
|
3428
|
+
this.localCachePath = options.localCachePath;
|
|
3504
3429
|
this.logger = options.logger ?? new Logger({ debug: false, prefix: "[SessionLogWriter]" });
|
|
3505
3430
|
}
|
|
3506
3431
|
async flushAll() {
|
|
@@ -3530,6 +3455,21 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
3530
3455
|
});
|
|
3531
3456
|
this.sessions.set(sessionId, { context });
|
|
3532
3457
|
this.lastFlushAttemptTime.set(sessionId, Date.now());
|
|
3458
|
+
if (this.localCachePath) {
|
|
3459
|
+
const sessionDir = path4.join(
|
|
3460
|
+
this.localCachePath,
|
|
3461
|
+
"sessions",
|
|
3462
|
+
context.runId
|
|
3463
|
+
);
|
|
3464
|
+
try {
|
|
3465
|
+
fs3.mkdirSync(sessionDir, { recursive: true });
|
|
3466
|
+
} catch (error) {
|
|
3467
|
+
this.logger.warn("Failed to create local cache directory", {
|
|
3468
|
+
sessionDir,
|
|
3469
|
+
error
|
|
3470
|
+
});
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3533
3473
|
}
|
|
3534
3474
|
isRegistered(sessionId) {
|
|
3535
3475
|
return this.sessions.has(sessionId);
|
|
@@ -3567,6 +3507,7 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
3567
3507
|
timestamp,
|
|
3568
3508
|
notification: message
|
|
3569
3509
|
};
|
|
3510
|
+
this.writeToLocalCache(sessionId, entry);
|
|
3570
3511
|
if (this.posthogAPI) {
|
|
3571
3512
|
const pending = this.pendingEntries.get(sessionId) ?? [];
|
|
3572
3513
|
pending.push(entry);
|
|
@@ -3667,6 +3608,7 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
3667
3608
|
}
|
|
3668
3609
|
}
|
|
3669
3610
|
};
|
|
3611
|
+
this.writeToLocalCache(sessionId, entry);
|
|
3670
3612
|
if (this.posthogAPI) {
|
|
3671
3613
|
const pending = this.pendingEntries.get(sessionId) ?? [];
|
|
3672
3614
|
pending.push(entry);
|
|
@@ -3694,6 +3636,23 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
3694
3636
|
const timeout = setTimeout(() => this.flush(sessionId), delay);
|
|
3695
3637
|
this.flushTimeouts.set(sessionId, timeout);
|
|
3696
3638
|
}
|
|
3639
|
+
writeToLocalCache(sessionId, entry) {
|
|
3640
|
+
if (!this.localCachePath) return;
|
|
3641
|
+
const session = this.sessions.get(sessionId);
|
|
3642
|
+
if (!session) return;
|
|
3643
|
+
const logPath = path4.join(
|
|
3644
|
+
this.localCachePath,
|
|
3645
|
+
"sessions",
|
|
3646
|
+
session.context.runId,
|
|
3647
|
+
"logs.ndjson"
|
|
3648
|
+
);
|
|
3649
|
+
try {
|
|
3650
|
+
fs3.appendFileSync(logPath, `${JSON.stringify(entry)}
|
|
3651
|
+
`);
|
|
3652
|
+
} catch (error) {
|
|
3653
|
+
this.logger.warn("Failed to write to local cache", { logPath, error });
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3697
3656
|
};
|
|
3698
3657
|
|
|
3699
3658
|
// src/agent.ts
|
|
@@ -3717,7 +3676,8 @@ var Agent = class {
|
|
|
3717
3676
|
if (config.posthog && !config.skipLogPersistence) {
|
|
3718
3677
|
this.sessionLogWriter = new SessionLogWriter({
|
|
3719
3678
|
posthogAPI: this.posthogAPI,
|
|
3720
|
-
logger: this.logger.child("SessionLogWriter")
|
|
3679
|
+
logger: this.logger.child("SessionLogWriter"),
|
|
3680
|
+
localCachePath: config.localCachePath
|
|
3721
3681
|
});
|
|
3722
3682
|
}
|
|
3723
3683
|
}
|
|
@@ -3771,7 +3731,6 @@ var Agent = class {
|
|
|
3771
3731
|
taskId,
|
|
3772
3732
|
deviceType: "local",
|
|
3773
3733
|
logger: this.logger,
|
|
3774
|
-
debug: this.debug,
|
|
3775
3734
|
processCallbacks: options.processCallbacks,
|
|
3776
3735
|
allowedModelIds,
|
|
3777
3736
|
codexOptions: options.adapter === "codex" && gatewayConfig ? {
|