ai-sdk-provider-claude-code 3.5.2 → 3.5.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 +16 -0
- package/dist/index.cjs +73 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- 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
|
@@ -616,6 +616,22 @@ All requests made through this provider report timing in `providerMetadata['clau
|
|
|
616
616
|
- 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
|
|
617
617
|
- `canUseTool` requires streaming input at the SDK level (AsyncIterable prompt). This provider supports it via `streamingInput`: use `'auto'` (default when `canUseTool` is set) or `'always'`. See GUIDE for details.
|
|
618
618
|
|
|
619
|
+
## Error Diagnostics
|
|
620
|
+
|
|
621
|
+
Mapped provider errors append a trimmed stderr tail directly to the message as `... | stderr (tail): <last lines>`, making failures visible in logs without inspecting metadata. The full captured stderr (capped at 4000 characters) remains available through `getErrorMetadata`:
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
import { generateText } from 'ai';
|
|
625
|
+
import { claudeCode, getErrorMetadata } from 'ai-sdk-provider-claude-code';
|
|
626
|
+
try {
|
|
627
|
+
await generateText({ model: claudeCode('haiku'), prompt: 'Hello, Claude!' });
|
|
628
|
+
} catch (error) {
|
|
629
|
+
console.error(getErrorMetadata(error)?.stderr);
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
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.
|
|
634
|
+
|
|
619
635
|
## Tool Error Parity (Streaming)
|
|
620
636
|
|
|
621
637
|
- In addition to `tool-call` and `tool-result`, this provider emits a distinct `tool-error` stream event when a tool execution fails.
|
package/dist/index.cjs
CHANGED
|
@@ -376,6 +376,21 @@ ${segmentText}`;
|
|
|
376
376
|
|
|
377
377
|
// src/errors.ts
|
|
378
378
|
var import_provider = require("@ai-sdk/provider");
|
|
379
|
+
var STDERR_TAIL_MARKER = " | stderr (tail):";
|
|
380
|
+
var ANSI_ESCAPE_SEQUENCE = (
|
|
381
|
+
// eslint-disable-next-line no-control-regex
|
|
382
|
+
/\x1b(?:\][^\x07\x1b]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])/g
|
|
383
|
+
);
|
|
384
|
+
function stderrTail(raw) {
|
|
385
|
+
const withoutAnsi = raw.replace(ANSI_ESCAPE_SEQUENCE, "");
|
|
386
|
+
const withoutControlCharacters = Array.from(withoutAnsi).filter((character) => {
|
|
387
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
388
|
+
return character === "\r" || character === "\n" || codePoint === 8232 || codePoint === 8233 || codePoint >= 32 && codePoint < 127 || codePoint > 159;
|
|
389
|
+
}).join("");
|
|
390
|
+
const tail = withoutControlCharacters.split(/\r\n|\r|\n|\u2028|\u2029/).map((line) => line.trim()).filter((line) => line.length > 0).slice(-5).join("; ");
|
|
391
|
+
const codePoints = Array.from(tail);
|
|
392
|
+
return codePoints.length > 600 ? `\u2026${codePoints.slice(-599).join("")}` : tail;
|
|
393
|
+
}
|
|
379
394
|
function createAPICallError({
|
|
380
395
|
message,
|
|
381
396
|
code,
|
|
@@ -390,26 +405,37 @@ function createAPICallError({
|
|
|
390
405
|
stderr,
|
|
391
406
|
promptExcerpt
|
|
392
407
|
};
|
|
408
|
+
const tail = typeof stderr === "string" && stderr.length > 0 ? stderrTail(stderr) : "";
|
|
409
|
+
const enrichedMessage = tail && !message.includes(STDERR_TAIL_MARKER) ? `${message}${STDERR_TAIL_MARKER} ${tail}` : message;
|
|
393
410
|
return new import_provider.APICallError({
|
|
394
|
-
message,
|
|
411
|
+
message: enrichedMessage,
|
|
395
412
|
isRetryable,
|
|
396
413
|
url: "claude-code-cli://command",
|
|
397
414
|
requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
|
|
398
415
|
data: metadata
|
|
399
416
|
});
|
|
400
417
|
}
|
|
401
|
-
function createAuthenticationError({
|
|
402
|
-
|
|
418
|
+
function createAuthenticationError({
|
|
419
|
+
message,
|
|
420
|
+
stderr
|
|
421
|
+
}) {
|
|
422
|
+
const error = new import_provider.LoadAPIKeyError({
|
|
403
423
|
message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
404
424
|
});
|
|
425
|
+
if (stderr) {
|
|
426
|
+
error.data = { stderr };
|
|
427
|
+
}
|
|
428
|
+
return error;
|
|
405
429
|
}
|
|
406
430
|
function createTimeoutError({
|
|
407
431
|
message,
|
|
432
|
+
stderr,
|
|
408
433
|
promptExcerpt,
|
|
409
434
|
timeoutMs
|
|
410
435
|
}) {
|
|
411
436
|
const metadata = {
|
|
412
437
|
code: "TIMEOUT",
|
|
438
|
+
stderr,
|
|
413
439
|
promptExcerpt
|
|
414
440
|
};
|
|
415
441
|
return new import_provider.APICallError({
|
|
@@ -435,6 +461,9 @@ function getErrorMetadata(error) {
|
|
|
435
461
|
if (error instanceof import_provider.APICallError && error.data) {
|
|
436
462
|
return error.data;
|
|
437
463
|
}
|
|
464
|
+
if (error instanceof import_provider.LoadAPIKeyError && error.data) {
|
|
465
|
+
return error.data;
|
|
466
|
+
}
|
|
438
467
|
return void 0;
|
|
439
468
|
}
|
|
440
469
|
|
|
@@ -1012,10 +1041,16 @@ function createVerboseLogger(logger, verbose = false) {
|
|
|
1012
1041
|
|
|
1013
1042
|
// src/claude-code-language-model.ts
|
|
1014
1043
|
var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
1015
|
-
var PROVIDER_VERSION = "3.5.
|
|
1044
|
+
var PROVIDER_VERSION = "3.5.3";
|
|
1016
1045
|
var DEFAULT_CLIENT_APP = `ai-sdk-provider-claude-code/${PROVIDER_VERSION}`;
|
|
1017
1046
|
var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
|
|
1018
1047
|
var MIN_TRUNCATION_LENGTH = 512;
|
|
1048
|
+
function capStderr(raw) {
|
|
1049
|
+
if (raw.length <= 4e3) {
|
|
1050
|
+
return raw;
|
|
1051
|
+
}
|
|
1052
|
+
return Array.from(raw).slice(-4e3).join("");
|
|
1053
|
+
}
|
|
1019
1054
|
function isClaudeCodeTruncationError(error, bufferedText) {
|
|
1020
1055
|
const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1021
1056
|
typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2024,12 +2059,18 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2024
2059
|
return opts;
|
|
2025
2060
|
}
|
|
2026
2061
|
handleClaudeCodeError(error, messagesPrompt, collectedStderr) {
|
|
2027
|
-
if (isAbortError(error)) {
|
|
2028
|
-
throw error;
|
|
2029
|
-
}
|
|
2030
2062
|
if (error instanceof import_provider2.APICallError || error instanceof import_provider2.LoadAPIKeyError) {
|
|
2031
2063
|
return error;
|
|
2032
2064
|
}
|
|
2065
|
+
const rawSdkStderr = typeof error === "object" && error !== null && "stderr" in error && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
2066
|
+
const cappedSdkStderr = rawSdkStderr !== void 0 ? capStderr(rawSdkStderr) : void 0;
|
|
2067
|
+
const selectedStderr = cappedSdkStderr !== void 0 && stderrTail(cappedSdkStderr) ? cappedSdkStderr : collectedStderr ? capStderr(collectedStderr) : void 0;
|
|
2068
|
+
const stderr = selectedStderr || void 0;
|
|
2069
|
+
const tail = stderr ? stderrTail(stderr) : "";
|
|
2070
|
+
const appendStderrTail = (message) => tail && !message.includes(STDERR_TAIL_MARKER) ? `${message}${STDERR_TAIL_MARKER} ${tail}` : message;
|
|
2071
|
+
if (isAbortError(error)) {
|
|
2072
|
+
throw error;
|
|
2073
|
+
}
|
|
2033
2074
|
const isErrorWithMessage = (err) => {
|
|
2034
2075
|
return typeof err === "object" && err !== null && "message" in err;
|
|
2035
2076
|
};
|
|
@@ -2050,26 +2091,43 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2050
2091
|
"oauth_org_not_allowed"
|
|
2051
2092
|
// SDK 0.3.x assistant error kind: OAuth org not permitted
|
|
2052
2093
|
];
|
|
2094
|
+
const stderrAuthPatterns = [
|
|
2095
|
+
"not logged in",
|
|
2096
|
+
"not authenticated",
|
|
2097
|
+
"auth failed",
|
|
2098
|
+
"please login",
|
|
2099
|
+
"please run /login",
|
|
2100
|
+
"claude login",
|
|
2101
|
+
"claude auth login",
|
|
2102
|
+
"invalid api key",
|
|
2103
|
+
"oauth token revoked",
|
|
2104
|
+
"oauth_org_not_allowed"
|
|
2105
|
+
];
|
|
2053
2106
|
const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
|
|
2107
|
+
const stderrMessage = stderr?.toLowerCase() ?? "";
|
|
2054
2108
|
const errorKind = getStructuredErrorKind(error);
|
|
2055
2109
|
const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
|
|
2056
|
-
const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
|
|
2110
|
+
const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || stderrAuthPatterns.some((pattern) => stderrMessage.includes(pattern)) || exitCode === 401;
|
|
2057
2111
|
if (isAuthError) {
|
|
2058
2112
|
return createAuthenticationError({
|
|
2059
|
-
message:
|
|
2113
|
+
message: appendStderrTail(
|
|
2114
|
+
isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
2115
|
+
),
|
|
2116
|
+
stderr
|
|
2060
2117
|
});
|
|
2061
2118
|
}
|
|
2062
2119
|
const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
|
|
2063
|
-
if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
|
|
2120
|
+
if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout") || /request timed out|etimedout/i.test(stderr ?? "")) {
|
|
2064
2121
|
return createTimeoutError({
|
|
2065
|
-
message:
|
|
2122
|
+
message: appendStderrTail(
|
|
2123
|
+
isErrorWithMessage(error) && error.message ? error.message : "Request timed out"
|
|
2124
|
+
),
|
|
2125
|
+
stderr,
|
|
2066
2126
|
promptExcerpt: messagesPrompt.substring(0, 200)
|
|
2067
2127
|
// Don't specify timeoutMs since we don't know the actual timeout value
|
|
2068
2128
|
// It's controlled by the consumer via AbortSignal
|
|
2069
2129
|
});
|
|
2070
2130
|
}
|
|
2071
|
-
const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
2072
|
-
const stderr = stderrFromError || collectedStderr || void 0;
|
|
2073
2131
|
if (errorKind === "overloaded" || errorKind === "rate_limit" || errorMessage.includes("overloaded")) {
|
|
2074
2132
|
return createAPICallError({
|
|
2075
2133
|
message: isErrorWithMessage(error) && error.message ? error.message : "Anthropic API is overloaded. Please retry.",
|
|
@@ -2293,6 +2351,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2293
2351
|
let collectedStderr = "";
|
|
2294
2352
|
const stderrCollector = (data) => {
|
|
2295
2353
|
collectedStderr += data;
|
|
2354
|
+
collectedStderr = capStderr(collectedStderr);
|
|
2296
2355
|
};
|
|
2297
2356
|
const sdkOptions = this.getSanitizedSdkOptions();
|
|
2298
2357
|
const effectiveResume = this.getEffectiveResume(sdkOptions);
|
|
@@ -2771,6 +2830,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2771
2830
|
let collectedStderr = "";
|
|
2772
2831
|
const stderrCollector = (data) => {
|
|
2773
2832
|
collectedStderr += data;
|
|
2833
|
+
collectedStderr = capStderr(collectedStderr);
|
|
2774
2834
|
};
|
|
2775
2835
|
const sdkOptions = this.getSanitizedSdkOptions();
|
|
2776
2836
|
const effectiveResume = this.getEffectiveResume(sdkOptions);
|