ai-sdk-provider-claude-code 3.4.1 → 3.4.3

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
@@ -58,9 +58,11 @@ npm install ai-sdk-provider-claude-code ai zod@^4.0.0
58
58
 
59
59
  ### 1. Install and authenticate the CLI
60
60
 
61
+ See the [official docs](https://docs.anthropic.com/en/docs/claude-code/overview) for platform-specific options.
62
+
61
63
  ```bash
62
- npm install -g @anthropic-ai/claude-code
63
- claude login
64
+ curl -fsSL https://claude.ai/install.sh | bash
65
+ claude auth login
64
66
  ```
65
67
 
66
68
  ### 2. Add the provider
@@ -198,8 +200,8 @@ const model = claudeCode('sonnet', {
198
200
  CLI install and auth are unchanged:
199
201
 
200
202
  ```bash
201
- npm install -g @anthropic-ai/claude-code
202
- claude login
203
+ curl -fsSL https://claude.ai/install.sh | bash
204
+ claude auth login
203
205
  ```
204
206
 
205
207
  ### Migrating from v1.x to v2.0.0
@@ -271,22 +273,25 @@ console.log(result.object); // Matches the schema above
271
273
 
272
274
  This provider exposes Agent SDK options directly. Key options include:
273
275
 
274
- | Option | Description |
275
- | --------------------------------- | --------------------------------------------------------------------------------------------------------- |
276
- | `betas` | Enable beta features (e.g., `['context-1m-2025-08-07']`) |
277
- | `sandbox` | Configure sandbox behavior (`{ enabled: true }`) |
278
- | `plugins` | Load custom plugins from local paths |
279
- | `resumeSessionAt` | Resume session at a specific message UUID |
280
- | `enableFileCheckpointing` | Enable file rewind support |
281
- | `maxBudgetUsd` | Maximum budget in USD for the query |
282
- | `tools` | Tool configuration (array of names or preset) |
283
- | `allowDangerouslySkipPermissions` | Allow bypassing permissions |
284
- | `persistSession` | When `false`, disables session persistence to disk (v3.2.0+) |
285
- | `spawnClaudeCodeProcess` | Custom process spawner for VMs/containers (v3.2.0+) |
286
- | `permissionMode` | Permission mode: `'default'`, `'acceptEdits'`, `'bypassPermissions'`, `'plan'`, `'delegate'`, `'dontAsk'` |
287
- | `sessionId` | Use a specific session ID for deterministic tracking and correlation (v3.4.0+) |
288
- | `debug` | Enable programmatic debug logging from the SDK (v3.4.0+) |
289
- | `debugFile` | Path to a file for SDK debug log output (v3.4.0+) |
276
+ | Option | Description |
277
+ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
278
+ | `betas` | Enable beta features (e.g., `['context-1m-2025-08-07']`) |
279
+ | `sandbox` | Configure sandbox behavior (`{ enabled: true }`) |
280
+ | `plugins` | Load custom plugins from local paths |
281
+ | `resumeSessionAt` | Resume session at a specific message UUID |
282
+ | `enableFileCheckpointing` | Enable file rewind support |
283
+ | `maxBudgetUsd` | Maximum budget in USD for the query |
284
+ | `tools` | Tool configuration (array of names or preset) |
285
+ | `allowDangerouslySkipPermissions` | Allow bypassing permissions |
286
+ | `persistSession` | When `false`, disables session persistence to disk (v3.2.0+) |
287
+ | `spawnClaudeCodeProcess` | Custom process spawner for VMs/containers (v3.2.0+) |
288
+ | `permissionMode` | Permission mode: `'default'`, `'acceptEdits'`, `'bypassPermissions'`, `'plan'`, `'delegate'`, `'dontAsk'` |
289
+ | `sessionId` | Use a specific session ID for deterministic tracking and correlation (v3.4.0+) |
290
+ | `debug` | Enable programmatic debug logging from the SDK (v3.4.0+) |
291
+ | `debugFile` | Path to a file for SDK debug log output (v3.4.0+) |
292
+ | `effort` | Effort level: `'low'`, `'medium'`, `'high'`, or `'max'` |
293
+ | `thinking` | Thinking config: `{ type: 'adaptive' }`, `{ type: 'enabled', budgetTokens?: number }`, or `{ type: 'disabled' }` |
294
+ | `promptSuggestions` | Enable prompt suggestions (`boolean`) |
290
295
 
291
296
  **Agent definitions** (`agents`) now support additional fields (v3.2.0+):
292
297
 
@@ -434,7 +439,7 @@ This provider handles Anthropic `content_block_*` stream events directly for mor
434
439
 
435
440
  - **Tool input streaming** — `tool-input-delta` streams arguments incrementally; `tool-call` emits when the tool input block completes (before results), enabling “running” state in UIs.
436
441
  - **Text streaming** — `text-start/delta/end` emitted from content blocks with proper lifecycle management.
437
- - **Extended thinking** — `reasoning-start/delta/end` emitted from `thinking` content blocks (availability depends on model and request).
442
+ - **Extended thinking** — `reasoning-start/delta/end` emitted from `thinking` content blocks in streaming mode; `reasoning` content parts returned from `doGenerate` in non-streaming mode (availability depends on model and request).
438
443
 
439
444
  For subagent parent/child tracking, see **Subagent Hierarchy Tracking** in this README.
440
445
 
package/dist/index.cjs CHANGED
@@ -465,6 +465,16 @@ var claudeCodeSettingsSchema = import_zod.z.object({
465
465
  ]).optional(),
466
466
  maxTurns: import_zod.z.number().int().min(1).max(100).optional(),
467
467
  maxThinkingTokens: import_zod.z.number().int().positive().max(1e5).optional(),
468
+ thinking: import_zod.z.union([
469
+ import_zod.z.object({ type: import_zod.z.literal("adaptive") }).strict(),
470
+ import_zod.z.object({
471
+ type: import_zod.z.literal("enabled"),
472
+ budgetTokens: import_zod.z.number().int().positive().optional()
473
+ }).strict(),
474
+ import_zod.z.object({ type: import_zod.z.literal("disabled") }).strict()
475
+ ]).optional(),
476
+ effort: import_zod.z.enum(["low", "medium", "high", "max"]).optional(),
477
+ promptSuggestions: import_zod.z.boolean().optional(),
468
478
  cwd: import_zod.z.string().refine(
469
479
  (val) => {
470
480
  if (typeof process === "undefined" || !process.versions?.node) {
@@ -791,6 +801,22 @@ function getBaseProcessEnv() {
791
801
  }
792
802
  var STREAMING_FEATURE_WARNING = "Claude Agent SDK features (hooks/MCP/images) require streaming input. Set `streamingInput: 'always'` or provide `canUseTool` (auto streams only when canUseTool is set).";
793
803
  var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
804
+ function isContentBlock(item) {
805
+ return typeof item === "object" && item !== null && "type" in item;
806
+ }
807
+ function filterContentBlocks(content, type) {
808
+ if (!Array.isArray(content)) return [];
809
+ const blocks = content.filter(
810
+ (item) => isContentBlock(item) && item.type === type
811
+ );
812
+ const mismatch = blocks.find((b) => b.type !== type);
813
+ if (mismatch) {
814
+ throw new Error(
815
+ `filterContentBlocks: block type '${mismatch.type}' passed filter for '${type}'`
816
+ );
817
+ }
818
+ return blocks;
819
+ }
794
820
  function createEmptyUsage() {
795
821
  return {
796
822
  inputTokens: {
@@ -1046,14 +1072,29 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1046
1072
  getEffectiveResume(sdkOptions) {
1047
1073
  return sdkOptions?.resume ?? this.settings.resume ?? this.sessionId;
1048
1074
  }
1049
- extractToolUses(content) {
1050
- if (!Array.isArray(content)) {
1051
- return [];
1075
+ extractTextAndThinking(content) {
1076
+ if (!Array.isArray(content)) return { text: "", thinking: [] };
1077
+ let text = "";
1078
+ const thinking = [];
1079
+ for (const part of content) {
1080
+ if (!isContentBlock(part)) continue;
1081
+ if (part.type === "text" && typeof part.text === "string") {
1082
+ text += part.text;
1083
+ } else if (part.type === "thinking" && typeof part.thinking === "string") {
1084
+ thinking.push(part.thinking);
1085
+ }
1086
+ }
1087
+ if (text.length > 0 && typeof text !== "string") {
1088
+ throw new Error("extractTextAndThinking: accumulated text must be a string");
1089
+ }
1090
+ if (thinking.some((t) => typeof t !== "string")) {
1091
+ throw new Error("extractTextAndThinking: all thinking entries must be strings");
1052
1092
  }
1053
- return content.filter(
1054
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_use"
1055
- ).map((item) => {
1056
- const { id, name, input, parent_tool_use_id } = item;
1093
+ return { text, thinking };
1094
+ }
1095
+ extractToolUses(content) {
1096
+ return filterContentBlocks(content, "tool_use").map((block) => {
1097
+ const { id, name, input, parent_tool_use_id } = block;
1057
1098
  return {
1058
1099
  id: typeof id === "string" && id.length > 0 ? id : (0, import_provider_utils.generateId)(),
1059
1100
  name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
@@ -1063,13 +1104,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1063
1104
  });
1064
1105
  }
1065
1106
  extractToolResults(content) {
1066
- if (!Array.isArray(content)) {
1067
- return [];
1068
- }
1069
- return content.filter(
1070
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_result"
1071
- ).map((item) => {
1072
- const { tool_use_id, content: content2, is_error, name } = item;
1107
+ return filterContentBlocks(content, "tool_result").map((block) => {
1108
+ const { tool_use_id, content: content2, is_error, name } = block;
1073
1109
  return {
1074
1110
  id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
1075
1111
  name: typeof name === "string" && name.length > 0 ? name : void 0,
@@ -1079,13 +1115,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1079
1115
  });
1080
1116
  }
1081
1117
  extractToolErrors(content) {
1082
- if (!Array.isArray(content)) {
1083
- return [];
1084
- }
1085
- return content.filter(
1086
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_error"
1087
- ).map((item) => {
1088
- const { tool_use_id, error, name } = item;
1118
+ return filterContentBlocks(content, "tool_error").map((block) => {
1119
+ const { tool_use_id, error, name } = block;
1089
1120
  return {
1090
1121
  id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
1091
1122
  name: typeof name === "string" && name.length > 0 ? name : void 0,
@@ -1209,6 +1240,9 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1209
1240
  pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
1210
1241
  maxTurns: this.settings.maxTurns,
1211
1242
  maxThinkingTokens: this.settings.maxThinkingTokens,
1243
+ thinking: this.settings.thinking,
1244
+ effort: this.settings.effort,
1245
+ promptSuggestions: this.settings.promptSuggestions,
1212
1246
  cwd: this.settings.cwd,
1213
1247
  executable: this.settings.executable,
1214
1248
  executableArgs: this.settings.executableArgs,
@@ -1332,6 +1366,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1332
1366
  "auth failed",
1333
1367
  "please login",
1334
1368
  "claude login",
1369
+ "claude auth login",
1335
1370
  "/login",
1336
1371
  // CLI returns "Please run /login"
1337
1372
  "invalid api key"
@@ -1372,6 +1407,25 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1372
1407
  this.logger.warn(`Claude Code Session: ${warning}`);
1373
1408
  }
1374
1409
  }
1410
+ logMcpConnectionIssues(mcpServers) {
1411
+ if (!Array.isArray(mcpServers) || mcpServers.length === 0) {
1412
+ return;
1413
+ }
1414
+ const serversNeedingAttention = mcpServers.filter((server) => {
1415
+ const status = typeof server.status === "string" ? server.status.toLowerCase() : "";
1416
+ return status === "failed" || status === "needs-auth";
1417
+ });
1418
+ if (serversNeedingAttention.length === 0) {
1419
+ return;
1420
+ }
1421
+ const details = serversNeedingAttention.map((server) => {
1422
+ const name = typeof server.name === "string" && server.name.trim().length > 0 ? server.name : "<unknown>";
1423
+ const status = typeof server.status === "string" && server.status.trim().length > 0 ? server.status : "unknown";
1424
+ const error = typeof server.error === "string" && server.error.trim().length > 0 ? ` (${server.error})` : "";
1425
+ return `${name}:${status}${error}`;
1426
+ }).join(", ");
1427
+ this.logger.warn(`[claude-code] MCP servers not connected: ${details}`);
1428
+ }
1375
1429
  async doGenerate(options) {
1376
1430
  this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
1377
1431
  this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
@@ -1406,6 +1460,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1406
1460
  effectiveResume
1407
1461
  );
1408
1462
  let text = "";
1463
+ const thinkingTraces = [];
1409
1464
  let structuredOutput;
1410
1465
  let usage = createEmptyUsage();
1411
1466
  let finishReason = { unified: "stop", raw: void 0 };
@@ -1461,7 +1516,11 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1461
1516
  for await (const message of response) {
1462
1517
  this.logger.debug(`[claude-code] Received message type: ${message.type}`);
1463
1518
  if (message.type === "assistant") {
1464
- text += message.message.content.map((c) => c.type === "text" ? c.text : "").join("");
1519
+ const { text: messageText, thinking: messageThinking } = this.extractTextAndThinking(
1520
+ message.message.content
1521
+ );
1522
+ text += messageText;
1523
+ thinkingTraces.push(...messageThinking);
1465
1524
  } else if (message.type === "result") {
1466
1525
  done();
1467
1526
  this.setSessionId(message.session_id);
@@ -1494,6 +1553,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1494
1553
  finishReason = mapClaudeCodeFinishReason(message.subtype, stopReason);
1495
1554
  this.logger.debug(`[claude-code] Finish reason: ${finishReason.unified}`);
1496
1555
  } else if (message.type === "system" && message.subtype === "init") {
1556
+ this.logMcpConnectionIssues(message.mcp_servers);
1497
1557
  this.setSessionId(message.session_id);
1498
1558
  this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
1499
1559
  }
@@ -1527,7 +1587,13 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1527
1587
  }
1528
1588
  const finalText = structuredOutput !== void 0 ? JSON.stringify(structuredOutput) : text;
1529
1589
  return {
1530
- content: [{ type: "text", text: finalText }],
1590
+ content: [
1591
+ ...thinkingTraces.map((trace) => ({
1592
+ type: "reasoning",
1593
+ text: trace
1594
+ })),
1595
+ { type: "text", text: finalText }
1596
+ ],
1531
1597
  usage,
1532
1598
  finishReason,
1533
1599
  warnings,
@@ -1545,7 +1611,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1545
1611
  ...costUsd !== void 0 && { costUsd },
1546
1612
  ...durationMs !== void 0 && { durationMs },
1547
1613
  ...modelUsage !== void 0 && { modelUsage },
1548
- ...wasTruncated && { truncated: true }
1614
+ ...wasTruncated && { truncated: true },
1615
+ ...thinkingTraces.length > 0 && { thinkingTraces }
1549
1616
  }
1550
1617
  }
1551
1618
  };
@@ -2315,6 +2382,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
2315
2382
  controller.close();
2316
2383
  return;
2317
2384
  } else if (message.type === "system" && message.subtype === "init") {
2385
+ this.logMcpConnectionIssues(message.mcp_servers);
2318
2386
  this.setSessionId(message.session_id);
2319
2387
  this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
2320
2388
  controller.enqueue({