@wrongstack/providers 0.1.9 → 0.1.10
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/index.d.ts +13 -0
- package/dist/index.js +489 -376
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -37,6 +37,8 @@ async function aggregateStream(stream, onEvent) {
|
|
|
37
37
|
const textBuffers = [];
|
|
38
38
|
let currentTextIndex = -1;
|
|
39
39
|
const toolBuffers = /* @__PURE__ */ new Map();
|
|
40
|
+
const thinkingBuffers = [];
|
|
41
|
+
let currentThinkingIndex = -1;
|
|
40
42
|
const blockOrder = [];
|
|
41
43
|
for await (const ev of stream) {
|
|
42
44
|
if (onEvent) onEvent(ev);
|
|
@@ -74,10 +76,45 @@ async function aggregateStream(stream, onEvent) {
|
|
|
74
76
|
} else {
|
|
75
77
|
b.input = { __raw: ev.input };
|
|
76
78
|
}
|
|
79
|
+
if (ev.providerMeta) b.providerMeta = ev.providerMeta;
|
|
77
80
|
}
|
|
78
81
|
currentTextIndex = -1;
|
|
79
82
|
break;
|
|
80
83
|
}
|
|
84
|
+
case "thinking_start": {
|
|
85
|
+
currentTextIndex = -1;
|
|
86
|
+
currentThinkingIndex = thinkingBuffers.length;
|
|
87
|
+
thinkingBuffers.push({
|
|
88
|
+
textBuf: "",
|
|
89
|
+
...ev.providerMeta ? { providerMeta: ev.providerMeta } : {}
|
|
90
|
+
});
|
|
91
|
+
blockOrder.push({ kind: "thinking", idx: currentThinkingIndex });
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case "thinking_delta": {
|
|
95
|
+
if (currentThinkingIndex === -1) {
|
|
96
|
+
currentThinkingIndex = thinkingBuffers.length;
|
|
97
|
+
thinkingBuffers.push({ textBuf: "" });
|
|
98
|
+
blockOrder.push({ kind: "thinking", idx: currentThinkingIndex });
|
|
99
|
+
}
|
|
100
|
+
const t = thinkingBuffers[currentThinkingIndex];
|
|
101
|
+
if (t) t.textBuf += ev.text;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case "thinking_signature": {
|
|
105
|
+
if (currentThinkingIndex === -1) {
|
|
106
|
+
currentThinkingIndex = thinkingBuffers.length;
|
|
107
|
+
thinkingBuffers.push({ textBuf: "" });
|
|
108
|
+
blockOrder.push({ kind: "thinking", idx: currentThinkingIndex });
|
|
109
|
+
}
|
|
110
|
+
const t = thinkingBuffers[currentThinkingIndex];
|
|
111
|
+
if (t) t.signature = ev.signature;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case "thinking_stop": {
|
|
115
|
+
currentThinkingIndex = -1;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
81
118
|
case "message_stop":
|
|
82
119
|
stopReason = ev.stopReason;
|
|
83
120
|
usage = ev.usage;
|
|
@@ -89,15 +126,28 @@ async function aggregateStream(stream, onEvent) {
|
|
|
89
126
|
if (b.kind === "text") {
|
|
90
127
|
const text = textBuffers[b.idx] ?? "";
|
|
91
128
|
if (text) content.push({ type: "text", text });
|
|
129
|
+
} else if (b.kind === "thinking") {
|
|
130
|
+
const t = thinkingBuffers[b.idx];
|
|
131
|
+
if (!t || !t.textBuf && !t.signature) continue;
|
|
132
|
+
const block = { type: "thinking", thinking: t.textBuf };
|
|
133
|
+
if (t.signature) block.signature = t.signature;
|
|
134
|
+
if (t.providerMeta && Object.keys(t.providerMeta).length > 0) {
|
|
135
|
+
block.providerMeta = t.providerMeta;
|
|
136
|
+
}
|
|
137
|
+
content.push(block);
|
|
92
138
|
} else {
|
|
93
139
|
const tb = toolBuffers.get(b.id);
|
|
94
140
|
if (tb) {
|
|
95
|
-
|
|
141
|
+
const block = {
|
|
96
142
|
type: "tool_use",
|
|
97
143
|
id: b.id,
|
|
98
144
|
name: tb.name,
|
|
99
145
|
input: tb.input && typeof tb.input === "object" && !Array.isArray(tb.input) ? tb.input : {}
|
|
100
|
-
}
|
|
146
|
+
};
|
|
147
|
+
if (tb.providerMeta && Object.keys(tb.providerMeta).length > 0) {
|
|
148
|
+
block.providerMeta = tb.providerMeta;
|
|
149
|
+
}
|
|
150
|
+
content.push(block);
|
|
101
151
|
}
|
|
102
152
|
}
|
|
103
153
|
}
|
|
@@ -109,6 +159,9 @@ var init_aggregate = __esm({
|
|
|
109
159
|
init_tool_input();
|
|
110
160
|
}
|
|
111
161
|
});
|
|
162
|
+
|
|
163
|
+
// src/anthropic.ts
|
|
164
|
+
init_tool_input();
|
|
112
165
|
function parseProviderHttpError(providerId, status, rawText) {
|
|
113
166
|
const body = parseBody(rawText);
|
|
114
167
|
const retryable = isRetryable(status, body.type);
|
|
@@ -162,71 +215,69 @@ function stringOf(v) {
|
|
|
162
215
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
163
216
|
}
|
|
164
217
|
|
|
165
|
-
// src/
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
case "max_tokens":
|
|
222
|
-
case "MAX_TOKENS":
|
|
223
|
-
return "max_tokens";
|
|
224
|
-
case "tool_use":
|
|
225
|
-
case "TOOL_USE":
|
|
226
|
-
return "tool_use";
|
|
227
|
-
default:
|
|
228
|
-
return "end_turn";
|
|
218
|
+
// src/family-capabilities.ts
|
|
219
|
+
var CAPABILITIES_BY_FAMILY = {
|
|
220
|
+
anthropic: {
|
|
221
|
+
tools: true,
|
|
222
|
+
parallelTools: true,
|
|
223
|
+
vision: true,
|
|
224
|
+
streaming: true,
|
|
225
|
+
promptCache: true,
|
|
226
|
+
systemPrompt: true,
|
|
227
|
+
jsonMode: false,
|
|
228
|
+
maxContext: 2e5,
|
|
229
|
+
cacheControl: "native"
|
|
230
|
+
},
|
|
231
|
+
openai: {
|
|
232
|
+
tools: true,
|
|
233
|
+
parallelTools: true,
|
|
234
|
+
vision: true,
|
|
235
|
+
streaming: true,
|
|
236
|
+
promptCache: false,
|
|
237
|
+
systemPrompt: true,
|
|
238
|
+
jsonMode: true,
|
|
239
|
+
maxContext: 128e3,
|
|
240
|
+
cacheControl: "auto"
|
|
241
|
+
},
|
|
242
|
+
"openai-compatible": {
|
|
243
|
+
tools: true,
|
|
244
|
+
parallelTools: true,
|
|
245
|
+
vision: false,
|
|
246
|
+
streaming: true,
|
|
247
|
+
promptCache: false,
|
|
248
|
+
systemPrompt: true,
|
|
249
|
+
jsonMode: false,
|
|
250
|
+
maxContext: 32e3,
|
|
251
|
+
cacheControl: "none"
|
|
252
|
+
},
|
|
253
|
+
google: {
|
|
254
|
+
tools: true,
|
|
255
|
+
parallelTools: true,
|
|
256
|
+
vision: true,
|
|
257
|
+
streaming: true,
|
|
258
|
+
promptCache: false,
|
|
259
|
+
systemPrompt: true,
|
|
260
|
+
jsonMode: true,
|
|
261
|
+
maxContext: 1e6,
|
|
262
|
+
cacheControl: "none"
|
|
263
|
+
},
|
|
264
|
+
unsupported: {
|
|
265
|
+
tools: false,
|
|
266
|
+
parallelTools: false,
|
|
267
|
+
vision: false,
|
|
268
|
+
streaming: false,
|
|
269
|
+
promptCache: false,
|
|
270
|
+
systemPrompt: false,
|
|
271
|
+
jsonMode: false,
|
|
272
|
+
maxContext: 0,
|
|
273
|
+
cacheControl: "none"
|
|
229
274
|
}
|
|
275
|
+
};
|
|
276
|
+
function capabilitiesForFamily(family, overrides = {}) {
|
|
277
|
+
return {
|
|
278
|
+
...CAPABILITIES_BY_FAMILY[family] ?? CAPABILITIES_BY_FAMILY.unsupported,
|
|
279
|
+
...overrides
|
|
280
|
+
};
|
|
230
281
|
}
|
|
231
282
|
|
|
232
283
|
// src/sse.ts
|
|
@@ -318,6 +369,70 @@ function splitBuffer(buf) {
|
|
|
318
369
|
function isNodeReadable(b) {
|
|
319
370
|
return !!b && typeof b === "object" && typeof b.pipe === "function" && typeof b.on === "function";
|
|
320
371
|
}
|
|
372
|
+
|
|
373
|
+
// src/stop-reason.ts
|
|
374
|
+
function normalizeAnthropic(stop) {
|
|
375
|
+
switch (stop) {
|
|
376
|
+
case "end_turn":
|
|
377
|
+
return "end_turn";
|
|
378
|
+
case "tool_use":
|
|
379
|
+
return "tool_use";
|
|
380
|
+
case "max_tokens":
|
|
381
|
+
return "max_tokens";
|
|
382
|
+
case "stop_sequence":
|
|
383
|
+
return "stop_sequence";
|
|
384
|
+
case "refusal":
|
|
385
|
+
return "refusal";
|
|
386
|
+
default:
|
|
387
|
+
return "end_turn";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function normalizeOpenAI(stop) {
|
|
391
|
+
switch (stop) {
|
|
392
|
+
case "stop":
|
|
393
|
+
return "end_turn";
|
|
394
|
+
case "tool_calls":
|
|
395
|
+
case "function_call":
|
|
396
|
+
return "tool_use";
|
|
397
|
+
case "length":
|
|
398
|
+
return "max_tokens";
|
|
399
|
+
case "content_filter":
|
|
400
|
+
return "refusal";
|
|
401
|
+
default:
|
|
402
|
+
return "end_turn";
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function normalizeGemini(stop) {
|
|
406
|
+
switch (stop) {
|
|
407
|
+
case "SAFETY":
|
|
408
|
+
case "RECITATION":
|
|
409
|
+
case "hallucination":
|
|
410
|
+
return "refusal";
|
|
411
|
+
case "stop":
|
|
412
|
+
case "STOP":
|
|
413
|
+
return "end_turn";
|
|
414
|
+
case "max_tokens":
|
|
415
|
+
case "MAX_TOKENS":
|
|
416
|
+
return "max_tokens";
|
|
417
|
+
case "tool_use":
|
|
418
|
+
case "TOOL_USE":
|
|
419
|
+
return "tool_use";
|
|
420
|
+
default:
|
|
421
|
+
return "end_turn";
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/tool-format/to-anthropic.ts
|
|
426
|
+
function toolsToAnthropic(tools) {
|
|
427
|
+
return tools.map((t) => ({
|
|
428
|
+
name: t.name,
|
|
429
|
+
description: t.description,
|
|
430
|
+
input_schema: t.inputSchema ?? {
|
|
431
|
+
type: "object",
|
|
432
|
+
properties: {}
|
|
433
|
+
}
|
|
434
|
+
}));
|
|
435
|
+
}
|
|
321
436
|
async function safeText(res) {
|
|
322
437
|
try {
|
|
323
438
|
return await res.text();
|
|
@@ -353,13 +468,10 @@ var WireAdapter = class {
|
|
|
353
468
|
});
|
|
354
469
|
} catch (err) {
|
|
355
470
|
if (opts.signal.aborted) throw err;
|
|
356
|
-
throw new ProviderError(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
this.id,
|
|
361
|
-
{ cause: err, body: { message: err instanceof Error ? err.message : String(err) } }
|
|
362
|
-
);
|
|
471
|
+
throw new ProviderError(err instanceof Error ? err.message : String(err), 0, true, this.id, {
|
|
472
|
+
cause: err,
|
|
473
|
+
body: { message: err instanceof Error ? err.message : String(err) }
|
|
474
|
+
});
|
|
363
475
|
}
|
|
364
476
|
if (!httpRes.ok) {
|
|
365
477
|
const text = await safeText(httpRes);
|
|
@@ -380,71 +492,6 @@ var WireAdapter = class {
|
|
|
380
492
|
}
|
|
381
493
|
};
|
|
382
494
|
|
|
383
|
-
// src/family-capabilities.ts
|
|
384
|
-
var CAPABILITIES_BY_FAMILY = {
|
|
385
|
-
anthropic: {
|
|
386
|
-
tools: true,
|
|
387
|
-
parallelTools: true,
|
|
388
|
-
vision: true,
|
|
389
|
-
streaming: true,
|
|
390
|
-
promptCache: true,
|
|
391
|
-
systemPrompt: true,
|
|
392
|
-
jsonMode: false,
|
|
393
|
-
maxContext: 2e5,
|
|
394
|
-
cacheControl: "native"
|
|
395
|
-
},
|
|
396
|
-
openai: {
|
|
397
|
-
tools: true,
|
|
398
|
-
parallelTools: true,
|
|
399
|
-
vision: true,
|
|
400
|
-
streaming: true,
|
|
401
|
-
promptCache: false,
|
|
402
|
-
systemPrompt: true,
|
|
403
|
-
jsonMode: true,
|
|
404
|
-
maxContext: 128e3,
|
|
405
|
-
cacheControl: "auto"
|
|
406
|
-
},
|
|
407
|
-
"openai-compatible": {
|
|
408
|
-
tools: true,
|
|
409
|
-
parallelTools: true,
|
|
410
|
-
vision: false,
|
|
411
|
-
streaming: true,
|
|
412
|
-
promptCache: false,
|
|
413
|
-
systemPrompt: true,
|
|
414
|
-
jsonMode: false,
|
|
415
|
-
maxContext: 32e3,
|
|
416
|
-
cacheControl: "none"
|
|
417
|
-
},
|
|
418
|
-
google: {
|
|
419
|
-
tools: true,
|
|
420
|
-
parallelTools: true,
|
|
421
|
-
vision: true,
|
|
422
|
-
streaming: true,
|
|
423
|
-
promptCache: false,
|
|
424
|
-
systemPrompt: true,
|
|
425
|
-
jsonMode: true,
|
|
426
|
-
maxContext: 1e6,
|
|
427
|
-
cacheControl: "none"
|
|
428
|
-
},
|
|
429
|
-
unsupported: {
|
|
430
|
-
tools: false,
|
|
431
|
-
parallelTools: false,
|
|
432
|
-
vision: false,
|
|
433
|
-
streaming: false,
|
|
434
|
-
promptCache: false,
|
|
435
|
-
systemPrompt: false,
|
|
436
|
-
jsonMode: false,
|
|
437
|
-
maxContext: 0,
|
|
438
|
-
cacheControl: "none"
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
function capabilitiesForFamily(family, overrides = {}) {
|
|
442
|
-
return {
|
|
443
|
-
...CAPABILITIES_BY_FAMILY[family] ?? CAPABILITIES_BY_FAMILY.unsupported,
|
|
444
|
-
...overrides
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
|
|
448
495
|
// src/anthropic.ts
|
|
449
496
|
var DEFAULT_BASE = "https://api.anthropic.com";
|
|
450
497
|
var DEFAULT_VERSION = "2023-06-01";
|
|
@@ -539,6 +586,9 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
539
586
|
}
|
|
540
587
|
} else if (cb?.type === "text") {
|
|
541
588
|
blocks.set(index, { kind: "text", partial: "" });
|
|
589
|
+
} else if (cb?.type === "thinking" || cb?.type === "redacted_thinking") {
|
|
590
|
+
blocks.set(index, { kind: "thinking", partial: "" });
|
|
591
|
+
yield { type: "thinking_start" };
|
|
542
592
|
} else {
|
|
543
593
|
blocks.set(index, { kind: "unknown", partial: "" });
|
|
544
594
|
}
|
|
@@ -556,6 +606,10 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
556
606
|
block.partial += delta.partial_json;
|
|
557
607
|
yield { type: "tool_use_input_delta", id: block.id, partial: delta.partial_json };
|
|
558
608
|
}
|
|
609
|
+
} else if (delta.type === "thinking_delta" && typeof delta.thinking === "string") {
|
|
610
|
+
yield { type: "thinking_delta", text: delta.thinking };
|
|
611
|
+
} else if (delta.type === "signature_delta" && typeof delta.signature === "string") {
|
|
612
|
+
yield { type: "thinking_signature", signature: delta.signature };
|
|
559
613
|
}
|
|
560
614
|
break;
|
|
561
615
|
}
|
|
@@ -565,6 +619,8 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
565
619
|
if (block?.kind === "tool_use" && block.id) {
|
|
566
620
|
const input = parseToolInput(block.partial);
|
|
567
621
|
yield { type: "tool_use_stop", id: block.id, input };
|
|
622
|
+
} else if (block?.kind === "thinking") {
|
|
623
|
+
yield { type: "thinking_stop" };
|
|
568
624
|
}
|
|
569
625
|
break;
|
|
570
626
|
}
|
|
@@ -582,20 +638,237 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
582
638
|
break;
|
|
583
639
|
case "error": {
|
|
584
640
|
const err = ev["error"];
|
|
585
|
-
throw new ProviderError(
|
|
586
|
-
err?.message
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
641
|
+
throw new ProviderError(err?.message ?? "Anthropic stream error", 0, false, "anthropic", {
|
|
642
|
+
body: { type: err?.type, message: err?.message }
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (started) {
|
|
648
|
+
yield { type: "message_stop", stopReason, usage };
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
var DEFAULT_BASE2 = "https://generativelanguage.googleapis.com/v1beta";
|
|
652
|
+
var GoogleProvider = class extends WireAdapter {
|
|
653
|
+
id;
|
|
654
|
+
capabilities;
|
|
655
|
+
opts;
|
|
656
|
+
constructor(opts) {
|
|
657
|
+
super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE2, opts.fetchImpl);
|
|
658
|
+
this.opts = opts;
|
|
659
|
+
this.id = opts.id ?? "google";
|
|
660
|
+
this.capabilities = capabilitiesForFamily("google", {
|
|
661
|
+
...opts.capabilities
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
buildUrl(req) {
|
|
665
|
+
return `${this.baseUrl}/models/${encodeURIComponent(req.model)}:streamGenerateContent?alt=sse`;
|
|
666
|
+
}
|
|
667
|
+
buildHeaders(req) {
|
|
668
|
+
return {
|
|
669
|
+
...super.buildHeaders(req),
|
|
670
|
+
"x-goog-api-key": this.apiKey
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
buildBody(req) {
|
|
674
|
+
const body = {
|
|
675
|
+
contents: messagesToGemini(req.messages),
|
|
676
|
+
generationConfig: this.buildGenConfig(req)
|
|
677
|
+
};
|
|
678
|
+
if (req.system && req.system.length > 0) {
|
|
679
|
+
body["systemInstruction"] = {
|
|
680
|
+
parts: req.system.map((b) => ({ text: b.text }))
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
if (req.tools && req.tools.length > 0) {
|
|
684
|
+
body["tools"] = [{ functionDeclarations: toolsToGemini(req.tools) }];
|
|
685
|
+
}
|
|
686
|
+
return body;
|
|
687
|
+
}
|
|
688
|
+
parseStream(body, fallbackModel) {
|
|
689
|
+
return parseGoogleStream(body, fallbackModel);
|
|
690
|
+
}
|
|
691
|
+
translateError(status, text) {
|
|
692
|
+
return parseProviderHttpError(this.id, status, text);
|
|
693
|
+
}
|
|
694
|
+
buildGenConfig(req) {
|
|
695
|
+
const cfg = { maxOutputTokens: req.maxTokens };
|
|
696
|
+
if (req.temperature !== void 0) cfg["temperature"] = req.temperature;
|
|
697
|
+
if (req.topP !== void 0) cfg["topP"] = req.topP;
|
|
698
|
+
if (req.stopSequences) cfg["stopSequences"] = req.stopSequences;
|
|
699
|
+
return cfg;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
function toolsToGemini(tools) {
|
|
703
|
+
return tools.map((t) => ({
|
|
704
|
+
name: t.name,
|
|
705
|
+
description: t.description,
|
|
706
|
+
parameters: sanitizeSchemaForGemini(t.inputSchema) ?? {
|
|
707
|
+
type: "object",
|
|
708
|
+
properties: {}
|
|
709
|
+
}
|
|
710
|
+
}));
|
|
711
|
+
}
|
|
712
|
+
var GEMINI_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
713
|
+
"type",
|
|
714
|
+
"format",
|
|
715
|
+
"description",
|
|
716
|
+
"nullable",
|
|
717
|
+
"enum",
|
|
718
|
+
"items",
|
|
719
|
+
"properties",
|
|
720
|
+
"required",
|
|
721
|
+
"anyOf",
|
|
722
|
+
"minLength",
|
|
723
|
+
"maxLength",
|
|
724
|
+
"pattern",
|
|
725
|
+
"minimum",
|
|
726
|
+
"maximum",
|
|
727
|
+
"minItems",
|
|
728
|
+
"maxItems",
|
|
729
|
+
"minProperties",
|
|
730
|
+
"maxProperties",
|
|
731
|
+
"propertyOrdering",
|
|
732
|
+
"title"
|
|
733
|
+
]);
|
|
734
|
+
function sanitizeSchemaForGemini(node) {
|
|
735
|
+
if (node === null || node === void 0) return void 0;
|
|
736
|
+
if (Array.isArray(node)) {
|
|
737
|
+
return void 0;
|
|
738
|
+
}
|
|
739
|
+
if (typeof node !== "object") return void 0;
|
|
740
|
+
const src = node;
|
|
741
|
+
const out = {};
|
|
742
|
+
for (const [k, v] of Object.entries(src)) {
|
|
743
|
+
if (!GEMINI_ALLOWED_KEYS.has(k)) continue;
|
|
744
|
+
if (k === "properties" && v && typeof v === "object") {
|
|
745
|
+
const props = {};
|
|
746
|
+
for (const [pname, pschema] of Object.entries(v)) {
|
|
747
|
+
const cleaned = sanitizeSchemaForGemini(pschema);
|
|
748
|
+
if (cleaned) props[pname] = cleaned;
|
|
749
|
+
}
|
|
750
|
+
out["properties"] = props;
|
|
751
|
+
} else if (k === "items") {
|
|
752
|
+
const cleaned = sanitizeSchemaForGemini(v);
|
|
753
|
+
if (cleaned) out["items"] = cleaned;
|
|
754
|
+
} else if (k === "anyOf" && Array.isArray(v)) {
|
|
755
|
+
const cleaned = v.map((s) => sanitizeSchemaForGemini(s)).filter((s) => s !== void 0);
|
|
756
|
+
if (cleaned.length > 0) out["anyOf"] = cleaned;
|
|
757
|
+
} else if (k === "required" && Array.isArray(v)) {
|
|
758
|
+
out["required"] = v.filter((s) => typeof s === "string");
|
|
759
|
+
} else if (k === "enum" && Array.isArray(v)) {
|
|
760
|
+
out["enum"] = v;
|
|
761
|
+
} else {
|
|
762
|
+
out[k] = v;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
return out;
|
|
766
|
+
}
|
|
767
|
+
function messagesToGemini(messages) {
|
|
768
|
+
const out = [];
|
|
769
|
+
for (const m of messages) {
|
|
770
|
+
if (m.role === "system") continue;
|
|
771
|
+
const blocks = typeof m.content === "string" ? [{ type: "text", text: m.content }] : m.content;
|
|
772
|
+
if (m.role === "assistant") {
|
|
773
|
+
const parts = [];
|
|
774
|
+
for (const b of blocks) {
|
|
775
|
+
if (b.type === "text" && b.text) parts.push({ text: b.text });
|
|
776
|
+
else if (b.type === "tool_use") {
|
|
777
|
+
const part = {
|
|
778
|
+
functionCall: { name: b.name, args: b.input }
|
|
779
|
+
};
|
|
780
|
+
const sig = b.providerMeta?.["google.thoughtSignature"];
|
|
781
|
+
if (typeof sig === "string" && sig.length > 0) {
|
|
782
|
+
part.thoughtSignature = sig;
|
|
783
|
+
}
|
|
784
|
+
parts.push(part);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (parts.length > 0) out.push({ role: "model", parts });
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
const textParts = [];
|
|
791
|
+
const functionParts = [];
|
|
792
|
+
for (const b of blocks) {
|
|
793
|
+
if (b.type === "text" && b.text) textParts.push({ text: b.text });
|
|
794
|
+
else if (b.type === "tool_result") {
|
|
795
|
+
const responseText = typeof b.content === "string" ? b.content : JSON.stringify(b.content);
|
|
796
|
+
const fnName = b.name ?? b.tool_use_id;
|
|
797
|
+
functionParts.push({
|
|
798
|
+
functionResponse: {
|
|
799
|
+
name: fnName,
|
|
800
|
+
response: { content: responseText }
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
} else if (b.type === "image" && b.source.type === "base64") {
|
|
804
|
+
textParts.push({
|
|
805
|
+
inlineData: {
|
|
806
|
+
mimeType: b.source.media_type ?? "image/png",
|
|
807
|
+
data: b.source.data ?? ""
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const userParts = [...textParts];
|
|
813
|
+
if (functionParts.length > 0) userParts.push(...functionParts);
|
|
814
|
+
if (userParts.length > 0) out.push({ role: "user", parts: userParts });
|
|
815
|
+
}
|
|
816
|
+
return out;
|
|
817
|
+
}
|
|
818
|
+
async function* parseGoogleStream(body, fallbackModel) {
|
|
819
|
+
let model = fallbackModel;
|
|
820
|
+
let usage = { input: 0, output: 0 };
|
|
821
|
+
let stopReason = "end_turn";
|
|
822
|
+
let started = false;
|
|
823
|
+
let sawFunctionCall = false;
|
|
824
|
+
for await (const msg of parseSSE(body)) {
|
|
825
|
+
if (!msg.data || msg.data === "[DONE]") continue;
|
|
826
|
+
const parsed = safeParse(msg.data);
|
|
827
|
+
if (!parsed.ok || !parsed.value) continue;
|
|
828
|
+
const obj = parsed.value;
|
|
829
|
+
if (obj.modelVersion) model = obj.modelVersion;
|
|
830
|
+
if (!started) {
|
|
831
|
+
started = true;
|
|
832
|
+
yield { type: "message_start", model };
|
|
833
|
+
}
|
|
834
|
+
const candidate = obj.candidates?.[0];
|
|
835
|
+
for (const part of candidate?.content?.parts ?? []) {
|
|
836
|
+
if (typeof part.text === "string" && part.text.length > 0) {
|
|
837
|
+
yield { type: "text_delta", text: part.text };
|
|
838
|
+
} else if (part.functionCall) {
|
|
839
|
+
sawFunctionCall = true;
|
|
840
|
+
const id = randomUUID();
|
|
841
|
+
yield { type: "tool_use_start", id, name: part.functionCall.name };
|
|
842
|
+
const providerMeta = typeof part.thoughtSignature === "string" ? { "google.thoughtSignature": part.thoughtSignature } : void 0;
|
|
843
|
+
yield {
|
|
844
|
+
type: "tool_use_stop",
|
|
845
|
+
id,
|
|
846
|
+
input: part.functionCall.args ?? {},
|
|
847
|
+
...providerMeta ? { providerMeta } : {}
|
|
848
|
+
};
|
|
592
849
|
}
|
|
593
850
|
}
|
|
851
|
+
if (candidate?.finishReason) {
|
|
852
|
+
stopReason = normalizeGemini(candidate.finishReason);
|
|
853
|
+
}
|
|
854
|
+
const u = obj.usageMetadata;
|
|
855
|
+
if (u) {
|
|
856
|
+
const cached = u.cachedContentTokenCount ?? 0;
|
|
857
|
+
const promptTotal = u.promptTokenCount ?? usage.input + cached;
|
|
858
|
+
usage = {
|
|
859
|
+
input: Math.max(0, promptTotal - cached),
|
|
860
|
+
output: u.candidatesTokenCount ?? usage.output,
|
|
861
|
+
cacheRead: cached || usage.cacheRead
|
|
862
|
+
};
|
|
863
|
+
}
|
|
594
864
|
}
|
|
595
865
|
if (started) {
|
|
596
|
-
|
|
866
|
+
const finalStop = sawFunctionCall ? "tool_use" : stopReason;
|
|
867
|
+
yield { type: "message_stop", stopReason: finalStop, usage };
|
|
597
868
|
}
|
|
598
869
|
}
|
|
870
|
+
|
|
871
|
+
// src/openai.ts
|
|
599
872
|
init_tool_input();
|
|
600
873
|
|
|
601
874
|
// src/tool-format/to-openai.ts
|
|
@@ -645,7 +918,9 @@ function messagesToOpenAI(system, messages, opts = {}) {
|
|
|
645
918
|
const blocks = normalizeContent(msg.content);
|
|
646
919
|
const textBlocks = blocks.filter((b) => b.type === "text");
|
|
647
920
|
const toolUses = blocks.filter((b) => b.type === "tool_use");
|
|
921
|
+
const thinkingBlocks = blocks.filter((b) => b.type === "thinking");
|
|
648
922
|
const text = textBlocks.map((b) => b.text).join("");
|
|
923
|
+
const reasoning = thinkingBlocks.map((b) => b.thinking).filter((t) => t && t.length > 0).join("");
|
|
649
924
|
const toolCalls = toolUses.map((u) => ({
|
|
650
925
|
id: u.id,
|
|
651
926
|
type: "function",
|
|
@@ -662,6 +937,9 @@ function messagesToOpenAI(system, messages, opts = {}) {
|
|
|
662
937
|
} else {
|
|
663
938
|
message.content = text;
|
|
664
939
|
}
|
|
940
|
+
if (reasoning.length > 0) {
|
|
941
|
+
message.reasoning_content = reasoning;
|
|
942
|
+
}
|
|
665
943
|
out.push(message);
|
|
666
944
|
}
|
|
667
945
|
}
|
|
@@ -693,13 +971,13 @@ function blocksToContentArray(blocks) {
|
|
|
693
971
|
}
|
|
694
972
|
|
|
695
973
|
// src/openai.ts
|
|
696
|
-
var
|
|
974
|
+
var DEFAULT_BASE3 = "https://api.openai.com/v1";
|
|
697
975
|
var OpenAIProvider = class extends WireAdapter {
|
|
698
976
|
id;
|
|
699
977
|
capabilities;
|
|
700
978
|
opts;
|
|
701
979
|
constructor(opts) {
|
|
702
|
-
super(opts.apiKey, opts.baseUrl ??
|
|
980
|
+
super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE3, opts.fetchImpl);
|
|
703
981
|
this.opts = opts;
|
|
704
982
|
this.id = opts.id ?? "openai";
|
|
705
983
|
this.capabilities = capabilitiesForFamily("openai", {
|
|
@@ -771,6 +1049,7 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
771
1049
|
let usage = { input: 0, output: 0 };
|
|
772
1050
|
let stopReason = "end_turn";
|
|
773
1051
|
let started = false;
|
|
1052
|
+
let thinkingOpen = false;
|
|
774
1053
|
const toolByIndex = /* @__PURE__ */ new Map();
|
|
775
1054
|
for await (const msg of parseSSE(body)) {
|
|
776
1055
|
if (!msg.data || msg.data === "[DONE]") continue;
|
|
@@ -784,10 +1063,26 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
784
1063
|
}
|
|
785
1064
|
const choices = obj["choices"];
|
|
786
1065
|
const choice = choices?.[0];
|
|
1066
|
+
const reasoningDelta = typeof choice?.delta?.reasoning_content === "string" ? choice.delta.reasoning_content : typeof choice?.delta?.reasoning === "string" ? choice.delta.reasoning : void 0;
|
|
1067
|
+
if (reasoningDelta && reasoningDelta.length > 0) {
|
|
1068
|
+
if (!thinkingOpen) {
|
|
1069
|
+
thinkingOpen = true;
|
|
1070
|
+
yield { type: "thinking_start" };
|
|
1071
|
+
}
|
|
1072
|
+
yield { type: "thinking_delta", text: reasoningDelta };
|
|
1073
|
+
}
|
|
787
1074
|
if (choice?.delta?.content) {
|
|
1075
|
+
if (thinkingOpen) {
|
|
1076
|
+
thinkingOpen = false;
|
|
1077
|
+
yield { type: "thinking_stop" };
|
|
1078
|
+
}
|
|
788
1079
|
yield { type: "text_delta", text: choice.delta.content };
|
|
789
1080
|
}
|
|
790
1081
|
if (choice?.delta?.tool_calls) {
|
|
1082
|
+
if (thinkingOpen) {
|
|
1083
|
+
thinkingOpen = false;
|
|
1084
|
+
yield { type: "thinking_stop" };
|
|
1085
|
+
}
|
|
791
1086
|
for (const tc of choice.delta.tool_calls) {
|
|
792
1087
|
const idx = tc.index ?? 0;
|
|
793
1088
|
let entry = toolByIndex.get(idx);
|
|
@@ -811,13 +1106,18 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
811
1106
|
}
|
|
812
1107
|
const u = obj["usage"];
|
|
813
1108
|
if (u) {
|
|
1109
|
+
const cached = u.prompt_tokens_details?.cached_tokens ?? 0;
|
|
1110
|
+
const promptTotal = u.prompt_tokens ?? usage.input + cached;
|
|
814
1111
|
usage = {
|
|
815
|
-
input:
|
|
1112
|
+
input: Math.max(0, promptTotal - cached),
|
|
816
1113
|
output: u.completion_tokens ?? usage.output,
|
|
817
|
-
cacheRead:
|
|
1114
|
+
cacheRead: cached || usage.cacheRead
|
|
818
1115
|
};
|
|
819
1116
|
}
|
|
820
1117
|
}
|
|
1118
|
+
if (thinkingOpen) {
|
|
1119
|
+
yield { type: "thinking_stop" };
|
|
1120
|
+
}
|
|
821
1121
|
for (const entry of toolByIndex.values()) {
|
|
822
1122
|
const input = parseToolInput(entry.argBuf);
|
|
823
1123
|
yield { type: "tool_use_stop", id: entry.id, input };
|
|
@@ -860,220 +1160,6 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
860
1160
|
};
|
|
861
1161
|
}
|
|
862
1162
|
};
|
|
863
|
-
var DEFAULT_BASE3 = "https://generativelanguage.googleapis.com/v1beta";
|
|
864
|
-
var GoogleProvider = class extends WireAdapter {
|
|
865
|
-
id;
|
|
866
|
-
capabilities;
|
|
867
|
-
opts;
|
|
868
|
-
constructor(opts) {
|
|
869
|
-
super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE3, opts.fetchImpl);
|
|
870
|
-
this.opts = opts;
|
|
871
|
-
this.id = opts.id ?? "google";
|
|
872
|
-
this.capabilities = capabilitiesForFamily("google", {
|
|
873
|
-
...opts.capabilities
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
buildUrl(req) {
|
|
877
|
-
return `${this.baseUrl}/models/${encodeURIComponent(req.model)}:streamGenerateContent?alt=sse`;
|
|
878
|
-
}
|
|
879
|
-
buildHeaders(req) {
|
|
880
|
-
return {
|
|
881
|
-
...super.buildHeaders(req),
|
|
882
|
-
"x-goog-api-key": this.apiKey
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
buildBody(req) {
|
|
886
|
-
const body = {
|
|
887
|
-
contents: messagesToGemini(req.messages),
|
|
888
|
-
generationConfig: this.buildGenConfig(req)
|
|
889
|
-
};
|
|
890
|
-
if (req.system && req.system.length > 0) {
|
|
891
|
-
body["systemInstruction"] = {
|
|
892
|
-
parts: req.system.map((b) => ({ text: b.text }))
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
if (req.tools && req.tools.length > 0) {
|
|
896
|
-
body["tools"] = [{ functionDeclarations: toolsToGemini(req.tools) }];
|
|
897
|
-
}
|
|
898
|
-
return body;
|
|
899
|
-
}
|
|
900
|
-
parseStream(body, fallbackModel) {
|
|
901
|
-
return parseGoogleStream(body, fallbackModel);
|
|
902
|
-
}
|
|
903
|
-
translateError(status, text) {
|
|
904
|
-
return parseProviderHttpError(this.id, status, text);
|
|
905
|
-
}
|
|
906
|
-
buildGenConfig(req) {
|
|
907
|
-
const cfg = { maxOutputTokens: req.maxTokens };
|
|
908
|
-
if (req.temperature !== void 0) cfg["temperature"] = req.temperature;
|
|
909
|
-
if (req.topP !== void 0) cfg["topP"] = req.topP;
|
|
910
|
-
if (req.stopSequences) cfg["stopSequences"] = req.stopSequences;
|
|
911
|
-
return cfg;
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
function toolsToGemini(tools) {
|
|
915
|
-
return tools.map((t) => ({
|
|
916
|
-
name: t.name,
|
|
917
|
-
description: t.description,
|
|
918
|
-
parameters: sanitizeSchemaForGemini(t.inputSchema) ?? { type: "object", properties: {} }
|
|
919
|
-
}));
|
|
920
|
-
}
|
|
921
|
-
var GEMINI_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
922
|
-
"type",
|
|
923
|
-
"format",
|
|
924
|
-
"description",
|
|
925
|
-
"nullable",
|
|
926
|
-
"enum",
|
|
927
|
-
"items",
|
|
928
|
-
"properties",
|
|
929
|
-
"required",
|
|
930
|
-
"anyOf",
|
|
931
|
-
"minLength",
|
|
932
|
-
"maxLength",
|
|
933
|
-
"pattern",
|
|
934
|
-
"minimum",
|
|
935
|
-
"maximum",
|
|
936
|
-
"minItems",
|
|
937
|
-
"maxItems",
|
|
938
|
-
"minProperties",
|
|
939
|
-
"maxProperties",
|
|
940
|
-
"propertyOrdering",
|
|
941
|
-
"title"
|
|
942
|
-
]);
|
|
943
|
-
function sanitizeSchemaForGemini(node) {
|
|
944
|
-
if (node === null || node === void 0) return void 0;
|
|
945
|
-
if (Array.isArray(node)) {
|
|
946
|
-
return void 0;
|
|
947
|
-
}
|
|
948
|
-
if (typeof node !== "object") return void 0;
|
|
949
|
-
const src = node;
|
|
950
|
-
const out = {};
|
|
951
|
-
for (const [k, v] of Object.entries(src)) {
|
|
952
|
-
if (!GEMINI_ALLOWED_KEYS.has(k)) continue;
|
|
953
|
-
if (k === "properties" && v && typeof v === "object") {
|
|
954
|
-
const props = {};
|
|
955
|
-
for (const [pname, pschema] of Object.entries(v)) {
|
|
956
|
-
const cleaned = sanitizeSchemaForGemini(pschema);
|
|
957
|
-
if (cleaned) props[pname] = cleaned;
|
|
958
|
-
}
|
|
959
|
-
out["properties"] = props;
|
|
960
|
-
} else if (k === "items") {
|
|
961
|
-
const cleaned = sanitizeSchemaForGemini(v);
|
|
962
|
-
if (cleaned) out["items"] = cleaned;
|
|
963
|
-
} else if (k === "anyOf" && Array.isArray(v)) {
|
|
964
|
-
const cleaned = v.map((s) => sanitizeSchemaForGemini(s)).filter((s) => s !== void 0);
|
|
965
|
-
if (cleaned.length > 0) out["anyOf"] = cleaned;
|
|
966
|
-
} else if (k === "required" && Array.isArray(v)) {
|
|
967
|
-
out["required"] = v.filter((s) => typeof s === "string");
|
|
968
|
-
} else if (k === "enum" && Array.isArray(v)) {
|
|
969
|
-
out["enum"] = v;
|
|
970
|
-
} else {
|
|
971
|
-
out[k] = v;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return out;
|
|
975
|
-
}
|
|
976
|
-
function messagesToGemini(messages) {
|
|
977
|
-
const out = [];
|
|
978
|
-
for (const m of messages) {
|
|
979
|
-
if (m.role === "system") continue;
|
|
980
|
-
const blocks = typeof m.content === "string" ? [{ type: "text", text: m.content }] : m.content;
|
|
981
|
-
if (m.role === "assistant") {
|
|
982
|
-
const parts = [];
|
|
983
|
-
for (const b of blocks) {
|
|
984
|
-
if (b.type === "text" && b.text) parts.push({ text: b.text });
|
|
985
|
-
else if (b.type === "tool_use") {
|
|
986
|
-
const part = {
|
|
987
|
-
functionCall: { name: b.name, args: b.input }
|
|
988
|
-
};
|
|
989
|
-
const sig = b.providerMeta?.["google.thoughtSignature"];
|
|
990
|
-
if (typeof sig === "string" && sig.length > 0) {
|
|
991
|
-
part.thoughtSignature = sig;
|
|
992
|
-
}
|
|
993
|
-
parts.push(part);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
if (parts.length > 0) out.push({ role: "model", parts });
|
|
997
|
-
continue;
|
|
998
|
-
}
|
|
999
|
-
const textParts = [];
|
|
1000
|
-
const functionParts = [];
|
|
1001
|
-
for (const b of blocks) {
|
|
1002
|
-
if (b.type === "text" && b.text) textParts.push({ text: b.text });
|
|
1003
|
-
else if (b.type === "tool_result") {
|
|
1004
|
-
const responseText = typeof b.content === "string" ? b.content : JSON.stringify(b.content);
|
|
1005
|
-
const fnName = b.name ?? b.tool_use_id;
|
|
1006
|
-
functionParts.push({
|
|
1007
|
-
functionResponse: {
|
|
1008
|
-
name: fnName,
|
|
1009
|
-
response: { content: responseText }
|
|
1010
|
-
}
|
|
1011
|
-
});
|
|
1012
|
-
} else if (b.type === "image" && b.source.type === "base64") {
|
|
1013
|
-
textParts.push({
|
|
1014
|
-
inlineData: {
|
|
1015
|
-
mimeType: b.source.media_type ?? "image/png",
|
|
1016
|
-
data: b.source.data ?? ""
|
|
1017
|
-
}
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
const userParts = [...textParts];
|
|
1022
|
-
if (functionParts.length > 0) userParts.push(...functionParts);
|
|
1023
|
-
if (userParts.length > 0) out.push({ role: "user", parts: userParts });
|
|
1024
|
-
}
|
|
1025
|
-
return out;
|
|
1026
|
-
}
|
|
1027
|
-
async function* parseGoogleStream(body, fallbackModel) {
|
|
1028
|
-
let model = fallbackModel;
|
|
1029
|
-
let usage = { input: 0, output: 0 };
|
|
1030
|
-
let stopReason = "end_turn";
|
|
1031
|
-
let started = false;
|
|
1032
|
-
let sawFunctionCall = false;
|
|
1033
|
-
for await (const msg of parseSSE(body)) {
|
|
1034
|
-
if (!msg.data || msg.data === "[DONE]") continue;
|
|
1035
|
-
const parsed = safeParse(msg.data);
|
|
1036
|
-
if (!parsed.ok || !parsed.value) continue;
|
|
1037
|
-
const obj = parsed.value;
|
|
1038
|
-
if (obj.modelVersion) model = obj.modelVersion;
|
|
1039
|
-
if (!started) {
|
|
1040
|
-
started = true;
|
|
1041
|
-
yield { type: "message_start", model };
|
|
1042
|
-
}
|
|
1043
|
-
const candidate = obj.candidates?.[0];
|
|
1044
|
-
for (const part of candidate?.content?.parts ?? []) {
|
|
1045
|
-
if (typeof part.text === "string" && part.text.length > 0) {
|
|
1046
|
-
yield { type: "text_delta", text: part.text };
|
|
1047
|
-
} else if (part.functionCall) {
|
|
1048
|
-
sawFunctionCall = true;
|
|
1049
|
-
const id = randomUUID();
|
|
1050
|
-
yield { type: "tool_use_start", id, name: part.functionCall.name };
|
|
1051
|
-
const providerMeta = typeof part.thoughtSignature === "string" ? { "google.thoughtSignature": part.thoughtSignature } : void 0;
|
|
1052
|
-
yield {
|
|
1053
|
-
type: "tool_use_stop",
|
|
1054
|
-
id,
|
|
1055
|
-
input: part.functionCall.args ?? {},
|
|
1056
|
-
...providerMeta ? { providerMeta } : {}
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
if (candidate?.finishReason) {
|
|
1061
|
-
stopReason = normalizeGemini(candidate.finishReason);
|
|
1062
|
-
}
|
|
1063
|
-
const u = obj.usageMetadata;
|
|
1064
|
-
if (u) {
|
|
1065
|
-
usage = {
|
|
1066
|
-
input: u.promptTokenCount ?? usage.input,
|
|
1067
|
-
output: u.candidatesTokenCount ?? usage.output,
|
|
1068
|
-
cacheRead: u.cachedContentTokenCount ?? usage.cacheRead
|
|
1069
|
-
};
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
if (started) {
|
|
1073
|
-
const finalStop = sawFunctionCall ? "tool_use" : stopReason;
|
|
1074
|
-
yield { type: "message_stop", stopReason: finalStop, usage };
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
1163
|
|
|
1078
1164
|
// src/wire-format.ts
|
|
1079
1165
|
var WireFormatProvider = class extends WireAdapter {
|
|
@@ -1356,13 +1442,9 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1356
1442
|
break;
|
|
1357
1443
|
case "error": {
|
|
1358
1444
|
const err = ev["error"];
|
|
1359
|
-
throw new ProviderError(
|
|
1360
|
-
err?.message
|
|
1361
|
-
|
|
1362
|
-
false,
|
|
1363
|
-
"anthropic",
|
|
1364
|
-
{ body: { type: err?.type, message: err?.message } }
|
|
1365
|
-
);
|
|
1445
|
+
throw new ProviderError(err?.message ?? "Anthropic stream error", 0, false, "anthropic", {
|
|
1446
|
+
body: { type: err?.type, message: err?.message }
|
|
1447
|
+
});
|
|
1366
1448
|
}
|
|
1367
1449
|
}
|
|
1368
1450
|
return out;
|
|
@@ -1421,6 +1503,7 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1421
1503
|
stopReason: "end_turn",
|
|
1422
1504
|
started: false,
|
|
1423
1505
|
textOpen: false,
|
|
1506
|
+
thinkingOpen: false,
|
|
1424
1507
|
toolByIndex: /* @__PURE__ */ new Map(),
|
|
1425
1508
|
finalEmitted: false
|
|
1426
1509
|
}),
|
|
@@ -1437,11 +1520,27 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1437
1520
|
}
|
|
1438
1521
|
const choices = obj["choices"];
|
|
1439
1522
|
const choice = choices?.[0];
|
|
1523
|
+
const reasoningDelta = typeof choice?.delta?.reasoning_content === "string" ? choice.delta.reasoning_content : typeof choice?.delta?.reasoning === "string" ? choice.delta.reasoning : void 0;
|
|
1524
|
+
if (reasoningDelta && reasoningDelta.length > 0) {
|
|
1525
|
+
if (!state.thinkingOpen) {
|
|
1526
|
+
state.thinkingOpen = true;
|
|
1527
|
+
out.push({ type: "thinking_start" });
|
|
1528
|
+
}
|
|
1529
|
+
out.push({ type: "thinking_delta", text: reasoningDelta });
|
|
1530
|
+
}
|
|
1440
1531
|
if (choice?.delta?.content) {
|
|
1532
|
+
if (state.thinkingOpen) {
|
|
1533
|
+
state.thinkingOpen = false;
|
|
1534
|
+
out.push({ type: "thinking_stop" });
|
|
1535
|
+
}
|
|
1441
1536
|
if (!state.textOpen) state.textOpen = true;
|
|
1442
1537
|
out.push({ type: "text_delta", text: choice.delta.content });
|
|
1443
1538
|
}
|
|
1444
1539
|
if (choice?.delta?.tool_calls) {
|
|
1540
|
+
if (state.thinkingOpen) {
|
|
1541
|
+
state.thinkingOpen = false;
|
|
1542
|
+
out.push({ type: "thinking_stop" });
|
|
1543
|
+
}
|
|
1445
1544
|
for (const tc of choice.delta.tool_calls) {
|
|
1446
1545
|
const idx = tc.index ?? 0;
|
|
1447
1546
|
let entry = state.toolByIndex.get(idx);
|
|
@@ -1466,10 +1565,12 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1466
1565
|
}
|
|
1467
1566
|
const u = obj["usage"];
|
|
1468
1567
|
if (u) {
|
|
1568
|
+
const cached = u.prompt_tokens_details?.cached_tokens ?? 0;
|
|
1569
|
+
const promptTotal = u.prompt_tokens ?? state.usage.input + cached;
|
|
1469
1570
|
state.usage = {
|
|
1470
|
-
input:
|
|
1571
|
+
input: Math.max(0, promptTotal - cached),
|
|
1471
1572
|
output: u.completion_tokens ?? state.usage.output,
|
|
1472
|
-
cacheRead:
|
|
1573
|
+
cacheRead: cached || state.usage.cacheRead
|
|
1473
1574
|
};
|
|
1474
1575
|
}
|
|
1475
1576
|
return out;
|
|
@@ -1478,6 +1579,10 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1478
1579
|
if (state.finalEmitted) return [];
|
|
1479
1580
|
state.finalEmitted = true;
|
|
1480
1581
|
const out = [];
|
|
1582
|
+
if (state.thinkingOpen) {
|
|
1583
|
+
state.thinkingOpen = false;
|
|
1584
|
+
out.push({ type: "thinking_stop" });
|
|
1585
|
+
}
|
|
1481
1586
|
for (const entry of state.toolByIndex.values()) {
|
|
1482
1587
|
const input = parseToolInput(entry.argBuf);
|
|
1483
1588
|
out.push({ type: "tool_use_stop", id: entry.id, input });
|
|
@@ -1542,7 +1647,7 @@ var googleWireFormat = defineWireFormat({
|
|
|
1542
1647
|
out.push({ type: "text_delta", text: part.text });
|
|
1543
1648
|
} else if (part.functionCall) {
|
|
1544
1649
|
state.sawFunctionCall = true;
|
|
1545
|
-
const id = `${part.functionCall.name}_${
|
|
1650
|
+
const id = `${part.functionCall.name}_${randomUUID().slice(0, 8)}`;
|
|
1546
1651
|
out.push({ type: "tool_use_start", id, name: part.functionCall.name });
|
|
1547
1652
|
const providerMeta = typeof part.thoughtSignature === "string" ? { "google.thoughtSignature": part.thoughtSignature } : void 0;
|
|
1548
1653
|
out.push({
|
|
@@ -1558,10 +1663,12 @@ var googleWireFormat = defineWireFormat({
|
|
|
1558
1663
|
}
|
|
1559
1664
|
const u = obj.usageMetadata;
|
|
1560
1665
|
if (u) {
|
|
1666
|
+
const cached = u.cachedContentTokenCount ?? 0;
|
|
1667
|
+
const promptTotal = u.promptTokenCount ?? state.usage.input + cached;
|
|
1561
1668
|
state.usage = {
|
|
1562
|
-
input:
|
|
1669
|
+
input: Math.max(0, promptTotal - cached),
|
|
1563
1670
|
output: u.candidatesTokenCount ?? state.usage.output,
|
|
1564
|
-
cacheRead:
|
|
1671
|
+
cacheRead: cached || state.usage.cacheRead
|
|
1565
1672
|
};
|
|
1566
1673
|
}
|
|
1567
1674
|
return out;
|
|
@@ -1725,6 +1832,12 @@ function contentFromAnthropic(blocks, opts = {}) {
|
|
|
1725
1832
|
content: normalizeToolResultContent(b.content, opts),
|
|
1726
1833
|
is_error: b.is_error
|
|
1727
1834
|
});
|
|
1835
|
+
} else if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
1836
|
+
out.push({
|
|
1837
|
+
type: "thinking",
|
|
1838
|
+
thinking: b.thinking,
|
|
1839
|
+
...b.signature ? { signature: b.signature } : {}
|
|
1840
|
+
});
|
|
1728
1841
|
} else if (b.type === "image" && b.source) {
|
|
1729
1842
|
const src = b.source;
|
|
1730
1843
|
const kind = src.type === "url" ? "url" : "base64";
|