@boostecom/provider 0.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 +90 -0
- package/dist/index.cjs +2522 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +848 -0
- package/dist/index.d.ts +848 -0
- package/dist/index.js +2484 -0
- package/dist/index.js.map +1 -0
- package/docs/content/README.md +337 -0
- package/docs/content/agent-teams.mdx +324 -0
- package/docs/content/api.mdx +757 -0
- package/docs/content/best-practices.mdx +624 -0
- package/docs/content/examples.mdx +675 -0
- package/docs/content/guide.mdx +516 -0
- package/docs/content/index.mdx +99 -0
- package/docs/content/installation.mdx +246 -0
- package/docs/content/skills.mdx +548 -0
- package/docs/content/troubleshooting.mdx +588 -0
- package/docs/examples/README.md +499 -0
- package/docs/examples/abort-signal.ts +125 -0
- package/docs/examples/agent-teams.ts +122 -0
- package/docs/examples/basic-usage.ts +73 -0
- package/docs/examples/check-cli.ts +51 -0
- package/docs/examples/conversation-history.ts +69 -0
- package/docs/examples/custom-config.ts +90 -0
- package/docs/examples/generate-object-constraints.ts +209 -0
- package/docs/examples/generate-object.ts +211 -0
- package/docs/examples/hooks-callbacks.ts +63 -0
- package/docs/examples/images.ts +76 -0
- package/docs/examples/integration-test.ts +241 -0
- package/docs/examples/limitations.ts +150 -0
- package/docs/examples/logging-custom-logger.ts +99 -0
- package/docs/examples/logging-default.ts +55 -0
- package/docs/examples/logging-disabled.ts +74 -0
- package/docs/examples/logging-verbose.ts +64 -0
- package/docs/examples/long-running-tasks.ts +179 -0
- package/docs/examples/message-injection.ts +210 -0
- package/docs/examples/mid-stream-injection.ts +126 -0
- package/docs/examples/run-all-examples.sh +48 -0
- package/docs/examples/sdk-tools-callbacks.ts +49 -0
- package/docs/examples/skills-discovery.ts +144 -0
- package/docs/examples/skills-management.ts +140 -0
- package/docs/examples/stream-object.ts +80 -0
- package/docs/examples/streaming.ts +52 -0
- package/docs/examples/structured-output-repro.ts +227 -0
- package/docs/examples/tool-management.ts +215 -0
- package/docs/examples/tool-streaming.ts +132 -0
- package/docs/examples/zod4-compatibility-test.ts +290 -0
- package/docs/src/claude-code-language-model.test.ts +3883 -0
- package/docs/src/claude-code-language-model.ts +2586 -0
- package/docs/src/claude-code-provider.test.ts +97 -0
- package/docs/src/claude-code-provider.ts +179 -0
- package/docs/src/convert-to-claude-code-messages.images.test.ts +104 -0
- package/docs/src/convert-to-claude-code-messages.test.ts +193 -0
- package/docs/src/convert-to-claude-code-messages.ts +419 -0
- package/docs/src/errors.test.ts +213 -0
- package/docs/src/errors.ts +216 -0
- package/docs/src/index.test.ts +49 -0
- package/docs/src/index.ts +98 -0
- package/docs/src/logger.integration.test.ts +164 -0
- package/docs/src/logger.test.ts +184 -0
- package/docs/src/logger.ts +65 -0
- package/docs/src/map-claude-code-finish-reason.test.ts +120 -0
- package/docs/src/map-claude-code-finish-reason.ts +60 -0
- package/docs/src/mcp-helpers.test.ts +71 -0
- package/docs/src/mcp-helpers.ts +123 -0
- package/docs/src/message-injection.test.ts +460 -0
- package/docs/src/types.ts +447 -0
- package/docs/src/validation.test.ts +558 -0
- package/docs/src/validation.ts +360 -0
- package/package.json +124 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2522 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// docs/src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ClaudeCodeLanguageModel: () => ClaudeCodeLanguageModel,
|
|
24
|
+
claudeCode: () => claudeCode,
|
|
25
|
+
createAPICallError: () => createAPICallError,
|
|
26
|
+
createAuthenticationError: () => createAuthenticationError,
|
|
27
|
+
createClaudeCode: () => createClaudeCode,
|
|
28
|
+
createCustomMcpServer: () => createCustomMcpServer,
|
|
29
|
+
createSdkMcpServer: () => import_claude_agent_sdk3.createSdkMcpServer,
|
|
30
|
+
createTimeoutError: () => createTimeoutError,
|
|
31
|
+
getErrorMetadata: () => getErrorMetadata,
|
|
32
|
+
isAuthenticationError: () => isAuthenticationError,
|
|
33
|
+
isTimeoutError: () => isTimeoutError,
|
|
34
|
+
tool: () => import_claude_agent_sdk3.tool
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// docs/src/claude-code-provider.ts
|
|
39
|
+
var import_provider3 = require("@ai-sdk/provider");
|
|
40
|
+
|
|
41
|
+
// docs/src/claude-code-language-model.ts
|
|
42
|
+
var import_provider2 = require("@ai-sdk/provider");
|
|
43
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
44
|
+
|
|
45
|
+
// docs/src/convert-to-claude-code-messages.ts
|
|
46
|
+
var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply base64/data URLs.";
|
|
47
|
+
var IMAGE_CONVERSION_WARNING = "Unable to convert image content; supply base64/data URLs.";
|
|
48
|
+
function normalizeBase64(base64) {
|
|
49
|
+
return base64.replace(/\s+/g, "");
|
|
50
|
+
}
|
|
51
|
+
function isImageMimeType(mimeType) {
|
|
52
|
+
return typeof mimeType === "string" && mimeType.trim().toLowerCase().startsWith("image/");
|
|
53
|
+
}
|
|
54
|
+
function createImageContent(mediaType, data) {
|
|
55
|
+
const trimmedType = mediaType.trim();
|
|
56
|
+
const trimmedData = normalizeBase64(data.trim());
|
|
57
|
+
if (!trimmedType || !trimmedData) {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
type: "image",
|
|
62
|
+
source: {
|
|
63
|
+
type: "base64",
|
|
64
|
+
media_type: trimmedType,
|
|
65
|
+
data: trimmedData
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function extractMimeType(candidate) {
|
|
70
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
71
|
+
return candidate.trim();
|
|
72
|
+
}
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
function parseObjectImage(imageObj, fallbackMimeType) {
|
|
76
|
+
const data = typeof imageObj.data === "string" ? imageObj.data : void 0;
|
|
77
|
+
const mimeType = extractMimeType(
|
|
78
|
+
imageObj.mimeType ?? imageObj.mediaType ?? imageObj.media_type ?? fallbackMimeType
|
|
79
|
+
);
|
|
80
|
+
if (!data || !mimeType) {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
return createImageContent(mimeType, data);
|
|
84
|
+
}
|
|
85
|
+
function parseStringImage(value, fallbackMimeType) {
|
|
86
|
+
const trimmed = value.trim();
|
|
87
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
88
|
+
return { warning: IMAGE_URL_WARNING };
|
|
89
|
+
}
|
|
90
|
+
const dataUrlMatch = trimmed.match(/^data:([^;]+);base64,(.+)$/i);
|
|
91
|
+
if (dataUrlMatch) {
|
|
92
|
+
const [, mediaType, data] = dataUrlMatch;
|
|
93
|
+
const content = createImageContent(mediaType, data);
|
|
94
|
+
return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
|
|
95
|
+
}
|
|
96
|
+
const base64Match = trimmed.match(/^base64:([^,]+),(.+)$/i);
|
|
97
|
+
if (base64Match) {
|
|
98
|
+
const [, explicitMimeType, data] = base64Match;
|
|
99
|
+
const content = createImageContent(explicitMimeType, data);
|
|
100
|
+
return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
|
|
101
|
+
}
|
|
102
|
+
if (fallbackMimeType) {
|
|
103
|
+
const content = createImageContent(fallbackMimeType, trimmed);
|
|
104
|
+
if (content) {
|
|
105
|
+
return { content };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { warning: IMAGE_CONVERSION_WARNING };
|
|
109
|
+
}
|
|
110
|
+
function parseImagePart(part) {
|
|
111
|
+
if (!part || typeof part !== "object") {
|
|
112
|
+
return { warning: IMAGE_CONVERSION_WARNING };
|
|
113
|
+
}
|
|
114
|
+
const imageValue = part.image;
|
|
115
|
+
const mimeType = extractMimeType(part.mimeType);
|
|
116
|
+
if (typeof imageValue === "string") {
|
|
117
|
+
return parseStringImage(imageValue, mimeType);
|
|
118
|
+
}
|
|
119
|
+
if (imageValue && typeof imageValue === "object") {
|
|
120
|
+
const content = parseObjectImage(imageValue, mimeType);
|
|
121
|
+
return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
|
|
122
|
+
}
|
|
123
|
+
return { warning: IMAGE_CONVERSION_WARNING };
|
|
124
|
+
}
|
|
125
|
+
function convertBinaryToBase64(data) {
|
|
126
|
+
if (typeof Buffer !== "undefined") {
|
|
127
|
+
const buffer = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(new Uint8Array(data));
|
|
128
|
+
return buffer.toString("base64");
|
|
129
|
+
}
|
|
130
|
+
if (typeof btoa === "function") {
|
|
131
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
132
|
+
let binary = "";
|
|
133
|
+
const chunkSize = 32768;
|
|
134
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
135
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
136
|
+
binary += String.fromCharCode(...chunk);
|
|
137
|
+
}
|
|
138
|
+
return btoa(binary);
|
|
139
|
+
}
|
|
140
|
+
return void 0;
|
|
141
|
+
}
|
|
142
|
+
function parseFilePart(part) {
|
|
143
|
+
const mimeType = extractMimeType(part.mediaType ?? part.mimeType);
|
|
144
|
+
if (!mimeType || !isImageMimeType(mimeType)) {
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
const data = part.data;
|
|
148
|
+
if (typeof data === "string") {
|
|
149
|
+
const content = createImageContent(mimeType, data);
|
|
150
|
+
return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
|
|
151
|
+
}
|
|
152
|
+
if (data instanceof Uint8Array || typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) {
|
|
153
|
+
const base64 = convertBinaryToBase64(data);
|
|
154
|
+
if (!base64) {
|
|
155
|
+
return { warning: IMAGE_CONVERSION_WARNING };
|
|
156
|
+
}
|
|
157
|
+
const content = createImageContent(mimeType, base64);
|
|
158
|
+
return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
|
|
159
|
+
}
|
|
160
|
+
return { warning: IMAGE_CONVERSION_WARNING };
|
|
161
|
+
}
|
|
162
|
+
function convertToClaudeCodeMessages(prompt) {
|
|
163
|
+
const messages = [];
|
|
164
|
+
const warnings = [];
|
|
165
|
+
let systemPrompt;
|
|
166
|
+
const streamingSegments = [];
|
|
167
|
+
const imageMap = /* @__PURE__ */ new Map();
|
|
168
|
+
let hasImageParts = false;
|
|
169
|
+
const addSegment = (formatted) => {
|
|
170
|
+
streamingSegments.push({ formatted });
|
|
171
|
+
return streamingSegments.length - 1;
|
|
172
|
+
};
|
|
173
|
+
const addImageForSegment = (segmentIndex, content) => {
|
|
174
|
+
hasImageParts = true;
|
|
175
|
+
if (!imageMap.has(segmentIndex)) {
|
|
176
|
+
imageMap.set(segmentIndex, []);
|
|
177
|
+
}
|
|
178
|
+
imageMap.get(segmentIndex)?.push(content);
|
|
179
|
+
};
|
|
180
|
+
for (const message of prompt) {
|
|
181
|
+
switch (message.role) {
|
|
182
|
+
case "system":
|
|
183
|
+
systemPrompt = message.content;
|
|
184
|
+
if (typeof message.content === "string" && message.content.trim().length > 0) {
|
|
185
|
+
addSegment(message.content);
|
|
186
|
+
} else {
|
|
187
|
+
addSegment("");
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case "user":
|
|
191
|
+
if (typeof message.content === "string") {
|
|
192
|
+
messages.push(message.content);
|
|
193
|
+
addSegment(`Human: ${message.content}`);
|
|
194
|
+
} else {
|
|
195
|
+
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
196
|
+
const segmentIndex = addSegment(textParts ? `Human: ${textParts}` : "");
|
|
197
|
+
if (textParts) {
|
|
198
|
+
messages.push(textParts);
|
|
199
|
+
}
|
|
200
|
+
for (const part of message.content) {
|
|
201
|
+
if (part.type === "image") {
|
|
202
|
+
const { content, warning } = parseImagePart(part);
|
|
203
|
+
if (content) {
|
|
204
|
+
addImageForSegment(segmentIndex, content);
|
|
205
|
+
} else if (warning) {
|
|
206
|
+
warnings.push(warning);
|
|
207
|
+
}
|
|
208
|
+
} else if (part.type === "file") {
|
|
209
|
+
const { content, warning } = parseFilePart(part);
|
|
210
|
+
if (content) {
|
|
211
|
+
addImageForSegment(segmentIndex, content);
|
|
212
|
+
} else if (warning) {
|
|
213
|
+
warnings.push(warning);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
case "assistant": {
|
|
220
|
+
let assistantContent = "";
|
|
221
|
+
if (typeof message.content === "string") {
|
|
222
|
+
assistantContent = message.content;
|
|
223
|
+
} else {
|
|
224
|
+
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
225
|
+
if (textParts) {
|
|
226
|
+
assistantContent = textParts;
|
|
227
|
+
}
|
|
228
|
+
const toolCalls = message.content.filter((part) => part.type === "tool-call");
|
|
229
|
+
if (toolCalls.length > 0) {
|
|
230
|
+
assistantContent += `
|
|
231
|
+
[Tool calls made]`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const formattedAssistant = `Assistant: ${assistantContent}`;
|
|
235
|
+
messages.push(formattedAssistant);
|
|
236
|
+
addSegment(formattedAssistant);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case "tool":
|
|
240
|
+
for (const tool3 of message.content) {
|
|
241
|
+
if (tool3.type === "tool-approval-response") {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
let resultText;
|
|
245
|
+
const output = tool3.output;
|
|
246
|
+
if (output.type === "text" || output.type === "error-text") {
|
|
247
|
+
resultText = output.value;
|
|
248
|
+
} else if (output.type === "json" || output.type === "error-json") {
|
|
249
|
+
resultText = JSON.stringify(output.value);
|
|
250
|
+
} else if (output.type === "execution-denied") {
|
|
251
|
+
resultText = `[Execution denied${output.reason ? `: ${output.reason}` : ""}]`;
|
|
252
|
+
} else if (output.type === "content") {
|
|
253
|
+
resultText = output.value.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
254
|
+
} else {
|
|
255
|
+
resultText = "[Unknown output type]";
|
|
256
|
+
}
|
|
257
|
+
const formattedToolResult = `Tool Result (${tool3.toolName}): ${resultText}`;
|
|
258
|
+
messages.push(formattedToolResult);
|
|
259
|
+
addSegment(formattedToolResult);
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
let finalPrompt = "";
|
|
265
|
+
if (systemPrompt) {
|
|
266
|
+
finalPrompt = systemPrompt;
|
|
267
|
+
}
|
|
268
|
+
if (messages.length > 0) {
|
|
269
|
+
const formattedMessages = [];
|
|
270
|
+
for (let i = 0; i < messages.length; i++) {
|
|
271
|
+
const msg = messages[i];
|
|
272
|
+
if (msg.startsWith("Assistant:") || msg.startsWith("Tool Result")) {
|
|
273
|
+
formattedMessages.push(msg);
|
|
274
|
+
} else {
|
|
275
|
+
formattedMessages.push(`Human: ${msg}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (finalPrompt) {
|
|
279
|
+
const joinedMessages = formattedMessages.join("\n\n");
|
|
280
|
+
finalPrompt = joinedMessages ? `${finalPrompt}
|
|
281
|
+
|
|
282
|
+
${joinedMessages}` : finalPrompt;
|
|
283
|
+
} else {
|
|
284
|
+
finalPrompt = formattedMessages.join("\n\n");
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const streamingParts = [];
|
|
288
|
+
const imagePartsInOrder = [];
|
|
289
|
+
const appendImagesForIndex = (index) => {
|
|
290
|
+
const images = imageMap.get(index);
|
|
291
|
+
if (!images) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
images.forEach((image) => {
|
|
295
|
+
streamingParts.push(image);
|
|
296
|
+
imagePartsInOrder.push(image);
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
if (streamingSegments.length > 0) {
|
|
300
|
+
let accumulatedText = "";
|
|
301
|
+
let emittedText = false;
|
|
302
|
+
const flushText = () => {
|
|
303
|
+
if (!accumulatedText) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
streamingParts.push({ type: "text", text: accumulatedText });
|
|
307
|
+
accumulatedText = "";
|
|
308
|
+
emittedText = true;
|
|
309
|
+
};
|
|
310
|
+
streamingSegments.forEach((segment, index) => {
|
|
311
|
+
const segmentText = segment.formatted;
|
|
312
|
+
if (segmentText) {
|
|
313
|
+
if (!accumulatedText) {
|
|
314
|
+
accumulatedText = emittedText ? `
|
|
315
|
+
|
|
316
|
+
${segmentText}` : segmentText;
|
|
317
|
+
} else {
|
|
318
|
+
accumulatedText += `
|
|
319
|
+
|
|
320
|
+
${segmentText}`;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (imageMap.has(index)) {
|
|
324
|
+
flushText();
|
|
325
|
+
appendImagesForIndex(index);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
flushText();
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
messagesPrompt: finalPrompt,
|
|
332
|
+
systemPrompt,
|
|
333
|
+
...warnings.length > 0 && { warnings },
|
|
334
|
+
streamingContentParts: streamingParts.length > 0 ? streamingParts : [
|
|
335
|
+
{ type: "text", text: finalPrompt },
|
|
336
|
+
...imagePartsInOrder
|
|
337
|
+
],
|
|
338
|
+
hasImageParts
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// docs/src/errors.ts
|
|
343
|
+
var import_provider = require("@ai-sdk/provider");
|
|
344
|
+
function createAPICallError({
|
|
345
|
+
message,
|
|
346
|
+
code,
|
|
347
|
+
exitCode,
|
|
348
|
+
stderr,
|
|
349
|
+
promptExcerpt,
|
|
350
|
+
isRetryable = false
|
|
351
|
+
}) {
|
|
352
|
+
const metadata = {
|
|
353
|
+
code,
|
|
354
|
+
exitCode,
|
|
355
|
+
stderr,
|
|
356
|
+
promptExcerpt
|
|
357
|
+
};
|
|
358
|
+
return new import_provider.APICallError({
|
|
359
|
+
message,
|
|
360
|
+
isRetryable,
|
|
361
|
+
url: "claude-code-cli://command",
|
|
362
|
+
requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
|
|
363
|
+
data: metadata
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
function createAuthenticationError({ message }) {
|
|
367
|
+
return new import_provider.LoadAPIKeyError({
|
|
368
|
+
message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function createTimeoutError({
|
|
372
|
+
message,
|
|
373
|
+
promptExcerpt,
|
|
374
|
+
timeoutMs
|
|
375
|
+
}) {
|
|
376
|
+
const metadata = {
|
|
377
|
+
code: "TIMEOUT",
|
|
378
|
+
promptExcerpt
|
|
379
|
+
};
|
|
380
|
+
return new import_provider.APICallError({
|
|
381
|
+
message,
|
|
382
|
+
isRetryable: true,
|
|
383
|
+
url: "claude-code-cli://command",
|
|
384
|
+
requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
|
|
385
|
+
data: timeoutMs !== void 0 ? { ...metadata, timeoutMs } : metadata
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
function isAuthenticationError(error) {
|
|
389
|
+
if (error instanceof import_provider.LoadAPIKeyError) return true;
|
|
390
|
+
if (error instanceof import_provider.APICallError && error.data?.exitCode === 401)
|
|
391
|
+
return true;
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
function isTimeoutError(error) {
|
|
395
|
+
if (error instanceof import_provider.APICallError && error.data?.code === "TIMEOUT")
|
|
396
|
+
return true;
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
function getErrorMetadata(error) {
|
|
400
|
+
if (error instanceof import_provider.APICallError && error.data) {
|
|
401
|
+
return error.data;
|
|
402
|
+
}
|
|
403
|
+
return void 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// docs/src/map-claude-code-finish-reason.ts
|
|
407
|
+
function mapClaudeCodeFinishReason(subtype, stopReason) {
|
|
408
|
+
if (stopReason != null) {
|
|
409
|
+
switch (stopReason) {
|
|
410
|
+
case "end_turn":
|
|
411
|
+
return { unified: "stop", raw: "end_turn" };
|
|
412
|
+
case "max_tokens":
|
|
413
|
+
return { unified: "length", raw: "max_tokens" };
|
|
414
|
+
case "stop_sequence":
|
|
415
|
+
return { unified: "stop", raw: "stop_sequence" };
|
|
416
|
+
case "tool_use":
|
|
417
|
+
return { unified: "tool-calls", raw: "tool_use" };
|
|
418
|
+
default:
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const raw = stopReason ?? subtype;
|
|
423
|
+
switch (subtype) {
|
|
424
|
+
case "success":
|
|
425
|
+
return { unified: "stop", raw };
|
|
426
|
+
case "error_max_turns":
|
|
427
|
+
return { unified: "length", raw };
|
|
428
|
+
case "error_during_execution":
|
|
429
|
+
return { unified: "error", raw };
|
|
430
|
+
case void 0:
|
|
431
|
+
return { unified: "stop", raw };
|
|
432
|
+
default:
|
|
433
|
+
return { unified: "other", raw };
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// docs/src/validation.ts
|
|
438
|
+
var import_zod = require("zod");
|
|
439
|
+
var import_fs = require("fs");
|
|
440
|
+
var loggerFunctionSchema = import_zod.z.object({
|
|
441
|
+
debug: import_zod.z.any().refine((val) => typeof val === "function", {
|
|
442
|
+
message: "debug must be a function"
|
|
443
|
+
}),
|
|
444
|
+
info: import_zod.z.any().refine((val) => typeof val === "function", {
|
|
445
|
+
message: "info must be a function"
|
|
446
|
+
}),
|
|
447
|
+
warn: import_zod.z.any().refine((val) => typeof val === "function", {
|
|
448
|
+
message: "warn must be a function"
|
|
449
|
+
}),
|
|
450
|
+
error: import_zod.z.any().refine((val) => typeof val === "function", {
|
|
451
|
+
message: "error must be a function"
|
|
452
|
+
})
|
|
453
|
+
});
|
|
454
|
+
var claudeCodeSettingsSchema = import_zod.z.object({
|
|
455
|
+
pathToClaudeCodeExecutable: import_zod.z.string().optional(),
|
|
456
|
+
customSystemPrompt: import_zod.z.string().optional(),
|
|
457
|
+
appendSystemPrompt: import_zod.z.string().optional(),
|
|
458
|
+
systemPrompt: import_zod.z.union([
|
|
459
|
+
import_zod.z.string(),
|
|
460
|
+
import_zod.z.object({
|
|
461
|
+
type: import_zod.z.literal("preset"),
|
|
462
|
+
preset: import_zod.z.literal("claude_code"),
|
|
463
|
+
append: import_zod.z.string().optional()
|
|
464
|
+
})
|
|
465
|
+
]).optional(),
|
|
466
|
+
maxTurns: import_zod.z.number().int().min(1).max(100).optional(),
|
|
467
|
+
maxThinkingTokens: import_zod.z.number().int().positive().max(1e5).optional(),
|
|
468
|
+
cwd: import_zod.z.string().refine(
|
|
469
|
+
(val) => {
|
|
470
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
return !val || (0, import_fs.existsSync)(val);
|
|
474
|
+
},
|
|
475
|
+
{ message: "Working directory must exist" }
|
|
476
|
+
).optional(),
|
|
477
|
+
executable: import_zod.z.enum(["bun", "deno", "node"]).optional(),
|
|
478
|
+
executableArgs: import_zod.z.array(import_zod.z.string()).optional(),
|
|
479
|
+
permissionMode: import_zod.z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "delegate", "dontAsk"]).optional(),
|
|
480
|
+
permissionPromptToolName: import_zod.z.string().optional(),
|
|
481
|
+
continue: import_zod.z.boolean().optional(),
|
|
482
|
+
resume: import_zod.z.string().optional(),
|
|
483
|
+
sessionId: import_zod.z.string().optional(),
|
|
484
|
+
allowedTools: import_zod.z.array(import_zod.z.string()).optional(),
|
|
485
|
+
disallowedTools: import_zod.z.array(import_zod.z.string()).optional(),
|
|
486
|
+
betas: import_zod.z.array(import_zod.z.string()).optional(),
|
|
487
|
+
allowDangerouslySkipPermissions: import_zod.z.boolean().optional(),
|
|
488
|
+
enableFileCheckpointing: import_zod.z.boolean().optional(),
|
|
489
|
+
maxBudgetUsd: import_zod.z.number().min(0).optional(),
|
|
490
|
+
plugins: import_zod.z.array(
|
|
491
|
+
import_zod.z.object({
|
|
492
|
+
type: import_zod.z.string(),
|
|
493
|
+
path: import_zod.z.string()
|
|
494
|
+
}).passthrough()
|
|
495
|
+
).optional(),
|
|
496
|
+
resumeSessionAt: import_zod.z.string().optional(),
|
|
497
|
+
sandbox: import_zod.z.any().refine((val) => val === void 0 || typeof val === "object", {
|
|
498
|
+
message: "sandbox must be an object"
|
|
499
|
+
}).optional(),
|
|
500
|
+
tools: import_zod.z.union([
|
|
501
|
+
import_zod.z.array(import_zod.z.string()),
|
|
502
|
+
import_zod.z.object({
|
|
503
|
+
type: import_zod.z.literal("preset"),
|
|
504
|
+
preset: import_zod.z.literal("claude_code")
|
|
505
|
+
})
|
|
506
|
+
]).optional(),
|
|
507
|
+
settingSources: import_zod.z.array(import_zod.z.enum(["user", "project", "local"])).optional(),
|
|
508
|
+
streamingInput: import_zod.z.enum(["auto", "always", "off"]).optional(),
|
|
509
|
+
// Hooks and tool-permission callback (permissive validation of shapes)
|
|
510
|
+
canUseTool: import_zod.z.any().refine((v) => v === void 0 || typeof v === "function", {
|
|
511
|
+
message: "canUseTool must be a function"
|
|
512
|
+
}).optional(),
|
|
513
|
+
hooks: import_zod.z.record(
|
|
514
|
+
import_zod.z.string(),
|
|
515
|
+
import_zod.z.array(
|
|
516
|
+
import_zod.z.object({
|
|
517
|
+
matcher: import_zod.z.string().optional(),
|
|
518
|
+
hooks: import_zod.z.array(import_zod.z.any()).nonempty()
|
|
519
|
+
})
|
|
520
|
+
)
|
|
521
|
+
).optional(),
|
|
522
|
+
mcpServers: import_zod.z.record(
|
|
523
|
+
import_zod.z.string(),
|
|
524
|
+
import_zod.z.union([
|
|
525
|
+
// McpStdioServerConfig
|
|
526
|
+
import_zod.z.object({
|
|
527
|
+
type: import_zod.z.literal("stdio").optional(),
|
|
528
|
+
command: import_zod.z.string(),
|
|
529
|
+
args: import_zod.z.array(import_zod.z.string()).optional(),
|
|
530
|
+
env: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
531
|
+
}),
|
|
532
|
+
// McpSSEServerConfig
|
|
533
|
+
import_zod.z.object({
|
|
534
|
+
type: import_zod.z.literal("sse"),
|
|
535
|
+
url: import_zod.z.string(),
|
|
536
|
+
headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
537
|
+
}),
|
|
538
|
+
// McpHttpServerConfig
|
|
539
|
+
import_zod.z.object({
|
|
540
|
+
type: import_zod.z.literal("http"),
|
|
541
|
+
url: import_zod.z.string(),
|
|
542
|
+
headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
543
|
+
}),
|
|
544
|
+
// McpSdkServerConfig (in-process custom tools)
|
|
545
|
+
import_zod.z.object({
|
|
546
|
+
type: import_zod.z.literal("sdk"),
|
|
547
|
+
name: import_zod.z.string(),
|
|
548
|
+
instance: import_zod.z.any()
|
|
549
|
+
})
|
|
550
|
+
])
|
|
551
|
+
).optional(),
|
|
552
|
+
verbose: import_zod.z.boolean().optional(),
|
|
553
|
+
debug: import_zod.z.boolean().optional(),
|
|
554
|
+
debugFile: import_zod.z.string().optional(),
|
|
555
|
+
logger: import_zod.z.union([import_zod.z.literal(false), loggerFunctionSchema]).optional(),
|
|
556
|
+
env: import_zod.z.record(import_zod.z.string(), import_zod.z.string().optional()).optional(),
|
|
557
|
+
additionalDirectories: import_zod.z.array(import_zod.z.string()).optional(),
|
|
558
|
+
agents: import_zod.z.record(
|
|
559
|
+
import_zod.z.string(),
|
|
560
|
+
import_zod.z.object({
|
|
561
|
+
description: import_zod.z.string(),
|
|
562
|
+
tools: import_zod.z.array(import_zod.z.string()).optional(),
|
|
563
|
+
disallowedTools: import_zod.z.array(import_zod.z.string()).optional(),
|
|
564
|
+
prompt: import_zod.z.string(),
|
|
565
|
+
model: import_zod.z.enum(["sonnet", "opus", "haiku", "inherit"]).optional(),
|
|
566
|
+
mcpServers: import_zod.z.array(
|
|
567
|
+
import_zod.z.union([
|
|
568
|
+
import_zod.z.string(),
|
|
569
|
+
import_zod.z.record(import_zod.z.string(), import_zod.z.any())
|
|
570
|
+
// McpServerConfigForProcessTransport
|
|
571
|
+
])
|
|
572
|
+
).optional(),
|
|
573
|
+
criticalSystemReminder_EXPERIMENTAL: import_zod.z.string().optional()
|
|
574
|
+
}).passthrough()
|
|
575
|
+
).optional(),
|
|
576
|
+
includePartialMessages: import_zod.z.boolean().optional(),
|
|
577
|
+
fallbackModel: import_zod.z.string().optional(),
|
|
578
|
+
forkSession: import_zod.z.boolean().optional(),
|
|
579
|
+
stderr: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
580
|
+
message: "stderr must be a function"
|
|
581
|
+
}).optional(),
|
|
582
|
+
strictMcpConfig: import_zod.z.boolean().optional(),
|
|
583
|
+
extraArgs: import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.string(), import_zod.z.null()])).optional(),
|
|
584
|
+
persistSession: import_zod.z.boolean().optional(),
|
|
585
|
+
spawnClaudeCodeProcess: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
586
|
+
message: "spawnClaudeCodeProcess must be a function"
|
|
587
|
+
}).optional(),
|
|
588
|
+
sdkOptions: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
|
|
589
|
+
maxToolResultSize: import_zod.z.number().int().min(100).max(1e6).optional(),
|
|
590
|
+
// Callback invoked when Query object is created - for mid-stream injection via streamInput()
|
|
591
|
+
onQueryCreated: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
592
|
+
message: "onQueryCreated must be a function"
|
|
593
|
+
}).optional(),
|
|
594
|
+
onStreamStart: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
595
|
+
message: "onStreamStart must be a function"
|
|
596
|
+
}).optional()
|
|
597
|
+
}).strict();
|
|
598
|
+
function validateModelId(modelId) {
|
|
599
|
+
const knownModels = ["opus", "sonnet", "haiku"];
|
|
600
|
+
if (!modelId || modelId.trim() === "") {
|
|
601
|
+
throw new Error("Model ID cannot be empty");
|
|
602
|
+
}
|
|
603
|
+
if (!knownModels.includes(modelId)) {
|
|
604
|
+
return `Unknown model ID: '${modelId}'. Proceeding with custom model. Known models are: ${knownModels.join(", ")}`;
|
|
605
|
+
}
|
|
606
|
+
return void 0;
|
|
607
|
+
}
|
|
608
|
+
function validateSettings(settings) {
|
|
609
|
+
const warnings = [];
|
|
610
|
+
const errors = [];
|
|
611
|
+
try {
|
|
612
|
+
const result = claudeCodeSettingsSchema.safeParse(settings);
|
|
613
|
+
if (!result.success) {
|
|
614
|
+
const errorObject = result.error;
|
|
615
|
+
const issues = errorObject.errors || errorObject.issues || [];
|
|
616
|
+
issues.forEach((err) => {
|
|
617
|
+
const path = err.path.join(".");
|
|
618
|
+
errors.push(`${path ? `${path}: ` : ""}${err.message}`);
|
|
619
|
+
});
|
|
620
|
+
return { valid: false, warnings, errors };
|
|
621
|
+
}
|
|
622
|
+
const validSettings = result.data;
|
|
623
|
+
if (validSettings.maxTurns && validSettings.maxTurns > 20) {
|
|
624
|
+
warnings.push(
|
|
625
|
+
`High maxTurns value (${validSettings.maxTurns}) may lead to long-running conversations`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
if (validSettings.maxThinkingTokens && validSettings.maxThinkingTokens > 5e4) {
|
|
629
|
+
warnings.push(
|
|
630
|
+
`Very high maxThinkingTokens (${validSettings.maxThinkingTokens}) may increase response time`
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
if (validSettings.allowedTools && validSettings.disallowedTools) {
|
|
634
|
+
warnings.push(
|
|
635
|
+
"Both allowedTools and disallowedTools are specified. Only allowedTools will be used."
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
const validateToolNames = (tools, type) => {
|
|
639
|
+
tools.forEach((tool3) => {
|
|
640
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\([^)]*\))?$/.test(tool3) && !tool3.startsWith("mcp__")) {
|
|
641
|
+
warnings.push(`Unusual ${type} tool name format: '${tool3}'`);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
};
|
|
645
|
+
if (validSettings.allowedTools) {
|
|
646
|
+
validateToolNames(validSettings.allowedTools, "allowed");
|
|
647
|
+
}
|
|
648
|
+
if (validSettings.disallowedTools) {
|
|
649
|
+
validateToolNames(validSettings.disallowedTools, "disallowed");
|
|
650
|
+
}
|
|
651
|
+
if (validSettings.allowedTools?.includes("Skill") && !validSettings.settingSources) {
|
|
652
|
+
warnings.push(
|
|
653
|
+
"allowedTools includes 'Skill' but settingSources is not set. Skills require settingSources (e.g., ['user', 'project']) to load skill definitions."
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
return { valid: true, warnings, errors };
|
|
657
|
+
} catch (error) {
|
|
658
|
+
errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);
|
|
659
|
+
return { valid: false, warnings, errors };
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function validatePrompt(prompt) {
|
|
663
|
+
const MAX_PROMPT_LENGTH = 1e5;
|
|
664
|
+
if (prompt.length > MAX_PROMPT_LENGTH) {
|
|
665
|
+
return `Very long prompt (${prompt.length} characters) may cause performance issues or timeouts`;
|
|
666
|
+
}
|
|
667
|
+
return void 0;
|
|
668
|
+
}
|
|
669
|
+
function validateSessionId(sessionId) {
|
|
670
|
+
if (sessionId && !/^[a-zA-Z0-9-_]+$/.test(sessionId)) {
|
|
671
|
+
return `Unusual session ID format. This may cause issues with session resumption.`;
|
|
672
|
+
}
|
|
673
|
+
return void 0;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// docs/src/logger.ts
|
|
677
|
+
var defaultLogger = {
|
|
678
|
+
// eslint-disable-next-line no-console
|
|
679
|
+
debug: (message) => console.debug(`[DEBUG] ${message}`),
|
|
680
|
+
// eslint-disable-next-line no-console
|
|
681
|
+
info: (message) => console.info(`[INFO] ${message}`),
|
|
682
|
+
warn: (message) => console.warn(`[WARN] ${message}`),
|
|
683
|
+
error: (message) => console.error(`[ERROR] ${message}`)
|
|
684
|
+
};
|
|
685
|
+
var noopLogger = {
|
|
686
|
+
debug: () => {
|
|
687
|
+
},
|
|
688
|
+
info: () => {
|
|
689
|
+
},
|
|
690
|
+
warn: () => {
|
|
691
|
+
},
|
|
692
|
+
error: () => {
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
function getLogger(logger) {
|
|
696
|
+
if (logger === false) {
|
|
697
|
+
return noopLogger;
|
|
698
|
+
}
|
|
699
|
+
if (logger === void 0) {
|
|
700
|
+
return defaultLogger;
|
|
701
|
+
}
|
|
702
|
+
return logger;
|
|
703
|
+
}
|
|
704
|
+
function createVerboseLogger(logger, verbose = false) {
|
|
705
|
+
if (verbose) {
|
|
706
|
+
return logger;
|
|
707
|
+
}
|
|
708
|
+
return {
|
|
709
|
+
debug: () => {
|
|
710
|
+
},
|
|
711
|
+
// No-op when not verbose
|
|
712
|
+
info: () => {
|
|
713
|
+
},
|
|
714
|
+
// No-op when not verbose
|
|
715
|
+
warn: logger.warn.bind(logger),
|
|
716
|
+
error: logger.error.bind(logger)
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// docs/src/claude-code-language-model.ts
|
|
721
|
+
var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
722
|
+
var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
|
|
723
|
+
var MIN_TRUNCATION_LENGTH = 512;
|
|
724
|
+
function isClaudeCodeTruncationError(error, bufferedText) {
|
|
725
|
+
const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
726
|
+
typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
727
|
+
error.name.toLowerCase() === "syntaxerror";
|
|
728
|
+
if (!isSyntaxError) {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
if (!bufferedText) {
|
|
732
|
+
return false;
|
|
733
|
+
}
|
|
734
|
+
const rawMessage = typeof error?.message === "string" ? error.message : "";
|
|
735
|
+
const message = rawMessage.toLowerCase();
|
|
736
|
+
const truncationIndicators = [
|
|
737
|
+
"unexpected end of json input",
|
|
738
|
+
"unexpected end of input",
|
|
739
|
+
"unexpected end of string",
|
|
740
|
+
"unexpected eof",
|
|
741
|
+
"end of file",
|
|
742
|
+
"unterminated string",
|
|
743
|
+
"unterminated string constant"
|
|
744
|
+
];
|
|
745
|
+
if (!truncationIndicators.some((indicator) => message.includes(indicator))) {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
if (bufferedText.length < MIN_TRUNCATION_LENGTH) {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
753
|
+
function isAbortError(err) {
|
|
754
|
+
if (err && typeof err === "object") {
|
|
755
|
+
const e = err;
|
|
756
|
+
if (typeof e.name === "string" && e.name === "AbortError") return true;
|
|
757
|
+
if (typeof e.code === "string" && e.code.toUpperCase() === "ABORT_ERR") return true;
|
|
758
|
+
}
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
|
|
762
|
+
"APPDATA",
|
|
763
|
+
"HOMEDRIVE",
|
|
764
|
+
"HOMEPATH",
|
|
765
|
+
"LOCALAPPDATA",
|
|
766
|
+
"PATH",
|
|
767
|
+
"PATHEXT",
|
|
768
|
+
"SYSTEMDRIVE",
|
|
769
|
+
"SYSTEMROOT",
|
|
770
|
+
"TEMP",
|
|
771
|
+
"TMP",
|
|
772
|
+
"USERNAME",
|
|
773
|
+
"USERPROFILE",
|
|
774
|
+
"WINDIR"
|
|
775
|
+
] : ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER", "LANG", "LC_ALL", "TMPDIR"];
|
|
776
|
+
var CLAUDE_ENV_VARS = ["CLAUDE_CONFIG_DIR"];
|
|
777
|
+
function getBaseProcessEnv() {
|
|
778
|
+
const env = {};
|
|
779
|
+
const allowedKeys = /* @__PURE__ */ new Set([...DEFAULT_INHERITED_ENV_VARS, ...CLAUDE_ENV_VARS]);
|
|
780
|
+
for (const key of allowedKeys) {
|
|
781
|
+
const value = process.env[key];
|
|
782
|
+
if (typeof value !== "string") {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
if (value.startsWith("()")) {
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
env[key] = value;
|
|
789
|
+
}
|
|
790
|
+
return env;
|
|
791
|
+
}
|
|
792
|
+
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
|
+
var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
|
|
794
|
+
function createEmptyUsage() {
|
|
795
|
+
return {
|
|
796
|
+
inputTokens: {
|
|
797
|
+
total: 0,
|
|
798
|
+
noCache: 0,
|
|
799
|
+
cacheRead: 0,
|
|
800
|
+
cacheWrite: 0
|
|
801
|
+
},
|
|
802
|
+
outputTokens: {
|
|
803
|
+
total: 0,
|
|
804
|
+
text: void 0,
|
|
805
|
+
reasoning: void 0
|
|
806
|
+
},
|
|
807
|
+
raw: void 0
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
function convertClaudeCodeUsage(usage) {
|
|
811
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
812
|
+
const outputTokens = usage.output_tokens ?? 0;
|
|
813
|
+
const cacheWrite = usage.cache_creation_input_tokens ?? 0;
|
|
814
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
815
|
+
return {
|
|
816
|
+
inputTokens: {
|
|
817
|
+
total: inputTokens + cacheWrite + cacheRead,
|
|
818
|
+
noCache: inputTokens,
|
|
819
|
+
cacheRead,
|
|
820
|
+
cacheWrite
|
|
821
|
+
},
|
|
822
|
+
outputTokens: {
|
|
823
|
+
total: outputTokens,
|
|
824
|
+
text: void 0,
|
|
825
|
+
reasoning: void 0
|
|
826
|
+
},
|
|
827
|
+
raw: usage
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
function createMessageInjector() {
|
|
831
|
+
const queue = [];
|
|
832
|
+
let closed = false;
|
|
833
|
+
let resolver = null;
|
|
834
|
+
const injector = {
|
|
835
|
+
inject(content, onResult) {
|
|
836
|
+
if (closed) {
|
|
837
|
+
onResult?.(false);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
const item = { content, onResult };
|
|
841
|
+
if (resolver) {
|
|
842
|
+
const r = resolver;
|
|
843
|
+
resolver = null;
|
|
844
|
+
r(item);
|
|
845
|
+
} else {
|
|
846
|
+
queue.push(item);
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
close() {
|
|
850
|
+
closed = true;
|
|
851
|
+
if (resolver && queue.length === 0) {
|
|
852
|
+
resolver(null);
|
|
853
|
+
resolver = null;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
const getNextItem = () => {
|
|
858
|
+
if (queue.length > 0) {
|
|
859
|
+
const item = queue.shift();
|
|
860
|
+
if (!item) {
|
|
861
|
+
return Promise.resolve(null);
|
|
862
|
+
}
|
|
863
|
+
return Promise.resolve(item);
|
|
864
|
+
}
|
|
865
|
+
if (closed) {
|
|
866
|
+
return Promise.resolve(null);
|
|
867
|
+
}
|
|
868
|
+
return new Promise((resolve) => {
|
|
869
|
+
resolver = (item) => {
|
|
870
|
+
resolve(item);
|
|
871
|
+
};
|
|
872
|
+
});
|
|
873
|
+
};
|
|
874
|
+
const notifySessionEnded = () => {
|
|
875
|
+
for (const item of queue) {
|
|
876
|
+
item.onResult?.(false);
|
|
877
|
+
}
|
|
878
|
+
queue.length = 0;
|
|
879
|
+
closed = true;
|
|
880
|
+
if (resolver) {
|
|
881
|
+
resolver(null);
|
|
882
|
+
resolver = null;
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
return { injector, getNextItem, notifySessionEnded };
|
|
886
|
+
}
|
|
887
|
+
function toAsyncIterablePrompt(messagesPrompt, outputStreamEnded, sessionId, contentParts, onStreamStart) {
|
|
888
|
+
const content = contentParts && contentParts.length > 0 ? contentParts : [{ type: "text", text: messagesPrompt }];
|
|
889
|
+
const initialMsg = {
|
|
890
|
+
type: "user",
|
|
891
|
+
message: {
|
|
892
|
+
role: "user",
|
|
893
|
+
content
|
|
894
|
+
},
|
|
895
|
+
parent_tool_use_id: null,
|
|
896
|
+
session_id: sessionId ?? ""
|
|
897
|
+
};
|
|
898
|
+
if (!onStreamStart) {
|
|
899
|
+
return {
|
|
900
|
+
async *[Symbol.asyncIterator]() {
|
|
901
|
+
yield initialMsg;
|
|
902
|
+
await outputStreamEnded;
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
const { injector, getNextItem, notifySessionEnded } = createMessageInjector();
|
|
907
|
+
return {
|
|
908
|
+
async *[Symbol.asyncIterator]() {
|
|
909
|
+
yield initialMsg;
|
|
910
|
+
onStreamStart(injector);
|
|
911
|
+
let streamEnded = false;
|
|
912
|
+
void outputStreamEnded.then(() => {
|
|
913
|
+
streamEnded = true;
|
|
914
|
+
notifySessionEnded();
|
|
915
|
+
});
|
|
916
|
+
while (!streamEnded) {
|
|
917
|
+
const item = await Promise.race([getNextItem(), outputStreamEnded.then(() => null)]);
|
|
918
|
+
if (item === null) {
|
|
919
|
+
await outputStreamEnded;
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
const sdkMsg = {
|
|
923
|
+
type: "user",
|
|
924
|
+
message: {
|
|
925
|
+
role: "user",
|
|
926
|
+
content: [{ type: "text", text: item.content }]
|
|
927
|
+
},
|
|
928
|
+
parent_tool_use_id: null,
|
|
929
|
+
session_id: sessionId ?? ""
|
|
930
|
+
};
|
|
931
|
+
yield sdkMsg;
|
|
932
|
+
item.onResult?.(true);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
var modelMap = {
|
|
938
|
+
opus: "opus",
|
|
939
|
+
sonnet: "sonnet",
|
|
940
|
+
haiku: "haiku"
|
|
941
|
+
};
|
|
942
|
+
var MAX_TOOL_RESULT_SIZE = 1e4;
|
|
943
|
+
function truncateToolResultForStream(result, maxSize = MAX_TOOL_RESULT_SIZE) {
|
|
944
|
+
if (typeof result === "string") {
|
|
945
|
+
if (result.length <= maxSize) return result;
|
|
946
|
+
return result.slice(0, maxSize) + `
|
|
947
|
+
...[truncated ${result.length - maxSize} chars]`;
|
|
948
|
+
}
|
|
949
|
+
if (typeof result !== "object" || result === null) return result;
|
|
950
|
+
if (Array.isArray(result)) {
|
|
951
|
+
let largestIndex = -1;
|
|
952
|
+
let largestSize2 = 0;
|
|
953
|
+
for (let i = 0; i < result.length; i++) {
|
|
954
|
+
const value = result[i];
|
|
955
|
+
if (typeof value === "string" && value.length > largestSize2) {
|
|
956
|
+
largestIndex = i;
|
|
957
|
+
largestSize2 = value.length;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (largestIndex >= 0 && largestSize2 > maxSize) {
|
|
961
|
+
const truncatedValue = result[largestIndex].slice(0, maxSize) + `
|
|
962
|
+
...[truncated ${largestSize2 - maxSize} chars]`;
|
|
963
|
+
const cloned = [...result];
|
|
964
|
+
cloned[largestIndex] = truncatedValue;
|
|
965
|
+
return cloned;
|
|
966
|
+
}
|
|
967
|
+
return result;
|
|
968
|
+
}
|
|
969
|
+
const obj = result;
|
|
970
|
+
let largestKey = null;
|
|
971
|
+
let largestSize = 0;
|
|
972
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
973
|
+
if (typeof value === "string" && value.length > largestSize) {
|
|
974
|
+
largestKey = key;
|
|
975
|
+
largestSize = value.length;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (largestKey && largestSize > maxSize) {
|
|
979
|
+
const truncatedValue = obj[largestKey].slice(0, maxSize) + `
|
|
980
|
+
...[truncated ${largestSize - maxSize} chars]`;
|
|
981
|
+
return { ...obj, [largestKey]: truncatedValue };
|
|
982
|
+
}
|
|
983
|
+
return result;
|
|
984
|
+
}
|
|
985
|
+
var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
986
|
+
specificationVersion = "v3";
|
|
987
|
+
defaultObjectGenerationMode = "json";
|
|
988
|
+
supportsImageUrls = false;
|
|
989
|
+
supportedUrls = {};
|
|
990
|
+
supportsStructuredOutputs = true;
|
|
991
|
+
// Fallback/magic string constants
|
|
992
|
+
static UNKNOWN_TOOL_NAME = "unknown-tool";
|
|
993
|
+
// Tool input safety limits
|
|
994
|
+
static MAX_TOOL_INPUT_SIZE = 1048576;
|
|
995
|
+
// 1MB hard limit
|
|
996
|
+
static MAX_TOOL_INPUT_WARN = 102400;
|
|
997
|
+
// 100KB warning threshold
|
|
998
|
+
static MAX_DELTA_CALC_SIZE = 1e4;
|
|
999
|
+
// 10KB delta computation threshold
|
|
1000
|
+
modelId;
|
|
1001
|
+
settings;
|
|
1002
|
+
sessionId;
|
|
1003
|
+
modelValidationWarning;
|
|
1004
|
+
settingsValidationWarnings;
|
|
1005
|
+
logger;
|
|
1006
|
+
constructor(options) {
|
|
1007
|
+
this.modelId = options.id;
|
|
1008
|
+
this.settings = options.settings ?? {};
|
|
1009
|
+
this.settingsValidationWarnings = options.settingsValidationWarnings ?? [];
|
|
1010
|
+
const baseLogger = getLogger(this.settings.logger);
|
|
1011
|
+
this.logger = createVerboseLogger(baseLogger, this.settings.verbose ?? false);
|
|
1012
|
+
if (!this.modelId || typeof this.modelId !== "string" || this.modelId.trim() === "") {
|
|
1013
|
+
throw new import_provider2.NoSuchModelError({
|
|
1014
|
+
modelId: this.modelId,
|
|
1015
|
+
modelType: "languageModel"
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
this.modelValidationWarning = validateModelId(this.modelId);
|
|
1019
|
+
if (this.modelValidationWarning) {
|
|
1020
|
+
this.logger.warn(`Claude Code Model: ${this.modelValidationWarning}`);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
get provider() {
|
|
1024
|
+
return "claude-code";
|
|
1025
|
+
}
|
|
1026
|
+
getModel() {
|
|
1027
|
+
const mapped = modelMap[this.modelId];
|
|
1028
|
+
return mapped ?? this.modelId;
|
|
1029
|
+
}
|
|
1030
|
+
getSanitizedSdkOptions() {
|
|
1031
|
+
if (!this.settings.sdkOptions || typeof this.settings.sdkOptions !== "object") {
|
|
1032
|
+
return void 0;
|
|
1033
|
+
}
|
|
1034
|
+
const sanitized = { ...this.settings.sdkOptions };
|
|
1035
|
+
const blockedKeys = Array.from(SDK_OPTIONS_BLOCKLIST).filter((key) => key in sanitized);
|
|
1036
|
+
if (blockedKeys.length > 0) {
|
|
1037
|
+
this.logger.warn(
|
|
1038
|
+
`[claude-code] sdkOptions includes provider-managed fields (${blockedKeys.join(
|
|
1039
|
+
", "
|
|
1040
|
+
)}); these will be ignored.`
|
|
1041
|
+
);
|
|
1042
|
+
blockedKeys.forEach((key) => delete sanitized[key]);
|
|
1043
|
+
}
|
|
1044
|
+
return sanitized;
|
|
1045
|
+
}
|
|
1046
|
+
getEffectiveResume(sdkOptions) {
|
|
1047
|
+
return sdkOptions?.resume ?? this.settings.resume ?? this.sessionId;
|
|
1048
|
+
}
|
|
1049
|
+
extractToolUses(content) {
|
|
1050
|
+
if (!Array.isArray(content)) {
|
|
1051
|
+
return [];
|
|
1052
|
+
}
|
|
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;
|
|
1057
|
+
return {
|
|
1058
|
+
id: typeof id === "string" && id.length > 0 ? id : (0, import_provider_utils.generateId)(),
|
|
1059
|
+
name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
|
|
1060
|
+
input,
|
|
1061
|
+
parentToolUseId: typeof parent_tool_use_id === "string" ? parent_tool_use_id : null
|
|
1062
|
+
};
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
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;
|
|
1073
|
+
return {
|
|
1074
|
+
id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
|
|
1075
|
+
name: typeof name === "string" && name.length > 0 ? name : void 0,
|
|
1076
|
+
result: content2,
|
|
1077
|
+
isError: Boolean(is_error)
|
|
1078
|
+
};
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
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;
|
|
1089
|
+
return {
|
|
1090
|
+
id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
|
|
1091
|
+
name: typeof name === "string" && name.length > 0 ? name : void 0,
|
|
1092
|
+
error
|
|
1093
|
+
};
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
serializeToolInput(input) {
|
|
1097
|
+
if (typeof input === "string") {
|
|
1098
|
+
return this.checkInputSize(input);
|
|
1099
|
+
}
|
|
1100
|
+
if (input === void 0) {
|
|
1101
|
+
return "";
|
|
1102
|
+
}
|
|
1103
|
+
try {
|
|
1104
|
+
const serialized = JSON.stringify(input);
|
|
1105
|
+
return this.checkInputSize(serialized);
|
|
1106
|
+
} catch {
|
|
1107
|
+
const fallback = String(input);
|
|
1108
|
+
return this.checkInputSize(fallback);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
checkInputSize(str) {
|
|
1112
|
+
const length = str.length;
|
|
1113
|
+
if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE) {
|
|
1114
|
+
throw new Error(
|
|
1115
|
+
`Tool input exceeds maximum size of ${_ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE} bytes (got ${length} bytes). This may indicate a malformed request or an attempt to process excessively large data.`
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_WARN) {
|
|
1119
|
+
this.logger.warn(
|
|
1120
|
+
`[claude-code] Large tool input detected: ${length} bytes. Performance may be impacted. Consider chunking or reducing input size.`
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
return str;
|
|
1124
|
+
}
|
|
1125
|
+
normalizeToolResult(result) {
|
|
1126
|
+
if (typeof result === "string") {
|
|
1127
|
+
try {
|
|
1128
|
+
return JSON.parse(result);
|
|
1129
|
+
} catch {
|
|
1130
|
+
return result;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
1134
|
+
const textBlocks = result.filter(
|
|
1135
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
1136
|
+
).map((block) => block.text);
|
|
1137
|
+
if (textBlocks.length !== result.length) {
|
|
1138
|
+
return result;
|
|
1139
|
+
}
|
|
1140
|
+
if (textBlocks.length === 1) {
|
|
1141
|
+
try {
|
|
1142
|
+
return JSON.parse(textBlocks[0]);
|
|
1143
|
+
} catch {
|
|
1144
|
+
return textBlocks[0];
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const combined = textBlocks.join("\n");
|
|
1148
|
+
try {
|
|
1149
|
+
return JSON.parse(combined);
|
|
1150
|
+
} catch {
|
|
1151
|
+
return combined;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return result;
|
|
1155
|
+
}
|
|
1156
|
+
generateAllWarnings(options, prompt) {
|
|
1157
|
+
const warnings = [];
|
|
1158
|
+
const unsupportedParams = [];
|
|
1159
|
+
if (options.temperature !== void 0) unsupportedParams.push("temperature");
|
|
1160
|
+
if (options.topP !== void 0) unsupportedParams.push("topP");
|
|
1161
|
+
if (options.topK !== void 0) unsupportedParams.push("topK");
|
|
1162
|
+
if (options.presencePenalty !== void 0) unsupportedParams.push("presencePenalty");
|
|
1163
|
+
if (options.frequencyPenalty !== void 0) unsupportedParams.push("frequencyPenalty");
|
|
1164
|
+
if (options.stopSequences !== void 0 && options.stopSequences.length > 0)
|
|
1165
|
+
unsupportedParams.push("stopSequences");
|
|
1166
|
+
if (options.seed !== void 0) unsupportedParams.push("seed");
|
|
1167
|
+
if (unsupportedParams.length > 0) {
|
|
1168
|
+
for (const param of unsupportedParams) {
|
|
1169
|
+
warnings.push({
|
|
1170
|
+
type: "unsupported",
|
|
1171
|
+
feature: param,
|
|
1172
|
+
details: `Claude Code SDK does not support the ${param} parameter. It will be ignored.`
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
if (this.modelValidationWarning) {
|
|
1177
|
+
warnings.push({
|
|
1178
|
+
type: "other",
|
|
1179
|
+
message: this.modelValidationWarning
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
this.settingsValidationWarnings.forEach((warning) => {
|
|
1183
|
+
warnings.push({
|
|
1184
|
+
type: "other",
|
|
1185
|
+
message: warning
|
|
1186
|
+
});
|
|
1187
|
+
});
|
|
1188
|
+
if (options.responseFormat?.type === "json" && !options.responseFormat.schema) {
|
|
1189
|
+
warnings.push({
|
|
1190
|
+
type: "unsupported",
|
|
1191
|
+
feature: "responseFormat",
|
|
1192
|
+
details: "JSON response format requires a schema for the Claude Code provider. The JSON responseFormat is ignored and the call is treated as plain text."
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
const promptWarning = validatePrompt(prompt);
|
|
1196
|
+
if (promptWarning) {
|
|
1197
|
+
warnings.push({
|
|
1198
|
+
type: "other",
|
|
1199
|
+
message: promptWarning
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
return warnings;
|
|
1203
|
+
}
|
|
1204
|
+
createQueryOptions(abortController, responseFormat, stderrCollector, sdkOptions, effectiveResume) {
|
|
1205
|
+
const opts = {
|
|
1206
|
+
model: this.getModel(),
|
|
1207
|
+
abortController,
|
|
1208
|
+
resume: effectiveResume ?? this.settings.resume ?? this.sessionId,
|
|
1209
|
+
pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
|
|
1210
|
+
maxTurns: this.settings.maxTurns,
|
|
1211
|
+
maxThinkingTokens: this.settings.maxThinkingTokens,
|
|
1212
|
+
cwd: this.settings.cwd,
|
|
1213
|
+
executable: this.settings.executable,
|
|
1214
|
+
executableArgs: this.settings.executableArgs,
|
|
1215
|
+
permissionMode: this.settings.permissionMode,
|
|
1216
|
+
permissionPromptToolName: this.settings.permissionPromptToolName,
|
|
1217
|
+
continue: this.settings.continue,
|
|
1218
|
+
allowedTools: this.settings.allowedTools,
|
|
1219
|
+
disallowedTools: this.settings.disallowedTools,
|
|
1220
|
+
betas: this.settings.betas,
|
|
1221
|
+
allowDangerouslySkipPermissions: this.settings.allowDangerouslySkipPermissions,
|
|
1222
|
+
enableFileCheckpointing: this.settings.enableFileCheckpointing,
|
|
1223
|
+
maxBudgetUsd: this.settings.maxBudgetUsd,
|
|
1224
|
+
plugins: this.settings.plugins,
|
|
1225
|
+
resumeSessionAt: this.settings.resumeSessionAt,
|
|
1226
|
+
sandbox: this.settings.sandbox,
|
|
1227
|
+
tools: this.settings.tools,
|
|
1228
|
+
mcpServers: this.settings.mcpServers,
|
|
1229
|
+
canUseTool: this.settings.canUseTool
|
|
1230
|
+
};
|
|
1231
|
+
if (this.settings.systemPrompt !== void 0) {
|
|
1232
|
+
opts.systemPrompt = this.settings.systemPrompt;
|
|
1233
|
+
} else if (this.settings.customSystemPrompt !== void 0) {
|
|
1234
|
+
this.logger.warn(
|
|
1235
|
+
"[claude-code] 'customSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt' instead (string or { type: 'preset', preset: 'claude_code', append? })."
|
|
1236
|
+
);
|
|
1237
|
+
opts.systemPrompt = this.settings.customSystemPrompt;
|
|
1238
|
+
} else if (this.settings.appendSystemPrompt !== void 0) {
|
|
1239
|
+
this.logger.warn(
|
|
1240
|
+
"[claude-code] 'appendSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt: { type: 'preset', preset: 'claude_code', append: <text> }' instead."
|
|
1241
|
+
);
|
|
1242
|
+
opts.systemPrompt = {
|
|
1243
|
+
type: "preset",
|
|
1244
|
+
preset: "claude_code",
|
|
1245
|
+
append: this.settings.appendSystemPrompt
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
if (this.settings.settingSources !== void 0) {
|
|
1249
|
+
opts.settingSources = this.settings.settingSources;
|
|
1250
|
+
}
|
|
1251
|
+
if (this.settings.additionalDirectories !== void 0) {
|
|
1252
|
+
opts.additionalDirectories = this.settings.additionalDirectories;
|
|
1253
|
+
}
|
|
1254
|
+
if (this.settings.agents !== void 0) {
|
|
1255
|
+
opts.agents = this.settings.agents;
|
|
1256
|
+
}
|
|
1257
|
+
if (this.settings.includePartialMessages !== void 0) {
|
|
1258
|
+
opts.includePartialMessages = this.settings.includePartialMessages;
|
|
1259
|
+
}
|
|
1260
|
+
if (this.settings.fallbackModel !== void 0) {
|
|
1261
|
+
opts.fallbackModel = this.settings.fallbackModel;
|
|
1262
|
+
}
|
|
1263
|
+
if (this.settings.forkSession !== void 0) {
|
|
1264
|
+
opts.forkSession = this.settings.forkSession;
|
|
1265
|
+
}
|
|
1266
|
+
if (this.settings.strictMcpConfig !== void 0) {
|
|
1267
|
+
opts.strictMcpConfig = this.settings.strictMcpConfig;
|
|
1268
|
+
}
|
|
1269
|
+
if (this.settings.extraArgs !== void 0) {
|
|
1270
|
+
opts.extraArgs = this.settings.extraArgs;
|
|
1271
|
+
}
|
|
1272
|
+
if (this.settings.persistSession !== void 0) {
|
|
1273
|
+
opts.persistSession = this.settings.persistSession;
|
|
1274
|
+
}
|
|
1275
|
+
if (this.settings.spawnClaudeCodeProcess !== void 0) {
|
|
1276
|
+
opts.spawnClaudeCodeProcess = this.settings.spawnClaudeCodeProcess;
|
|
1277
|
+
}
|
|
1278
|
+
if (this.settings.hooks) {
|
|
1279
|
+
opts.hooks = this.settings.hooks;
|
|
1280
|
+
}
|
|
1281
|
+
if (this.settings.sessionId !== void 0) {
|
|
1282
|
+
opts.sessionId = this.settings.sessionId;
|
|
1283
|
+
}
|
|
1284
|
+
if (this.settings.debug !== void 0) {
|
|
1285
|
+
opts.debug = this.settings.debug;
|
|
1286
|
+
}
|
|
1287
|
+
if (this.settings.debugFile !== void 0) {
|
|
1288
|
+
opts.debugFile = this.settings.debugFile;
|
|
1289
|
+
}
|
|
1290
|
+
const sdkOverrides = sdkOptions ? sdkOptions : void 0;
|
|
1291
|
+
const sdkEnv = sdkOverrides && typeof sdkOverrides.env === "object" && sdkOverrides.env !== null ? sdkOverrides.env : void 0;
|
|
1292
|
+
const sdkStderr = sdkOverrides && typeof sdkOverrides.stderr === "function" ? sdkOverrides.stderr : void 0;
|
|
1293
|
+
if (sdkOverrides) {
|
|
1294
|
+
const rest = { ...sdkOverrides };
|
|
1295
|
+
delete rest.env;
|
|
1296
|
+
delete rest.stderr;
|
|
1297
|
+
Object.assign(opts, rest);
|
|
1298
|
+
}
|
|
1299
|
+
const userStderrCallback = sdkStderr ?? this.settings.stderr;
|
|
1300
|
+
if (stderrCollector || userStderrCallback) {
|
|
1301
|
+
opts.stderr = (data) => {
|
|
1302
|
+
if (stderrCollector) stderrCollector(data);
|
|
1303
|
+
if (userStderrCallback) userStderrCallback(data);
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
if (this.settings.env !== void 0 || sdkEnv !== void 0) {
|
|
1307
|
+
const baseEnv = getBaseProcessEnv();
|
|
1308
|
+
opts.env = { ...baseEnv, ...this.settings.env, ...sdkEnv };
|
|
1309
|
+
}
|
|
1310
|
+
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
1311
|
+
opts.outputFormat = {
|
|
1312
|
+
type: "json_schema",
|
|
1313
|
+
schema: responseFormat.schema
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
return opts;
|
|
1317
|
+
}
|
|
1318
|
+
handleClaudeCodeError(error, messagesPrompt, collectedStderr) {
|
|
1319
|
+
if (isAbortError(error)) {
|
|
1320
|
+
throw error;
|
|
1321
|
+
}
|
|
1322
|
+
const isErrorWithMessage = (err) => {
|
|
1323
|
+
return typeof err === "object" && err !== null && "message" in err;
|
|
1324
|
+
};
|
|
1325
|
+
const isErrorWithCode = (err) => {
|
|
1326
|
+
return typeof err === "object" && err !== null;
|
|
1327
|
+
};
|
|
1328
|
+
const authErrorPatterns = [
|
|
1329
|
+
"not logged in",
|
|
1330
|
+
"authentication",
|
|
1331
|
+
"unauthorized",
|
|
1332
|
+
"auth failed",
|
|
1333
|
+
"please login",
|
|
1334
|
+
"claude login",
|
|
1335
|
+
"/login",
|
|
1336
|
+
// CLI returns "Please run /login"
|
|
1337
|
+
"invalid api key"
|
|
1338
|
+
];
|
|
1339
|
+
const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
|
|
1340
|
+
const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
|
|
1341
|
+
const isAuthError = authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
|
|
1342
|
+
if (isAuthError) {
|
|
1343
|
+
return createAuthenticationError({
|
|
1344
|
+
message: isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
|
|
1348
|
+
if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
|
|
1349
|
+
return createTimeoutError({
|
|
1350
|
+
message: isErrorWithMessage(error) && error.message ? error.message : "Request timed out",
|
|
1351
|
+
promptExcerpt: messagesPrompt.substring(0, 200)
|
|
1352
|
+
// Don't specify timeoutMs since we don't know the actual timeout value
|
|
1353
|
+
// It's controlled by the consumer via AbortSignal
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
|
|
1357
|
+
const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
1358
|
+
const stderr = stderrFromError || collectedStderr || void 0;
|
|
1359
|
+
return createAPICallError({
|
|
1360
|
+
message: isErrorWithMessage(error) && error.message ? error.message : "Claude Code SDK error",
|
|
1361
|
+
code: errorCode || void 0,
|
|
1362
|
+
exitCode,
|
|
1363
|
+
stderr,
|
|
1364
|
+
promptExcerpt: messagesPrompt.substring(0, 200),
|
|
1365
|
+
isRetryable
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
setSessionId(sessionId) {
|
|
1369
|
+
this.sessionId = sessionId;
|
|
1370
|
+
const warning = validateSessionId(sessionId);
|
|
1371
|
+
if (warning) {
|
|
1372
|
+
this.logger.warn(`Claude Code Session: ${warning}`);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
async doGenerate(options) {
|
|
1376
|
+
this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
|
|
1377
|
+
this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
|
|
1378
|
+
const {
|
|
1379
|
+
messagesPrompt,
|
|
1380
|
+
warnings: messageWarnings,
|
|
1381
|
+
streamingContentParts,
|
|
1382
|
+
hasImageParts
|
|
1383
|
+
} = convertToClaudeCodeMessages(options.prompt);
|
|
1384
|
+
this.logger.debug(
|
|
1385
|
+
`[claude-code] Converted ${options.prompt.length} messages, hasImageParts: ${hasImageParts}`
|
|
1386
|
+
);
|
|
1387
|
+
const abortController = new AbortController();
|
|
1388
|
+
let abortListener;
|
|
1389
|
+
if (options.abortSignal?.aborted) {
|
|
1390
|
+
abortController.abort(options.abortSignal.reason);
|
|
1391
|
+
} else if (options.abortSignal) {
|
|
1392
|
+
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
1393
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
1394
|
+
}
|
|
1395
|
+
let collectedStderr = "";
|
|
1396
|
+
const stderrCollector = (data) => {
|
|
1397
|
+
collectedStderr += data;
|
|
1398
|
+
};
|
|
1399
|
+
const sdkOptions = this.getSanitizedSdkOptions();
|
|
1400
|
+
const effectiveResume = this.getEffectiveResume(sdkOptions);
|
|
1401
|
+
const queryOptions = this.createQueryOptions(
|
|
1402
|
+
abortController,
|
|
1403
|
+
options.responseFormat,
|
|
1404
|
+
stderrCollector,
|
|
1405
|
+
sdkOptions,
|
|
1406
|
+
effectiveResume
|
|
1407
|
+
);
|
|
1408
|
+
let text = "";
|
|
1409
|
+
let structuredOutput;
|
|
1410
|
+
let usage = createEmptyUsage();
|
|
1411
|
+
let finishReason = { unified: "stop", raw: void 0 };
|
|
1412
|
+
let wasTruncated = false;
|
|
1413
|
+
let costUsd;
|
|
1414
|
+
let durationMs;
|
|
1415
|
+
let modelUsage;
|
|
1416
|
+
const warnings = this.generateAllWarnings(options, messagesPrompt);
|
|
1417
|
+
if (messageWarnings) {
|
|
1418
|
+
messageWarnings.forEach((warning) => {
|
|
1419
|
+
warnings.push({
|
|
1420
|
+
type: "other",
|
|
1421
|
+
message: warning
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
}
|
|
1425
|
+
const modeSetting = this.settings.streamingInput ?? "auto";
|
|
1426
|
+
const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
|
|
1427
|
+
const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
|
|
1428
|
+
const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
|
|
1429
|
+
if (!wantsStreamInput && hasImageParts) {
|
|
1430
|
+
warnings.push({
|
|
1431
|
+
type: "other",
|
|
1432
|
+
message: STREAMING_FEATURE_WARNING
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
let done = () => {
|
|
1436
|
+
};
|
|
1437
|
+
const outputStreamEnded = new Promise((resolve) => {
|
|
1438
|
+
done = () => resolve(void 0);
|
|
1439
|
+
});
|
|
1440
|
+
try {
|
|
1441
|
+
if (effectiveCanUseTool && effectivePermissionPromptToolName) {
|
|
1442
|
+
throw new Error(
|
|
1443
|
+
"canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
|
|
1447
|
+
messagesPrompt,
|
|
1448
|
+
outputStreamEnded,
|
|
1449
|
+
effectiveResume,
|
|
1450
|
+
streamingContentParts,
|
|
1451
|
+
this.settings.onStreamStart
|
|
1452
|
+
) : messagesPrompt;
|
|
1453
|
+
this.logger.debug(
|
|
1454
|
+
`[claude-code] Executing query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
|
|
1455
|
+
);
|
|
1456
|
+
const response = (0, import_claude_agent_sdk.query)({
|
|
1457
|
+
prompt: sdkPrompt,
|
|
1458
|
+
options: queryOptions
|
|
1459
|
+
});
|
|
1460
|
+
this.settings.onQueryCreated?.(response);
|
|
1461
|
+
for await (const message of response) {
|
|
1462
|
+
this.logger.debug(`[claude-code] Received message type: ${message.type}`);
|
|
1463
|
+
if (message.type === "assistant") {
|
|
1464
|
+
text += message.message.content.map((c) => c.type === "text" ? c.text : "").join("");
|
|
1465
|
+
} else if (message.type === "result") {
|
|
1466
|
+
done();
|
|
1467
|
+
this.setSessionId(message.session_id);
|
|
1468
|
+
costUsd = message.total_cost_usd;
|
|
1469
|
+
durationMs = message.duration_ms;
|
|
1470
|
+
modelUsage = message.modelUsage;
|
|
1471
|
+
if ("is_error" in message && message.is_error === true) {
|
|
1472
|
+
const errorMessage = "result" in message && typeof message.result === "string" ? message.result : "Claude Code CLI returned an error";
|
|
1473
|
+
throw Object.assign(new Error(errorMessage), { exitCode: 1 });
|
|
1474
|
+
}
|
|
1475
|
+
if (message.subtype === "error_max_structured_output_retries") {
|
|
1476
|
+
throw new Error(
|
|
1477
|
+
"Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
if ("structured_output" in message && message.structured_output !== void 0) {
|
|
1481
|
+
structuredOutput = message.structured_output;
|
|
1482
|
+
this.logger.debug("[claude-code] Received structured output from SDK");
|
|
1483
|
+
}
|
|
1484
|
+
this.logger.info(
|
|
1485
|
+
`[claude-code] Request completed - Session: ${message.session_id}, Cost: $${costUsd?.toFixed(4) ?? "N/A"}, Duration: ${durationMs ?? "N/A"}ms`
|
|
1486
|
+
);
|
|
1487
|
+
if ("usage" in message) {
|
|
1488
|
+
usage = convertClaudeCodeUsage(message.usage);
|
|
1489
|
+
this.logger.debug(
|
|
1490
|
+
`[claude-code] Token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
|
|
1494
|
+
finishReason = mapClaudeCodeFinishReason(message.subtype, stopReason);
|
|
1495
|
+
this.logger.debug(`[claude-code] Finish reason: ${finishReason.unified}`);
|
|
1496
|
+
} else if (message.type === "system" && message.subtype === "init") {
|
|
1497
|
+
this.setSessionId(message.session_id);
|
|
1498
|
+
this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
} catch (error) {
|
|
1502
|
+
done();
|
|
1503
|
+
this.logger.debug(
|
|
1504
|
+
`[claude-code] Error during doGenerate: ${error instanceof Error ? error.message : String(error)}`
|
|
1505
|
+
);
|
|
1506
|
+
if (isAbortError(error)) {
|
|
1507
|
+
this.logger.debug("[claude-code] Request aborted by user");
|
|
1508
|
+
throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
|
|
1509
|
+
}
|
|
1510
|
+
if (isClaudeCodeTruncationError(error, text)) {
|
|
1511
|
+
this.logger.warn(
|
|
1512
|
+
`[claude-code] Detected truncated response, returning ${text.length} characters of buffered text`
|
|
1513
|
+
);
|
|
1514
|
+
wasTruncated = true;
|
|
1515
|
+
finishReason = { unified: "length", raw: "truncation" };
|
|
1516
|
+
warnings.push({
|
|
1517
|
+
type: "other",
|
|
1518
|
+
message: CLAUDE_CODE_TRUNCATION_WARNING
|
|
1519
|
+
});
|
|
1520
|
+
} else {
|
|
1521
|
+
throw this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
|
|
1522
|
+
}
|
|
1523
|
+
} finally {
|
|
1524
|
+
if (options.abortSignal && abortListener) {
|
|
1525
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
const finalText = structuredOutput !== void 0 ? JSON.stringify(structuredOutput) : text;
|
|
1529
|
+
return {
|
|
1530
|
+
content: [{ type: "text", text: finalText }],
|
|
1531
|
+
usage,
|
|
1532
|
+
finishReason,
|
|
1533
|
+
warnings,
|
|
1534
|
+
response: {
|
|
1535
|
+
id: (0, import_provider_utils.generateId)(),
|
|
1536
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1537
|
+
modelId: this.modelId
|
|
1538
|
+
},
|
|
1539
|
+
request: {
|
|
1540
|
+
body: messagesPrompt
|
|
1541
|
+
},
|
|
1542
|
+
providerMetadata: {
|
|
1543
|
+
"claude-code": {
|
|
1544
|
+
...this.sessionId !== void 0 && { sessionId: this.sessionId },
|
|
1545
|
+
...costUsd !== void 0 && { costUsd },
|
|
1546
|
+
...durationMs !== void 0 && { durationMs },
|
|
1547
|
+
...modelUsage !== void 0 && { modelUsage },
|
|
1548
|
+
...wasTruncated && { truncated: true }
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
async doStream(options) {
|
|
1554
|
+
this.logger.debug(`[claude-code] Starting doStream request with model: ${this.modelId}`);
|
|
1555
|
+
this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
|
|
1556
|
+
const {
|
|
1557
|
+
messagesPrompt,
|
|
1558
|
+
warnings: messageWarnings,
|
|
1559
|
+
streamingContentParts,
|
|
1560
|
+
hasImageParts
|
|
1561
|
+
} = convertToClaudeCodeMessages(options.prompt);
|
|
1562
|
+
this.logger.debug(
|
|
1563
|
+
`[claude-code] Converted ${options.prompt.length} messages for streaming, hasImageParts: ${hasImageParts}`
|
|
1564
|
+
);
|
|
1565
|
+
const abortController = new AbortController();
|
|
1566
|
+
let abortListener;
|
|
1567
|
+
if (options.abortSignal?.aborted) {
|
|
1568
|
+
abortController.abort(options.abortSignal.reason);
|
|
1569
|
+
} else if (options.abortSignal) {
|
|
1570
|
+
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
1571
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
1572
|
+
}
|
|
1573
|
+
let collectedStderr = "";
|
|
1574
|
+
const stderrCollector = (data) => {
|
|
1575
|
+
collectedStderr += data;
|
|
1576
|
+
};
|
|
1577
|
+
const sdkOptions = this.getSanitizedSdkOptions();
|
|
1578
|
+
const effectiveResume = this.getEffectiveResume(sdkOptions);
|
|
1579
|
+
const queryOptions = this.createQueryOptions(
|
|
1580
|
+
abortController,
|
|
1581
|
+
options.responseFormat,
|
|
1582
|
+
stderrCollector,
|
|
1583
|
+
sdkOptions,
|
|
1584
|
+
effectiveResume
|
|
1585
|
+
);
|
|
1586
|
+
if (queryOptions.includePartialMessages === void 0) {
|
|
1587
|
+
queryOptions.includePartialMessages = true;
|
|
1588
|
+
}
|
|
1589
|
+
const warnings = this.generateAllWarnings(options, messagesPrompt);
|
|
1590
|
+
if (messageWarnings) {
|
|
1591
|
+
messageWarnings.forEach((warning) => {
|
|
1592
|
+
warnings.push({
|
|
1593
|
+
type: "other",
|
|
1594
|
+
message: warning
|
|
1595
|
+
});
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
const modeSetting = this.settings.streamingInput ?? "auto";
|
|
1599
|
+
const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
|
|
1600
|
+
const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
|
|
1601
|
+
const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
|
|
1602
|
+
if (!wantsStreamInput && hasImageParts) {
|
|
1603
|
+
warnings.push({
|
|
1604
|
+
type: "other",
|
|
1605
|
+
message: STREAMING_FEATURE_WARNING
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
const stream = new ReadableStream({
|
|
1609
|
+
start: async (controller) => {
|
|
1610
|
+
let done = () => {
|
|
1611
|
+
};
|
|
1612
|
+
const outputStreamEnded = new Promise((resolve) => {
|
|
1613
|
+
done = () => resolve(void 0);
|
|
1614
|
+
});
|
|
1615
|
+
const toolStates = /* @__PURE__ */ new Map();
|
|
1616
|
+
const activeTaskTools = /* @__PURE__ */ new Map();
|
|
1617
|
+
const getFallbackParentId = () => {
|
|
1618
|
+
if (activeTaskTools.size === 1) {
|
|
1619
|
+
return activeTaskTools.keys().next().value ?? null;
|
|
1620
|
+
}
|
|
1621
|
+
return null;
|
|
1622
|
+
};
|
|
1623
|
+
const streamWarnings = [];
|
|
1624
|
+
const closeToolInput = (toolId, state) => {
|
|
1625
|
+
if (!state.inputClosed && state.inputStarted) {
|
|
1626
|
+
controller.enqueue({
|
|
1627
|
+
type: "tool-input-end",
|
|
1628
|
+
id: toolId
|
|
1629
|
+
});
|
|
1630
|
+
state.inputClosed = true;
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
const emitToolCall = (toolId, state) => {
|
|
1634
|
+
if (state.callEmitted) {
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
closeToolInput(toolId, state);
|
|
1638
|
+
controller.enqueue({
|
|
1639
|
+
type: "tool-call",
|
|
1640
|
+
toolCallId: toolId,
|
|
1641
|
+
toolName: state.name,
|
|
1642
|
+
input: state.lastSerializedInput ?? "",
|
|
1643
|
+
providerExecuted: true,
|
|
1644
|
+
dynamic: true,
|
|
1645
|
+
// V3 field: indicates tool is provider-defined (not in user's tools map)
|
|
1646
|
+
providerMetadata: {
|
|
1647
|
+
"claude-code": {
|
|
1648
|
+
// rawInput preserves the original serialized format before AI SDK normalization.
|
|
1649
|
+
// Use this if you need the exact string sent to the Claude CLI, which may differ
|
|
1650
|
+
// from the `input` field after AI SDK processing.
|
|
1651
|
+
rawInput: state.lastSerializedInput ?? "",
|
|
1652
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
state.callEmitted = true;
|
|
1657
|
+
};
|
|
1658
|
+
const finalizeToolCalls = () => {
|
|
1659
|
+
for (const [toolId, state] of toolStates) {
|
|
1660
|
+
emitToolCall(toolId, state);
|
|
1661
|
+
}
|
|
1662
|
+
toolStates.clear();
|
|
1663
|
+
};
|
|
1664
|
+
let usage = createEmptyUsage();
|
|
1665
|
+
let accumulatedText = "";
|
|
1666
|
+
let textPartId;
|
|
1667
|
+
let streamedTextLength = 0;
|
|
1668
|
+
let hasReceivedStreamEvents = false;
|
|
1669
|
+
let hasStreamedJson = false;
|
|
1670
|
+
const toolBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1671
|
+
const toolInputAccumulators = /* @__PURE__ */ new Map();
|
|
1672
|
+
const textBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1673
|
+
let textStreamedViaContentBlock = false;
|
|
1674
|
+
const reasoningBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1675
|
+
let currentReasoningPartId;
|
|
1676
|
+
try {
|
|
1677
|
+
controller.enqueue({ type: "stream-start", warnings });
|
|
1678
|
+
if (effectiveCanUseTool && effectivePermissionPromptToolName) {
|
|
1679
|
+
throw new Error(
|
|
1680
|
+
"canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
|
|
1684
|
+
messagesPrompt,
|
|
1685
|
+
outputStreamEnded,
|
|
1686
|
+
effectiveResume,
|
|
1687
|
+
streamingContentParts,
|
|
1688
|
+
this.settings.onStreamStart
|
|
1689
|
+
) : messagesPrompt;
|
|
1690
|
+
this.logger.debug(
|
|
1691
|
+
`[claude-code] Starting stream query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
|
|
1692
|
+
);
|
|
1693
|
+
const response = (0, import_claude_agent_sdk.query)({
|
|
1694
|
+
prompt: sdkPrompt,
|
|
1695
|
+
options: queryOptions
|
|
1696
|
+
});
|
|
1697
|
+
this.settings.onQueryCreated?.(response);
|
|
1698
|
+
for await (const message of response) {
|
|
1699
|
+
this.logger.debug(`[claude-code] Stream received message type: ${message.type}`);
|
|
1700
|
+
if (message.type === "stream_event") {
|
|
1701
|
+
const streamEvent = message;
|
|
1702
|
+
const event = streamEvent.event;
|
|
1703
|
+
if (event.type === "content_block_delta" && event.delta.type === "text_delta" && "text" in event.delta && event.delta.text) {
|
|
1704
|
+
const deltaText = event.delta.text;
|
|
1705
|
+
hasReceivedStreamEvents = true;
|
|
1706
|
+
if (options.responseFormat?.type === "json") {
|
|
1707
|
+
accumulatedText += deltaText;
|
|
1708
|
+
streamedTextLength += deltaText.length;
|
|
1709
|
+
continue;
|
|
1710
|
+
}
|
|
1711
|
+
if (!textPartId) {
|
|
1712
|
+
textPartId = (0, import_provider_utils.generateId)();
|
|
1713
|
+
controller.enqueue({
|
|
1714
|
+
type: "text-start",
|
|
1715
|
+
id: textPartId
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
controller.enqueue({
|
|
1719
|
+
type: "text-delta",
|
|
1720
|
+
id: textPartId,
|
|
1721
|
+
delta: deltaText
|
|
1722
|
+
});
|
|
1723
|
+
accumulatedText += deltaText;
|
|
1724
|
+
streamedTextLength += deltaText.length;
|
|
1725
|
+
}
|
|
1726
|
+
if (event.type === "content_block_delta" && event.delta.type === "input_json_delta" && "partial_json" in event.delta && event.delta.partial_json) {
|
|
1727
|
+
const jsonDelta = event.delta.partial_json;
|
|
1728
|
+
hasReceivedStreamEvents = true;
|
|
1729
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1730
|
+
if (options.responseFormat?.type === "json") {
|
|
1731
|
+
if (!textPartId) {
|
|
1732
|
+
textPartId = (0, import_provider_utils.generateId)();
|
|
1733
|
+
controller.enqueue({
|
|
1734
|
+
type: "text-start",
|
|
1735
|
+
id: textPartId
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
controller.enqueue({
|
|
1739
|
+
type: "text-delta",
|
|
1740
|
+
id: textPartId,
|
|
1741
|
+
delta: jsonDelta
|
|
1742
|
+
});
|
|
1743
|
+
accumulatedText += jsonDelta;
|
|
1744
|
+
streamedTextLength += jsonDelta.length;
|
|
1745
|
+
hasStreamedJson = true;
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1748
|
+
const toolId = toolBlocksByIndex.get(blockIndex);
|
|
1749
|
+
if (toolId) {
|
|
1750
|
+
const accumulated = (toolInputAccumulators.get(toolId) ?? "") + jsonDelta;
|
|
1751
|
+
toolInputAccumulators.set(toolId, accumulated);
|
|
1752
|
+
controller.enqueue({
|
|
1753
|
+
type: "tool-input-delta",
|
|
1754
|
+
id: toolId,
|
|
1755
|
+
delta: jsonDelta
|
|
1756
|
+
});
|
|
1757
|
+
continue;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "tool_use") {
|
|
1761
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1762
|
+
const toolBlock = event.content_block;
|
|
1763
|
+
const toolId = typeof toolBlock.id === "string" && toolBlock.id.length > 0 ? toolBlock.id : (0, import_provider_utils.generateId)();
|
|
1764
|
+
const toolName = typeof toolBlock.name === "string" && toolBlock.name.length > 0 ? toolBlock.name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
1765
|
+
hasReceivedStreamEvents = true;
|
|
1766
|
+
if (textPartId) {
|
|
1767
|
+
controller.enqueue({
|
|
1768
|
+
type: "text-end",
|
|
1769
|
+
id: textPartId
|
|
1770
|
+
});
|
|
1771
|
+
textPartId = void 0;
|
|
1772
|
+
}
|
|
1773
|
+
toolBlocksByIndex.set(blockIndex, toolId);
|
|
1774
|
+
toolInputAccumulators.set(toolId, "");
|
|
1775
|
+
let state = toolStates.get(toolId);
|
|
1776
|
+
if (!state) {
|
|
1777
|
+
const currentParentId = toolName === "Task" ? null : getFallbackParentId();
|
|
1778
|
+
state = {
|
|
1779
|
+
name: toolName,
|
|
1780
|
+
inputStarted: false,
|
|
1781
|
+
inputClosed: false,
|
|
1782
|
+
callEmitted: false,
|
|
1783
|
+
parentToolCallId: currentParentId
|
|
1784
|
+
};
|
|
1785
|
+
toolStates.set(toolId, state);
|
|
1786
|
+
}
|
|
1787
|
+
if (!state.inputStarted) {
|
|
1788
|
+
this.logger.debug(
|
|
1789
|
+
`[claude-code] Tool input started (content_block) - Tool: ${toolName}, ID: ${toolId}, parent: ${state.parentToolCallId}`
|
|
1790
|
+
);
|
|
1791
|
+
controller.enqueue({
|
|
1792
|
+
type: "tool-input-start",
|
|
1793
|
+
id: toolId,
|
|
1794
|
+
toolName,
|
|
1795
|
+
providerExecuted: true,
|
|
1796
|
+
dynamic: true,
|
|
1797
|
+
providerMetadata: {
|
|
1798
|
+
"claude-code": {
|
|
1799
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
if (toolName === "Task") {
|
|
1804
|
+
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
1805
|
+
}
|
|
1806
|
+
state.inputStarted = true;
|
|
1807
|
+
}
|
|
1808
|
+
continue;
|
|
1809
|
+
}
|
|
1810
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "text") {
|
|
1811
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1812
|
+
hasReceivedStreamEvents = true;
|
|
1813
|
+
const partId = (0, import_provider_utils.generateId)();
|
|
1814
|
+
textBlocksByIndex.set(blockIndex, partId);
|
|
1815
|
+
textPartId = partId;
|
|
1816
|
+
this.logger.debug(
|
|
1817
|
+
`[claude-code] Text content block started - Index: ${blockIndex}, ID: ${partId}`
|
|
1818
|
+
);
|
|
1819
|
+
controller.enqueue({
|
|
1820
|
+
type: "text-start",
|
|
1821
|
+
id: partId
|
|
1822
|
+
});
|
|
1823
|
+
textStreamedViaContentBlock = true;
|
|
1824
|
+
continue;
|
|
1825
|
+
}
|
|
1826
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "thinking") {
|
|
1827
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1828
|
+
hasReceivedStreamEvents = true;
|
|
1829
|
+
if (textPartId) {
|
|
1830
|
+
controller.enqueue({
|
|
1831
|
+
type: "text-end",
|
|
1832
|
+
id: textPartId
|
|
1833
|
+
});
|
|
1834
|
+
textPartId = void 0;
|
|
1835
|
+
}
|
|
1836
|
+
const reasoningPartId = (0, import_provider_utils.generateId)();
|
|
1837
|
+
reasoningBlocksByIndex.set(blockIndex, reasoningPartId);
|
|
1838
|
+
currentReasoningPartId = reasoningPartId;
|
|
1839
|
+
this.logger.debug(
|
|
1840
|
+
`[claude-code] Reasoning started (content_block) - ID: ${reasoningPartId}`
|
|
1841
|
+
);
|
|
1842
|
+
controller.enqueue({
|
|
1843
|
+
type: "reasoning-start",
|
|
1844
|
+
id: reasoningPartId
|
|
1845
|
+
});
|
|
1846
|
+
continue;
|
|
1847
|
+
}
|
|
1848
|
+
if (event.type === "content_block_delta" && event.delta.type === "thinking_delta" && "thinking" in event.delta && event.delta.thinking) {
|
|
1849
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1850
|
+
const reasoningPartId = reasoningBlocksByIndex.get(blockIndex) ?? currentReasoningPartId;
|
|
1851
|
+
hasReceivedStreamEvents = true;
|
|
1852
|
+
if (reasoningPartId) {
|
|
1853
|
+
controller.enqueue({
|
|
1854
|
+
type: "reasoning-delta",
|
|
1855
|
+
id: reasoningPartId,
|
|
1856
|
+
delta: event.delta.thinking
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
if (event.type === "content_block_stop") {
|
|
1862
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1863
|
+
hasReceivedStreamEvents = true;
|
|
1864
|
+
const toolId = toolBlocksByIndex.get(blockIndex);
|
|
1865
|
+
if (toolId) {
|
|
1866
|
+
const state = toolStates.get(toolId);
|
|
1867
|
+
if (state && !state.inputClosed) {
|
|
1868
|
+
const accumulatedInput = toolInputAccumulators.get(toolId) ?? "";
|
|
1869
|
+
this.logger.debug(
|
|
1870
|
+
`[claude-code] Tool content block stopped - Index: ${blockIndex}, Tool: ${state.name}, ID: ${toolId}`
|
|
1871
|
+
);
|
|
1872
|
+
controller.enqueue({
|
|
1873
|
+
type: "tool-input-end",
|
|
1874
|
+
id: toolId
|
|
1875
|
+
});
|
|
1876
|
+
state.inputClosed = true;
|
|
1877
|
+
const effectiveInput = accumulatedInput || state.lastSerializedInput || "";
|
|
1878
|
+
state.lastSerializedInput = effectiveInput;
|
|
1879
|
+
if (!state.callEmitted) {
|
|
1880
|
+
controller.enqueue({
|
|
1881
|
+
type: "tool-call",
|
|
1882
|
+
toolCallId: toolId,
|
|
1883
|
+
toolName: state.name,
|
|
1884
|
+
input: effectiveInput,
|
|
1885
|
+
providerExecuted: true,
|
|
1886
|
+
dynamic: true,
|
|
1887
|
+
providerMetadata: {
|
|
1888
|
+
"claude-code": {
|
|
1889
|
+
rawInput: effectiveInput,
|
|
1890
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
});
|
|
1894
|
+
state.callEmitted = true;
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
toolBlocksByIndex.delete(blockIndex);
|
|
1898
|
+
toolInputAccumulators.delete(toolId);
|
|
1899
|
+
continue;
|
|
1900
|
+
}
|
|
1901
|
+
const textId = textBlocksByIndex.get(blockIndex);
|
|
1902
|
+
if (textId) {
|
|
1903
|
+
this.logger.debug(
|
|
1904
|
+
`[claude-code] Text content block stopped - Index: ${blockIndex}, ID: ${textId}`
|
|
1905
|
+
);
|
|
1906
|
+
controller.enqueue({
|
|
1907
|
+
type: "text-end",
|
|
1908
|
+
id: textId
|
|
1909
|
+
});
|
|
1910
|
+
textBlocksByIndex.delete(blockIndex);
|
|
1911
|
+
if (textPartId === textId) {
|
|
1912
|
+
textPartId = void 0;
|
|
1913
|
+
}
|
|
1914
|
+
continue;
|
|
1915
|
+
}
|
|
1916
|
+
const reasoningPartId = reasoningBlocksByIndex.get(blockIndex);
|
|
1917
|
+
if (reasoningPartId) {
|
|
1918
|
+
this.logger.debug(
|
|
1919
|
+
`[claude-code] Reasoning ended (content_block) - ID: ${reasoningPartId}`
|
|
1920
|
+
);
|
|
1921
|
+
controller.enqueue({
|
|
1922
|
+
type: "reasoning-end",
|
|
1923
|
+
id: reasoningPartId
|
|
1924
|
+
});
|
|
1925
|
+
reasoningBlocksByIndex.delete(blockIndex);
|
|
1926
|
+
if (currentReasoningPartId === reasoningPartId) {
|
|
1927
|
+
currentReasoningPartId = void 0;
|
|
1928
|
+
}
|
|
1929
|
+
continue;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1934
|
+
if (message.type === "assistant") {
|
|
1935
|
+
if (!message.message?.content) {
|
|
1936
|
+
this.logger.warn(
|
|
1937
|
+
`[claude-code] Unexpected assistant message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
|
|
1938
|
+
);
|
|
1939
|
+
continue;
|
|
1940
|
+
}
|
|
1941
|
+
const sdkParentToolUseId = message.parent_tool_use_id;
|
|
1942
|
+
const content = message.message.content;
|
|
1943
|
+
const tools = this.extractToolUses(content);
|
|
1944
|
+
if (textPartId && tools.length > 0) {
|
|
1945
|
+
controller.enqueue({
|
|
1946
|
+
type: "text-end",
|
|
1947
|
+
id: textPartId
|
|
1948
|
+
});
|
|
1949
|
+
textPartId = void 0;
|
|
1950
|
+
}
|
|
1951
|
+
for (const tool3 of tools) {
|
|
1952
|
+
const toolId = tool3.id;
|
|
1953
|
+
let state = toolStates.get(toolId);
|
|
1954
|
+
if (!state) {
|
|
1955
|
+
const currentParentId = tool3.name === "Task" ? null : sdkParentToolUseId ?? tool3.parentToolUseId ?? getFallbackParentId();
|
|
1956
|
+
state = {
|
|
1957
|
+
name: tool3.name,
|
|
1958
|
+
inputStarted: false,
|
|
1959
|
+
inputClosed: false,
|
|
1960
|
+
callEmitted: false,
|
|
1961
|
+
parentToolCallId: currentParentId
|
|
1962
|
+
};
|
|
1963
|
+
toolStates.set(toolId, state);
|
|
1964
|
+
this.logger.debug(
|
|
1965
|
+
`[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${currentParentId}`
|
|
1966
|
+
);
|
|
1967
|
+
} else if (!state.parentToolCallId && sdkParentToolUseId && tool3.name !== "Task") {
|
|
1968
|
+
state.parentToolCallId = sdkParentToolUseId;
|
|
1969
|
+
this.logger.debug(
|
|
1970
|
+
`[claude-code] Retroactive parent context - Tool: ${tool3.name}, ID: ${toolId}, parent: ${sdkParentToolUseId}`
|
|
1971
|
+
);
|
|
1972
|
+
}
|
|
1973
|
+
state.name = tool3.name;
|
|
1974
|
+
if (!state.inputStarted) {
|
|
1975
|
+
this.logger.debug(
|
|
1976
|
+
`[claude-code] Tool input started - Tool: ${tool3.name}, ID: ${toolId}`
|
|
1977
|
+
);
|
|
1978
|
+
controller.enqueue({
|
|
1979
|
+
type: "tool-input-start",
|
|
1980
|
+
id: toolId,
|
|
1981
|
+
toolName: tool3.name,
|
|
1982
|
+
providerExecuted: true,
|
|
1983
|
+
dynamic: true,
|
|
1984
|
+
// V3 field: indicates tool is provider-defined
|
|
1985
|
+
providerMetadata: {
|
|
1986
|
+
"claude-code": {
|
|
1987
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
});
|
|
1991
|
+
if (tool3.name === "Task") {
|
|
1992
|
+
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
1993
|
+
}
|
|
1994
|
+
state.inputStarted = true;
|
|
1995
|
+
}
|
|
1996
|
+
const serializedInput = this.serializeToolInput(tool3.input);
|
|
1997
|
+
if (serializedInput) {
|
|
1998
|
+
let deltaPayload = "";
|
|
1999
|
+
if (state.lastSerializedInput === void 0) {
|
|
2000
|
+
if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE) {
|
|
2001
|
+
deltaPayload = serializedInput;
|
|
2002
|
+
}
|
|
2003
|
+
} else if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && state.lastSerializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && serializedInput.startsWith(state.lastSerializedInput)) {
|
|
2004
|
+
deltaPayload = serializedInput.slice(state.lastSerializedInput.length);
|
|
2005
|
+
} else if (serializedInput !== state.lastSerializedInput) {
|
|
2006
|
+
deltaPayload = "";
|
|
2007
|
+
}
|
|
2008
|
+
if (deltaPayload) {
|
|
2009
|
+
controller.enqueue({
|
|
2010
|
+
type: "tool-input-delta",
|
|
2011
|
+
id: toolId,
|
|
2012
|
+
delta: deltaPayload
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
state.lastSerializedInput = serializedInput;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const text = content.map((c) => c.type === "text" ? c.text : "").join("");
|
|
2019
|
+
if (text) {
|
|
2020
|
+
if (hasReceivedStreamEvents) {
|
|
2021
|
+
const newTextStart = streamedTextLength;
|
|
2022
|
+
const deltaText = text.length > newTextStart ? text.slice(newTextStart) : "";
|
|
2023
|
+
accumulatedText = text;
|
|
2024
|
+
if (options.responseFormat?.type !== "json" && deltaText) {
|
|
2025
|
+
if (!textPartId) {
|
|
2026
|
+
textPartId = (0, import_provider_utils.generateId)();
|
|
2027
|
+
controller.enqueue({
|
|
2028
|
+
type: "text-start",
|
|
2029
|
+
id: textPartId
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
controller.enqueue({
|
|
2033
|
+
type: "text-delta",
|
|
2034
|
+
id: textPartId,
|
|
2035
|
+
delta: deltaText
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
streamedTextLength = text.length;
|
|
2039
|
+
} else {
|
|
2040
|
+
accumulatedText += text;
|
|
2041
|
+
if (options.responseFormat?.type !== "json") {
|
|
2042
|
+
if (!textPartId) {
|
|
2043
|
+
textPartId = (0, import_provider_utils.generateId)();
|
|
2044
|
+
controller.enqueue({
|
|
2045
|
+
type: "text-start",
|
|
2046
|
+
id: textPartId
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
controller.enqueue({
|
|
2050
|
+
type: "text-delta",
|
|
2051
|
+
id: textPartId,
|
|
2052
|
+
delta: text
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
} else if (message.type === "user") {
|
|
2058
|
+
if (!message.message?.content) {
|
|
2059
|
+
this.logger.warn(
|
|
2060
|
+
`[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
|
|
2061
|
+
);
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
2064
|
+
if (textPartId) {
|
|
2065
|
+
const closedTextId = textPartId;
|
|
2066
|
+
controller.enqueue({
|
|
2067
|
+
type: "text-end",
|
|
2068
|
+
id: closedTextId
|
|
2069
|
+
});
|
|
2070
|
+
textPartId = void 0;
|
|
2071
|
+
for (const [blockIndex, blockTextId] of textBlocksByIndex) {
|
|
2072
|
+
if (blockTextId === closedTextId) {
|
|
2073
|
+
textBlocksByIndex.delete(blockIndex);
|
|
2074
|
+
break;
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
accumulatedText = "";
|
|
2078
|
+
streamedTextLength = 0;
|
|
2079
|
+
this.logger.debug("[claude-code] Closed text part due to user message");
|
|
2080
|
+
}
|
|
2081
|
+
const sdkParentToolUseIdForResults = message.parent_tool_use_id;
|
|
2082
|
+
const content = message.message.content;
|
|
2083
|
+
for (const result of this.extractToolResults(content)) {
|
|
2084
|
+
let state = toolStates.get(result.id);
|
|
2085
|
+
const toolName = result.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2086
|
+
this.logger.debug(
|
|
2087
|
+
`[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
|
|
2088
|
+
);
|
|
2089
|
+
if (!state) {
|
|
2090
|
+
this.logger.warn(
|
|
2091
|
+
`[claude-code] Received tool result for unknown tool ID: ${result.id}`
|
|
2092
|
+
);
|
|
2093
|
+
const resolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
|
|
2094
|
+
state = {
|
|
2095
|
+
name: toolName,
|
|
2096
|
+
inputStarted: false,
|
|
2097
|
+
inputClosed: false,
|
|
2098
|
+
callEmitted: false,
|
|
2099
|
+
parentToolCallId: resolvedParentId
|
|
2100
|
+
};
|
|
2101
|
+
toolStates.set(result.id, state);
|
|
2102
|
+
if (!state.inputStarted) {
|
|
2103
|
+
controller.enqueue({
|
|
2104
|
+
type: "tool-input-start",
|
|
2105
|
+
id: result.id,
|
|
2106
|
+
toolName,
|
|
2107
|
+
providerExecuted: true,
|
|
2108
|
+
dynamic: true,
|
|
2109
|
+
// V3 field: indicates tool is provider-defined
|
|
2110
|
+
providerMetadata: {
|
|
2111
|
+
"claude-code": {
|
|
2112
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
state.inputStarted = true;
|
|
2117
|
+
}
|
|
2118
|
+
if (!state.inputClosed) {
|
|
2119
|
+
controller.enqueue({
|
|
2120
|
+
type: "tool-input-end",
|
|
2121
|
+
id: result.id
|
|
2122
|
+
});
|
|
2123
|
+
state.inputClosed = true;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
state.name = toolName;
|
|
2127
|
+
const normalizedResult = this.normalizeToolResult(result.result);
|
|
2128
|
+
const rawResult = typeof result.result === "string" ? result.result : (() => {
|
|
2129
|
+
try {
|
|
2130
|
+
return JSON.stringify(result.result);
|
|
2131
|
+
} catch {
|
|
2132
|
+
return String(result.result);
|
|
2133
|
+
}
|
|
2134
|
+
})();
|
|
2135
|
+
const maxToolResultSize = this.settings.maxToolResultSize;
|
|
2136
|
+
const truncatedResult = truncateToolResultForStream(
|
|
2137
|
+
normalizedResult,
|
|
2138
|
+
maxToolResultSize
|
|
2139
|
+
);
|
|
2140
|
+
const truncatedRawResult = truncateToolResultForStream(
|
|
2141
|
+
rawResult,
|
|
2142
|
+
maxToolResultSize
|
|
2143
|
+
);
|
|
2144
|
+
const rawResultTruncated = truncatedRawResult !== rawResult;
|
|
2145
|
+
emitToolCall(result.id, state);
|
|
2146
|
+
if (toolName === "Task") {
|
|
2147
|
+
activeTaskTools.delete(result.id);
|
|
2148
|
+
}
|
|
2149
|
+
controller.enqueue({
|
|
2150
|
+
type: "tool-result",
|
|
2151
|
+
toolCallId: result.id,
|
|
2152
|
+
toolName,
|
|
2153
|
+
result: truncatedResult,
|
|
2154
|
+
isError: result.isError,
|
|
2155
|
+
providerExecuted: true,
|
|
2156
|
+
dynamic: true,
|
|
2157
|
+
// V3 field: indicates tool is provider-defined
|
|
2158
|
+
providerMetadata: {
|
|
2159
|
+
"claude-code": {
|
|
2160
|
+
// rawResult preserves the original CLI output string before JSON parsing.
|
|
2161
|
+
// Use this when you need the exact string returned by the tool, especially
|
|
2162
|
+
// if the `result` field has been parsed/normalized and you need the original format.
|
|
2163
|
+
rawResult: truncatedRawResult,
|
|
2164
|
+
rawResultTruncated,
|
|
2165
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
for (const error of this.extractToolErrors(content)) {
|
|
2171
|
+
let state = toolStates.get(error.id);
|
|
2172
|
+
const toolName = error.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2173
|
+
this.logger.debug(
|
|
2174
|
+
`[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
|
|
2175
|
+
);
|
|
2176
|
+
if (!state) {
|
|
2177
|
+
this.logger.warn(
|
|
2178
|
+
`[claude-code] Received tool error for unknown tool ID: ${error.id}`
|
|
2179
|
+
);
|
|
2180
|
+
const errorResolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
|
|
2181
|
+
state = {
|
|
2182
|
+
name: toolName,
|
|
2183
|
+
inputStarted: true,
|
|
2184
|
+
inputClosed: true,
|
|
2185
|
+
callEmitted: false,
|
|
2186
|
+
parentToolCallId: errorResolvedParentId
|
|
2187
|
+
};
|
|
2188
|
+
toolStates.set(error.id, state);
|
|
2189
|
+
}
|
|
2190
|
+
emitToolCall(error.id, state);
|
|
2191
|
+
if (toolName === "Task") {
|
|
2192
|
+
activeTaskTools.delete(error.id);
|
|
2193
|
+
}
|
|
2194
|
+
const rawError = typeof error.error === "string" ? error.error : typeof error.error === "object" && error.error !== null ? (() => {
|
|
2195
|
+
try {
|
|
2196
|
+
return JSON.stringify(error.error);
|
|
2197
|
+
} catch {
|
|
2198
|
+
return String(error.error);
|
|
2199
|
+
}
|
|
2200
|
+
})() : String(error.error);
|
|
2201
|
+
controller.enqueue({
|
|
2202
|
+
type: "tool-error",
|
|
2203
|
+
toolCallId: error.id,
|
|
2204
|
+
toolName,
|
|
2205
|
+
error: rawError,
|
|
2206
|
+
providerExecuted: true,
|
|
2207
|
+
dynamic: true,
|
|
2208
|
+
// V3 field: indicates tool is provider-defined
|
|
2209
|
+
providerMetadata: {
|
|
2210
|
+
"claude-code": {
|
|
2211
|
+
rawError,
|
|
2212
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
});
|
|
2216
|
+
}
|
|
2217
|
+
} else if (message.type === "result") {
|
|
2218
|
+
done();
|
|
2219
|
+
if ("is_error" in message && message.is_error === true) {
|
|
2220
|
+
const errorMessage = "result" in message && typeof message.result === "string" ? message.result : "Claude Code CLI returned an error";
|
|
2221
|
+
throw Object.assign(new Error(errorMessage), { exitCode: 1 });
|
|
2222
|
+
}
|
|
2223
|
+
if (message.subtype === "error_max_structured_output_retries") {
|
|
2224
|
+
throw new Error(
|
|
2225
|
+
"Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
|
|
2226
|
+
);
|
|
2227
|
+
}
|
|
2228
|
+
this.logger.info(
|
|
2229
|
+
`[claude-code] Stream completed - Session: ${message.session_id}, Cost: $${message.total_cost_usd?.toFixed(4) ?? "N/A"}, Duration: ${message.duration_ms ?? "N/A"}ms`
|
|
2230
|
+
);
|
|
2231
|
+
if ("usage" in message) {
|
|
2232
|
+
usage = convertClaudeCodeUsage(message.usage);
|
|
2233
|
+
this.logger.debug(
|
|
2234
|
+
`[claude-code] Stream token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
|
|
2235
|
+
);
|
|
2236
|
+
}
|
|
2237
|
+
const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
|
|
2238
|
+
const finishReason = mapClaudeCodeFinishReason(
|
|
2239
|
+
message.subtype,
|
|
2240
|
+
stopReason
|
|
2241
|
+
);
|
|
2242
|
+
this.logger.debug(`[claude-code] Stream finish reason: ${finishReason.unified}`);
|
|
2243
|
+
this.setSessionId(message.session_id);
|
|
2244
|
+
const structuredOutput = "structured_output" in message ? message.structured_output : void 0;
|
|
2245
|
+
const alreadyStreamedJson = hasStreamedJson && options.responseFormat?.type === "json" && hasReceivedStreamEvents;
|
|
2246
|
+
if (alreadyStreamedJson) {
|
|
2247
|
+
if (textPartId) {
|
|
2248
|
+
controller.enqueue({
|
|
2249
|
+
type: "text-end",
|
|
2250
|
+
id: textPartId
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2253
|
+
} else if (structuredOutput !== void 0) {
|
|
2254
|
+
const jsonTextId = (0, import_provider_utils.generateId)();
|
|
2255
|
+
const jsonText = JSON.stringify(structuredOutput);
|
|
2256
|
+
controller.enqueue({
|
|
2257
|
+
type: "text-start",
|
|
2258
|
+
id: jsonTextId
|
|
2259
|
+
});
|
|
2260
|
+
controller.enqueue({
|
|
2261
|
+
type: "text-delta",
|
|
2262
|
+
id: jsonTextId,
|
|
2263
|
+
delta: jsonText
|
|
2264
|
+
});
|
|
2265
|
+
controller.enqueue({
|
|
2266
|
+
type: "text-end",
|
|
2267
|
+
id: jsonTextId
|
|
2268
|
+
});
|
|
2269
|
+
} else if (textPartId) {
|
|
2270
|
+
controller.enqueue({
|
|
2271
|
+
type: "text-end",
|
|
2272
|
+
id: textPartId
|
|
2273
|
+
});
|
|
2274
|
+
} else if (accumulatedText && !textStreamedViaContentBlock) {
|
|
2275
|
+
const fallbackTextId = (0, import_provider_utils.generateId)();
|
|
2276
|
+
controller.enqueue({
|
|
2277
|
+
type: "text-start",
|
|
2278
|
+
id: fallbackTextId
|
|
2279
|
+
});
|
|
2280
|
+
controller.enqueue({
|
|
2281
|
+
type: "text-delta",
|
|
2282
|
+
id: fallbackTextId,
|
|
2283
|
+
delta: accumulatedText
|
|
2284
|
+
});
|
|
2285
|
+
controller.enqueue({
|
|
2286
|
+
type: "text-end",
|
|
2287
|
+
id: fallbackTextId
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
finalizeToolCalls();
|
|
2291
|
+
const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
|
|
2292
|
+
controller.enqueue({
|
|
2293
|
+
type: "finish",
|
|
2294
|
+
finishReason,
|
|
2295
|
+
usage,
|
|
2296
|
+
providerMetadata: {
|
|
2297
|
+
"claude-code": {
|
|
2298
|
+
sessionId: message.session_id,
|
|
2299
|
+
...message.total_cost_usd !== void 0 && {
|
|
2300
|
+
costUsd: message.total_cost_usd
|
|
2301
|
+
},
|
|
2302
|
+
...message.duration_ms !== void 0 && { durationMs: message.duration_ms },
|
|
2303
|
+
...message.modelUsage !== void 0 && {
|
|
2304
|
+
modelUsage: message.modelUsage
|
|
2305
|
+
},
|
|
2306
|
+
// JSON validation warnings are collected during streaming and included
|
|
2307
|
+
// in providerMetadata since the AI SDK's finish event doesn't support
|
|
2308
|
+
// a top-level warnings field (unlike stream-start which was already emitted)
|
|
2309
|
+
...streamWarnings.length > 0 && {
|
|
2310
|
+
warnings: warningsJson
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
controller.close();
|
|
2316
|
+
return;
|
|
2317
|
+
} else if (message.type === "system" && message.subtype === "init") {
|
|
2318
|
+
this.setSessionId(message.session_id);
|
|
2319
|
+
this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
|
|
2320
|
+
controller.enqueue({
|
|
2321
|
+
type: "response-metadata",
|
|
2322
|
+
id: message.session_id,
|
|
2323
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
2324
|
+
modelId: this.modelId
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
finalizeToolCalls();
|
|
2329
|
+
this.logger.debug("[claude-code] Stream finalized, closing stream");
|
|
2330
|
+
controller.close();
|
|
2331
|
+
} catch (error) {
|
|
2332
|
+
done();
|
|
2333
|
+
this.logger.debug(
|
|
2334
|
+
`[claude-code] Error during doStream: ${error instanceof Error ? error.message : String(error)}`
|
|
2335
|
+
);
|
|
2336
|
+
if (isClaudeCodeTruncationError(error, accumulatedText)) {
|
|
2337
|
+
this.logger.warn(
|
|
2338
|
+
`[claude-code] Detected truncated stream response, returning ${accumulatedText.length} characters of buffered text`
|
|
2339
|
+
);
|
|
2340
|
+
const truncationWarning = {
|
|
2341
|
+
type: "other",
|
|
2342
|
+
message: CLAUDE_CODE_TRUNCATION_WARNING
|
|
2343
|
+
};
|
|
2344
|
+
streamWarnings.push(truncationWarning);
|
|
2345
|
+
if (textPartId) {
|
|
2346
|
+
controller.enqueue({
|
|
2347
|
+
type: "text-end",
|
|
2348
|
+
id: textPartId
|
|
2349
|
+
});
|
|
2350
|
+
} else if (accumulatedText && !textStreamedViaContentBlock) {
|
|
2351
|
+
const fallbackTextId = (0, import_provider_utils.generateId)();
|
|
2352
|
+
controller.enqueue({
|
|
2353
|
+
type: "text-start",
|
|
2354
|
+
id: fallbackTextId
|
|
2355
|
+
});
|
|
2356
|
+
controller.enqueue({
|
|
2357
|
+
type: "text-delta",
|
|
2358
|
+
id: fallbackTextId,
|
|
2359
|
+
delta: accumulatedText
|
|
2360
|
+
});
|
|
2361
|
+
controller.enqueue({
|
|
2362
|
+
type: "text-end",
|
|
2363
|
+
id: fallbackTextId
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
finalizeToolCalls();
|
|
2367
|
+
const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
|
|
2368
|
+
controller.enqueue({
|
|
2369
|
+
type: "finish",
|
|
2370
|
+
finishReason: { unified: "length", raw: "truncation" },
|
|
2371
|
+
usage,
|
|
2372
|
+
providerMetadata: {
|
|
2373
|
+
"claude-code": {
|
|
2374
|
+
...this.sessionId !== void 0 && { sessionId: this.sessionId },
|
|
2375
|
+
truncated: true,
|
|
2376
|
+
...streamWarnings.length > 0 && {
|
|
2377
|
+
warnings: warningsJson
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
});
|
|
2382
|
+
controller.close();
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2385
|
+
finalizeToolCalls();
|
|
2386
|
+
let errorToEmit;
|
|
2387
|
+
if (isAbortError(error)) {
|
|
2388
|
+
errorToEmit = options.abortSignal?.aborted ? options.abortSignal.reason : error;
|
|
2389
|
+
} else {
|
|
2390
|
+
errorToEmit = this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
|
|
2391
|
+
}
|
|
2392
|
+
controller.enqueue({
|
|
2393
|
+
type: "error",
|
|
2394
|
+
error: errorToEmit
|
|
2395
|
+
});
|
|
2396
|
+
controller.close();
|
|
2397
|
+
} finally {
|
|
2398
|
+
if (options.abortSignal && abortListener) {
|
|
2399
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
},
|
|
2403
|
+
cancel: () => {
|
|
2404
|
+
if (options.abortSignal && abortListener) {
|
|
2405
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
return {
|
|
2410
|
+
stream,
|
|
2411
|
+
request: {
|
|
2412
|
+
body: messagesPrompt
|
|
2413
|
+
}
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
serializeWarningsForMetadata(warnings) {
|
|
2417
|
+
const result = warnings.map((w) => {
|
|
2418
|
+
const base = { type: w.type };
|
|
2419
|
+
if ("message" in w) {
|
|
2420
|
+
const m = w.message;
|
|
2421
|
+
if (m !== void 0) base.message = String(m);
|
|
2422
|
+
}
|
|
2423
|
+
if (w.type === "unsupported" || w.type === "compatibility") {
|
|
2424
|
+
const feature = w.feature;
|
|
2425
|
+
if (feature !== void 0) base.feature = String(feature);
|
|
2426
|
+
if ("details" in w) {
|
|
2427
|
+
const d = w.details;
|
|
2428
|
+
if (d !== void 0) base.details = String(d);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
return base;
|
|
2432
|
+
});
|
|
2433
|
+
return result;
|
|
2434
|
+
}
|
|
2435
|
+
};
|
|
2436
|
+
|
|
2437
|
+
// docs/src/claude-code-provider.ts
|
|
2438
|
+
function createClaudeCode(options = {}) {
|
|
2439
|
+
const logger = getLogger(options.defaultSettings?.logger);
|
|
2440
|
+
if (options.defaultSettings) {
|
|
2441
|
+
const validation = validateSettings(options.defaultSettings);
|
|
2442
|
+
if (!validation.valid) {
|
|
2443
|
+
throw new Error(`Invalid default settings: ${validation.errors.join(", ")}`);
|
|
2444
|
+
}
|
|
2445
|
+
if (validation.warnings.length > 0) {
|
|
2446
|
+
validation.warnings.forEach((warning) => logger.warn(`Claude Code Provider: ${warning}`));
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
const createModel = (modelId, settings = {}) => {
|
|
2450
|
+
const mergedSettings = {
|
|
2451
|
+
...options.defaultSettings,
|
|
2452
|
+
...settings
|
|
2453
|
+
};
|
|
2454
|
+
const validation = validateSettings(mergedSettings);
|
|
2455
|
+
if (!validation.valid) {
|
|
2456
|
+
throw new Error(`Invalid settings: ${validation.errors.join(", ")}`);
|
|
2457
|
+
}
|
|
2458
|
+
return new ClaudeCodeLanguageModel({
|
|
2459
|
+
id: modelId,
|
|
2460
|
+
settings: mergedSettings,
|
|
2461
|
+
settingsValidationWarnings: validation.warnings
|
|
2462
|
+
});
|
|
2463
|
+
};
|
|
2464
|
+
const provider = function(modelId, settings) {
|
|
2465
|
+
if (new.target) {
|
|
2466
|
+
throw new Error("The Claude Code model function cannot be called with the new keyword.");
|
|
2467
|
+
}
|
|
2468
|
+
return createModel(modelId, settings);
|
|
2469
|
+
};
|
|
2470
|
+
provider.languageModel = createModel;
|
|
2471
|
+
provider.chat = createModel;
|
|
2472
|
+
provider.specificationVersion = "v3";
|
|
2473
|
+
provider.embeddingModel = (modelId) => {
|
|
2474
|
+
throw new import_provider3.NoSuchModelError({
|
|
2475
|
+
modelId,
|
|
2476
|
+
modelType: "embeddingModel"
|
|
2477
|
+
});
|
|
2478
|
+
};
|
|
2479
|
+
provider.imageModel = (modelId) => {
|
|
2480
|
+
throw new import_provider3.NoSuchModelError({
|
|
2481
|
+
modelId,
|
|
2482
|
+
modelType: "imageModel"
|
|
2483
|
+
});
|
|
2484
|
+
};
|
|
2485
|
+
return provider;
|
|
2486
|
+
}
|
|
2487
|
+
var claudeCode = createClaudeCode();
|
|
2488
|
+
|
|
2489
|
+
// docs/src/index.ts
|
|
2490
|
+
var import_claude_agent_sdk3 = require("@anthropic-ai/claude-agent-sdk");
|
|
2491
|
+
|
|
2492
|
+
// docs/src/mcp-helpers.ts
|
|
2493
|
+
var import_claude_agent_sdk2 = require("@anthropic-ai/claude-agent-sdk");
|
|
2494
|
+
var import_zod2 = require("zod");
|
|
2495
|
+
function createCustomMcpServer(config) {
|
|
2496
|
+
const defs = Object.entries(config.tools).map(
|
|
2497
|
+
([name, def]) => (0, import_claude_agent_sdk2.tool)(
|
|
2498
|
+
name,
|
|
2499
|
+
def.description,
|
|
2500
|
+
def.inputSchema.shape,
|
|
2501
|
+
(args, extra) => def.handler(args, extra),
|
|
2502
|
+
def.annotations ? { annotations: def.annotations } : void 0
|
|
2503
|
+
)
|
|
2504
|
+
);
|
|
2505
|
+
return (0, import_claude_agent_sdk2.createSdkMcpServer)({ name: config.name, version: config.version, tools: defs });
|
|
2506
|
+
}
|
|
2507
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2508
|
+
0 && (module.exports = {
|
|
2509
|
+
ClaudeCodeLanguageModel,
|
|
2510
|
+
claudeCode,
|
|
2511
|
+
createAPICallError,
|
|
2512
|
+
createAuthenticationError,
|
|
2513
|
+
createClaudeCode,
|
|
2514
|
+
createCustomMcpServer,
|
|
2515
|
+
createSdkMcpServer,
|
|
2516
|
+
createTimeoutError,
|
|
2517
|
+
getErrorMetadata,
|
|
2518
|
+
isAuthenticationError,
|
|
2519
|
+
isTimeoutError,
|
|
2520
|
+
tool
|
|
2521
|
+
});
|
|
2522
|
+
//# sourceMappingURL=index.cjs.map
|