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