ai-sdk-provider-codex-cli 0.3.0 → 0.5.0
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/README.md +124 -0
- package/dist/index.cjs +254 -22
- package/dist/index.d.cts +154 -1
- package/dist/index.d.ts +154 -1
- package/dist/index.js +254 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,27 +5,66 @@ import { createRequire } from 'module';
|
|
|
5
5
|
import { mkdtempSync, writeFileSync, rmSync, readFileSync } from 'fs';
|
|
6
6
|
import { tmpdir } from 'os';
|
|
7
7
|
import { join, dirname } from 'path';
|
|
8
|
-
import { generateId } from '@ai-sdk/provider-utils';
|
|
9
8
|
import { z } from 'zod';
|
|
9
|
+
import { parseProviderOptions, generateId } from '@ai-sdk/provider-utils';
|
|
10
10
|
|
|
11
11
|
// src/codex-cli-provider.ts
|
|
12
12
|
|
|
13
13
|
// src/logger.ts
|
|
14
14
|
var defaultLogger = {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
debug: (message) => console.debug(`[DEBUG] ${message}`),
|
|
16
|
+
info: (message) => console.info(`[INFO] ${message}`),
|
|
17
|
+
warn: (message) => console.warn(`[WARN] ${message}`),
|
|
18
|
+
error: (message) => console.error(`[ERROR] ${message}`)
|
|
17
19
|
};
|
|
18
20
|
var noopLogger = {
|
|
21
|
+
debug: () => {
|
|
22
|
+
},
|
|
23
|
+
info: () => {
|
|
24
|
+
},
|
|
19
25
|
warn: () => {
|
|
20
26
|
},
|
|
21
27
|
error: () => {
|
|
22
28
|
}
|
|
23
29
|
};
|
|
24
30
|
function getLogger(logger) {
|
|
25
|
-
if (logger === false)
|
|
26
|
-
|
|
31
|
+
if (logger === false) {
|
|
32
|
+
return noopLogger;
|
|
33
|
+
}
|
|
34
|
+
if (logger === void 0) {
|
|
35
|
+
return defaultLogger;
|
|
36
|
+
}
|
|
27
37
|
return logger;
|
|
28
38
|
}
|
|
39
|
+
function createVerboseLogger(logger, verbose = false) {
|
|
40
|
+
if (verbose) {
|
|
41
|
+
return logger;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
debug: () => {
|
|
45
|
+
},
|
|
46
|
+
// No-op when not verbose
|
|
47
|
+
info: () => {
|
|
48
|
+
},
|
|
49
|
+
// No-op when not verbose
|
|
50
|
+
warn: logger.warn.bind(logger),
|
|
51
|
+
error: logger.error.bind(logger)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
var loggerFunctionSchema = z.object({
|
|
55
|
+
debug: z.any().refine((val) => typeof val === "function", {
|
|
56
|
+
message: "debug must be a function"
|
|
57
|
+
}),
|
|
58
|
+
info: z.any().refine((val) => typeof val === "function", {
|
|
59
|
+
message: "info must be a function"
|
|
60
|
+
}),
|
|
61
|
+
warn: z.any().refine((val) => typeof val === "function", {
|
|
62
|
+
message: "warn must be a function"
|
|
63
|
+
}),
|
|
64
|
+
error: z.any().refine((val) => typeof val === "function", {
|
|
65
|
+
message: "error must be a function"
|
|
66
|
+
})
|
|
67
|
+
});
|
|
29
68
|
var settingsSchema = z.object({
|
|
30
69
|
codexPath: z.string().optional(),
|
|
31
70
|
cwd: z.string().optional(),
|
|
@@ -38,7 +77,29 @@ var settingsSchema = z.object({
|
|
|
38
77
|
allowNpx: z.boolean().optional(),
|
|
39
78
|
env: z.record(z.string(), z.string()).optional(),
|
|
40
79
|
verbose: z.boolean().optional(),
|
|
41
|
-
logger: z.
|
|
80
|
+
logger: z.union([z.literal(false), loggerFunctionSchema]).optional(),
|
|
81
|
+
// NEW: Reasoning & Verbosity
|
|
82
|
+
reasoningEffort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
83
|
+
// Note: API rejects 'concise' and 'none' despite error messages claiming they're valid
|
|
84
|
+
reasoningSummary: z.enum(["auto", "detailed"]).optional(),
|
|
85
|
+
reasoningSummaryFormat: z.enum(["none", "experimental"]).optional(),
|
|
86
|
+
modelVerbosity: z.enum(["low", "medium", "high"]).optional(),
|
|
87
|
+
// NEW: Advanced features
|
|
88
|
+
includePlanTool: z.boolean().optional(),
|
|
89
|
+
profile: z.string().optional(),
|
|
90
|
+
oss: z.boolean().optional(),
|
|
91
|
+
webSearch: z.boolean().optional(),
|
|
92
|
+
// NEW: Generic overrides
|
|
93
|
+
configOverrides: z.record(
|
|
94
|
+
z.string(),
|
|
95
|
+
z.union([
|
|
96
|
+
z.string(),
|
|
97
|
+
z.number(),
|
|
98
|
+
z.boolean(),
|
|
99
|
+
z.object({}).passthrough(),
|
|
100
|
+
z.array(z.any())
|
|
101
|
+
])
|
|
102
|
+
).optional()
|
|
42
103
|
}).strict();
|
|
43
104
|
function validateSettings(settings) {
|
|
44
105
|
const warnings = [];
|
|
@@ -166,6 +227,22 @@ function isAuthenticationError(err) {
|
|
|
166
227
|
}
|
|
167
228
|
|
|
168
229
|
// src/codex-cli-language-model.ts
|
|
230
|
+
var codexCliProviderOptionsSchema = z.object({
|
|
231
|
+
reasoningEffort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
232
|
+
reasoningSummary: z.enum(["auto", "detailed"]).optional(),
|
|
233
|
+
reasoningSummaryFormat: z.enum(["none", "experimental"]).optional(),
|
|
234
|
+
textVerbosity: z.enum(["low", "medium", "high"]).optional(),
|
|
235
|
+
configOverrides: z.record(
|
|
236
|
+
z.string(),
|
|
237
|
+
z.union([
|
|
238
|
+
z.string(),
|
|
239
|
+
z.number(),
|
|
240
|
+
z.boolean(),
|
|
241
|
+
z.object({}).passthrough(),
|
|
242
|
+
z.array(z.any())
|
|
243
|
+
])
|
|
244
|
+
).optional()
|
|
245
|
+
}).strict();
|
|
169
246
|
function resolveCodexPath(explicitPath, allowNpx) {
|
|
170
247
|
if (explicitPath) return { cmd: "node", args: [explicitPath] };
|
|
171
248
|
try {
|
|
@@ -192,13 +269,29 @@ var CodexCliLanguageModel = class {
|
|
|
192
269
|
constructor(options) {
|
|
193
270
|
this.modelId = options.id;
|
|
194
271
|
this.settings = options.settings ?? {};
|
|
195
|
-
|
|
272
|
+
const baseLogger = getLogger(this.settings.logger);
|
|
273
|
+
this.logger = createVerboseLogger(baseLogger, this.settings.verbose ?? false);
|
|
196
274
|
if (!this.modelId || this.modelId.trim() === "") {
|
|
197
275
|
throw new NoSuchModelError({ modelId: this.modelId, modelType: "languageModel" });
|
|
198
276
|
}
|
|
199
277
|
const warn = validateModelId(this.modelId);
|
|
200
278
|
if (warn) this.logger.warn(`Codex CLI model: ${warn}`);
|
|
201
279
|
}
|
|
280
|
+
mergeSettings(providerOptions) {
|
|
281
|
+
if (!providerOptions) return this.settings;
|
|
282
|
+
const mergedConfigOverrides = providerOptions.configOverrides || this.settings.configOverrides ? {
|
|
283
|
+
...this.settings.configOverrides ?? {},
|
|
284
|
+
...providerOptions.configOverrides ?? {}
|
|
285
|
+
} : void 0;
|
|
286
|
+
return {
|
|
287
|
+
...this.settings,
|
|
288
|
+
reasoningEffort: providerOptions.reasoningEffort ?? this.settings.reasoningEffort,
|
|
289
|
+
reasoningSummary: providerOptions.reasoningSummary ?? this.settings.reasoningSummary,
|
|
290
|
+
reasoningSummaryFormat: providerOptions.reasoningSummaryFormat ?? this.settings.reasoningSummaryFormat,
|
|
291
|
+
modelVerbosity: providerOptions.textVerbosity ?? this.settings.modelVerbosity,
|
|
292
|
+
configOverrides: mergedConfigOverrides
|
|
293
|
+
};
|
|
294
|
+
}
|
|
202
295
|
// Codex JSONL items use `type` for the item discriminator, but some
|
|
203
296
|
// earlier fixtures (and defensive parsing) might still surface `item_type`.
|
|
204
297
|
// This helper returns whichever is present.
|
|
@@ -209,28 +302,57 @@ var CodexCliLanguageModel = class {
|
|
|
209
302
|
const current = typeof data.type === "string" ? data.type : void 0;
|
|
210
303
|
return legacy ?? current;
|
|
211
304
|
}
|
|
212
|
-
buildArgs(promptText, responseFormat) {
|
|
213
|
-
const base = resolveCodexPath(
|
|
305
|
+
buildArgs(promptText, responseFormat, settings = this.settings) {
|
|
306
|
+
const base = resolveCodexPath(settings.codexPath, settings.allowNpx);
|
|
214
307
|
const args = [...base.args, "exec", "--experimental-json"];
|
|
215
|
-
if (
|
|
308
|
+
if (settings.fullAuto) {
|
|
216
309
|
args.push("--full-auto");
|
|
217
|
-
} else if (
|
|
310
|
+
} else if (settings.dangerouslyBypassApprovalsAndSandbox) {
|
|
218
311
|
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
219
312
|
} else {
|
|
220
|
-
const approval =
|
|
313
|
+
const approval = settings.approvalMode ?? "on-failure";
|
|
221
314
|
args.push("-c", `approval_policy=${approval}`);
|
|
222
|
-
const sandbox =
|
|
315
|
+
const sandbox = settings.sandboxMode ?? "workspace-write";
|
|
223
316
|
args.push("-c", `sandbox_mode=${sandbox}`);
|
|
224
317
|
}
|
|
225
|
-
if (
|
|
318
|
+
if (settings.skipGitRepoCheck !== false) {
|
|
226
319
|
args.push("--skip-git-repo-check");
|
|
227
320
|
}
|
|
228
|
-
if (
|
|
229
|
-
args.push("
|
|
321
|
+
if (settings.reasoningEffort) {
|
|
322
|
+
args.push("-c", `model_reasoning_effort=${settings.reasoningEffort}`);
|
|
323
|
+
}
|
|
324
|
+
if (settings.reasoningSummary) {
|
|
325
|
+
args.push("-c", `model_reasoning_summary=${settings.reasoningSummary}`);
|
|
326
|
+
}
|
|
327
|
+
if (settings.reasoningSummaryFormat) {
|
|
328
|
+
args.push("-c", `model_reasoning_summary_format=${settings.reasoningSummaryFormat}`);
|
|
329
|
+
}
|
|
330
|
+
if (settings.modelVerbosity) {
|
|
331
|
+
args.push("-c", `model_verbosity=${settings.modelVerbosity}`);
|
|
332
|
+
}
|
|
333
|
+
if (settings.includePlanTool) {
|
|
334
|
+
args.push("--include-plan-tool");
|
|
335
|
+
}
|
|
336
|
+
if (settings.profile) {
|
|
337
|
+
args.push("--profile", settings.profile);
|
|
338
|
+
}
|
|
339
|
+
if (settings.oss) {
|
|
340
|
+
args.push("--oss");
|
|
341
|
+
}
|
|
342
|
+
if (settings.webSearch) {
|
|
343
|
+
args.push("-c", "tools.web_search=true");
|
|
344
|
+
}
|
|
345
|
+
if (settings.color) {
|
|
346
|
+
args.push("--color", settings.color);
|
|
230
347
|
}
|
|
231
348
|
if (this.modelId) {
|
|
232
349
|
args.push("-m", this.modelId);
|
|
233
350
|
}
|
|
351
|
+
if (settings.configOverrides) {
|
|
352
|
+
for (const [key, value] of Object.entries(settings.configOverrides)) {
|
|
353
|
+
this.addConfigOverride(args, key, value);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
234
356
|
let schemaPath;
|
|
235
357
|
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
236
358
|
const schema = typeof responseFormat.schema === "object" ? responseFormat.schema : {};
|
|
@@ -250,16 +372,55 @@ var CodexCliLanguageModel = class {
|
|
|
250
372
|
args.push(promptText);
|
|
251
373
|
const env = {
|
|
252
374
|
...process.env,
|
|
253
|
-
...
|
|
375
|
+
...settings.env || {},
|
|
254
376
|
RUST_LOG: process.env.RUST_LOG || "error"
|
|
255
377
|
};
|
|
256
|
-
let lastMessagePath =
|
|
378
|
+
let lastMessagePath = settings.outputLastMessageFile;
|
|
257
379
|
if (!lastMessagePath) {
|
|
258
380
|
const dir = mkdtempSync(join(tmpdir(), "codex-cli-"));
|
|
259
381
|
lastMessagePath = join(dir, "last-message.txt");
|
|
260
382
|
}
|
|
261
383
|
args.push("--output-last-message", lastMessagePath);
|
|
262
|
-
return { cmd: base.cmd, args, env, cwd:
|
|
384
|
+
return { cmd: base.cmd, args, env, cwd: settings.cwd, lastMessagePath, schemaPath };
|
|
385
|
+
}
|
|
386
|
+
addConfigOverride(args, key, value) {
|
|
387
|
+
if (this.isPlainObject(value)) {
|
|
388
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
389
|
+
this.addConfigOverride(
|
|
390
|
+
args,
|
|
391
|
+
`${key}.${childKey}`,
|
|
392
|
+
childValue
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const serialized = this.serializeConfigValue(value);
|
|
398
|
+
args.push("-c", `${key}=${serialized}`);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Serialize a config override value into a CLI-safe string.
|
|
402
|
+
*/
|
|
403
|
+
serializeConfigValue(value) {
|
|
404
|
+
if (typeof value === "string") return value;
|
|
405
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
406
|
+
if (Array.isArray(value)) {
|
|
407
|
+
try {
|
|
408
|
+
return JSON.stringify(value);
|
|
409
|
+
} catch {
|
|
410
|
+
return String(value);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (value && typeof value === "object") {
|
|
414
|
+
try {
|
|
415
|
+
return JSON.stringify(value);
|
|
416
|
+
} catch {
|
|
417
|
+
return String(value);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return String(value);
|
|
421
|
+
}
|
|
422
|
+
isPlainObject(value) {
|
|
423
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
263
424
|
}
|
|
264
425
|
sanitizeJsonSchema(value) {
|
|
265
426
|
if (typeof value !== "object" || value === null) {
|
|
@@ -501,20 +662,35 @@ var CodexCliLanguageModel = class {
|
|
|
501
662
|
});
|
|
502
663
|
}
|
|
503
664
|
async doGenerate(options) {
|
|
665
|
+
this.logger.debug(`[codex-cli] Starting doGenerate request with model: ${this.modelId}`);
|
|
504
666
|
const { promptText, warnings: mappingWarnings } = mapMessagesToPrompt(options.prompt);
|
|
505
667
|
const promptExcerpt = promptText.slice(0, 200);
|
|
506
668
|
const warnings = [
|
|
507
669
|
...this.mapWarnings(options),
|
|
508
670
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
509
671
|
];
|
|
672
|
+
this.logger.debug(
|
|
673
|
+
`[codex-cli] Converted ${options.prompt.length} messages, response format: ${options.responseFormat?.type ?? "none"}`
|
|
674
|
+
);
|
|
675
|
+
const providerOptions = await parseProviderOptions({
|
|
676
|
+
provider: this.provider,
|
|
677
|
+
providerOptions: options.providerOptions,
|
|
678
|
+
schema: codexCliProviderOptionsSchema
|
|
679
|
+
});
|
|
680
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
510
681
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
511
682
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
512
683
|
promptText,
|
|
513
|
-
responseFormat
|
|
684
|
+
responseFormat,
|
|
685
|
+
effectiveSettings
|
|
686
|
+
);
|
|
687
|
+
this.logger.debug(
|
|
688
|
+
`[codex-cli] Executing Codex CLI: ${cmd} with ${args.length} arguments, cwd: ${cwd ?? "default"}`
|
|
514
689
|
);
|
|
515
690
|
let text = "";
|
|
516
691
|
const usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
517
692
|
const finishReason = "stop";
|
|
693
|
+
const startTime = Date.now();
|
|
518
694
|
const child = spawn(cmd, args, { env, cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
519
695
|
let onAbort;
|
|
520
696
|
if (options.abortSignal) {
|
|
@@ -536,11 +712,14 @@ var CodexCliLanguageModel = class {
|
|
|
536
712
|
for (const line of lines) {
|
|
537
713
|
const event = this.parseExperimentalJsonEvent(line);
|
|
538
714
|
if (!event) continue;
|
|
715
|
+
this.logger.debug(`[codex-cli] Received event type: ${event.type ?? "unknown"}`);
|
|
539
716
|
if (event.type === "thread.started" && typeof event.thread_id === "string") {
|
|
540
717
|
this.sessionId = event.thread_id;
|
|
718
|
+
this.logger.debug(`[codex-cli] Session started: ${this.sessionId}`);
|
|
541
719
|
}
|
|
542
720
|
if (event.type === "session.created" && typeof event.session_id === "string") {
|
|
543
721
|
this.sessionId = event.session_id;
|
|
722
|
+
this.logger.debug(`[codex-cli] Session created: ${this.sessionId}`);
|
|
544
723
|
}
|
|
545
724
|
if (event.type === "turn.completed") {
|
|
546
725
|
const usageEvent = this.extractUsage(event);
|
|
@@ -556,15 +735,21 @@ var CodexCliLanguageModel = class {
|
|
|
556
735
|
if (event.type === "turn.failed") {
|
|
557
736
|
const errorText = event.error && typeof event.error.message === "string" && event.error.message || (typeof event.message === "string" ? event.message : void 0);
|
|
558
737
|
turnFailureMessage = errorText ?? turnFailureMessage ?? "Codex turn failed";
|
|
738
|
+
this.logger.error(`[codex-cli] Turn failed: ${turnFailureMessage}`);
|
|
559
739
|
}
|
|
560
740
|
if (event.type === "error") {
|
|
561
741
|
const errorText = typeof event.message === "string" ? event.message : void 0;
|
|
562
742
|
turnFailureMessage = errorText ?? turnFailureMessage ?? "Codex error";
|
|
743
|
+
this.logger.error(`[codex-cli] Error event: ${turnFailureMessage}`);
|
|
563
744
|
}
|
|
564
745
|
}
|
|
565
746
|
});
|
|
566
|
-
child.on("error", (e) =>
|
|
747
|
+
child.on("error", (e) => {
|
|
748
|
+
this.logger.error(`[codex-cli] Spawn error: ${String(e)}`);
|
|
749
|
+
reject(this.handleSpawnError(e, promptExcerpt));
|
|
750
|
+
});
|
|
567
751
|
child.on("close", (code) => {
|
|
752
|
+
const duration = Date.now() - startTime;
|
|
568
753
|
if (code === 0) {
|
|
569
754
|
if (turnFailureMessage) {
|
|
570
755
|
reject(
|
|
@@ -576,8 +761,15 @@ var CodexCliLanguageModel = class {
|
|
|
576
761
|
);
|
|
577
762
|
return;
|
|
578
763
|
}
|
|
764
|
+
this.logger.info(
|
|
765
|
+
`[codex-cli] Request completed - Session: ${this.sessionId ?? "N/A"}, Duration: ${duration}ms, Tokens: ${usage.totalTokens}`
|
|
766
|
+
);
|
|
767
|
+
this.logger.debug(
|
|
768
|
+
`[codex-cli] Token usage - Input: ${usage.inputTokens}, Output: ${usage.outputTokens}, Total: ${usage.totalTokens}`
|
|
769
|
+
);
|
|
579
770
|
resolve();
|
|
580
771
|
} else {
|
|
772
|
+
this.logger.error(`[codex-cli] Process exited with code ${code} after ${duration}ms`);
|
|
581
773
|
reject(
|
|
582
774
|
createAPICallError({
|
|
583
775
|
message: `Codex CLI exited with code ${code}`,
|
|
@@ -626,19 +818,34 @@ var CodexCliLanguageModel = class {
|
|
|
626
818
|
};
|
|
627
819
|
}
|
|
628
820
|
async doStream(options) {
|
|
821
|
+
this.logger.debug(`[codex-cli] Starting doStream request with model: ${this.modelId}`);
|
|
629
822
|
const { promptText, warnings: mappingWarnings } = mapMessagesToPrompt(options.prompt);
|
|
630
823
|
const promptExcerpt = promptText.slice(0, 200);
|
|
631
824
|
const warnings = [
|
|
632
825
|
...this.mapWarnings(options),
|
|
633
826
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
634
827
|
];
|
|
828
|
+
this.logger.debug(
|
|
829
|
+
`[codex-cli] Converted ${options.prompt.length} messages for streaming, response format: ${options.responseFormat?.type ?? "none"}`
|
|
830
|
+
);
|
|
831
|
+
const providerOptions = await parseProviderOptions({
|
|
832
|
+
provider: this.provider,
|
|
833
|
+
providerOptions: options.providerOptions,
|
|
834
|
+
schema: codexCliProviderOptionsSchema
|
|
835
|
+
});
|
|
836
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
635
837
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
636
838
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
637
839
|
promptText,
|
|
638
|
-
responseFormat
|
|
840
|
+
responseFormat,
|
|
841
|
+
effectiveSettings
|
|
842
|
+
);
|
|
843
|
+
this.logger.debug(
|
|
844
|
+
`[codex-cli] Executing Codex CLI for streaming: ${cmd} with ${args.length} arguments`
|
|
639
845
|
);
|
|
640
846
|
const stream = new ReadableStream({
|
|
641
847
|
start: (controller) => {
|
|
848
|
+
const startTime = Date.now();
|
|
642
849
|
const child = spawn(cmd, args, { env, cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
643
850
|
controller.enqueue({ type: "stream-start", warnings });
|
|
644
851
|
let stderr = "";
|
|
@@ -661,12 +868,18 @@ var CodexCliLanguageModel = class {
|
|
|
661
868
|
if (!item) return;
|
|
662
869
|
if (event.type === "item.completed" && this.getItemType(item) === "assistant_message" && typeof item.text === "string") {
|
|
663
870
|
accumulatedText = item.text;
|
|
871
|
+
this.logger.debug(
|
|
872
|
+
`[codex-cli] Received assistant message, length: ${item.text.length}`
|
|
873
|
+
);
|
|
664
874
|
return;
|
|
665
875
|
}
|
|
666
876
|
const toolName = this.getToolName(item);
|
|
667
877
|
if (!toolName) {
|
|
668
878
|
return;
|
|
669
879
|
}
|
|
880
|
+
this.logger.debug(
|
|
881
|
+
`[codex-cli] Tool detected: ${toolName}, item type: ${this.getItemType(item)}`
|
|
882
|
+
);
|
|
670
883
|
const mapKey = typeof item.id === "string" && item.id.length > 0 ? item.id : randomUUID();
|
|
671
884
|
let toolState = activeTools.get(mapKey);
|
|
672
885
|
const latestInput = this.buildToolInputPayload(item);
|
|
@@ -685,6 +898,7 @@ var CodexCliLanguageModel = class {
|
|
|
685
898
|
}
|
|
686
899
|
}
|
|
687
900
|
if (!toolState.hasEmittedCall) {
|
|
901
|
+
this.logger.debug(`[codex-cli] Emitting tool invocation: ${toolState.toolName}`);
|
|
688
902
|
this.emitToolInvocation(
|
|
689
903
|
controller,
|
|
690
904
|
toolState.toolCallId,
|
|
@@ -695,6 +909,7 @@ var CodexCliLanguageModel = class {
|
|
|
695
909
|
}
|
|
696
910
|
if (event.type === "item.completed") {
|
|
697
911
|
const { result, metadata } = this.buildToolResultPayload(item);
|
|
912
|
+
this.logger.debug(`[codex-cli] Tool completed: ${toolState.toolName}`);
|
|
698
913
|
this.emitToolResult(
|
|
699
914
|
controller,
|
|
700
915
|
toolState.toolCallId,
|
|
@@ -718,7 +933,11 @@ var CodexCliLanguageModel = class {
|
|
|
718
933
|
options.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
719
934
|
}
|
|
720
935
|
const finishStream = (code) => {
|
|
936
|
+
const duration = Date.now() - startTime;
|
|
721
937
|
if (code !== 0) {
|
|
938
|
+
this.logger.error(
|
|
939
|
+
`[codex-cli] Stream process exited with code ${code} after ${duration}ms`
|
|
940
|
+
);
|
|
722
941
|
controller.error(
|
|
723
942
|
createAPICallError({
|
|
724
943
|
message: `Codex CLI exited with code ${code}`,
|
|
@@ -730,6 +949,7 @@ var CodexCliLanguageModel = class {
|
|
|
730
949
|
return;
|
|
731
950
|
}
|
|
732
951
|
if (turnFailureMessage) {
|
|
952
|
+
this.logger.error(`[codex-cli] Stream failed: ${turnFailureMessage}`);
|
|
733
953
|
controller.error(
|
|
734
954
|
createAPICallError({
|
|
735
955
|
message: turnFailureMessage,
|
|
@@ -758,6 +978,12 @@ var CodexCliLanguageModel = class {
|
|
|
758
978
|
controller.enqueue({ type: "text-end", id: textId });
|
|
759
979
|
}
|
|
760
980
|
const usageSummary = lastUsage ?? { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
981
|
+
this.logger.info(
|
|
982
|
+
`[codex-cli] Stream completed - Session: ${this.sessionId ?? "N/A"}, Duration: ${duration}ms, Tokens: ${usageSummary.totalTokens}`
|
|
983
|
+
);
|
|
984
|
+
this.logger.debug(
|
|
985
|
+
`[codex-cli] Token usage - Input: ${usageSummary.inputTokens}, Output: ${usageSummary.outputTokens}, Total: ${usageSummary.totalTokens}`
|
|
986
|
+
);
|
|
761
987
|
controller.enqueue({
|
|
762
988
|
type: "finish",
|
|
763
989
|
finishReason: "stop",
|
|
@@ -772,8 +998,10 @@ var CodexCliLanguageModel = class {
|
|
|
772
998
|
for (const line of lines) {
|
|
773
999
|
const event = this.parseExperimentalJsonEvent(line);
|
|
774
1000
|
if (!event) continue;
|
|
1001
|
+
this.logger.debug(`[codex-cli] Stream event: ${event.type ?? "unknown"}`);
|
|
775
1002
|
if (event.type === "thread.started" && typeof event.thread_id === "string") {
|
|
776
1003
|
this.sessionId = event.thread_id;
|
|
1004
|
+
this.logger.debug(`[codex-cli] Stream session started: ${this.sessionId}`);
|
|
777
1005
|
if (!responseMetadataSent) {
|
|
778
1006
|
responseMetadataSent = true;
|
|
779
1007
|
sendMetadata();
|
|
@@ -782,6 +1010,7 @@ var CodexCliLanguageModel = class {
|
|
|
782
1010
|
}
|
|
783
1011
|
if (event.type === "session.created" && typeof event.session_id === "string") {
|
|
784
1012
|
this.sessionId = event.session_id;
|
|
1013
|
+
this.logger.debug(`[codex-cli] Stream session created: ${this.sessionId}`);
|
|
785
1014
|
if (!responseMetadataSent) {
|
|
786
1015
|
responseMetadataSent = true;
|
|
787
1016
|
sendMetadata();
|
|
@@ -798,6 +1027,7 @@ var CodexCliLanguageModel = class {
|
|
|
798
1027
|
if (event.type === "turn.failed") {
|
|
799
1028
|
const errorText = event.error && typeof event.error.message === "string" && event.error.message || (typeof event.message === "string" ? event.message : void 0);
|
|
800
1029
|
turnFailureMessage = errorText ?? turnFailureMessage ?? "Codex turn failed";
|
|
1030
|
+
this.logger.error(`[codex-cli] Stream turn failed: ${turnFailureMessage}`);
|
|
801
1031
|
sendMetadata({ error: turnFailureMessage });
|
|
802
1032
|
continue;
|
|
803
1033
|
}
|
|
@@ -805,6 +1035,7 @@ var CodexCliLanguageModel = class {
|
|
|
805
1035
|
const errorText = typeof event.message === "string" ? event.message : void 0;
|
|
806
1036
|
const effective = errorText ?? "Codex error";
|
|
807
1037
|
turnFailureMessage = turnFailureMessage ?? effective;
|
|
1038
|
+
this.logger.error(`[codex-cli] Stream error event: ${effective}`);
|
|
808
1039
|
sendMetadata({ error: effective });
|
|
809
1040
|
continue;
|
|
810
1041
|
}
|
|
@@ -822,6 +1053,7 @@ var CodexCliLanguageModel = class {
|
|
|
822
1053
|
}
|
|
823
1054
|
};
|
|
824
1055
|
child.on("error", (e) => {
|
|
1056
|
+
this.logger.error(`[codex-cli] Stream spawn error: ${String(e)}`);
|
|
825
1057
|
if (options.abortSignal) options.abortSignal.removeEventListener("abort", onAbort);
|
|
826
1058
|
cleanupSchema();
|
|
827
1059
|
controller.error(this.handleSpawnError(e, promptExcerpt));
|