@jsonstudio/rcc 0.90.141 → 0.90.181
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/dist/build-info.js +2 -2
- package/dist/cli/commands/config.js +5 -5
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/init/basic.js +30 -25
- package/dist/cli/commands/init/basic.js.map +1 -1
- package/dist/cli/commands/init/interactive.js +6 -1
- package/dist/cli/commands/init/interactive.js.map +1 -1
- package/dist/cli/commands/init/workflows.js +7 -7
- package/dist/cli/commands/init/workflows.js.map +1 -1
- package/dist/cli/commands/init.js +45 -104
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/config/bootstrap-provider-templates.d.ts +4 -0
- package/dist/cli/config/bootstrap-provider-templates.js +107 -0
- package/dist/cli/config/bootstrap-provider-templates.js.map +1 -0
- package/dist/cli/config/init-config.js +37 -102
- package/dist/cli/config/init-config.js.map +1 -1
- package/dist/cli/config/init-provider-catalog.d.ts +30 -0
- package/dist/cli/config/init-provider-catalog.js +381 -265
- package/dist/cli/config/init-provider-catalog.js.map +1 -1
- package/dist/cli/config/init-v2-builder.d.ts +20 -0
- package/dist/cli/config/init-v2-builder.js +150 -0
- package/dist/cli/config/init-v2-builder.js.map +1 -0
- package/dist/commands/provider-update.js +163 -173
- package/dist/commands/provider-update.js.map +1 -1
- package/dist/provider-sdk/provider-add-template.d.ts +17 -0
- package/dist/provider-sdk/provider-add-template.js +110 -0
- package/dist/provider-sdk/provider-add-template.js.map +1 -0
- package/dist/provider-sdk/provider-inspect.d.ts +37 -0
- package/dist/provider-sdk/provider-inspect.js +166 -0
- package/dist/provider-sdk/provider-inspect.js.map +1 -0
- package/dist/provider-sdk/provider-runtime-inference.d.ts +14 -0
- package/dist/provider-sdk/provider-runtime-inference.js +226 -0
- package/dist/provider-sdk/provider-runtime-inference.js.map +1 -0
- package/dist/provider-sdk/vercel-ai-doctor.d.ts +35 -0
- package/dist/provider-sdk/vercel-ai-doctor.js +150 -0
- package/dist/provider-sdk/vercel-ai-doctor.js.map +1 -0
- package/dist/providers/core/api/provider-types.d.ts +2 -0
- package/dist/providers/core/api/provider-types.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.d.ts +2 -0
- package/dist/providers/core/runtime/http-request-executor.js +39 -40
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +5 -0
- package/dist/providers/core/runtime/http-transport-provider.js +53 -6
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/openai-responses-sdk-transport.d.ts +7 -0
- package/dist/providers/core/runtime/openai-responses-sdk-transport.js +142 -0
- package/dist/providers/core/runtime/openai-responses-sdk-transport.js.map +1 -0
- package/dist/providers/core/runtime/provider-factory.js +3 -0
- package/dist/providers/core/runtime/provider-factory.js.map +1 -1
- package/dist/providers/core/runtime/provider-request-executor-deps-factory.d.ts +2 -1
- package/dist/providers/core/runtime/provider-request-executor-deps-factory.js +1 -0
- package/dist/providers/core/runtime/provider-request-executor-deps-factory.js.map +1 -1
- package/dist/providers/core/runtime/provider-startup-tasks.d.ts +1 -0
- package/dist/providers/core/runtime/provider-startup-tasks.js +12 -0
- package/dist/providers/core/runtime/provider-startup-tasks.js.map +1 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/anthropic-sdk-transport.d.ts +9 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/anthropic-sdk-transport.js +642 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/anthropic-sdk-transport.js.map +1 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/openai-sdk-transport.d.ts +10 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/openai-sdk-transport.js +539 -0
- package/dist/providers/core/runtime/vercel-ai-sdk/openai-sdk-transport.js.map +1 -0
- package/dist/providers/profile/provider-profile-loader.js +12 -1
- package/dist/providers/profile/provider-profile-loader.js.map +1 -1
- package/dist/providers/profile/provider-profile.d.ts +2 -0
- package/dist/server/handlers/chat-handler.js +4 -2
- package/dist/server/handlers/chat-handler.js.map +1 -1
- package/dist/server/handlers/config-admin-handler.js +75 -67
- package/dist/server/handlers/config-admin-handler.js.map +1 -1
- package/dist/server/handlers/handler-response-utils.js +126 -1
- package/dist/server/handlers/handler-response-utils.js.map +1 -1
- package/dist/server/handlers/handler-utils.d.ts +1 -1
- package/dist/server/handlers/handler-utils.js +5 -2
- package/dist/server/handlers/handler-utils.js.map +1 -1
- package/dist/server/handlers/messages-handler.js +4 -2
- package/dist/server/handlers/messages-handler.js.map +1 -1
- package/dist/server/handlers/responses-handler.js +4 -2
- package/dist/server/handlers/responses-handler.js.map +1 -1
- package/dist/server/runtime/http-server/antigravity-startup-tasks.d.ts +30 -0
- package/dist/server/runtime/http-server/antigravity-startup-tasks.js +108 -0
- package/dist/server/runtime/http-server/antigravity-startup-tasks.js.map +1 -0
- package/dist/server/runtime/http-server/executor/provider-response-converter.js +5 -0
- package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
- package/dist/server/runtime/http-server/executor-response.js +7 -1
- package/dist/server/runtime/http-server/executor-response.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-bootstrap.js +3 -0
- package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
- package/dist/server/runtime/http-server/http-server-runtime-providers.js +3 -72
- package/dist/server/runtime/http-server/http-server-runtime-providers.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.js +19 -8
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.js +185 -25
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/utils/finish-reason.d.ts +2 -0
- package/dist/server/utils/finish-reason.js +75 -0
- package/dist/server/utils/finish-reason.js.map +1 -0
- package/docs/provider-analysis.md +331 -0
- package/package.json +5 -2
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { AnthropicMessagesLanguageModel } from '@ai-sdk/anthropic/internal';
|
|
3
|
+
import { stripInternalKeysDeep } from '../../../../utils/strip-internal-keys.js';
|
|
4
|
+
function asRecord(value) {
|
|
5
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
6
|
+
? value
|
|
7
|
+
: {};
|
|
8
|
+
}
|
|
9
|
+
function asArray(value) {
|
|
10
|
+
return Array.isArray(value) ? value : [];
|
|
11
|
+
}
|
|
12
|
+
function pickString(value) {
|
|
13
|
+
if (typeof value !== 'string') {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
return trimmed || undefined;
|
|
18
|
+
}
|
|
19
|
+
function pickNumber(value) {
|
|
20
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
function pickBoolean(value) {
|
|
26
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
27
|
+
}
|
|
28
|
+
function normalizeToolChoice(value) {
|
|
29
|
+
if (typeof value === 'string') {
|
|
30
|
+
const normalized = value.trim().toLowerCase();
|
|
31
|
+
if (!normalized) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
if (normalized === 'auto') {
|
|
35
|
+
return { type: 'auto' };
|
|
36
|
+
}
|
|
37
|
+
if (normalized === 'none') {
|
|
38
|
+
return { type: 'none' };
|
|
39
|
+
}
|
|
40
|
+
if (normalized === 'any' || normalized === 'required') {
|
|
41
|
+
return { type: 'required' };
|
|
42
|
+
}
|
|
43
|
+
return { type: 'tool', toolName: value.trim() };
|
|
44
|
+
}
|
|
45
|
+
const record = asRecord(value);
|
|
46
|
+
const type = pickString(record.type)?.toLowerCase();
|
|
47
|
+
if (!type) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (type === 'auto') {
|
|
51
|
+
return { type: 'auto' };
|
|
52
|
+
}
|
|
53
|
+
if (type === 'none') {
|
|
54
|
+
return { type: 'none' };
|
|
55
|
+
}
|
|
56
|
+
if (type === 'any' || type === 'required') {
|
|
57
|
+
return { type: 'required' };
|
|
58
|
+
}
|
|
59
|
+
if (type === 'tool') {
|
|
60
|
+
const toolName = pickString(record.name ?? record.toolName);
|
|
61
|
+
return toolName ? { type: 'tool', toolName } : undefined;
|
|
62
|
+
}
|
|
63
|
+
return { type: 'tool', toolName: type };
|
|
64
|
+
}
|
|
65
|
+
function buildToolNameIndex(messages) {
|
|
66
|
+
const index = new Map();
|
|
67
|
+
for (const message of messages) {
|
|
68
|
+
const bag = asRecord(message);
|
|
69
|
+
for (const block of asArray(bag.content)) {
|
|
70
|
+
const item = asRecord(block);
|
|
71
|
+
const type = pickString(item.type)?.toLowerCase();
|
|
72
|
+
if (type !== 'tool_use' && type !== 'server_tool_use') {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const toolId = pickString(item.id);
|
|
76
|
+
const toolName = pickString(item.name);
|
|
77
|
+
if (toolId && toolName) {
|
|
78
|
+
index.set(toolId, toolName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return index;
|
|
83
|
+
}
|
|
84
|
+
function toDataContent(source) {
|
|
85
|
+
const sourceType = pickString(source.type)?.toLowerCase();
|
|
86
|
+
if (!sourceType) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const mediaType = pickString(source.media_type ?? source.mediaType) ?? 'application/octet-stream';
|
|
90
|
+
const filename = pickString(source.filename ?? source.name);
|
|
91
|
+
if (sourceType === 'base64') {
|
|
92
|
+
const data = pickString(source.data);
|
|
93
|
+
if (!data) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return { data, mediaType, ...(filename ? { filename } : {}) };
|
|
97
|
+
}
|
|
98
|
+
if (sourceType === 'url') {
|
|
99
|
+
const url = pickString(source.url);
|
|
100
|
+
if (!url) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return { data: new URL(url), mediaType, ...(filename ? { filename } : {}) };
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
function toFilePart(block) {
|
|
108
|
+
const source = asRecord(block.source);
|
|
109
|
+
const normalized = toDataContent(source);
|
|
110
|
+
if (!normalized) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
type: 'file',
|
|
115
|
+
data: normalized.data,
|
|
116
|
+
mediaType: normalized.mediaType,
|
|
117
|
+
...(normalized.filename ? { filename: normalized.filename } : {})
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function toTextPart(text) {
|
|
121
|
+
return { type: 'text', text };
|
|
122
|
+
}
|
|
123
|
+
function convertToolResultOutput(content, isError) {
|
|
124
|
+
if (typeof content === 'string') {
|
|
125
|
+
return isError
|
|
126
|
+
? { type: 'error-text', value: content }
|
|
127
|
+
: { type: 'text', value: content };
|
|
128
|
+
}
|
|
129
|
+
if (Array.isArray(content)) {
|
|
130
|
+
const value = [];
|
|
131
|
+
for (const block of content) {
|
|
132
|
+
const item = asRecord(block);
|
|
133
|
+
const type = pickString(item.type)?.toLowerCase();
|
|
134
|
+
if (type === 'text') {
|
|
135
|
+
const text = pickString(item.text);
|
|
136
|
+
if (text) {
|
|
137
|
+
value.push({ type: 'text', text });
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (type === 'image') {
|
|
142
|
+
const source = toDataContent(asRecord(item.source));
|
|
143
|
+
if (!source) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (typeof source.data === 'string') {
|
|
147
|
+
value.push({ type: 'image-data', data: source.data, mediaType: source.mediaType });
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
value.push({ type: 'image-url', url: source.data.toString() });
|
|
151
|
+
}
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (type === 'document') {
|
|
155
|
+
const source = toDataContent(asRecord(item.source));
|
|
156
|
+
if (!source) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (typeof source.data === 'string') {
|
|
160
|
+
value.push({
|
|
161
|
+
type: 'file-data',
|
|
162
|
+
data: source.data,
|
|
163
|
+
mediaType: source.mediaType,
|
|
164
|
+
...(source.filename ? { filename: source.filename } : {})
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
value.push({ type: 'file-url', url: source.data.toString() });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (value.length > 0) {
|
|
173
|
+
return { type: 'content', value: value };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (content && typeof content === 'object') {
|
|
177
|
+
return isError
|
|
178
|
+
? { type: 'error-json', value: content }
|
|
179
|
+
: { type: 'json', value: content };
|
|
180
|
+
}
|
|
181
|
+
const fallback = content == null ? '' : String(content);
|
|
182
|
+
return isError
|
|
183
|
+
? { type: 'error-text', value: fallback }
|
|
184
|
+
: { type: 'text', value: fallback };
|
|
185
|
+
}
|
|
186
|
+
function convertMessageContent(role, content, toolNameIndex) {
|
|
187
|
+
if (role === 'system') {
|
|
188
|
+
if (typeof content === 'string') {
|
|
189
|
+
return [{ role: 'system', content }];
|
|
190
|
+
}
|
|
191
|
+
const parts = asArray(content)
|
|
192
|
+
.map((block) => pickString(asRecord(block).text))
|
|
193
|
+
.filter((value) => Boolean(value));
|
|
194
|
+
return parts.length ? [{ role: 'system', content: parts.join('\n') }] : [];
|
|
195
|
+
}
|
|
196
|
+
const blocks = typeof content === 'string' ? [{ type: 'text', text: content }] : asArray(content);
|
|
197
|
+
const assistantParts = [];
|
|
198
|
+
const userParts = [];
|
|
199
|
+
const toolParts = [];
|
|
200
|
+
for (const block of blocks) {
|
|
201
|
+
const item = asRecord(block);
|
|
202
|
+
const type = pickString(item.type)?.toLowerCase();
|
|
203
|
+
if (!type) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (type === 'text') {
|
|
207
|
+
const text = pickString(item.text);
|
|
208
|
+
if (!text) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (role === 'assistant') {
|
|
212
|
+
assistantParts.push({ type: 'text', text });
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
userParts.push(toTextPart(text));
|
|
216
|
+
}
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (type === 'image' || type === 'document') {
|
|
220
|
+
const filePart = toFilePart(item);
|
|
221
|
+
if (!filePart) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (role === 'assistant') {
|
|
225
|
+
assistantParts.push(filePart);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
userParts.push(filePart);
|
|
229
|
+
}
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (type === 'thinking') {
|
|
233
|
+
if (role === 'assistant') {
|
|
234
|
+
assistantParts.push({
|
|
235
|
+
type: 'reasoning',
|
|
236
|
+
text: pickString(item.thinking) ?? '',
|
|
237
|
+
providerOptions: item.signature
|
|
238
|
+
? { anthropic: { signature: item.signature } }
|
|
239
|
+
: undefined
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (type === 'redacted_thinking') {
|
|
245
|
+
if (role === 'assistant') {
|
|
246
|
+
assistantParts.push({
|
|
247
|
+
type: 'reasoning',
|
|
248
|
+
text: '',
|
|
249
|
+
providerOptions: { anthropic: { redactedData: pickString(item.data) ?? '' } }
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (type === 'tool_use' || type === 'server_tool_use') {
|
|
255
|
+
const toolCallId = pickString(item.id);
|
|
256
|
+
const toolName = pickString(item.name);
|
|
257
|
+
if (!toolCallId || !toolName) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
assistantParts.push({
|
|
261
|
+
type: 'tool-call',
|
|
262
|
+
toolCallId,
|
|
263
|
+
toolName,
|
|
264
|
+
input: item.input ?? {},
|
|
265
|
+
providerExecuted: pickBoolean(item.provider_executed ?? item.providerExecuted)
|
|
266
|
+
});
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (type === 'tool_result') {
|
|
270
|
+
const toolCallId = pickString(item.tool_use_id ?? item.toolCallId);
|
|
271
|
+
if (!toolCallId) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
toolParts.push({
|
|
275
|
+
type: 'tool-result',
|
|
276
|
+
toolCallId,
|
|
277
|
+
toolName: toolNameIndex.get(toolCallId) ?? 'tool',
|
|
278
|
+
output: convertToolResultOutput(item.content, item.is_error === true)
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const output = [];
|
|
283
|
+
if (toolParts.length > 0) {
|
|
284
|
+
output.push({ role: 'tool', content: toolParts });
|
|
285
|
+
}
|
|
286
|
+
if (role === 'assistant' && assistantParts.length > 0) {
|
|
287
|
+
output.push({ role: 'assistant', content: assistantParts });
|
|
288
|
+
}
|
|
289
|
+
if (role !== 'assistant' && userParts.length > 0) {
|
|
290
|
+
output.push({ role: 'user', content: userParts });
|
|
291
|
+
}
|
|
292
|
+
return output;
|
|
293
|
+
}
|
|
294
|
+
function convertPrompt(rawBody) {
|
|
295
|
+
const prompt = [];
|
|
296
|
+
const toolNameIndex = buildToolNameIndex(asArray(rawBody.messages));
|
|
297
|
+
const system = rawBody.system;
|
|
298
|
+
if (typeof system === 'string') {
|
|
299
|
+
prompt.push({ role: 'system', content: system });
|
|
300
|
+
}
|
|
301
|
+
else if (Array.isArray(system)) {
|
|
302
|
+
const text = system
|
|
303
|
+
.map((block) => pickString(asRecord(block).text))
|
|
304
|
+
.filter((value) => Boolean(value))
|
|
305
|
+
.join('\n');
|
|
306
|
+
if (text) {
|
|
307
|
+
prompt.push({ role: 'system', content: text });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
for (const message of asArray(rawBody.messages)) {
|
|
311
|
+
const bag = asRecord(message);
|
|
312
|
+
const role = pickString(bag.role)?.toLowerCase();
|
|
313
|
+
if (!role) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
for (const converted of convertMessageContent(role, bag.content, toolNameIndex)) {
|
|
317
|
+
prompt.push(converted);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return prompt;
|
|
321
|
+
}
|
|
322
|
+
function convertTools(rawBody) {
|
|
323
|
+
const tools = asArray(rawBody.tools)
|
|
324
|
+
.map((entry) => asRecord(entry))
|
|
325
|
+
.map((tool) => {
|
|
326
|
+
const name = pickString(tool.name);
|
|
327
|
+
if (!name) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
type: 'function',
|
|
332
|
+
name,
|
|
333
|
+
...(pickString(tool.description) ? { description: pickString(tool.description) } : {}),
|
|
334
|
+
inputSchema: (tool.input_schema ?? tool.inputSchema ?? {})
|
|
335
|
+
};
|
|
336
|
+
})
|
|
337
|
+
.filter((tool) => tool !== null);
|
|
338
|
+
return tools.length ? tools : undefined;
|
|
339
|
+
}
|
|
340
|
+
function convertProviderOptions(rawBody) {
|
|
341
|
+
const thinking = asRecord(rawBody.thinking);
|
|
342
|
+
const outputConfig = asRecord(rawBody.output_config ?? rawBody.outputConfig);
|
|
343
|
+
const providerOptions = {};
|
|
344
|
+
const thinkingType = pickString(thinking.type);
|
|
345
|
+
if (thinkingType === 'adaptive') {
|
|
346
|
+
providerOptions.thinking = { type: 'adaptive' };
|
|
347
|
+
}
|
|
348
|
+
else if (thinkingType === 'enabled') {
|
|
349
|
+
providerOptions.thinking = {
|
|
350
|
+
type: 'enabled',
|
|
351
|
+
...(pickNumber(thinking.budget_tokens ?? thinking.budgetTokens) !== undefined
|
|
352
|
+
? { budgetTokens: pickNumber(thinking.budget_tokens ?? thinking.budgetTokens) }
|
|
353
|
+
: {})
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
else if (thinkingType === 'disabled') {
|
|
357
|
+
providerOptions.thinking = { type: 'disabled' };
|
|
358
|
+
}
|
|
359
|
+
const effort = pickString(outputConfig.effort);
|
|
360
|
+
if (effort && ['low', 'medium', 'high', 'max'].includes(effort)) {
|
|
361
|
+
providerOptions.effort = effort;
|
|
362
|
+
}
|
|
363
|
+
const speed = pickString(rawBody.speed);
|
|
364
|
+
if (speed && ['fast', 'standard'].includes(speed)) {
|
|
365
|
+
providerOptions.speed = speed;
|
|
366
|
+
}
|
|
367
|
+
const disableParallelToolUse = pickBoolean(rawBody.disable_parallel_tool_use ?? rawBody.disableParallelToolUse ?? asRecord(rawBody.tool_choice).disable_parallel_tool_use);
|
|
368
|
+
if (disableParallelToolUse !== undefined) {
|
|
369
|
+
providerOptions.disableParallelToolUse = disableParallelToolUse;
|
|
370
|
+
}
|
|
371
|
+
const container = rawBody.container;
|
|
372
|
+
if (typeof container === 'string') {
|
|
373
|
+
providerOptions.container = { id: container };
|
|
374
|
+
}
|
|
375
|
+
else if (container && typeof container === 'object' && !Array.isArray(container)) {
|
|
376
|
+
const containerBag = asRecord(container);
|
|
377
|
+
const id = pickString(containerBag.id);
|
|
378
|
+
const skills = asArray(containerBag.skills)
|
|
379
|
+
.map((entry) => asRecord(entry))
|
|
380
|
+
.map((entry) => {
|
|
381
|
+
const type = pickString(entry.type);
|
|
382
|
+
const skillId = pickString(entry.skill_id ?? entry.skillId);
|
|
383
|
+
if (!type || !skillId) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
type: type === 'custom' ? 'custom' : 'anthropic',
|
|
388
|
+
skillId,
|
|
389
|
+
...(pickString(entry.version) ? { version: pickString(entry.version) } : {})
|
|
390
|
+
};
|
|
391
|
+
})
|
|
392
|
+
.filter(Boolean);
|
|
393
|
+
if (id || skills.length > 0) {
|
|
394
|
+
providerOptions.container = {
|
|
395
|
+
...(id ? { id } : {}),
|
|
396
|
+
...(skills.length > 0 ? { skills: skills } : {})
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
const mcpServers = asArray(rawBody.mcp_servers ?? rawBody.mcpServers)
|
|
401
|
+
.map((entry) => asRecord(entry))
|
|
402
|
+
.map((entry) => {
|
|
403
|
+
const type = pickString(entry.type);
|
|
404
|
+
const name = pickString(entry.name);
|
|
405
|
+
const url = pickString(entry.url);
|
|
406
|
+
if (type !== 'url' || !name || !url) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
const toolConfiguration = asRecord(entry.tool_configuration ?? entry.toolConfiguration);
|
|
410
|
+
return {
|
|
411
|
+
type: 'url',
|
|
412
|
+
name,
|
|
413
|
+
url,
|
|
414
|
+
authorizationToken: pickString(entry.authorization_token ?? entry.authorizationToken) ?? null,
|
|
415
|
+
...(Object.keys(toolConfiguration).length > 0
|
|
416
|
+
? {
|
|
417
|
+
toolConfiguration: {
|
|
418
|
+
...(pickBoolean(toolConfiguration.enabled) !== undefined
|
|
419
|
+
? { enabled: pickBoolean(toolConfiguration.enabled) }
|
|
420
|
+
: {}),
|
|
421
|
+
...(Array.isArray(toolConfiguration.allowed_tools ?? toolConfiguration.allowedTools)
|
|
422
|
+
? { allowedTools: asArray(toolConfiguration.allowed_tools ?? toolConfiguration.allowedTools).map(String) }
|
|
423
|
+
: {})
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
: {})
|
|
427
|
+
};
|
|
428
|
+
})
|
|
429
|
+
.filter(Boolean);
|
|
430
|
+
if (mcpServers.length > 0) {
|
|
431
|
+
providerOptions.mcpServers = mcpServers;
|
|
432
|
+
}
|
|
433
|
+
const contextManagement = asRecord(rawBody.context_management ?? rawBody.contextManagement);
|
|
434
|
+
const edits = asArray(contextManagement.edits)
|
|
435
|
+
.map((entry) => asRecord(entry))
|
|
436
|
+
.map((entry) => {
|
|
437
|
+
const type = pickString(entry.type);
|
|
438
|
+
if (!type) {
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
if (type === 'clear_tool_uses_20250919') {
|
|
442
|
+
return {
|
|
443
|
+
type,
|
|
444
|
+
...(entry.trigger && typeof entry.trigger === 'object' ? { trigger: entry.trigger } : {}),
|
|
445
|
+
...(entry.keep && typeof entry.keep === 'object' ? { keep: entry.keep } : {}),
|
|
446
|
+
...(entry.clear_at_least && typeof entry.clear_at_least === 'object'
|
|
447
|
+
? { clearAtLeast: entry.clear_at_least }
|
|
448
|
+
: entry.clearAtLeast && typeof entry.clearAtLeast === 'object'
|
|
449
|
+
? { clearAtLeast: entry.clearAtLeast }
|
|
450
|
+
: {}),
|
|
451
|
+
...(pickBoolean(entry.clear_tool_inputs ?? entry.clearToolInputs) !== undefined
|
|
452
|
+
? { clearToolInputs: pickBoolean(entry.clear_tool_inputs ?? entry.clearToolInputs) }
|
|
453
|
+
: {}),
|
|
454
|
+
...(Array.isArray(entry.exclude_tools ?? entry.excludeTools)
|
|
455
|
+
? { excludeTools: asArray(entry.exclude_tools ?? entry.excludeTools).map(String) }
|
|
456
|
+
: {})
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
if (type === 'clear_thinking_20251015') {
|
|
460
|
+
return {
|
|
461
|
+
type,
|
|
462
|
+
...(entry.keep !== undefined ? { keep: entry.keep } : {})
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
if (type === 'compact_20260112') {
|
|
466
|
+
return {
|
|
467
|
+
type,
|
|
468
|
+
...(entry.trigger && typeof entry.trigger === 'object' ? { trigger: entry.trigger } : {}),
|
|
469
|
+
...(pickBoolean(entry.pause_after_compaction ?? entry.pauseAfterCompaction) !== undefined
|
|
470
|
+
? { pauseAfterCompaction: pickBoolean(entry.pause_after_compaction ?? entry.pauseAfterCompaction) }
|
|
471
|
+
: {}),
|
|
472
|
+
...(pickString(entry.instructions) ? { instructions: pickString(entry.instructions) } : {})
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
})
|
|
477
|
+
.filter(Boolean);
|
|
478
|
+
if (edits.length > 0) {
|
|
479
|
+
providerOptions.contextManagement = { edits };
|
|
480
|
+
}
|
|
481
|
+
return Object.keys(providerOptions).length ? providerOptions : undefined;
|
|
482
|
+
}
|
|
483
|
+
function convertResponseFormat(rawBody) {
|
|
484
|
+
const outputConfig = asRecord(rawBody.output_config ?? rawBody.outputConfig);
|
|
485
|
+
const format = asRecord(outputConfig.format);
|
|
486
|
+
const type = pickString(format.type)?.toLowerCase();
|
|
487
|
+
if (type !== 'json_schema') {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
const schema = format.schema;
|
|
491
|
+
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
type: 'json',
|
|
496
|
+
schema: schema,
|
|
497
|
+
...(pickString(format.name) ? { name: pickString(format.name) } : {}),
|
|
498
|
+
...(pickString(format.description) ? { description: pickString(format.description) } : {})
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
export function buildAnthropicSdkCallOptions(body, requestHeaders) {
|
|
502
|
+
return {
|
|
503
|
+
prompt: convertPrompt(body),
|
|
504
|
+
headers: requestHeaders,
|
|
505
|
+
maxOutputTokens: pickNumber(body.max_tokens ?? body.maxTokens),
|
|
506
|
+
temperature: pickNumber(body.temperature),
|
|
507
|
+
topP: pickNumber(body.top_p ?? body.topP),
|
|
508
|
+
topK: pickNumber(body.top_k ?? body.topK),
|
|
509
|
+
stopSequences: asArray(body.stop_sequences ?? body.stopSequences).map(String),
|
|
510
|
+
tools: convertTools(body),
|
|
511
|
+
toolChoice: normalizeToolChoice(body.tool_choice ?? body.toolChoice),
|
|
512
|
+
responseFormat: convertResponseFormat(body),
|
|
513
|
+
providerOptions: (() => {
|
|
514
|
+
const anthropic = convertProviderOptions(body);
|
|
515
|
+
return anthropic
|
|
516
|
+
? { anthropic }
|
|
517
|
+
: undefined;
|
|
518
|
+
})()
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function mergePreservedRequestFields(rawBody, builtBody) {
|
|
522
|
+
const next = { ...builtBody };
|
|
523
|
+
const metadata = rawBody.metadata;
|
|
524
|
+
if (metadata && typeof metadata === 'object' && !Array.isArray(metadata)) {
|
|
525
|
+
next.metadata = stripInternalKeysDeep(metadata);
|
|
526
|
+
}
|
|
527
|
+
return next;
|
|
528
|
+
}
|
|
529
|
+
function buildSyntheticAnthropicMessage(rawBody, result) {
|
|
530
|
+
return {
|
|
531
|
+
id: result.response?.id ?? `msg_${Date.now()}`,
|
|
532
|
+
type: 'message',
|
|
533
|
+
role: 'assistant',
|
|
534
|
+
model: pickString(rawBody.model) ?? 'unknown',
|
|
535
|
+
content: [],
|
|
536
|
+
stop_reason: 'end_turn',
|
|
537
|
+
usage: {
|
|
538
|
+
input_tokens: 0,
|
|
539
|
+
output_tokens: 0
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function responseHeadersToRecord(headers) {
|
|
544
|
+
if (!headers || typeof headers !== 'object') {
|
|
545
|
+
return undefined;
|
|
546
|
+
}
|
|
547
|
+
const entries = Object.entries(headers)
|
|
548
|
+
.filter((entry) => typeof entry[1] === 'string');
|
|
549
|
+
if (!entries.length) {
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
return Object.fromEntries(entries);
|
|
553
|
+
}
|
|
554
|
+
function buildHttpError(status, responseText) {
|
|
555
|
+
const error = new Error(`HTTP ${status}: ${responseText}`);
|
|
556
|
+
error.statusCode = status;
|
|
557
|
+
error.status = status;
|
|
558
|
+
error.response = {
|
|
559
|
+
status,
|
|
560
|
+
data: {
|
|
561
|
+
error: {
|
|
562
|
+
message: responseText,
|
|
563
|
+
code: `HTTP_${status}`
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
return error;
|
|
568
|
+
}
|
|
569
|
+
function buildInvalidJsonError(responseText) {
|
|
570
|
+
const error = new Error('Invalid JSON response');
|
|
571
|
+
error.statusCode = 200;
|
|
572
|
+
error.status = 200;
|
|
573
|
+
error.response = {
|
|
574
|
+
status: 200,
|
|
575
|
+
data: {
|
|
576
|
+
error: {
|
|
577
|
+
message: responseText,
|
|
578
|
+
code: 'HTTP_200'
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
return error;
|
|
583
|
+
}
|
|
584
|
+
export class VercelAiSdkAnthropicTransport {
|
|
585
|
+
async executePreparedRequest(requestInfo, _context) {
|
|
586
|
+
const rawBody = asRecord(requestInfo.body);
|
|
587
|
+
const modelId = pickString(rawBody.model);
|
|
588
|
+
if (!modelId) {
|
|
589
|
+
throw new Error('provider-runtime-error: missing model from anthropic sdk transport');
|
|
590
|
+
}
|
|
591
|
+
const model = new AnthropicMessagesLanguageModel(modelId, {
|
|
592
|
+
provider: 'anthropic.messages',
|
|
593
|
+
baseURL: requestInfo.targetUrl,
|
|
594
|
+
headers: () => ({}),
|
|
595
|
+
buildRequestUrl: () => requestInfo.targetUrl,
|
|
596
|
+
transformRequestBody: (body) => mergePreservedRequestFields(rawBody, body)
|
|
597
|
+
});
|
|
598
|
+
const callOptions = buildAnthropicSdkCallOptions(rawBody, requestInfo.headers);
|
|
599
|
+
const argsResult = await model.getArgs({
|
|
600
|
+
...callOptions,
|
|
601
|
+
stream: requestInfo.wantsSse,
|
|
602
|
+
userSuppliedBetas: await model.getBetasFromHeaders(callOptions.headers)
|
|
603
|
+
});
|
|
604
|
+
const args = asRecord(argsResult.args);
|
|
605
|
+
const betas = argsResult.betas instanceof Set ? argsResult.betas : new Set();
|
|
606
|
+
const url = model.buildRequestUrl(requestInfo.wantsSse);
|
|
607
|
+
const headers = await model.getHeaders({ betas, headers: callOptions.headers });
|
|
608
|
+
const body = model.transformRequestBody(args, betas);
|
|
609
|
+
const response = await fetch(url, {
|
|
610
|
+
method: 'POST',
|
|
611
|
+
headers,
|
|
612
|
+
body: JSON.stringify(body)
|
|
613
|
+
});
|
|
614
|
+
if (!response.ok) {
|
|
615
|
+
throw buildHttpError(response.status, await response.text());
|
|
616
|
+
}
|
|
617
|
+
const responseHeaders = responseHeadersToRecord(Object.fromEntries(response.headers.entries()));
|
|
618
|
+
if (requestInfo.wantsSse) {
|
|
619
|
+
if (!response.body) {
|
|
620
|
+
throw buildHttpError(502, 'missing upstream SSE body');
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
__sse_responses: Readable.fromWeb(response.body),
|
|
624
|
+
...(responseHeaders ? { headers: responseHeaders } : {})
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
const responseText = await response.text();
|
|
628
|
+
let responseBody;
|
|
629
|
+
try {
|
|
630
|
+
responseBody = JSON.parse(responseText);
|
|
631
|
+
}
|
|
632
|
+
catch {
|
|
633
|
+
throw buildInvalidJsonError(responseText);
|
|
634
|
+
}
|
|
635
|
+
return {
|
|
636
|
+
data: responseBody,
|
|
637
|
+
status: response.status,
|
|
638
|
+
...(responseHeaders ? { headers: responseHeaders } : {})
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
//# sourceMappingURL=anthropic-sdk-transport.js.map
|