ai-sdk-provider-codex-cli 1.0.4 → 1.1.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 +145 -38
- package/dist/index.cjs +4781 -441
- package/dist/index.d.cts +663 -196
- package/dist/index.d.ts +663 -196
- package/dist/index.js +4768 -444
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -10,9 +10,14 @@
|
|
|
10
10
|
[](https://github.com/ben-vargas/ai-sdk-provider-codex-cli/issues)
|
|
11
11
|
[](https://github.com/ben-vargas/ai-sdk-provider-codex-cli/releases/latest)
|
|
12
12
|
|
|
13
|
-
A community provider for Vercel AI SDK v6 that
|
|
13
|
+
A community provider for Vercel AI SDK v6 that integrates OpenAI's Codex CLI with GPT‑5.1 / GPT‑5.2 class models (`gpt-5.1`, `gpt-5.2`, the Codex-specific `gpt-5.3-codex` / `gpt-5.2-codex`, the flagship `*-codex-max`, and the lightweight `*-codex-mini` slugs) using your ChatGPT Plus/Pro subscription.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
This package ships two provider modes:
|
|
16
|
+
|
|
17
|
+
- `codexExec`: non-interactive `codex exec` (spawn a new process per call)
|
|
18
|
+
- `codexAppServer`: persistent `codex app-server` JSON-RPC client (shared process, true delta streaming, optional stateful threads)
|
|
19
|
+
|
|
20
|
+
- Works with `generateText`, `streamText`, and `generateObject`
|
|
16
21
|
- Uses ChatGPT OAuth from `codex login` (tokens in `~/.codex/auth.json`) or `OPENAI_API_KEY`
|
|
17
22
|
- Node-only (spawns a local process); supports CI and local dev
|
|
18
23
|
- **v1.0.0**: AI SDK v6 stable migration with LanguageModelV3 interface
|
|
@@ -49,7 +54,7 @@ npm i ai ai-sdk-provider-codex-cli
|
|
|
49
54
|
npm i ai@^5.0.0 ai-sdk-provider-codex-cli@ai-sdk-v5
|
|
50
55
|
```
|
|
51
56
|
|
|
52
|
-
> **⚠️ Codex CLI Version**: Requires Codex CLI **>= 0.
|
|
57
|
+
> **⚠️ Codex CLI Version**: Requires Codex CLI **>= 0.105.0** for full support of both provider modes (`codexExec` and `codexAppServer`). If you supply your own Codex CLI (global install or custom `codexPath`), check it with `codex --version` and upgrade if needed. The optional dependency `@openai/codex` in this package pulls a compatible version automatically.
|
|
53
58
|
>
|
|
54
59
|
> ```bash
|
|
55
60
|
> npm i -g @openai/codex@latest
|
|
@@ -57,13 +62,13 @@ npm i ai@^5.0.0 ai-sdk-provider-codex-cli@ai-sdk-v5
|
|
|
57
62
|
|
|
58
63
|
## Quick Start
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
### Exec provider (`codexExec`) — process-per-call
|
|
61
66
|
|
|
62
67
|
```js
|
|
63
68
|
import { generateText } from 'ai';
|
|
64
|
-
import {
|
|
69
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
65
70
|
|
|
66
|
-
const model =
|
|
71
|
+
const model = codexExec('gpt-5.3-codex', {
|
|
67
72
|
allowNpx: true,
|
|
68
73
|
skipGitRepoCheck: true,
|
|
69
74
|
approvalMode: 'on-failure',
|
|
@@ -77,31 +82,67 @@ const { text } = await generateText({
|
|
|
77
82
|
console.log(text);
|
|
78
83
|
```
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
### App-server provider (`createCodexAppServer`) — persistent process
|
|
81
86
|
|
|
82
87
|
```js
|
|
83
88
|
import { streamText } from 'ai';
|
|
84
|
-
import {
|
|
89
|
+
import { createCodexAppServer } from 'ai-sdk-provider-codex-cli';
|
|
90
|
+
|
|
91
|
+
const provider = createCodexAppServer({
|
|
92
|
+
defaultSettings: {
|
|
93
|
+
minCodexVersion: '0.105.0',
|
|
94
|
+
autoApprove: false,
|
|
95
|
+
personality: 'pragmatic',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
85
98
|
|
|
86
|
-
// The provider works with both `gpt-5.1` and `gpt-5.1-codex`; use the latter for
|
|
87
|
-
// the Codex CLI specific slug. Legacy `gpt-5` slugs still work if you need them.
|
|
88
99
|
const { textStream } = await streamText({
|
|
89
|
-
model:
|
|
100
|
+
model: provider('gpt-5.3-codex'),
|
|
90
101
|
prompt: 'Write two short lines of encouragement.',
|
|
91
102
|
});
|
|
92
103
|
for await (const chunk of textStream) process.stdout.write(chunk);
|
|
104
|
+
|
|
105
|
+
await provider.close();
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### App-server stateful threads (optional)
|
|
109
|
+
|
|
110
|
+
By default, `codexAppServer` is stateless (new ephemeral thread per call). To continue a prior conversation, pass `threadId` in `providerOptions['codex-app-server']`.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
import { generateText } from 'ai';
|
|
114
|
+
import { createCodexAppServer } from 'ai-sdk-provider-codex-cli';
|
|
115
|
+
|
|
116
|
+
const provider = createCodexAppServer();
|
|
117
|
+
|
|
118
|
+
const first = await generateText({
|
|
119
|
+
model: provider('gpt-5.3-codex'),
|
|
120
|
+
prompt: 'Start a migration checklist.',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const threadId = first.providerMetadata?.['codex-app-server']?.threadId;
|
|
124
|
+
|
|
125
|
+
const second = await generateText({
|
|
126
|
+
model: provider('gpt-5.3-codex'),
|
|
127
|
+
prompt: 'Continue from step 2.',
|
|
128
|
+
providerOptions: {
|
|
129
|
+
'codex-app-server': { threadId },
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
await provider.close();
|
|
93
134
|
```
|
|
94
135
|
|
|
95
|
-
Object generation (Zod)
|
|
136
|
+
### Object generation (Zod)
|
|
96
137
|
|
|
97
138
|
```js
|
|
98
139
|
import { generateObject } from 'ai';
|
|
99
140
|
import { z } from 'zod';
|
|
100
|
-
import {
|
|
141
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
101
142
|
|
|
102
143
|
const schema = z.object({ name: z.string(), age: z.number().int() });
|
|
103
144
|
const { object } = await generateObject({
|
|
104
|
-
model:
|
|
145
|
+
model: codexExec('gpt-5.3-codex', { allowNpx: true, skipGitRepoCheck: true }),
|
|
105
146
|
schema,
|
|
106
147
|
prompt: 'Generate a small user profile.',
|
|
107
148
|
});
|
|
@@ -111,6 +152,10 @@ console.log(object);
|
|
|
111
152
|
## Features
|
|
112
153
|
|
|
113
154
|
- AI SDK v6 compatible (LanguageModelV3)
|
|
155
|
+
- Dual provider architecture:
|
|
156
|
+
- `codexExec` / `createCodexExec` for `codex exec`
|
|
157
|
+
- `codexAppServer` / `createCodexAppServer` for `codex app-server`
|
|
158
|
+
- Backward-compatible aliases: `codexCli` / `createCodexCli` map to exec mode
|
|
114
159
|
- Streaming and non‑streaming
|
|
115
160
|
- **Configurable logging** (v0.5.0+) - Verbose mode, custom loggers, or silent operation
|
|
116
161
|
- **Tool streaming support** (v0.3.0+) - Monitor autonomous tool execution in real-time
|
|
@@ -119,7 +164,7 @@ console.log(object);
|
|
|
119
164
|
- Safe defaults for non‑interactive automation (`on-failure`, `workspace-write`, `--skip-git-repo-check`)
|
|
120
165
|
- Fallback to `npx @openai/codex` when not on PATH (`allowNpx`)
|
|
121
166
|
- Usage tracking from experimental JSON event format
|
|
122
|
-
- **Image support** -
|
|
167
|
+
- **Image support** - Local binary images in both providers, plus remote HTTP/HTTPS image URLs in app-server mode
|
|
123
168
|
|
|
124
169
|
### Image Support
|
|
125
170
|
|
|
@@ -127,10 +172,10 @@ The provider supports multimodal (image) inputs for vision-capable models:
|
|
|
127
172
|
|
|
128
173
|
```js
|
|
129
174
|
import { generateText } from 'ai';
|
|
130
|
-
import {
|
|
175
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
131
176
|
import { readFileSync } from 'fs';
|
|
132
177
|
|
|
133
|
-
const model =
|
|
178
|
+
const model = codexExec('gpt-5.3-codex', { allowNpx: true, skipGitRepoCheck: true });
|
|
134
179
|
const imageBuffer = readFileSync('./screenshot.png');
|
|
135
180
|
|
|
136
181
|
const { text } = await generateText({
|
|
@@ -154,13 +199,14 @@ console.log(text);
|
|
|
154
199
|
- Base64 string (without data URL prefix)
|
|
155
200
|
- `Buffer` / `Uint8Array` / `ArrayBuffer`
|
|
156
201
|
|
|
157
|
-
**
|
|
202
|
+
**Remote image URLs:**
|
|
158
203
|
|
|
159
|
-
- HTTP/HTTPS URLs
|
|
204
|
+
- `codexExec` mode: HTTP/HTTPS image URLs are not supported (provide binary/image data)
|
|
205
|
+
- `codexAppServer` mode: HTTP/HTTPS image URLs are supported and forwarded to app-server as remote image inputs
|
|
160
206
|
|
|
161
|
-
|
|
207
|
+
Local image data is written to temporary files and passed to Codex CLI via `--image` (or app-server `localImage`). Temp files are automatically cleaned up after each request.
|
|
162
208
|
|
|
163
|
-
See [examples/image-support.mjs](examples/image-support.mjs) for
|
|
209
|
+
See [examples/exec/image-support.mjs](examples/exec/image-support.mjs) and [examples/app-server/image-support.mjs](examples/app-server/image-support.mjs) for complete working examples.
|
|
164
210
|
|
|
165
211
|
### Tool Streaming (v0.3.0+)
|
|
166
212
|
|
|
@@ -168,10 +214,10 @@ The provider supports comprehensive tool streaming, enabling real-time monitorin
|
|
|
168
214
|
|
|
169
215
|
```js
|
|
170
216
|
import { streamText } from 'ai';
|
|
171
|
-
import {
|
|
217
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
172
218
|
|
|
173
219
|
const result = await streamText({
|
|
174
|
-
model:
|
|
220
|
+
model: codexExec('gpt-5.3-codex', { allowNpx: true, skipGitRepoCheck: true }),
|
|
175
221
|
prompt: 'List files and count lines in the largest one',
|
|
176
222
|
});
|
|
177
223
|
|
|
@@ -192,30 +238,35 @@ for await (const part of result.fullStream) {
|
|
|
192
238
|
- Tool result events with complete output payloads
|
|
193
239
|
- `providerExecuted: true` on all tool calls (Codex executes autonomously, app doesn't need to)
|
|
194
240
|
|
|
195
|
-
**
|
|
241
|
+
**Current behavior:**
|
|
242
|
+
|
|
243
|
+
- `codexExec`: tool outputs are delivered in final `tool-result` events.
|
|
244
|
+
- `codexAppServer`: when Codex emits tool output delta notifications, the provider surfaces `tool-result` parts with `result.type === 'output-delta'` during streaming.
|
|
245
|
+
|
|
246
|
+
See `examples/exec/streaming-tool-calls.mjs`, `examples/exec/streaming-multiple-tools.mjs`, and their app-server counterparts under `examples/app-server/`.
|
|
196
247
|
|
|
197
248
|
### Logging Configuration (v0.5.0+)
|
|
198
249
|
|
|
199
250
|
Control logging verbosity and integrate with your observability stack:
|
|
200
251
|
|
|
201
252
|
```js
|
|
202
|
-
import {
|
|
253
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
203
254
|
|
|
204
255
|
// Default: warn/error only (clean production output)
|
|
205
|
-
const model =
|
|
256
|
+
const model = codexExec('gpt-5.3-codex', {
|
|
206
257
|
allowNpx: true,
|
|
207
258
|
skipGitRepoCheck: true,
|
|
208
259
|
});
|
|
209
260
|
|
|
210
261
|
// Verbose mode: enable debug/info logs for troubleshooting
|
|
211
|
-
const verboseModel =
|
|
262
|
+
const verboseModel = codexExec('gpt-5.3-codex', {
|
|
212
263
|
allowNpx: true,
|
|
213
264
|
skipGitRepoCheck: true,
|
|
214
265
|
verbose: true, // Shows all log levels
|
|
215
266
|
});
|
|
216
267
|
|
|
217
268
|
// Custom logger: integrate with Winston, Pino, Datadog, etc.
|
|
218
|
-
const customModel =
|
|
269
|
+
const customModel = codexExec('gpt-5.3-codex', {
|
|
219
270
|
allowNpx: true,
|
|
220
271
|
skipGitRepoCheck: true,
|
|
221
272
|
verbose: true,
|
|
@@ -228,7 +279,7 @@ const customModel = codexCli('gpt-5.1-codex', {
|
|
|
228
279
|
});
|
|
229
280
|
|
|
230
281
|
// Silent: disable all logging
|
|
231
|
-
const silentModel =
|
|
282
|
+
const silentModel = codexExec('gpt-5.3-codex', {
|
|
232
283
|
allowNpx: true,
|
|
233
284
|
skipGitRepoCheck: true,
|
|
234
285
|
logger: false, // No logs at all
|
|
@@ -244,23 +295,23 @@ const silentModel = codexCli('gpt-5.1-codex', {
|
|
|
244
295
|
|
|
245
296
|
**Default Logger:** Adds level tags `[DEBUG]`, `[INFO]`, `[WARN]`, `[ERROR]` to console output. Use a custom logger or `logger: false` if you need different formatting.
|
|
246
297
|
|
|
247
|
-
See `examples/logging-*.mjs` for complete examples and [docs/ai-sdk-v5/guide.md](docs/ai-sdk-v5/guide.md) for detailed configuration.
|
|
298
|
+
See `examples/exec/logging-*.mjs` and `examples/app-server/logging-*.mjs` for complete examples, and [docs/ai-sdk-v5/guide.md](docs/ai-sdk-v5/guide.md) for detailed configuration.
|
|
248
299
|
|
|
249
300
|
### Text Streaming behavior
|
|
250
301
|
|
|
251
|
-
|
|
302
|
+
**`codexExec` mode:** Incremental streaming is not currently available with `codex exec --experimental-json`.
|
|
252
303
|
|
|
253
304
|
The `--experimental-json` output format (introduced Sept 25, 2025) currently only emits `item.completed` events with full text content. Incremental streaming via `item.updated` or delta events is not yet implemented by OpenAI.
|
|
254
305
|
|
|
255
|
-
**What this means:**
|
|
306
|
+
**What this means in exec mode:**
|
|
256
307
|
|
|
257
308
|
- `streamText()` works functionally but delivers the entire response in a single chunk after generation completes
|
|
258
309
|
- No incremental text deltas—you wait for the full response, then receive it all at once
|
|
259
310
|
- The AI SDK's streaming interface is supported, but actual incremental streaming is not available
|
|
260
311
|
|
|
261
|
-
|
|
312
|
+
**`codexAppServer` mode:** supports true incremental text deltas via `item/agentMessage/delta`, so `streamText()` emits progressively as tokens arrive.
|
|
262
313
|
|
|
263
|
-
When OpenAI adds streaming support
|
|
314
|
+
When OpenAI adds streaming support to `codex exec --experimental-json`, this provider will surface those deltas in exec mode as well.
|
|
264
315
|
|
|
265
316
|
## Documentation
|
|
266
317
|
|
|
@@ -269,7 +320,12 @@ When OpenAI adds streaming support, this provider will be updated to handle thos
|
|
|
269
320
|
- [docs/ai-sdk-v5/configuration.md](docs/ai-sdk-v5/configuration.md) – all settings and how they map to CLI flags
|
|
270
321
|
- [docs/ai-sdk-v5/troubleshooting.md](docs/ai-sdk-v5/troubleshooting.md) – common issues and fixes
|
|
271
322
|
- [docs/ai-sdk-v5/limitations.md](docs/ai-sdk-v5/limitations.md) – known constraints and behavior differences
|
|
323
|
+
- [docs/ai-sdk-v5/migration-app-server-v2.md](docs/ai-sdk-v5/migration-app-server-v2.md) – app-server v2 migration notes
|
|
272
324
|
- See [examples/](examples/) for runnable scripts covering core usage, streaming, permissions/sandboxing, and object generation.
|
|
325
|
+
- Validation helpers:
|
|
326
|
+
- `npm run validate:docs` checks markdown links and example command paths
|
|
327
|
+
- `npm run validate:examples:app-server` runs all app-server examples with intent checks
|
|
328
|
+
- `npm run validate:full` runs build/type/lint/test plus docs and app-server example validation
|
|
273
329
|
|
|
274
330
|
## Authentication
|
|
275
331
|
|
|
@@ -294,14 +350,45 @@ When OpenAI adds streaming support, this provider will be updated to handle thos
|
|
|
294
350
|
|
|
295
351
|
See [docs/ai-sdk-v5/configuration.md](docs/ai-sdk-v5/configuration.md) for the full list and examples.
|
|
296
352
|
|
|
353
|
+
### App-server settings highlights
|
|
354
|
+
|
|
355
|
+
`createCodexAppServer({ defaultSettings })` accepts app-server specific options:
|
|
356
|
+
|
|
357
|
+
- `connectionTimeoutMs`: initialize handshake timeout
|
|
358
|
+
- `requestTimeoutMs`: default per-request JSON-RPC timeout
|
|
359
|
+
- `idleTimeoutMs`: close idle app-server process after inactivity
|
|
360
|
+
- `minCodexVersion`: minimum supported app-server version (semver)
|
|
361
|
+
- `includeRawChunks`: emit raw JSON-RPC notifications as `raw` stream parts by default
|
|
362
|
+
- `serverRequests`: typed handlers for server-initiated JSON-RPC requests
|
|
363
|
+
- `autoApprove`: default approval response when no custom handler is provided
|
|
364
|
+
- `persistExtendedHistory`: request extended thread history persistence
|
|
365
|
+
- `threadMode`: `stateless` (default) or `persistent` automatic thread reuse
|
|
366
|
+
- `resume`: shorthand to resume an existing thread id
|
|
367
|
+
- `onSessionCreated`: receive a session object for `injectMessage()` / `interrupt()`
|
|
368
|
+
|
|
369
|
+
Per-call app-server overrides use `providerOptions['codex-app-server']` (for example `threadId`, `threadMode`, `includeRawChunks`, `personality`, `approvalPolicy`, `sandboxPolicy`, `serverRequests`, `configOverrides`).
|
|
370
|
+
|
|
371
|
+
Additional app-server helpers:
|
|
372
|
+
|
|
373
|
+
- `listModels()`: query available models via a temporary app-server process (or use `provider.listModels()` to query through an existing provider/client)
|
|
374
|
+
- `tool()`, `createLocalMcpServer()`, `createSdkMcpServer()`: define and expose local MCP tools
|
|
375
|
+
|
|
376
|
+
Local MCP security defaults:
|
|
377
|
+
|
|
378
|
+
- `createLocalMcpServer()` binds to loopback hosts by default and rejects non-loopback `host` values unless you set `allowNonLoopbackHost: true`.
|
|
379
|
+
- `createLocalMcpServer()` generates a per-server bearer token and expects `Authorization: Bearer <token>` on direct HTTP calls. The token is available at `server.config.bearerToken`.
|
|
380
|
+
- `createSdkMcpServer()` propagates this auth config automatically, so provider-level MCP wiring works without extra manual headers.
|
|
381
|
+
- Without `cacheKey`, SDK MCP server/tool function identity participates in persistent keying to avoid conflating closure-dependent tool behavior.
|
|
382
|
+
- Use `createSdkMcpServer({ cacheKey })` when you intentionally recreate equivalent SDK MCP definitions per call and want stable persistent model reuse.
|
|
383
|
+
|
|
297
384
|
## Model Parameters & Advanced Options (v0.4.0+)
|
|
298
385
|
|
|
299
386
|
Control reasoning effort, verbosity, and advanced Codex features at model creation time:
|
|
300
387
|
|
|
301
388
|
```ts
|
|
302
|
-
import {
|
|
389
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
303
390
|
|
|
304
|
-
const model =
|
|
391
|
+
const model = codexExec('gpt-5.3-codex', {
|
|
305
392
|
allowNpx: true,
|
|
306
393
|
skipGitRepoCheck: true,
|
|
307
394
|
addDirs: ['../shared'],
|
|
@@ -353,9 +440,9 @@ values take precedence over constructor defaults while leaving other settings in
|
|
|
353
440
|
|
|
354
441
|
```ts
|
|
355
442
|
import { generateText } from 'ai';
|
|
356
|
-
import {
|
|
443
|
+
import { codexExec } from 'ai-sdk-provider-codex-cli';
|
|
357
444
|
|
|
358
|
-
const model =
|
|
445
|
+
const model = codexExec('gpt-5.3-codex', {
|
|
359
446
|
allowNpx: true,
|
|
360
447
|
reasoningEffort: 'medium',
|
|
361
448
|
modelVerbosity: 'medium',
|
|
@@ -387,6 +474,26 @@ const response = await generateText({
|
|
|
387
474
|
|
|
388
475
|
**Precedence:** `providerOptions['codex-cli']` > constructor `CodexCliSettings` > Codex CLI defaults.
|
|
389
476
|
|
|
477
|
+
App-server per-call overrides use `providerOptions['codex-app-server']`:
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
import { createCodexAppServer } from 'ai-sdk-provider-codex-cli';
|
|
481
|
+
|
|
482
|
+
const appServerProvider = createCodexAppServer();
|
|
483
|
+
|
|
484
|
+
const response = await generateText({
|
|
485
|
+
model: appServerProvider('gpt-5.3-codex'),
|
|
486
|
+
prompt: 'Continue this task.',
|
|
487
|
+
providerOptions: {
|
|
488
|
+
'codex-app-server': {
|
|
489
|
+
threadId: 'thr_existing',
|
|
490
|
+
personality: 'pragmatic',
|
|
491
|
+
approvalPolicy: 'on-request',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
390
497
|
## Zod Compatibility
|
|
391
498
|
|
|
392
499
|
- Peer supports `zod@^3 || ^4`
|