ai-sdk-provider-claude-code 2.0.2 → 2.0.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 +5 -4
- package/dist/index.cjs +159 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -6
- package/dist/index.d.ts +82 -6
- package/dist/index.js +159 -7
- package/dist/index.js.map +1 -1
- package/docs/ai-sdk-v5/DEVELOPMENT-STATUS.md +3 -2
- package/docs/ai-sdk-v5/GUIDE.md +1 -1
- package/docs/ai-sdk-v5/TROUBLESHOOTING.md +3 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ import { streamText } from 'ai';
|
|
|
79
79
|
import { claudeCode } from 'ai-sdk-provider-claude-code';
|
|
80
80
|
|
|
81
81
|
const result = streamText({
|
|
82
|
-
model: claudeCode('
|
|
82
|
+
model: claudeCode('haiku'),
|
|
83
83
|
prompt: 'Hello, Claude!',
|
|
84
84
|
});
|
|
85
85
|
|
|
@@ -94,7 +94,7 @@ import { generateText } from 'ai';
|
|
|
94
94
|
import { claudeCode } from 'ai-sdk-provider-claude-code';
|
|
95
95
|
|
|
96
96
|
const { text } = await generateText({
|
|
97
|
-
model: claudeCode('
|
|
97
|
+
model: claudeCode('haiku'),
|
|
98
98
|
prompt: 'Hello, Claude!',
|
|
99
99
|
});
|
|
100
100
|
|
|
@@ -124,8 +124,9 @@ Key changes:
|
|
|
124
124
|
|
|
125
125
|
## Models
|
|
126
126
|
|
|
127
|
-
- **`opus`** - Claude 4 Opus (most capable)
|
|
128
|
-
- **`sonnet`** - Claude 4 Sonnet (balanced performance)
|
|
127
|
+
- **`opus`** - Claude 4.1 Opus (most capable)
|
|
128
|
+
- **`sonnet`** - Claude 4.5 Sonnet (balanced performance)
|
|
129
|
+
- **`haiku`** - Claude 4.5 Haiku (fastest, most cost-effective)
|
|
129
130
|
|
|
130
131
|
## Documentation
|
|
131
132
|
|
package/dist/index.cjs
CHANGED
|
@@ -613,7 +613,7 @@ var claudeCodeSettingsSchema = import_zod.z.object({
|
|
|
613
613
|
extraArgs: import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.string(), import_zod.z.null()])).optional()
|
|
614
614
|
}).strict();
|
|
615
615
|
function validateModelId(modelId) {
|
|
616
|
-
const knownModels = ["opus", "sonnet"];
|
|
616
|
+
const knownModels = ["opus", "sonnet", "haiku"];
|
|
617
617
|
if (!modelId || modelId.trim() === "") {
|
|
618
618
|
throw new Error("Model ID cannot be empty");
|
|
619
619
|
}
|
|
@@ -708,6 +708,81 @@ function getLogger(logger) {
|
|
|
708
708
|
|
|
709
709
|
// src/claude-code-language-model.ts
|
|
710
710
|
var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
711
|
+
var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code CLI output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
|
|
712
|
+
var MIN_TRUNCATION_LENGTH = 1024;
|
|
713
|
+
var POSITION_PATTERN = /position\s+(\d+)/i;
|
|
714
|
+
function hasUnclosedJsonStructure(text) {
|
|
715
|
+
let depth = 0;
|
|
716
|
+
let inString = false;
|
|
717
|
+
let escapeNext = false;
|
|
718
|
+
for (let i = 0; i < text.length; i++) {
|
|
719
|
+
const char = text[i];
|
|
720
|
+
if (escapeNext) {
|
|
721
|
+
escapeNext = false;
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
if (inString) {
|
|
725
|
+
if (char === "\\") {
|
|
726
|
+
escapeNext = true;
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
if (char === '"') {
|
|
730
|
+
inString = false;
|
|
731
|
+
}
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (char === '"') {
|
|
735
|
+
inString = true;
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (char === "{" || char === "[") {
|
|
739
|
+
depth++;
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
if (char === "}" || char === "]") {
|
|
743
|
+
if (depth > 0) {
|
|
744
|
+
depth--;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
return depth > 0 || inString;
|
|
749
|
+
}
|
|
750
|
+
function isClaudeCodeTruncationError(error, bufferedText) {
|
|
751
|
+
if (!(error instanceof SyntaxError)) {
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
if (!bufferedText) {
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
const rawMessage = typeof error.message === "string" ? error.message : "";
|
|
758
|
+
const message = rawMessage.toLowerCase();
|
|
759
|
+
const truncationIndicators = [
|
|
760
|
+
"unexpected end of json input",
|
|
761
|
+
"unexpected end of input",
|
|
762
|
+
"unexpected end of string",
|
|
763
|
+
"unterminated string"
|
|
764
|
+
];
|
|
765
|
+
if (!truncationIndicators.some((indicator) => message.includes(indicator))) {
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
const positionMatch = rawMessage.match(POSITION_PATTERN);
|
|
769
|
+
if (positionMatch) {
|
|
770
|
+
const position = Number.parseInt(positionMatch[1], 10);
|
|
771
|
+
if (Number.isFinite(position)) {
|
|
772
|
+
const isNearBufferEnd = Math.abs(position - bufferedText.length) <= 16;
|
|
773
|
+
if (isNearBufferEnd && position >= MIN_TRUNCATION_LENGTH) {
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
if (!isNearBufferEnd) {
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (bufferedText.length < MIN_TRUNCATION_LENGTH) {
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
784
|
+
return hasUnclosedJsonStructure(bufferedText);
|
|
785
|
+
}
|
|
711
786
|
function isAbortError(err) {
|
|
712
787
|
if (err && typeof err === "object") {
|
|
713
788
|
const e = err;
|
|
@@ -737,7 +812,8 @@ function toAsyncIterablePrompt(messagesPrompt, outputStreamEnded, sessionId, con
|
|
|
737
812
|
}
|
|
738
813
|
var modelMap = {
|
|
739
814
|
opus: "opus",
|
|
740
|
-
sonnet: "sonnet"
|
|
815
|
+
sonnet: "sonnet",
|
|
816
|
+
haiku: "haiku"
|
|
741
817
|
};
|
|
742
818
|
var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
743
819
|
specificationVersion = "v2";
|
|
@@ -1087,6 +1163,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1087
1163
|
let text = "";
|
|
1088
1164
|
let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
1089
1165
|
let finishReason = "stop";
|
|
1166
|
+
let wasTruncated = false;
|
|
1090
1167
|
let costUsd;
|
|
1091
1168
|
let durationMs;
|
|
1092
1169
|
let rawUsage;
|
|
@@ -1157,7 +1234,16 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1157
1234
|
if (isAbortError(error)) {
|
|
1158
1235
|
throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
|
|
1159
1236
|
}
|
|
1160
|
-
|
|
1237
|
+
if (isClaudeCodeTruncationError(error, text)) {
|
|
1238
|
+
wasTruncated = true;
|
|
1239
|
+
finishReason = "length";
|
|
1240
|
+
warnings.push({
|
|
1241
|
+
type: "other",
|
|
1242
|
+
message: CLAUDE_CODE_TRUNCATION_WARNING
|
|
1243
|
+
});
|
|
1244
|
+
} else {
|
|
1245
|
+
throw this.handleClaudeCodeError(error, messagesPrompt);
|
|
1246
|
+
}
|
|
1161
1247
|
} finally {
|
|
1162
1248
|
if (options.abortSignal && abortListener) {
|
|
1163
1249
|
options.abortSignal.removeEventListener("abort", abortListener);
|
|
@@ -1184,7 +1270,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1184
1270
|
...this.sessionId !== void 0 && { sessionId: this.sessionId },
|
|
1185
1271
|
...costUsd !== void 0 && { costUsd },
|
|
1186
1272
|
...durationMs !== void 0 && { durationMs },
|
|
1187
|
-
...rawUsage !== void 0 && { rawUsage }
|
|
1273
|
+
...rawUsage !== void 0 && { rawUsage },
|
|
1274
|
+
...wasTruncated && { truncated: true }
|
|
1188
1275
|
}
|
|
1189
1276
|
}
|
|
1190
1277
|
};
|
|
@@ -1276,6 +1363,9 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1276
1363
|
}
|
|
1277
1364
|
toolStates.clear();
|
|
1278
1365
|
};
|
|
1366
|
+
let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
1367
|
+
let accumulatedText = "";
|
|
1368
|
+
let textPartId;
|
|
1279
1369
|
try {
|
|
1280
1370
|
controller.enqueue({ type: "stream-start", warnings });
|
|
1281
1371
|
if (this.settings.canUseTool && this.settings.permissionPromptToolName) {
|
|
@@ -1293,9 +1383,6 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1293
1383
|
prompt: sdkPrompt,
|
|
1294
1384
|
options: queryOptions
|
|
1295
1385
|
});
|
|
1296
|
-
let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
1297
|
-
let accumulatedText = "";
|
|
1298
|
-
let textPartId;
|
|
1299
1386
|
for await (const message of response) {
|
|
1300
1387
|
if (message.type === "assistant") {
|
|
1301
1388
|
if (!message.message?.content) {
|
|
@@ -1545,6 +1632,71 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1545
1632
|
controller.close();
|
|
1546
1633
|
} catch (error) {
|
|
1547
1634
|
done();
|
|
1635
|
+
if (isClaudeCodeTruncationError(error, accumulatedText)) {
|
|
1636
|
+
const truncationWarning = {
|
|
1637
|
+
type: "other",
|
|
1638
|
+
message: CLAUDE_CODE_TRUNCATION_WARNING
|
|
1639
|
+
};
|
|
1640
|
+
streamWarnings.push(truncationWarning);
|
|
1641
|
+
const emitJsonText = () => {
|
|
1642
|
+
const extractedJson = this.handleJsonExtraction(accumulatedText, streamWarnings);
|
|
1643
|
+
const jsonTextId = (0, import_provider_utils.generateId)();
|
|
1644
|
+
controller.enqueue({
|
|
1645
|
+
type: "text-start",
|
|
1646
|
+
id: jsonTextId
|
|
1647
|
+
});
|
|
1648
|
+
controller.enqueue({
|
|
1649
|
+
type: "text-delta",
|
|
1650
|
+
id: jsonTextId,
|
|
1651
|
+
delta: extractedJson
|
|
1652
|
+
});
|
|
1653
|
+
controller.enqueue({
|
|
1654
|
+
type: "text-end",
|
|
1655
|
+
id: jsonTextId
|
|
1656
|
+
});
|
|
1657
|
+
};
|
|
1658
|
+
if (options.responseFormat?.type === "json") {
|
|
1659
|
+
emitJsonText();
|
|
1660
|
+
} else if (textPartId) {
|
|
1661
|
+
controller.enqueue({
|
|
1662
|
+
type: "text-end",
|
|
1663
|
+
id: textPartId
|
|
1664
|
+
});
|
|
1665
|
+
} else if (accumulatedText) {
|
|
1666
|
+
const fallbackTextId = (0, import_provider_utils.generateId)();
|
|
1667
|
+
controller.enqueue({
|
|
1668
|
+
type: "text-start",
|
|
1669
|
+
id: fallbackTextId
|
|
1670
|
+
});
|
|
1671
|
+
controller.enqueue({
|
|
1672
|
+
type: "text-delta",
|
|
1673
|
+
id: fallbackTextId,
|
|
1674
|
+
delta: accumulatedText
|
|
1675
|
+
});
|
|
1676
|
+
controller.enqueue({
|
|
1677
|
+
type: "text-end",
|
|
1678
|
+
id: fallbackTextId
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
finalizeToolCalls();
|
|
1682
|
+
const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
|
|
1683
|
+
controller.enqueue({
|
|
1684
|
+
type: "finish",
|
|
1685
|
+
finishReason: "length",
|
|
1686
|
+
usage,
|
|
1687
|
+
providerMetadata: {
|
|
1688
|
+
"claude-code": {
|
|
1689
|
+
...this.sessionId !== void 0 && { sessionId: this.sessionId },
|
|
1690
|
+
truncated: true,
|
|
1691
|
+
...streamWarnings.length > 0 && {
|
|
1692
|
+
warnings: warningsJson
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
controller.close();
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1548
1700
|
finalizeToolCalls();
|
|
1549
1701
|
let errorToEmit;
|
|
1550
1702
|
if (isAbortError(error)) {
|