ai-sdk-provider-claude-code 4.0.0 → 4.0.1
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 +17 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +73 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -706,6 +706,23 @@ All requests made through this provider report timing in `finalStep.providerMeta
|
|
|
706
706
|
- When replaying conversation history through the prompt, assistant tool calls are serialized as text lines — `[Tool call: Read({"file_path":"/x"})]` (inputs truncated at 1000 characters) — paired with `Tool Result (Read): ...` lines for tool messages
|
|
707
707
|
- `canUseTool` requires streaming input at the SDK level (AsyncIterable prompt), and image prompts use the same path. This provider supports it via `streamingInput`: use `'auto'` (streams when `canUseTool` is set or image parts are present), `'always'`, or `'off'` (`'off'` disables streaming image input, emits a generic `type: 'other'` image streaming-input warning, and omits image parts). See GUIDE for details.
|
|
708
708
|
|
|
709
|
+
## Error Diagnostics
|
|
710
|
+
|
|
711
|
+
Mapped errors from this provider append a trimmed stderr tail to the error message as `... | stderr (tail): <last lines>`, making CLI failures visible in logs without inspecting metadata.
|
|
712
|
+
|
|
713
|
+
```ts
|
|
714
|
+
import { generateText } from 'ai';
|
|
715
|
+
import { claudeCode, getErrorMetadata } from 'ai-sdk-provider-claude-code';
|
|
716
|
+
|
|
717
|
+
try {
|
|
718
|
+
await generateText({ model: claudeCode('sonnet'), prompt: 'Hello!' });
|
|
719
|
+
} catch (error) {
|
|
720
|
+
console.error(getErrorMetadata(error)?.stderr);
|
|
721
|
+
}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
The metadata accessor returns the full captured stderr, capped at 4000 characters. Authentication and timeout failures are also classified when the only evidence is in stderr, using high-precision matching to avoid false positives from unrelated stderr output.
|
|
725
|
+
|
|
709
726
|
## Tool Error Parity (Streaming)
|
|
710
727
|
|
|
711
728
|
- AI SDK v7 represents failed tool executions with the standard `tool-result` stream event/part and `isError: true`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1428,8 +1428,9 @@ declare function createAPICallError({ message, code, exitCode, stderr, promptExc
|
|
|
1428
1428
|
* });
|
|
1429
1429
|
* ```
|
|
1430
1430
|
*/
|
|
1431
|
-
declare function createAuthenticationError({ message }: {
|
|
1431
|
+
declare function createAuthenticationError({ message, stderr, }: {
|
|
1432
1432
|
message: string;
|
|
1433
|
+
stderr?: string;
|
|
1433
1434
|
}): LoadAPIKeyError;
|
|
1434
1435
|
/**
|
|
1435
1436
|
* Creates a timeout error for Claude Code SDK operations.
|
|
@@ -1448,8 +1449,9 @@ declare function createAuthenticationError({ message }: {
|
|
|
1448
1449
|
* });
|
|
1449
1450
|
* ```
|
|
1450
1451
|
*/
|
|
1451
|
-
declare function createTimeoutError({ message, promptExcerpt, timeoutMs, }: {
|
|
1452
|
+
declare function createTimeoutError({ message, stderr, promptExcerpt, timeoutMs, }: {
|
|
1452
1453
|
message: string;
|
|
1454
|
+
stderr?: string;
|
|
1453
1455
|
promptExcerpt?: string;
|
|
1454
1456
|
timeoutMs?: number;
|
|
1455
1457
|
}): APICallError;
|
package/dist/index.js
CHANGED
|
@@ -488,6 +488,21 @@ ${segmentText}`;
|
|
|
488
488
|
|
|
489
489
|
// src/errors.ts
|
|
490
490
|
import { APICallError, LoadAPIKeyError } from "@ai-sdk/provider";
|
|
491
|
+
var STDERR_TAIL_MARKER = " | stderr (tail):";
|
|
492
|
+
var ANSI_ESCAPE_SEQUENCE = (
|
|
493
|
+
// eslint-disable-next-line no-control-regex
|
|
494
|
+
/\x1b(?:\][^\x07\x1b]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])/g
|
|
495
|
+
);
|
|
496
|
+
function stderrTail(raw) {
|
|
497
|
+
const withoutAnsi = raw.replace(ANSI_ESCAPE_SEQUENCE, "");
|
|
498
|
+
const withoutControlCharacters = Array.from(withoutAnsi).filter((character) => {
|
|
499
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
500
|
+
return character === "\r" || character === "\n" || codePoint === 8232 || codePoint === 8233 || codePoint >= 32 && codePoint < 127 || codePoint > 159;
|
|
501
|
+
}).join("");
|
|
502
|
+
const tail = withoutControlCharacters.split(/\r\n|\r|\n|\u2028|\u2029/).map((line) => line.trim()).filter((line) => line.length > 0).slice(-5).join("; ");
|
|
503
|
+
const codePoints = Array.from(tail);
|
|
504
|
+
return codePoints.length > 600 ? `\u2026${codePoints.slice(-599).join("")}` : tail;
|
|
505
|
+
}
|
|
491
506
|
function createAPICallError({
|
|
492
507
|
message,
|
|
493
508
|
code,
|
|
@@ -502,26 +517,37 @@ function createAPICallError({
|
|
|
502
517
|
stderr,
|
|
503
518
|
promptExcerpt
|
|
504
519
|
};
|
|
520
|
+
const tail = typeof stderr === "string" && stderr.length > 0 ? stderrTail(stderr) : "";
|
|
521
|
+
const enrichedMessage = tail && !message.includes(STDERR_TAIL_MARKER) ? `${message}${STDERR_TAIL_MARKER} ${tail}` : message;
|
|
505
522
|
return new APICallError({
|
|
506
|
-
message,
|
|
523
|
+
message: enrichedMessage,
|
|
507
524
|
isRetryable,
|
|
508
525
|
url: "claude-code-cli://command",
|
|
509
526
|
requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
|
|
510
527
|
data: metadata
|
|
511
528
|
});
|
|
512
529
|
}
|
|
513
|
-
function createAuthenticationError({
|
|
514
|
-
|
|
530
|
+
function createAuthenticationError({
|
|
531
|
+
message,
|
|
532
|
+
stderr
|
|
533
|
+
}) {
|
|
534
|
+
const error = new LoadAPIKeyError({
|
|
515
535
|
message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
516
536
|
});
|
|
537
|
+
if (stderr) {
|
|
538
|
+
error.data = { stderr };
|
|
539
|
+
}
|
|
540
|
+
return error;
|
|
517
541
|
}
|
|
518
542
|
function createTimeoutError({
|
|
519
543
|
message,
|
|
544
|
+
stderr,
|
|
520
545
|
promptExcerpt,
|
|
521
546
|
timeoutMs
|
|
522
547
|
}) {
|
|
523
548
|
const metadata = {
|
|
524
549
|
code: "TIMEOUT",
|
|
550
|
+
stderr,
|
|
525
551
|
promptExcerpt
|
|
526
552
|
};
|
|
527
553
|
return new APICallError({
|
|
@@ -547,6 +573,9 @@ function getErrorMetadata(error) {
|
|
|
547
573
|
if (error instanceof APICallError && error.data) {
|
|
548
574
|
return error.data;
|
|
549
575
|
}
|
|
576
|
+
if (error instanceof LoadAPIKeyError && error.data) {
|
|
577
|
+
return error.data;
|
|
578
|
+
}
|
|
550
579
|
return void 0;
|
|
551
580
|
}
|
|
552
581
|
|
|
@@ -1177,10 +1206,16 @@ function createClaudeCodeQueryController(query2) {
|
|
|
1177
1206
|
|
|
1178
1207
|
// src/claude-code-language-model.ts
|
|
1179
1208
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
1180
|
-
var PROVIDER_VERSION = "4.0.
|
|
1209
|
+
var PROVIDER_VERSION = "4.0.1";
|
|
1181
1210
|
var DEFAULT_CLIENT_APP = `ai-sdk-provider-claude-code/${PROVIDER_VERSION}`;
|
|
1182
1211
|
var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
|
|
1183
1212
|
var MIN_TRUNCATION_LENGTH = 512;
|
|
1213
|
+
function capStderr(raw) {
|
|
1214
|
+
if (raw.length <= 4e3) {
|
|
1215
|
+
return raw;
|
|
1216
|
+
}
|
|
1217
|
+
return Array.from(raw).slice(-4e3).join("");
|
|
1218
|
+
}
|
|
1184
1219
|
function isClaudeCodeTruncationError(error, bufferedText) {
|
|
1185
1220
|
const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1186
1221
|
typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2401,12 +2436,18 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2401
2436
|
return opts;
|
|
2402
2437
|
}
|
|
2403
2438
|
handleClaudeCodeError(error, messagesPrompt, collectedStderr) {
|
|
2404
|
-
if (isAbortError(error)) {
|
|
2405
|
-
throw error;
|
|
2406
|
-
}
|
|
2407
2439
|
if (error instanceof APICallError2 || error instanceof LoadAPIKeyError2) {
|
|
2408
2440
|
return error;
|
|
2409
2441
|
}
|
|
2442
|
+
const rawSdkStderr = typeof error === "object" && error !== null && "stderr" in error && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
2443
|
+
const cappedSdkStderr = rawSdkStderr !== void 0 ? capStderr(rawSdkStderr) : void 0;
|
|
2444
|
+
const selectedStderr = cappedSdkStderr !== void 0 && stderrTail(cappedSdkStderr) ? cappedSdkStderr : collectedStderr ? capStderr(collectedStderr) : void 0;
|
|
2445
|
+
const stderr = selectedStderr || void 0;
|
|
2446
|
+
const tail = stderr ? stderrTail(stderr) : "";
|
|
2447
|
+
const appendStderrTail = (message) => tail && !message.includes(STDERR_TAIL_MARKER) ? `${message}${STDERR_TAIL_MARKER} ${tail}` : message;
|
|
2448
|
+
if (isAbortError(error)) {
|
|
2449
|
+
throw error;
|
|
2450
|
+
}
|
|
2410
2451
|
const isErrorWithMessage = (err) => {
|
|
2411
2452
|
return typeof err === "object" && err !== null && "message" in err;
|
|
2412
2453
|
};
|
|
@@ -2427,26 +2468,43 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2427
2468
|
"oauth_org_not_allowed"
|
|
2428
2469
|
// SDK 0.3.x assistant error kind: OAuth org not permitted
|
|
2429
2470
|
];
|
|
2471
|
+
const stderrAuthPatterns = [
|
|
2472
|
+
"not logged in",
|
|
2473
|
+
"not authenticated",
|
|
2474
|
+
"auth failed",
|
|
2475
|
+
"please login",
|
|
2476
|
+
"please run /login",
|
|
2477
|
+
"claude login",
|
|
2478
|
+
"claude auth login",
|
|
2479
|
+
"invalid api key",
|
|
2480
|
+
"oauth token revoked",
|
|
2481
|
+
"oauth_org_not_allowed"
|
|
2482
|
+
];
|
|
2430
2483
|
const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
|
|
2484
|
+
const stderrMessage = stderr?.toLowerCase() ?? "";
|
|
2431
2485
|
const errorKind = getStructuredErrorKind(error);
|
|
2432
2486
|
const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
|
|
2433
|
-
const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
|
|
2487
|
+
const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || stderrAuthPatterns.some((pattern) => stderrMessage.includes(pattern)) || exitCode === 401;
|
|
2434
2488
|
if (isAuthError) {
|
|
2435
2489
|
return createAuthenticationError({
|
|
2436
|
-
message:
|
|
2490
|
+
message: appendStderrTail(
|
|
2491
|
+
isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
2492
|
+
),
|
|
2493
|
+
stderr
|
|
2437
2494
|
});
|
|
2438
2495
|
}
|
|
2439
2496
|
const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
|
|
2440
|
-
if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
|
|
2497
|
+
if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout") || /request timed out|etimedout/i.test(stderr ?? "")) {
|
|
2441
2498
|
return createTimeoutError({
|
|
2442
|
-
message:
|
|
2499
|
+
message: appendStderrTail(
|
|
2500
|
+
isErrorWithMessage(error) && error.message ? error.message : "Request timed out"
|
|
2501
|
+
),
|
|
2502
|
+
stderr,
|
|
2443
2503
|
promptExcerpt: messagesPrompt.substring(0, 200)
|
|
2444
2504
|
// Don't specify timeoutMs since we don't know the actual timeout value
|
|
2445
2505
|
// It's controlled by the consumer via AbortSignal
|
|
2446
2506
|
});
|
|
2447
2507
|
}
|
|
2448
|
-
const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
2449
|
-
const stderr = stderrFromError || collectedStderr || void 0;
|
|
2450
2508
|
if (errorKind === "overloaded" || errorKind === "rate_limit" || errorMessage.includes("overloaded")) {
|
|
2451
2509
|
return createAPICallError({
|
|
2452
2510
|
message: isErrorWithMessage(error) && error.message ? error.message : "Anthropic API is overloaded. Please retry.",
|
|
@@ -2822,6 +2880,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2822
2880
|
let collectedStderr = "";
|
|
2823
2881
|
const stderrCollector = (data) => {
|
|
2824
2882
|
collectedStderr += data;
|
|
2883
|
+
collectedStderr = capStderr(collectedStderr);
|
|
2825
2884
|
};
|
|
2826
2885
|
const sdkOptions = this.getSanitizedSdkOptions();
|
|
2827
2886
|
const effectiveResume = this.getEffectiveResume(sdkOptions);
|
|
@@ -3322,6 +3381,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
3322
3381
|
let collectedStderr = "";
|
|
3323
3382
|
const stderrCollector = (data) => {
|
|
3324
3383
|
collectedStderr += data;
|
|
3384
|
+
collectedStderr = capStderr(collectedStderr);
|
|
3325
3385
|
};
|
|
3326
3386
|
const sdkOptions = this.getSanitizedSdkOptions();
|
|
3327
3387
|
const effectiveResume = this.getEffectiveResume(sdkOptions);
|