ai-sdk-provider-codex-cli 0.3.0 → 0.4.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 +67 -0
- package/dist/index.cjs +151 -16
- package/dist/index.d.cts +123 -1
- package/dist/index.d.ts +123 -1
- package/dist/index.js +151 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -179,6 +179,73 @@ When OpenAI adds streaming support, this provider will be updated to handle thos
|
|
|
179
179
|
|
|
180
180
|
See [docs/ai-sdk-v5/configuration.md](docs/ai-sdk-v5/configuration.md) for the full list and examples.
|
|
181
181
|
|
|
182
|
+
## Model Parameters & Advanced Options (v0.4.0+)
|
|
183
|
+
|
|
184
|
+
Control reasoning effort, verbosity, and advanced Codex features at model creation time:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { codexCli } from 'ai-sdk-provider-codex-cli';
|
|
188
|
+
|
|
189
|
+
const model = codexCli('gpt-5-codex', {
|
|
190
|
+
allowNpx: true,
|
|
191
|
+
skipGitRepoCheck: true,
|
|
192
|
+
|
|
193
|
+
// Reasoning & verbosity
|
|
194
|
+
reasoningEffort: 'medium', // minimal | low | medium | high
|
|
195
|
+
reasoningSummary: 'auto', // auto | detailed (Note: 'concise' and 'none' are rejected by API)
|
|
196
|
+
reasoningSummaryFormat: 'none', // none | experimental
|
|
197
|
+
modelVerbosity: 'high', // low | medium | high
|
|
198
|
+
|
|
199
|
+
// Advanced features
|
|
200
|
+
includePlanTool: true, // adds --include-plan-tool
|
|
201
|
+
profile: 'production', // adds --profile production
|
|
202
|
+
oss: false, // adds --oss when true
|
|
203
|
+
webSearch: true, // maps to -c tools.web_search=true
|
|
204
|
+
|
|
205
|
+
// Generic overrides (maps to -c key=value)
|
|
206
|
+
configOverrides: {
|
|
207
|
+
experimental_resume: '/tmp/session.jsonl',
|
|
208
|
+
sandbox_workspace_write: { network_access: true },
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Nested override objects are flattened to dotted keys (e.g., the example above emits
|
|
214
|
+
`-c sandbox_workspace_write.network_access=true`). Arrays are serialized to JSON strings.
|
|
215
|
+
|
|
216
|
+
### Per-call overrides via `providerOptions` (v0.4.0+)
|
|
217
|
+
|
|
218
|
+
Override these parameters for individual AI SDK calls using the `providerOptions` map. Per-call
|
|
219
|
+
values take precedence over constructor defaults while leaving other settings intact.
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { generateText } from 'ai';
|
|
223
|
+
import { codexCli } from 'ai-sdk-provider-codex-cli';
|
|
224
|
+
|
|
225
|
+
const model = codexCli('gpt-5-codex', {
|
|
226
|
+
allowNpx: true,
|
|
227
|
+
reasoningEffort: 'medium',
|
|
228
|
+
modelVerbosity: 'medium',
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const response = await generateText({
|
|
232
|
+
model,
|
|
233
|
+
prompt: 'Summarize the latest release notes.',
|
|
234
|
+
providerOptions: {
|
|
235
|
+
'codex-cli': {
|
|
236
|
+
reasoningEffort: 'high',
|
|
237
|
+
reasoningSummary: 'detailed',
|
|
238
|
+
textVerbosity: 'high', // AI SDK naming; maps to model_verbosity
|
|
239
|
+
configOverrides: {
|
|
240
|
+
experimental_resume: '/tmp/resume.jsonl',
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Precedence:** `providerOptions['codex-cli']` > constructor `CodexCliSettings` > Codex CLI defaults.
|
|
248
|
+
|
|
182
249
|
## Zod Compatibility
|
|
183
250
|
|
|
184
251
|
- Peer supports `zod@^3 || ^4`
|
package/dist/index.cjs
CHANGED
|
@@ -7,8 +7,8 @@ var module$1 = require('module');
|
|
|
7
7
|
var fs = require('fs');
|
|
8
8
|
var os = require('os');
|
|
9
9
|
var path = require('path');
|
|
10
|
-
var providerUtils = require('@ai-sdk/provider-utils');
|
|
11
10
|
var zod = require('zod');
|
|
11
|
+
var providerUtils = require('@ai-sdk/provider-utils');
|
|
12
12
|
|
|
13
13
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
14
14
|
// src/codex-cli-provider.ts
|
|
@@ -41,7 +41,29 @@ var settingsSchema = zod.z.object({
|
|
|
41
41
|
allowNpx: zod.z.boolean().optional(),
|
|
42
42
|
env: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
43
43
|
verbose: zod.z.boolean().optional(),
|
|
44
|
-
logger: zod.z.any().optional()
|
|
44
|
+
logger: zod.z.any().optional(),
|
|
45
|
+
// NEW: Reasoning & Verbosity
|
|
46
|
+
reasoningEffort: zod.z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
47
|
+
// Note: API rejects 'concise' and 'none' despite error messages claiming they're valid
|
|
48
|
+
reasoningSummary: zod.z.enum(["auto", "detailed"]).optional(),
|
|
49
|
+
reasoningSummaryFormat: zod.z.enum(["none", "experimental"]).optional(),
|
|
50
|
+
modelVerbosity: zod.z.enum(["low", "medium", "high"]).optional(),
|
|
51
|
+
// NEW: Advanced features
|
|
52
|
+
includePlanTool: zod.z.boolean().optional(),
|
|
53
|
+
profile: zod.z.string().optional(),
|
|
54
|
+
oss: zod.z.boolean().optional(),
|
|
55
|
+
webSearch: zod.z.boolean().optional(),
|
|
56
|
+
// NEW: Generic overrides
|
|
57
|
+
configOverrides: zod.z.record(
|
|
58
|
+
zod.z.string(),
|
|
59
|
+
zod.z.union([
|
|
60
|
+
zod.z.string(),
|
|
61
|
+
zod.z.number(),
|
|
62
|
+
zod.z.boolean(),
|
|
63
|
+
zod.z.object({}).passthrough(),
|
|
64
|
+
zod.z.array(zod.z.any())
|
|
65
|
+
])
|
|
66
|
+
).optional()
|
|
45
67
|
}).strict();
|
|
46
68
|
function validateSettings(settings) {
|
|
47
69
|
const warnings = [];
|
|
@@ -169,6 +191,22 @@ function isAuthenticationError(err) {
|
|
|
169
191
|
}
|
|
170
192
|
|
|
171
193
|
// src/codex-cli-language-model.ts
|
|
194
|
+
var codexCliProviderOptionsSchema = zod.z.object({
|
|
195
|
+
reasoningEffort: zod.z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
196
|
+
reasoningSummary: zod.z.enum(["auto", "detailed"]).optional(),
|
|
197
|
+
reasoningSummaryFormat: zod.z.enum(["none", "experimental"]).optional(),
|
|
198
|
+
textVerbosity: zod.z.enum(["low", "medium", "high"]).optional(),
|
|
199
|
+
configOverrides: zod.z.record(
|
|
200
|
+
zod.z.string(),
|
|
201
|
+
zod.z.union([
|
|
202
|
+
zod.z.string(),
|
|
203
|
+
zod.z.number(),
|
|
204
|
+
zod.z.boolean(),
|
|
205
|
+
zod.z.object({}).passthrough(),
|
|
206
|
+
zod.z.array(zod.z.any())
|
|
207
|
+
])
|
|
208
|
+
).optional()
|
|
209
|
+
}).strict();
|
|
172
210
|
function resolveCodexPath(explicitPath, allowNpx) {
|
|
173
211
|
if (explicitPath) return { cmd: "node", args: [explicitPath] };
|
|
174
212
|
try {
|
|
@@ -202,6 +240,21 @@ var CodexCliLanguageModel = class {
|
|
|
202
240
|
const warn = validateModelId(this.modelId);
|
|
203
241
|
if (warn) this.logger.warn(`Codex CLI model: ${warn}`);
|
|
204
242
|
}
|
|
243
|
+
mergeSettings(providerOptions) {
|
|
244
|
+
if (!providerOptions) return this.settings;
|
|
245
|
+
const mergedConfigOverrides = providerOptions.configOverrides || this.settings.configOverrides ? {
|
|
246
|
+
...this.settings.configOverrides ?? {},
|
|
247
|
+
...providerOptions.configOverrides ?? {}
|
|
248
|
+
} : void 0;
|
|
249
|
+
return {
|
|
250
|
+
...this.settings,
|
|
251
|
+
reasoningEffort: providerOptions.reasoningEffort ?? this.settings.reasoningEffort,
|
|
252
|
+
reasoningSummary: providerOptions.reasoningSummary ?? this.settings.reasoningSummary,
|
|
253
|
+
reasoningSummaryFormat: providerOptions.reasoningSummaryFormat ?? this.settings.reasoningSummaryFormat,
|
|
254
|
+
modelVerbosity: providerOptions.textVerbosity ?? this.settings.modelVerbosity,
|
|
255
|
+
configOverrides: mergedConfigOverrides
|
|
256
|
+
};
|
|
257
|
+
}
|
|
205
258
|
// Codex JSONL items use `type` for the item discriminator, but some
|
|
206
259
|
// earlier fixtures (and defensive parsing) might still surface `item_type`.
|
|
207
260
|
// This helper returns whichever is present.
|
|
@@ -212,28 +265,57 @@ var CodexCliLanguageModel = class {
|
|
|
212
265
|
const current = typeof data.type === "string" ? data.type : void 0;
|
|
213
266
|
return legacy ?? current;
|
|
214
267
|
}
|
|
215
|
-
buildArgs(promptText, responseFormat) {
|
|
216
|
-
const base = resolveCodexPath(
|
|
268
|
+
buildArgs(promptText, responseFormat, settings = this.settings) {
|
|
269
|
+
const base = resolveCodexPath(settings.codexPath, settings.allowNpx);
|
|
217
270
|
const args = [...base.args, "exec", "--experimental-json"];
|
|
218
|
-
if (
|
|
271
|
+
if (settings.fullAuto) {
|
|
219
272
|
args.push("--full-auto");
|
|
220
|
-
} else if (
|
|
273
|
+
} else if (settings.dangerouslyBypassApprovalsAndSandbox) {
|
|
221
274
|
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
222
275
|
} else {
|
|
223
|
-
const approval =
|
|
276
|
+
const approval = settings.approvalMode ?? "on-failure";
|
|
224
277
|
args.push("-c", `approval_policy=${approval}`);
|
|
225
|
-
const sandbox =
|
|
278
|
+
const sandbox = settings.sandboxMode ?? "workspace-write";
|
|
226
279
|
args.push("-c", `sandbox_mode=${sandbox}`);
|
|
227
280
|
}
|
|
228
|
-
if (
|
|
281
|
+
if (settings.skipGitRepoCheck !== false) {
|
|
229
282
|
args.push("--skip-git-repo-check");
|
|
230
283
|
}
|
|
231
|
-
if (
|
|
232
|
-
args.push("
|
|
284
|
+
if (settings.reasoningEffort) {
|
|
285
|
+
args.push("-c", `model_reasoning_effort=${settings.reasoningEffort}`);
|
|
286
|
+
}
|
|
287
|
+
if (settings.reasoningSummary) {
|
|
288
|
+
args.push("-c", `model_reasoning_summary=${settings.reasoningSummary}`);
|
|
289
|
+
}
|
|
290
|
+
if (settings.reasoningSummaryFormat) {
|
|
291
|
+
args.push("-c", `model_reasoning_summary_format=${settings.reasoningSummaryFormat}`);
|
|
292
|
+
}
|
|
293
|
+
if (settings.modelVerbosity) {
|
|
294
|
+
args.push("-c", `model_verbosity=${settings.modelVerbosity}`);
|
|
295
|
+
}
|
|
296
|
+
if (settings.includePlanTool) {
|
|
297
|
+
args.push("--include-plan-tool");
|
|
298
|
+
}
|
|
299
|
+
if (settings.profile) {
|
|
300
|
+
args.push("--profile", settings.profile);
|
|
301
|
+
}
|
|
302
|
+
if (settings.oss) {
|
|
303
|
+
args.push("--oss");
|
|
304
|
+
}
|
|
305
|
+
if (settings.webSearch) {
|
|
306
|
+
args.push("-c", "tools.web_search=true");
|
|
307
|
+
}
|
|
308
|
+
if (settings.color) {
|
|
309
|
+
args.push("--color", settings.color);
|
|
233
310
|
}
|
|
234
311
|
if (this.modelId) {
|
|
235
312
|
args.push("-m", this.modelId);
|
|
236
313
|
}
|
|
314
|
+
if (settings.configOverrides) {
|
|
315
|
+
for (const [key, value] of Object.entries(settings.configOverrides)) {
|
|
316
|
+
this.addConfigOverride(args, key, value);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
237
319
|
let schemaPath;
|
|
238
320
|
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
239
321
|
const schema = typeof responseFormat.schema === "object" ? responseFormat.schema : {};
|
|
@@ -253,16 +335,55 @@ var CodexCliLanguageModel = class {
|
|
|
253
335
|
args.push(promptText);
|
|
254
336
|
const env = {
|
|
255
337
|
...process.env,
|
|
256
|
-
...
|
|
338
|
+
...settings.env || {},
|
|
257
339
|
RUST_LOG: process.env.RUST_LOG || "error"
|
|
258
340
|
};
|
|
259
|
-
let lastMessagePath =
|
|
341
|
+
let lastMessagePath = settings.outputLastMessageFile;
|
|
260
342
|
if (!lastMessagePath) {
|
|
261
343
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "codex-cli-"));
|
|
262
344
|
lastMessagePath = path.join(dir, "last-message.txt");
|
|
263
345
|
}
|
|
264
346
|
args.push("--output-last-message", lastMessagePath);
|
|
265
|
-
return { cmd: base.cmd, args, env, cwd:
|
|
347
|
+
return { cmd: base.cmd, args, env, cwd: settings.cwd, lastMessagePath, schemaPath };
|
|
348
|
+
}
|
|
349
|
+
addConfigOverride(args, key, value) {
|
|
350
|
+
if (this.isPlainObject(value)) {
|
|
351
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
352
|
+
this.addConfigOverride(
|
|
353
|
+
args,
|
|
354
|
+
`${key}.${childKey}`,
|
|
355
|
+
childValue
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const serialized = this.serializeConfigValue(value);
|
|
361
|
+
args.push("-c", `${key}=${serialized}`);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Serialize a config override value into a CLI-safe string.
|
|
365
|
+
*/
|
|
366
|
+
serializeConfigValue(value) {
|
|
367
|
+
if (typeof value === "string") return value;
|
|
368
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
369
|
+
if (Array.isArray(value)) {
|
|
370
|
+
try {
|
|
371
|
+
return JSON.stringify(value);
|
|
372
|
+
} catch {
|
|
373
|
+
return String(value);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (value && typeof value === "object") {
|
|
377
|
+
try {
|
|
378
|
+
return JSON.stringify(value);
|
|
379
|
+
} catch {
|
|
380
|
+
return String(value);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return String(value);
|
|
384
|
+
}
|
|
385
|
+
isPlainObject(value) {
|
|
386
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
266
387
|
}
|
|
267
388
|
sanitizeJsonSchema(value) {
|
|
268
389
|
if (typeof value !== "object" || value === null) {
|
|
@@ -510,10 +631,17 @@ var CodexCliLanguageModel = class {
|
|
|
510
631
|
...this.mapWarnings(options),
|
|
511
632
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
512
633
|
];
|
|
634
|
+
const providerOptions = await providerUtils.parseProviderOptions({
|
|
635
|
+
provider: this.provider,
|
|
636
|
+
providerOptions: options.providerOptions,
|
|
637
|
+
schema: codexCliProviderOptionsSchema
|
|
638
|
+
});
|
|
639
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
513
640
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
514
641
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
515
642
|
promptText,
|
|
516
|
-
responseFormat
|
|
643
|
+
responseFormat,
|
|
644
|
+
effectiveSettings
|
|
517
645
|
);
|
|
518
646
|
let text = "";
|
|
519
647
|
const usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
@@ -635,10 +763,17 @@ var CodexCliLanguageModel = class {
|
|
|
635
763
|
...this.mapWarnings(options),
|
|
636
764
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
637
765
|
];
|
|
766
|
+
const providerOptions = await providerUtils.parseProviderOptions({
|
|
767
|
+
provider: this.provider,
|
|
768
|
+
providerOptions: options.providerOptions,
|
|
769
|
+
schema: codexCliProviderOptionsSchema
|
|
770
|
+
});
|
|
771
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
638
772
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
639
773
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
640
774
|
promptText,
|
|
641
|
-
responseFormat
|
|
775
|
+
responseFormat,
|
|
776
|
+
effectiveSettings
|
|
642
777
|
);
|
|
643
778
|
const stream = new ReadableStream({
|
|
644
779
|
start: (controller) => {
|
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,15 @@ interface Logger {
|
|
|
6
6
|
}
|
|
7
7
|
type ApprovalMode = 'untrusted' | 'on-failure' | 'on-request' | 'never';
|
|
8
8
|
type SandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
9
|
+
type ReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';
|
|
10
|
+
/**
|
|
11
|
+
* Reasoning summary detail level.
|
|
12
|
+
* Note: The API error messages claim 'concise' and 'none' are valid, but they are
|
|
13
|
+
* actually rejected with 400 errors. Only 'auto' and 'detailed' work in practice.
|
|
14
|
+
*/
|
|
15
|
+
type ReasoningSummary = 'auto' | 'detailed';
|
|
16
|
+
type ReasoningSummaryFormat = 'none' | 'experimental';
|
|
17
|
+
type ModelVerbosity = 'low' | 'medium' | 'high';
|
|
9
18
|
interface CodexCliSettings {
|
|
10
19
|
codexPath?: string;
|
|
11
20
|
cwd?: string;
|
|
@@ -20,10 +29,116 @@ interface CodexCliSettings {
|
|
|
20
29
|
env?: Record<string, string>;
|
|
21
30
|
verbose?: boolean;
|
|
22
31
|
logger?: Logger | false;
|
|
32
|
+
/**
|
|
33
|
+
* Controls reasoning effort for reasoning-capable models (o3, o4-mini, gpt-5, gpt-5-codex).
|
|
34
|
+
* Higher effort produces more thorough reasoning at the cost of latency.
|
|
35
|
+
*
|
|
36
|
+
* Maps to: `-c model_reasoning_effort=<value>`
|
|
37
|
+
* @see https://platform.openai.com/docs/guides/reasoning
|
|
38
|
+
*/
|
|
39
|
+
reasoningEffort?: ReasoningEffort;
|
|
40
|
+
/**
|
|
41
|
+
* Controls reasoning summary detail level.
|
|
42
|
+
*
|
|
43
|
+
* Valid values: 'auto' | 'detailed'
|
|
44
|
+
* Note: Despite API error messages claiming 'concise' and 'none' are valid,
|
|
45
|
+
* they are rejected with 400 errors in practice.
|
|
46
|
+
*
|
|
47
|
+
* Maps to: `-c model_reasoning_summary=<value>`
|
|
48
|
+
* @see https://platform.openai.com/docs/guides/reasoning#reasoning-summaries
|
|
49
|
+
*/
|
|
50
|
+
reasoningSummary?: ReasoningSummary;
|
|
51
|
+
/**
|
|
52
|
+
* Controls reasoning summary format (experimental).
|
|
53
|
+
*
|
|
54
|
+
* Maps to: `-c model_reasoning_summary_format=<value>`
|
|
55
|
+
*/
|
|
56
|
+
reasoningSummaryFormat?: ReasoningSummaryFormat;
|
|
57
|
+
/**
|
|
58
|
+
* Controls output length/detail for GPT-5 family models.
|
|
59
|
+
* Only applies to models using the Responses API.
|
|
60
|
+
*
|
|
61
|
+
* Maps to: `-c model_verbosity=<value>`
|
|
62
|
+
*/
|
|
63
|
+
modelVerbosity?: ModelVerbosity;
|
|
64
|
+
/**
|
|
65
|
+
* Include experimental plan tool that the model can use to update its current plan.
|
|
66
|
+
*
|
|
67
|
+
* Maps to: `--include-plan-tool`
|
|
68
|
+
*/
|
|
69
|
+
includePlanTool?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Configuration profile from config.toml to specify default options.
|
|
72
|
+
*
|
|
73
|
+
* Maps to: `--profile <name>`
|
|
74
|
+
*/
|
|
75
|
+
profile?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Use OSS provider (experimental).
|
|
78
|
+
*
|
|
79
|
+
* Maps to: `--oss`
|
|
80
|
+
*/
|
|
81
|
+
oss?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Enable web search tool for the model.
|
|
84
|
+
*
|
|
85
|
+
* Maps to: `-c tools.web_search=true`
|
|
86
|
+
*/
|
|
87
|
+
webSearch?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Generic Codex CLI config overrides. Allows setting any config value
|
|
90
|
+
* without updating the provider.
|
|
91
|
+
*
|
|
92
|
+
* Each entry maps to: `-c <key>=<value>`
|
|
93
|
+
*
|
|
94
|
+
* Examples:
|
|
95
|
+
* - `{ experimental_resume: '/tmp/session.jsonl' }`
|
|
96
|
+
* - `{ 'model_providers.custom.base_url': 'http://localhost:8000' }`
|
|
97
|
+
* - `{ 'sandbox_workspace_write': { network_access: true } }`
|
|
98
|
+
*
|
|
99
|
+
* Values are serialized:
|
|
100
|
+
* - string → raw string
|
|
101
|
+
* - number/boolean → String(value)
|
|
102
|
+
* - plain objects → flattened recursively to dotted keys
|
|
103
|
+
* - arrays → JSON.stringify(value)
|
|
104
|
+
* - other objects (Date, RegExp, Map, etc.) → JSON.stringify(value)
|
|
105
|
+
*/
|
|
106
|
+
configOverrides?: Record<string, string | number | boolean | object>;
|
|
23
107
|
}
|
|
24
108
|
interface CodexCliProviderSettings {
|
|
25
109
|
defaultSettings?: CodexCliSettings;
|
|
26
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Per-call overrides supplied through AI SDK providerOptions.
|
|
113
|
+
* These values take precedence over constructor-level CodexCliSettings.
|
|
114
|
+
*/
|
|
115
|
+
interface CodexCliProviderOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Per-call override for reasoning depth.
|
|
118
|
+
* Maps to `model_reasoning_effort`.
|
|
119
|
+
*/
|
|
120
|
+
reasoningEffort?: ReasoningEffort;
|
|
121
|
+
/**
|
|
122
|
+
* Per-call override for reasoning summary detail level.
|
|
123
|
+
* Maps to `model_reasoning_summary`.
|
|
124
|
+
*/
|
|
125
|
+
reasoningSummary?: ReasoningSummary;
|
|
126
|
+
/**
|
|
127
|
+
* Per-call override for reasoning summary format.
|
|
128
|
+
* Maps to `model_reasoning_summary_format`.
|
|
129
|
+
*/
|
|
130
|
+
reasoningSummaryFormat?: ReasoningSummaryFormat;
|
|
131
|
+
/**
|
|
132
|
+
* AI SDK naming for per-call verbosity overrides.
|
|
133
|
+
* Maps to Codex `model_verbosity`.
|
|
134
|
+
*/
|
|
135
|
+
textVerbosity?: ModelVerbosity;
|
|
136
|
+
/**
|
|
137
|
+
* Per-call Codex CLI config overrides. These are merged with
|
|
138
|
+
* constructor-level overrides with per-call values taking precedence.
|
|
139
|
+
*/
|
|
140
|
+
configOverrides?: Record<string, string | number | boolean | object>;
|
|
141
|
+
}
|
|
27
142
|
|
|
28
143
|
interface CodexCliProvider extends ProviderV2 {
|
|
29
144
|
(modelId: string, settings?: CodexCliSettings): LanguageModelV2;
|
|
@@ -51,8 +166,15 @@ declare class CodexCliLanguageModel implements LanguageModelV2 {
|
|
|
51
166
|
private logger;
|
|
52
167
|
private sessionId?;
|
|
53
168
|
constructor(options: CodexLanguageModelOptions);
|
|
169
|
+
private mergeSettings;
|
|
54
170
|
private getItemType;
|
|
55
171
|
private buildArgs;
|
|
172
|
+
private addConfigOverride;
|
|
173
|
+
/**
|
|
174
|
+
* Serialize a config override value into a CLI-safe string.
|
|
175
|
+
*/
|
|
176
|
+
private serializeConfigValue;
|
|
177
|
+
private isPlainObject;
|
|
56
178
|
private sanitizeJsonSchema;
|
|
57
179
|
private mapWarnings;
|
|
58
180
|
private parseExperimentalJsonEvent;
|
|
@@ -70,4 +192,4 @@ declare class CodexCliLanguageModel implements LanguageModelV2 {
|
|
|
70
192
|
|
|
71
193
|
declare function isAuthenticationError(err: unknown): boolean;
|
|
72
194
|
|
|
73
|
-
export { CodexCliLanguageModel, type CodexCliProvider, type CodexCliProviderSettings, type CodexCliSettings, type Logger, codexCli, createCodexCli, isAuthenticationError };
|
|
195
|
+
export { CodexCliLanguageModel, type CodexCliProvider, type CodexCliProviderOptions, type CodexCliProviderSettings, type CodexCliSettings, type Logger, type ModelVerbosity, type ReasoningEffort, type ReasoningSummary, type ReasoningSummaryFormat, codexCli, createCodexCli, isAuthenticationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,15 @@ interface Logger {
|
|
|
6
6
|
}
|
|
7
7
|
type ApprovalMode = 'untrusted' | 'on-failure' | 'on-request' | 'never';
|
|
8
8
|
type SandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
9
|
+
type ReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';
|
|
10
|
+
/**
|
|
11
|
+
* Reasoning summary detail level.
|
|
12
|
+
* Note: The API error messages claim 'concise' and 'none' are valid, but they are
|
|
13
|
+
* actually rejected with 400 errors. Only 'auto' and 'detailed' work in practice.
|
|
14
|
+
*/
|
|
15
|
+
type ReasoningSummary = 'auto' | 'detailed';
|
|
16
|
+
type ReasoningSummaryFormat = 'none' | 'experimental';
|
|
17
|
+
type ModelVerbosity = 'low' | 'medium' | 'high';
|
|
9
18
|
interface CodexCliSettings {
|
|
10
19
|
codexPath?: string;
|
|
11
20
|
cwd?: string;
|
|
@@ -20,10 +29,116 @@ interface CodexCliSettings {
|
|
|
20
29
|
env?: Record<string, string>;
|
|
21
30
|
verbose?: boolean;
|
|
22
31
|
logger?: Logger | false;
|
|
32
|
+
/**
|
|
33
|
+
* Controls reasoning effort for reasoning-capable models (o3, o4-mini, gpt-5, gpt-5-codex).
|
|
34
|
+
* Higher effort produces more thorough reasoning at the cost of latency.
|
|
35
|
+
*
|
|
36
|
+
* Maps to: `-c model_reasoning_effort=<value>`
|
|
37
|
+
* @see https://platform.openai.com/docs/guides/reasoning
|
|
38
|
+
*/
|
|
39
|
+
reasoningEffort?: ReasoningEffort;
|
|
40
|
+
/**
|
|
41
|
+
* Controls reasoning summary detail level.
|
|
42
|
+
*
|
|
43
|
+
* Valid values: 'auto' | 'detailed'
|
|
44
|
+
* Note: Despite API error messages claiming 'concise' and 'none' are valid,
|
|
45
|
+
* they are rejected with 400 errors in practice.
|
|
46
|
+
*
|
|
47
|
+
* Maps to: `-c model_reasoning_summary=<value>`
|
|
48
|
+
* @see https://platform.openai.com/docs/guides/reasoning#reasoning-summaries
|
|
49
|
+
*/
|
|
50
|
+
reasoningSummary?: ReasoningSummary;
|
|
51
|
+
/**
|
|
52
|
+
* Controls reasoning summary format (experimental).
|
|
53
|
+
*
|
|
54
|
+
* Maps to: `-c model_reasoning_summary_format=<value>`
|
|
55
|
+
*/
|
|
56
|
+
reasoningSummaryFormat?: ReasoningSummaryFormat;
|
|
57
|
+
/**
|
|
58
|
+
* Controls output length/detail for GPT-5 family models.
|
|
59
|
+
* Only applies to models using the Responses API.
|
|
60
|
+
*
|
|
61
|
+
* Maps to: `-c model_verbosity=<value>`
|
|
62
|
+
*/
|
|
63
|
+
modelVerbosity?: ModelVerbosity;
|
|
64
|
+
/**
|
|
65
|
+
* Include experimental plan tool that the model can use to update its current plan.
|
|
66
|
+
*
|
|
67
|
+
* Maps to: `--include-plan-tool`
|
|
68
|
+
*/
|
|
69
|
+
includePlanTool?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Configuration profile from config.toml to specify default options.
|
|
72
|
+
*
|
|
73
|
+
* Maps to: `--profile <name>`
|
|
74
|
+
*/
|
|
75
|
+
profile?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Use OSS provider (experimental).
|
|
78
|
+
*
|
|
79
|
+
* Maps to: `--oss`
|
|
80
|
+
*/
|
|
81
|
+
oss?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Enable web search tool for the model.
|
|
84
|
+
*
|
|
85
|
+
* Maps to: `-c tools.web_search=true`
|
|
86
|
+
*/
|
|
87
|
+
webSearch?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Generic Codex CLI config overrides. Allows setting any config value
|
|
90
|
+
* without updating the provider.
|
|
91
|
+
*
|
|
92
|
+
* Each entry maps to: `-c <key>=<value>`
|
|
93
|
+
*
|
|
94
|
+
* Examples:
|
|
95
|
+
* - `{ experimental_resume: '/tmp/session.jsonl' }`
|
|
96
|
+
* - `{ 'model_providers.custom.base_url': 'http://localhost:8000' }`
|
|
97
|
+
* - `{ 'sandbox_workspace_write': { network_access: true } }`
|
|
98
|
+
*
|
|
99
|
+
* Values are serialized:
|
|
100
|
+
* - string → raw string
|
|
101
|
+
* - number/boolean → String(value)
|
|
102
|
+
* - plain objects → flattened recursively to dotted keys
|
|
103
|
+
* - arrays → JSON.stringify(value)
|
|
104
|
+
* - other objects (Date, RegExp, Map, etc.) → JSON.stringify(value)
|
|
105
|
+
*/
|
|
106
|
+
configOverrides?: Record<string, string | number | boolean | object>;
|
|
23
107
|
}
|
|
24
108
|
interface CodexCliProviderSettings {
|
|
25
109
|
defaultSettings?: CodexCliSettings;
|
|
26
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Per-call overrides supplied through AI SDK providerOptions.
|
|
113
|
+
* These values take precedence over constructor-level CodexCliSettings.
|
|
114
|
+
*/
|
|
115
|
+
interface CodexCliProviderOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Per-call override for reasoning depth.
|
|
118
|
+
* Maps to `model_reasoning_effort`.
|
|
119
|
+
*/
|
|
120
|
+
reasoningEffort?: ReasoningEffort;
|
|
121
|
+
/**
|
|
122
|
+
* Per-call override for reasoning summary detail level.
|
|
123
|
+
* Maps to `model_reasoning_summary`.
|
|
124
|
+
*/
|
|
125
|
+
reasoningSummary?: ReasoningSummary;
|
|
126
|
+
/**
|
|
127
|
+
* Per-call override for reasoning summary format.
|
|
128
|
+
* Maps to `model_reasoning_summary_format`.
|
|
129
|
+
*/
|
|
130
|
+
reasoningSummaryFormat?: ReasoningSummaryFormat;
|
|
131
|
+
/**
|
|
132
|
+
* AI SDK naming for per-call verbosity overrides.
|
|
133
|
+
* Maps to Codex `model_verbosity`.
|
|
134
|
+
*/
|
|
135
|
+
textVerbosity?: ModelVerbosity;
|
|
136
|
+
/**
|
|
137
|
+
* Per-call Codex CLI config overrides. These are merged with
|
|
138
|
+
* constructor-level overrides with per-call values taking precedence.
|
|
139
|
+
*/
|
|
140
|
+
configOverrides?: Record<string, string | number | boolean | object>;
|
|
141
|
+
}
|
|
27
142
|
|
|
28
143
|
interface CodexCliProvider extends ProviderV2 {
|
|
29
144
|
(modelId: string, settings?: CodexCliSettings): LanguageModelV2;
|
|
@@ -51,8 +166,15 @@ declare class CodexCliLanguageModel implements LanguageModelV2 {
|
|
|
51
166
|
private logger;
|
|
52
167
|
private sessionId?;
|
|
53
168
|
constructor(options: CodexLanguageModelOptions);
|
|
169
|
+
private mergeSettings;
|
|
54
170
|
private getItemType;
|
|
55
171
|
private buildArgs;
|
|
172
|
+
private addConfigOverride;
|
|
173
|
+
/**
|
|
174
|
+
* Serialize a config override value into a CLI-safe string.
|
|
175
|
+
*/
|
|
176
|
+
private serializeConfigValue;
|
|
177
|
+
private isPlainObject;
|
|
56
178
|
private sanitizeJsonSchema;
|
|
57
179
|
private mapWarnings;
|
|
58
180
|
private parseExperimentalJsonEvent;
|
|
@@ -70,4 +192,4 @@ declare class CodexCliLanguageModel implements LanguageModelV2 {
|
|
|
70
192
|
|
|
71
193
|
declare function isAuthenticationError(err: unknown): boolean;
|
|
72
194
|
|
|
73
|
-
export { CodexCliLanguageModel, type CodexCliProvider, type CodexCliProviderSettings, type CodexCliSettings, type Logger, codexCli, createCodexCli, isAuthenticationError };
|
|
195
|
+
export { CodexCliLanguageModel, type CodexCliProvider, type CodexCliProviderOptions, type CodexCliProviderSettings, type CodexCliSettings, type Logger, type ModelVerbosity, type ReasoningEffort, type ReasoningSummary, type ReasoningSummaryFormat, codexCli, createCodexCli, isAuthenticationError };
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ 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
|
|
|
@@ -38,7 +38,29 @@ var settingsSchema = z.object({
|
|
|
38
38
|
allowNpx: z.boolean().optional(),
|
|
39
39
|
env: z.record(z.string(), z.string()).optional(),
|
|
40
40
|
verbose: z.boolean().optional(),
|
|
41
|
-
logger: z.any().optional()
|
|
41
|
+
logger: z.any().optional(),
|
|
42
|
+
// NEW: Reasoning & Verbosity
|
|
43
|
+
reasoningEffort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
44
|
+
// Note: API rejects 'concise' and 'none' despite error messages claiming they're valid
|
|
45
|
+
reasoningSummary: z.enum(["auto", "detailed"]).optional(),
|
|
46
|
+
reasoningSummaryFormat: z.enum(["none", "experimental"]).optional(),
|
|
47
|
+
modelVerbosity: z.enum(["low", "medium", "high"]).optional(),
|
|
48
|
+
// NEW: Advanced features
|
|
49
|
+
includePlanTool: z.boolean().optional(),
|
|
50
|
+
profile: z.string().optional(),
|
|
51
|
+
oss: z.boolean().optional(),
|
|
52
|
+
webSearch: z.boolean().optional(),
|
|
53
|
+
// NEW: Generic overrides
|
|
54
|
+
configOverrides: z.record(
|
|
55
|
+
z.string(),
|
|
56
|
+
z.union([
|
|
57
|
+
z.string(),
|
|
58
|
+
z.number(),
|
|
59
|
+
z.boolean(),
|
|
60
|
+
z.object({}).passthrough(),
|
|
61
|
+
z.array(z.any())
|
|
62
|
+
])
|
|
63
|
+
).optional()
|
|
42
64
|
}).strict();
|
|
43
65
|
function validateSettings(settings) {
|
|
44
66
|
const warnings = [];
|
|
@@ -166,6 +188,22 @@ function isAuthenticationError(err) {
|
|
|
166
188
|
}
|
|
167
189
|
|
|
168
190
|
// src/codex-cli-language-model.ts
|
|
191
|
+
var codexCliProviderOptionsSchema = z.object({
|
|
192
|
+
reasoningEffort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
193
|
+
reasoningSummary: z.enum(["auto", "detailed"]).optional(),
|
|
194
|
+
reasoningSummaryFormat: z.enum(["none", "experimental"]).optional(),
|
|
195
|
+
textVerbosity: z.enum(["low", "medium", "high"]).optional(),
|
|
196
|
+
configOverrides: z.record(
|
|
197
|
+
z.string(),
|
|
198
|
+
z.union([
|
|
199
|
+
z.string(),
|
|
200
|
+
z.number(),
|
|
201
|
+
z.boolean(),
|
|
202
|
+
z.object({}).passthrough(),
|
|
203
|
+
z.array(z.any())
|
|
204
|
+
])
|
|
205
|
+
).optional()
|
|
206
|
+
}).strict();
|
|
169
207
|
function resolveCodexPath(explicitPath, allowNpx) {
|
|
170
208
|
if (explicitPath) return { cmd: "node", args: [explicitPath] };
|
|
171
209
|
try {
|
|
@@ -199,6 +237,21 @@ var CodexCliLanguageModel = class {
|
|
|
199
237
|
const warn = validateModelId(this.modelId);
|
|
200
238
|
if (warn) this.logger.warn(`Codex CLI model: ${warn}`);
|
|
201
239
|
}
|
|
240
|
+
mergeSettings(providerOptions) {
|
|
241
|
+
if (!providerOptions) return this.settings;
|
|
242
|
+
const mergedConfigOverrides = providerOptions.configOverrides || this.settings.configOverrides ? {
|
|
243
|
+
...this.settings.configOverrides ?? {},
|
|
244
|
+
...providerOptions.configOverrides ?? {}
|
|
245
|
+
} : void 0;
|
|
246
|
+
return {
|
|
247
|
+
...this.settings,
|
|
248
|
+
reasoningEffort: providerOptions.reasoningEffort ?? this.settings.reasoningEffort,
|
|
249
|
+
reasoningSummary: providerOptions.reasoningSummary ?? this.settings.reasoningSummary,
|
|
250
|
+
reasoningSummaryFormat: providerOptions.reasoningSummaryFormat ?? this.settings.reasoningSummaryFormat,
|
|
251
|
+
modelVerbosity: providerOptions.textVerbosity ?? this.settings.modelVerbosity,
|
|
252
|
+
configOverrides: mergedConfigOverrides
|
|
253
|
+
};
|
|
254
|
+
}
|
|
202
255
|
// Codex JSONL items use `type` for the item discriminator, but some
|
|
203
256
|
// earlier fixtures (and defensive parsing) might still surface `item_type`.
|
|
204
257
|
// This helper returns whichever is present.
|
|
@@ -209,28 +262,57 @@ var CodexCliLanguageModel = class {
|
|
|
209
262
|
const current = typeof data.type === "string" ? data.type : void 0;
|
|
210
263
|
return legacy ?? current;
|
|
211
264
|
}
|
|
212
|
-
buildArgs(promptText, responseFormat) {
|
|
213
|
-
const base = resolveCodexPath(
|
|
265
|
+
buildArgs(promptText, responseFormat, settings = this.settings) {
|
|
266
|
+
const base = resolveCodexPath(settings.codexPath, settings.allowNpx);
|
|
214
267
|
const args = [...base.args, "exec", "--experimental-json"];
|
|
215
|
-
if (
|
|
268
|
+
if (settings.fullAuto) {
|
|
216
269
|
args.push("--full-auto");
|
|
217
|
-
} else if (
|
|
270
|
+
} else if (settings.dangerouslyBypassApprovalsAndSandbox) {
|
|
218
271
|
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
219
272
|
} else {
|
|
220
|
-
const approval =
|
|
273
|
+
const approval = settings.approvalMode ?? "on-failure";
|
|
221
274
|
args.push("-c", `approval_policy=${approval}`);
|
|
222
|
-
const sandbox =
|
|
275
|
+
const sandbox = settings.sandboxMode ?? "workspace-write";
|
|
223
276
|
args.push("-c", `sandbox_mode=${sandbox}`);
|
|
224
277
|
}
|
|
225
|
-
if (
|
|
278
|
+
if (settings.skipGitRepoCheck !== false) {
|
|
226
279
|
args.push("--skip-git-repo-check");
|
|
227
280
|
}
|
|
228
|
-
if (
|
|
229
|
-
args.push("
|
|
281
|
+
if (settings.reasoningEffort) {
|
|
282
|
+
args.push("-c", `model_reasoning_effort=${settings.reasoningEffort}`);
|
|
283
|
+
}
|
|
284
|
+
if (settings.reasoningSummary) {
|
|
285
|
+
args.push("-c", `model_reasoning_summary=${settings.reasoningSummary}`);
|
|
286
|
+
}
|
|
287
|
+
if (settings.reasoningSummaryFormat) {
|
|
288
|
+
args.push("-c", `model_reasoning_summary_format=${settings.reasoningSummaryFormat}`);
|
|
289
|
+
}
|
|
290
|
+
if (settings.modelVerbosity) {
|
|
291
|
+
args.push("-c", `model_verbosity=${settings.modelVerbosity}`);
|
|
292
|
+
}
|
|
293
|
+
if (settings.includePlanTool) {
|
|
294
|
+
args.push("--include-plan-tool");
|
|
295
|
+
}
|
|
296
|
+
if (settings.profile) {
|
|
297
|
+
args.push("--profile", settings.profile);
|
|
298
|
+
}
|
|
299
|
+
if (settings.oss) {
|
|
300
|
+
args.push("--oss");
|
|
301
|
+
}
|
|
302
|
+
if (settings.webSearch) {
|
|
303
|
+
args.push("-c", "tools.web_search=true");
|
|
304
|
+
}
|
|
305
|
+
if (settings.color) {
|
|
306
|
+
args.push("--color", settings.color);
|
|
230
307
|
}
|
|
231
308
|
if (this.modelId) {
|
|
232
309
|
args.push("-m", this.modelId);
|
|
233
310
|
}
|
|
311
|
+
if (settings.configOverrides) {
|
|
312
|
+
for (const [key, value] of Object.entries(settings.configOverrides)) {
|
|
313
|
+
this.addConfigOverride(args, key, value);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
234
316
|
let schemaPath;
|
|
235
317
|
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
236
318
|
const schema = typeof responseFormat.schema === "object" ? responseFormat.schema : {};
|
|
@@ -250,16 +332,55 @@ var CodexCliLanguageModel = class {
|
|
|
250
332
|
args.push(promptText);
|
|
251
333
|
const env = {
|
|
252
334
|
...process.env,
|
|
253
|
-
...
|
|
335
|
+
...settings.env || {},
|
|
254
336
|
RUST_LOG: process.env.RUST_LOG || "error"
|
|
255
337
|
};
|
|
256
|
-
let lastMessagePath =
|
|
338
|
+
let lastMessagePath = settings.outputLastMessageFile;
|
|
257
339
|
if (!lastMessagePath) {
|
|
258
340
|
const dir = mkdtempSync(join(tmpdir(), "codex-cli-"));
|
|
259
341
|
lastMessagePath = join(dir, "last-message.txt");
|
|
260
342
|
}
|
|
261
343
|
args.push("--output-last-message", lastMessagePath);
|
|
262
|
-
return { cmd: base.cmd, args, env, cwd:
|
|
344
|
+
return { cmd: base.cmd, args, env, cwd: settings.cwd, lastMessagePath, schemaPath };
|
|
345
|
+
}
|
|
346
|
+
addConfigOverride(args, key, value) {
|
|
347
|
+
if (this.isPlainObject(value)) {
|
|
348
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
349
|
+
this.addConfigOverride(
|
|
350
|
+
args,
|
|
351
|
+
`${key}.${childKey}`,
|
|
352
|
+
childValue
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const serialized = this.serializeConfigValue(value);
|
|
358
|
+
args.push("-c", `${key}=${serialized}`);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Serialize a config override value into a CLI-safe string.
|
|
362
|
+
*/
|
|
363
|
+
serializeConfigValue(value) {
|
|
364
|
+
if (typeof value === "string") return value;
|
|
365
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
366
|
+
if (Array.isArray(value)) {
|
|
367
|
+
try {
|
|
368
|
+
return JSON.stringify(value);
|
|
369
|
+
} catch {
|
|
370
|
+
return String(value);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (value && typeof value === "object") {
|
|
374
|
+
try {
|
|
375
|
+
return JSON.stringify(value);
|
|
376
|
+
} catch {
|
|
377
|
+
return String(value);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return String(value);
|
|
381
|
+
}
|
|
382
|
+
isPlainObject(value) {
|
|
383
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
263
384
|
}
|
|
264
385
|
sanitizeJsonSchema(value) {
|
|
265
386
|
if (typeof value !== "object" || value === null) {
|
|
@@ -507,10 +628,17 @@ var CodexCliLanguageModel = class {
|
|
|
507
628
|
...this.mapWarnings(options),
|
|
508
629
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
509
630
|
];
|
|
631
|
+
const providerOptions = await parseProviderOptions({
|
|
632
|
+
provider: this.provider,
|
|
633
|
+
providerOptions: options.providerOptions,
|
|
634
|
+
schema: codexCliProviderOptionsSchema
|
|
635
|
+
});
|
|
636
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
510
637
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
511
638
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
512
639
|
promptText,
|
|
513
|
-
responseFormat
|
|
640
|
+
responseFormat,
|
|
641
|
+
effectiveSettings
|
|
514
642
|
);
|
|
515
643
|
let text = "";
|
|
516
644
|
const usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
@@ -632,10 +760,17 @@ var CodexCliLanguageModel = class {
|
|
|
632
760
|
...this.mapWarnings(options),
|
|
633
761
|
...mappingWarnings?.map((m) => ({ type: "other", message: m })) || []
|
|
634
762
|
];
|
|
763
|
+
const providerOptions = await parseProviderOptions({
|
|
764
|
+
provider: this.provider,
|
|
765
|
+
providerOptions: options.providerOptions,
|
|
766
|
+
schema: codexCliProviderOptionsSchema
|
|
767
|
+
});
|
|
768
|
+
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
635
769
|
const responseFormat = options.responseFormat?.type === "json" ? { type: "json", schema: options.responseFormat.schema } : void 0;
|
|
636
770
|
const { cmd, args, env, cwd, lastMessagePath, schemaPath } = this.buildArgs(
|
|
637
771
|
promptText,
|
|
638
|
-
responseFormat
|
|
772
|
+
responseFormat,
|
|
773
|
+
effectiveSettings
|
|
639
774
|
);
|
|
640
775
|
const stream = new ReadableStream({
|
|
641
776
|
start: (controller) => {
|