ai-sdk-provider-codex-cli 1.2.0 → 1.2.2

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
@@ -363,7 +363,7 @@ See [docs/ai-sdk-v5/configuration.md](docs/ai-sdk-v5/configuration.md) for the f
363
363
  - `minCodexVersion`: minimum supported app-server version (semver)
364
364
  - `includeRawChunks`: emit raw JSON-RPC notifications as `raw` stream parts by default
365
365
  - `serverRequests`: typed handlers for server-initiated JSON-RPC requests
366
- - `autoApprove`: default approval response when no custom handler is provided
366
+ - `autoApprove`: default approval response when no custom handler is provided (covers command execution, file changes, skills, and MCP tool call approvals via `mcpServer/elicitation/request` on Codex >= 0.139)
367
367
  - `persistExtendedHistory`: request extended thread history persistence
368
368
  - `threadMode`: `stateless` (default) or `persistent` automatic thread reuse
369
369
  - `resume`: shorthand to resume an existing thread id
package/dist/index.cjs CHANGED
@@ -203,6 +203,9 @@ var serverRequestsSchema = zod.z.object({
203
203
  onSkillApproval: zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
204
204
  message: "onSkillApproval must be a function"
205
205
  }).optional(),
206
+ onMcpElicitation: zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
207
+ message: "onMcpElicitation must be a function"
208
+ }).optional(),
206
209
  onToolRequestUserInput: zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
207
210
  message: "onToolRequestUserInput must be a function"
208
211
  }).optional(),
@@ -1623,7 +1626,13 @@ var ExecLanguageModel = class {
1623
1626
  }
1624
1627
  emitToolInvocation(controller, toolCallId, toolName, inputPayload) {
1625
1628
  const inputString = safeStringify(inputPayload);
1626
- controller.enqueue({ type: "tool-input-start", id: toolCallId, toolName });
1629
+ controller.enqueue({
1630
+ type: "tool-input-start",
1631
+ id: toolCallId,
1632
+ toolName,
1633
+ providerExecuted: true,
1634
+ dynamic: true
1635
+ });
1627
1636
  if (inputString) {
1628
1637
  controller.enqueue({ type: "tool-input-delta", id: toolCallId, delta: inputString });
1629
1638
  }
@@ -1633,7 +1642,8 @@ var ExecLanguageModel = class {
1633
1642
  toolCallId,
1634
1643
  toolName,
1635
1644
  input: inputString,
1636
- providerExecuted: true
1645
+ providerExecuted: true,
1646
+ dynamic: true
1637
1647
  });
1638
1648
  }
1639
1649
  emitToolResult(controller, toolCallId, toolName, item, resultPayload, metadata) {
@@ -1661,6 +1671,7 @@ var ExecLanguageModel = class {
1661
1671
  toolCallId,
1662
1672
  toolName,
1663
1673
  result: resultPayload ?? {},
1674
+ dynamic: true,
1664
1675
  ...isError ? { isError: true } : {},
1665
1676
  ...Object.keys(providerMetadataEntries).length ? { providerMetadata: { "codex-cli": providerMetadataEntries } } : {}
1666
1677
  });
@@ -2319,10 +2330,10 @@ function normalizeItemType(type) {
2319
2330
  function mapTool(item) {
2320
2331
  const type = normalizeItemType(item.type);
2321
2332
  if (type === "commandexecution") {
2322
- return { toolName: "exec" };
2333
+ return { toolName: "exec", dynamic: true };
2323
2334
  }
2324
2335
  if (type === "filechange") {
2325
- return { toolName: "patch" };
2336
+ return { toolName: "patch", dynamic: true };
2326
2337
  }
2327
2338
  if (type === "mcptoolcall") {
2328
2339
  const server = typeof item.server === "string" ? item.server || "server" : "server";
@@ -2333,7 +2344,7 @@ function mapTool(item) {
2333
2344
  };
2334
2345
  }
2335
2346
  if (type === "websearch") {
2336
- return { toolName: "web_search" };
2347
+ return { toolName: "web_search", dynamic: true };
2337
2348
  }
2338
2349
  return void 0;
2339
2350
  }
@@ -2400,7 +2411,8 @@ function createNotificationHandlers(context) {
2400
2411
  context.emitter.emitToolOutputDelta(
2401
2412
  itemId,
2402
2413
  tracked?.toolName ?? defaultToolName,
2403
- params.delta
2414
+ params.delta,
2415
+ tracked?.dynamic ?? true
2404
2416
  );
2405
2417
  };
2406
2418
  return {
@@ -2732,7 +2744,7 @@ var AppServerStreamEmitter = class {
2732
2744
  ...dynamic ? { dynamic: true } : {}
2733
2745
  });
2734
2746
  }
2735
- emitToolOutputDelta(toolCallId, toolName, delta) {
2747
+ emitToolOutputDelta(toolCallId, toolName, delta, dynamic) {
2736
2748
  this.safeEnqueue({
2737
2749
  type: "tool-result",
2738
2750
  toolCallId,
@@ -2741,7 +2753,8 @@ var AppServerStreamEmitter = class {
2741
2753
  result: {
2742
2754
  type: "output-delta",
2743
2755
  delta
2744
- }
2756
+ },
2757
+ ...dynamic ? { dynamic: true } : {}
2745
2758
  });
2746
2759
  }
2747
2760
  emitToolResult(toolCallId, toolName, result, dynamic, isError) {
@@ -4375,6 +4388,17 @@ var skillRequestApprovalParamsSchema = zod.z.object({
4375
4388
  itemId: zod.z.string(),
4376
4389
  skillName: zod.z.string()
4377
4390
  }).passthrough();
4391
+ var mcpServerElicitationRequestParamsSchema = zod.z.object({
4392
+ threadId: zod.z.string(),
4393
+ turnId: zod.z.string().nullable().optional(),
4394
+ serverName: zod.z.string(),
4395
+ mode: zod.z.string().optional(),
4396
+ message: zod.z.string().optional(),
4397
+ requestedSchema: zod.z.unknown().optional(),
4398
+ url: zod.z.string().optional(),
4399
+ elicitationId: zod.z.string().optional(),
4400
+ _meta: zod.z.record(zod.z.string(), zod.z.unknown()).nullable().optional()
4401
+ }).passthrough();
4378
4402
  var dynamicToolCallParamsSchema = zod.z.object({
4379
4403
  threadId: zod.z.string(),
4380
4404
  turnId: zod.z.string(),
@@ -4390,6 +4414,7 @@ var serverRequestParamSchemas = {
4390
4414
  "item/commandExecution/requestApproval": commandExecutionRequestApprovalParamsSchema,
4391
4415
  "item/fileChange/requestApproval": fileChangeRequestApprovalParamsSchema,
4392
4416
  "item/tool/requestUserInput": toolRequestUserInputParamsSchema,
4417
+ "mcpServer/elicitation/request": mcpServerElicitationRequestParamsSchema,
4393
4418
  "skill/requestApproval": skillRequestApprovalParamsSchema,
4394
4419
  "item/tool/call": dynamicToolCallParamsSchema,
4395
4420
  "account/chatgptAuthTokens/refresh": chatgptAuthTokensRefreshParamsSchema
@@ -4413,6 +4438,11 @@ var serverRequestSchema = zod.z.discriminatedUnion("method", [
4413
4438
  method: zod.z.literal("item/tool/requestUserInput"),
4414
4439
  params: toolRequestUserInputParamsSchema
4415
4440
  }).passthrough(),
4441
+ zod.z.object({
4442
+ id: jsonRpcIdSchema,
4443
+ method: zod.z.literal("mcpServer/elicitation/request"),
4444
+ params: mcpServerElicitationRequestParamsSchema
4445
+ }).passthrough(),
4416
4446
  zod.z.object({
4417
4447
  id: jsonRpcIdSchema,
4418
4448
  method: zod.z.literal("skill/requestApproval"),
@@ -5098,6 +5128,30 @@ var AppServerRpcClient = class extends events.EventEmitter {
5098
5128
  await sendResult({ decision: autoApprove ? "approve" : "decline" });
5099
5129
  return;
5100
5130
  }
5131
+ case "mcpServer/elicitation/request": {
5132
+ const handled = await runHandler(
5133
+ () => handlers.onMcpElicitation?.(normalized)
5134
+ );
5135
+ if (handled !== void 0) {
5136
+ await sendResult(handled);
5137
+ return;
5138
+ }
5139
+ const fallback = await runHandler(
5140
+ () => handlers.onUnhandled?.(normalized)
5141
+ );
5142
+ if (fallback !== void 0) {
5143
+ await sendResult(fallback);
5144
+ return;
5145
+ }
5146
+ const meta = normalized.params._meta;
5147
+ const isToolCallApproval = meta?.codex_approval_kind === "mcp_tool_call";
5148
+ if (isToolCallApproval && autoApprove) {
5149
+ await sendResult({ action: "accept", content: {} });
5150
+ } else {
5151
+ await sendResult({ action: "decline", content: null });
5152
+ }
5153
+ return;
5154
+ }
5101
5155
  case "item/tool/requestUserInput": {
5102
5156
  const handled = await runHandler(
5103
5157
  () => handlers.onToolRequestUserInput?.(
package/dist/index.d.cts CHANGED
@@ -407,6 +407,29 @@ interface ToolRequestUserInputParams {
407
407
  interface ToolRequestUserInputResponse {
408
408
  answers: Record<string, unknown>;
409
409
  }
410
+ type McpServerElicitationAction = 'accept' | 'decline' | 'cancel';
411
+ interface McpServerElicitationRequestParams {
412
+ threadId: string;
413
+ /** Nullable: the elicitation may arrive outside of an active turn. */
414
+ turnId?: string | null;
415
+ serverName: string;
416
+ /** 'form' requests carry message/requestedSchema; 'url' requests carry url/elicitationId. */
417
+ mode?: string;
418
+ message?: string;
419
+ requestedSchema?: unknown;
420
+ url?: string;
421
+ elicitationId?: string;
422
+ /**
423
+ * For MCP tool approval elicitations, Codex sets
424
+ * `codex_approval_kind: 'mcp_tool_call'` and may include `persist` hints.
425
+ */
426
+ _meta?: Record<string, unknown> | null;
427
+ }
428
+ interface McpServerElicitationRequestResponse {
429
+ action: McpServerElicitationAction;
430
+ /** Structured user input for accepted elicitations; null for decline/cancel. */
431
+ content?: Record<string, unknown> | null;
432
+ }
410
433
  interface DynamicToolCallParams {
411
434
  threadId: string;
412
435
  turnId: string;
@@ -547,6 +570,11 @@ interface AppServerSkillApprovalRequest {
547
570
  method: 'skill/requestApproval';
548
571
  params: SkillRequestApprovalParams;
549
572
  }
573
+ interface AppServerMcpElicitationRequest {
574
+ id: JsonRpcId;
575
+ method: 'mcpServer/elicitation/request';
576
+ params: McpServerElicitationRequestParams;
577
+ }
550
578
  interface AppServerToolRequestUserInputRequest {
551
579
  id: JsonRpcId;
552
580
  method: 'item/tool/requestUserInput';
@@ -580,6 +608,13 @@ interface CodexAppServerRequestHandlers {
580
608
  onCommandExecutionApproval?: (request: AppServerCommandExecutionApprovalRequest) => Promise<CommandExecutionRequestApprovalResponse | undefined>;
581
609
  onFileChangeApproval?: (request: AppServerFileChangeApprovalRequest) => Promise<FileChangeRequestApprovalResponse | undefined>;
582
610
  onSkillApproval?: (request: AppServerSkillApprovalRequest) => Promise<SkillRequestApprovalResponse | undefined>;
611
+ /**
612
+ * Handles `mcpServer/elicitation/request` (Codex >= 0.139), which includes
613
+ * MCP tool call approvals (`params._meta.codex_approval_kind === 'mcp_tool_call'`).
614
+ * Built-in default: accept tool call approvals when `autoApprove` is true,
615
+ * decline all other elicitations.
616
+ */
617
+ onMcpElicitation?: (request: AppServerMcpElicitationRequest) => Promise<McpServerElicitationRequestResponse | undefined>;
583
618
  onToolRequestUserInput?: (request: AppServerToolRequestUserInputRequest) => Promise<ToolRequestUserInputResponse | undefined>;
584
619
  onDynamicToolCall?: (request: AppServerDynamicToolCallRequest) => Promise<DynamicToolCallResponse | undefined>;
585
620
  onAuthRefresh?: (request: AppServerAuthRefreshRequest) => Promise<ChatgptAuthTokensRefreshResponse | undefined>;
package/dist/index.d.ts CHANGED
@@ -407,6 +407,29 @@ interface ToolRequestUserInputParams {
407
407
  interface ToolRequestUserInputResponse {
408
408
  answers: Record<string, unknown>;
409
409
  }
410
+ type McpServerElicitationAction = 'accept' | 'decline' | 'cancel';
411
+ interface McpServerElicitationRequestParams {
412
+ threadId: string;
413
+ /** Nullable: the elicitation may arrive outside of an active turn. */
414
+ turnId?: string | null;
415
+ serverName: string;
416
+ /** 'form' requests carry message/requestedSchema; 'url' requests carry url/elicitationId. */
417
+ mode?: string;
418
+ message?: string;
419
+ requestedSchema?: unknown;
420
+ url?: string;
421
+ elicitationId?: string;
422
+ /**
423
+ * For MCP tool approval elicitations, Codex sets
424
+ * `codex_approval_kind: 'mcp_tool_call'` and may include `persist` hints.
425
+ */
426
+ _meta?: Record<string, unknown> | null;
427
+ }
428
+ interface McpServerElicitationRequestResponse {
429
+ action: McpServerElicitationAction;
430
+ /** Structured user input for accepted elicitations; null for decline/cancel. */
431
+ content?: Record<string, unknown> | null;
432
+ }
410
433
  interface DynamicToolCallParams {
411
434
  threadId: string;
412
435
  turnId: string;
@@ -547,6 +570,11 @@ interface AppServerSkillApprovalRequest {
547
570
  method: 'skill/requestApproval';
548
571
  params: SkillRequestApprovalParams;
549
572
  }
573
+ interface AppServerMcpElicitationRequest {
574
+ id: JsonRpcId;
575
+ method: 'mcpServer/elicitation/request';
576
+ params: McpServerElicitationRequestParams;
577
+ }
550
578
  interface AppServerToolRequestUserInputRequest {
551
579
  id: JsonRpcId;
552
580
  method: 'item/tool/requestUserInput';
@@ -580,6 +608,13 @@ interface CodexAppServerRequestHandlers {
580
608
  onCommandExecutionApproval?: (request: AppServerCommandExecutionApprovalRequest) => Promise<CommandExecutionRequestApprovalResponse | undefined>;
581
609
  onFileChangeApproval?: (request: AppServerFileChangeApprovalRequest) => Promise<FileChangeRequestApprovalResponse | undefined>;
582
610
  onSkillApproval?: (request: AppServerSkillApprovalRequest) => Promise<SkillRequestApprovalResponse | undefined>;
611
+ /**
612
+ * Handles `mcpServer/elicitation/request` (Codex >= 0.139), which includes
613
+ * MCP tool call approvals (`params._meta.codex_approval_kind === 'mcp_tool_call'`).
614
+ * Built-in default: accept tool call approvals when `autoApprove` is true,
615
+ * decline all other elicitations.
616
+ */
617
+ onMcpElicitation?: (request: AppServerMcpElicitationRequest) => Promise<McpServerElicitationRequestResponse | undefined>;
583
618
  onToolRequestUserInput?: (request: AppServerToolRequestUserInputRequest) => Promise<ToolRequestUserInputResponse | undefined>;
584
619
  onDynamicToolCall?: (request: AppServerDynamicToolCallRequest) => Promise<DynamicToolCallResponse | undefined>;
585
620
  onAuthRefresh?: (request: AppServerAuthRefreshRequest) => Promise<ChatgptAuthTokensRefreshResponse | undefined>;
package/dist/index.js CHANGED
@@ -195,6 +195,9 @@ var serverRequestsSchema = z.object({
195
195
  onSkillApproval: z.any().refine((val) => val === void 0 || typeof val === "function", {
196
196
  message: "onSkillApproval must be a function"
197
197
  }).optional(),
198
+ onMcpElicitation: z.any().refine((val) => val === void 0 || typeof val === "function", {
199
+ message: "onMcpElicitation must be a function"
200
+ }).optional(),
198
201
  onToolRequestUserInput: z.any().refine((val) => val === void 0 || typeof val === "function", {
199
202
  message: "onToolRequestUserInput must be a function"
200
203
  }).optional(),
@@ -1615,7 +1618,13 @@ var ExecLanguageModel = class {
1615
1618
  }
1616
1619
  emitToolInvocation(controller, toolCallId, toolName, inputPayload) {
1617
1620
  const inputString = safeStringify(inputPayload);
1618
- controller.enqueue({ type: "tool-input-start", id: toolCallId, toolName });
1621
+ controller.enqueue({
1622
+ type: "tool-input-start",
1623
+ id: toolCallId,
1624
+ toolName,
1625
+ providerExecuted: true,
1626
+ dynamic: true
1627
+ });
1619
1628
  if (inputString) {
1620
1629
  controller.enqueue({ type: "tool-input-delta", id: toolCallId, delta: inputString });
1621
1630
  }
@@ -1625,7 +1634,8 @@ var ExecLanguageModel = class {
1625
1634
  toolCallId,
1626
1635
  toolName,
1627
1636
  input: inputString,
1628
- providerExecuted: true
1637
+ providerExecuted: true,
1638
+ dynamic: true
1629
1639
  });
1630
1640
  }
1631
1641
  emitToolResult(controller, toolCallId, toolName, item, resultPayload, metadata) {
@@ -1653,6 +1663,7 @@ var ExecLanguageModel = class {
1653
1663
  toolCallId,
1654
1664
  toolName,
1655
1665
  result: resultPayload ?? {},
1666
+ dynamic: true,
1656
1667
  ...isError ? { isError: true } : {},
1657
1668
  ...Object.keys(providerMetadataEntries).length ? { providerMetadata: { "codex-cli": providerMetadataEntries } } : {}
1658
1669
  });
@@ -2311,10 +2322,10 @@ function normalizeItemType(type) {
2311
2322
  function mapTool(item) {
2312
2323
  const type = normalizeItemType(item.type);
2313
2324
  if (type === "commandexecution") {
2314
- return { toolName: "exec" };
2325
+ return { toolName: "exec", dynamic: true };
2315
2326
  }
2316
2327
  if (type === "filechange") {
2317
- return { toolName: "patch" };
2328
+ return { toolName: "patch", dynamic: true };
2318
2329
  }
2319
2330
  if (type === "mcptoolcall") {
2320
2331
  const server = typeof item.server === "string" ? item.server || "server" : "server";
@@ -2325,7 +2336,7 @@ function mapTool(item) {
2325
2336
  };
2326
2337
  }
2327
2338
  if (type === "websearch") {
2328
- return { toolName: "web_search" };
2339
+ return { toolName: "web_search", dynamic: true };
2329
2340
  }
2330
2341
  return void 0;
2331
2342
  }
@@ -2392,7 +2403,8 @@ function createNotificationHandlers(context) {
2392
2403
  context.emitter.emitToolOutputDelta(
2393
2404
  itemId,
2394
2405
  tracked?.toolName ?? defaultToolName,
2395
- params.delta
2406
+ params.delta,
2407
+ tracked?.dynamic ?? true
2396
2408
  );
2397
2409
  };
2398
2410
  return {
@@ -2724,7 +2736,7 @@ var AppServerStreamEmitter = class {
2724
2736
  ...dynamic ? { dynamic: true } : {}
2725
2737
  });
2726
2738
  }
2727
- emitToolOutputDelta(toolCallId, toolName, delta) {
2739
+ emitToolOutputDelta(toolCallId, toolName, delta, dynamic) {
2728
2740
  this.safeEnqueue({
2729
2741
  type: "tool-result",
2730
2742
  toolCallId,
@@ -2733,7 +2745,8 @@ var AppServerStreamEmitter = class {
2733
2745
  result: {
2734
2746
  type: "output-delta",
2735
2747
  delta
2736
- }
2748
+ },
2749
+ ...dynamic ? { dynamic: true } : {}
2737
2750
  });
2738
2751
  }
2739
2752
  emitToolResult(toolCallId, toolName, result, dynamic, isError) {
@@ -4367,6 +4380,17 @@ var skillRequestApprovalParamsSchema = z.object({
4367
4380
  itemId: z.string(),
4368
4381
  skillName: z.string()
4369
4382
  }).passthrough();
4383
+ var mcpServerElicitationRequestParamsSchema = z.object({
4384
+ threadId: z.string(),
4385
+ turnId: z.string().nullable().optional(),
4386
+ serverName: z.string(),
4387
+ mode: z.string().optional(),
4388
+ message: z.string().optional(),
4389
+ requestedSchema: z.unknown().optional(),
4390
+ url: z.string().optional(),
4391
+ elicitationId: z.string().optional(),
4392
+ _meta: z.record(z.string(), z.unknown()).nullable().optional()
4393
+ }).passthrough();
4370
4394
  var dynamicToolCallParamsSchema = z.object({
4371
4395
  threadId: z.string(),
4372
4396
  turnId: z.string(),
@@ -4382,6 +4406,7 @@ var serverRequestParamSchemas = {
4382
4406
  "item/commandExecution/requestApproval": commandExecutionRequestApprovalParamsSchema,
4383
4407
  "item/fileChange/requestApproval": fileChangeRequestApprovalParamsSchema,
4384
4408
  "item/tool/requestUserInput": toolRequestUserInputParamsSchema,
4409
+ "mcpServer/elicitation/request": mcpServerElicitationRequestParamsSchema,
4385
4410
  "skill/requestApproval": skillRequestApprovalParamsSchema,
4386
4411
  "item/tool/call": dynamicToolCallParamsSchema,
4387
4412
  "account/chatgptAuthTokens/refresh": chatgptAuthTokensRefreshParamsSchema
@@ -4405,6 +4430,11 @@ var serverRequestSchema = z.discriminatedUnion("method", [
4405
4430
  method: z.literal("item/tool/requestUserInput"),
4406
4431
  params: toolRequestUserInputParamsSchema
4407
4432
  }).passthrough(),
4433
+ z.object({
4434
+ id: jsonRpcIdSchema,
4435
+ method: z.literal("mcpServer/elicitation/request"),
4436
+ params: mcpServerElicitationRequestParamsSchema
4437
+ }).passthrough(),
4408
4438
  z.object({
4409
4439
  id: jsonRpcIdSchema,
4410
4440
  method: z.literal("skill/requestApproval"),
@@ -5090,6 +5120,30 @@ var AppServerRpcClient = class extends EventEmitter {
5090
5120
  await sendResult({ decision: autoApprove ? "approve" : "decline" });
5091
5121
  return;
5092
5122
  }
5123
+ case "mcpServer/elicitation/request": {
5124
+ const handled = await runHandler(
5125
+ () => handlers.onMcpElicitation?.(normalized)
5126
+ );
5127
+ if (handled !== void 0) {
5128
+ await sendResult(handled);
5129
+ return;
5130
+ }
5131
+ const fallback = await runHandler(
5132
+ () => handlers.onUnhandled?.(normalized)
5133
+ );
5134
+ if (fallback !== void 0) {
5135
+ await sendResult(fallback);
5136
+ return;
5137
+ }
5138
+ const meta = normalized.params._meta;
5139
+ const isToolCallApproval = meta?.codex_approval_kind === "mcp_tool_call";
5140
+ if (isToolCallApproval && autoApprove) {
5141
+ await sendResult({ action: "accept", content: {} });
5142
+ } else {
5143
+ await sendResult({ action: "decline", content: null });
5144
+ }
5145
+ return;
5146
+ }
5093
5147
  case "item/tool/requestUserInput": {
5094
5148
  const handled = await runHandler(
5095
5149
  () => handlers.onToolRequestUserInput?.(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-sdk-provider-codex-cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "AI SDK v6 provider for OpenAI Codex CLI (use ChatGPT Plus/Pro subscription)",
5
5
  "keywords": [
6
6
  "ai-sdk",