@wrongstack/providers 0.3.3 → 0.3.4
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 +33 -21
- package/dist/index.d.ts +7 -3
- package/dist/index.js +128 -37
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Most providers ride a single declarative `WireFormatConfig` adapter; only the th
|
|
|
10
10
|
pnpm add @wrongstack/providers @wrongstack/core
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
`@wrongstack/core`
|
|
13
|
+
`@wrongstack/core` provides the shared `Provider` interface, message types, and tool format.
|
|
14
14
|
|
|
15
15
|
## What's in here
|
|
16
16
|
|
|
@@ -37,13 +37,16 @@ import { AnthropicProvider } from '@wrongstack/providers';
|
|
|
37
37
|
|
|
38
38
|
const provider = new AnthropicProvider({
|
|
39
39
|
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
40
|
-
modelId: 'claude-sonnet-4-6',
|
|
41
40
|
});
|
|
42
41
|
|
|
43
|
-
const stream = provider.stream(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
42
|
+
const stream = provider.stream(
|
|
43
|
+
{
|
|
44
|
+
model: 'claude-sonnet-4-6',
|
|
45
|
+
messages: [{ role: 'user', content: 'hello' }],
|
|
46
|
+
maxTokens: 512,
|
|
47
|
+
},
|
|
48
|
+
{ signal: new AbortController().signal },
|
|
49
|
+
);
|
|
47
50
|
|
|
48
51
|
for await (const event of stream) {
|
|
49
52
|
if (event.type === 'text_delta') process.stdout.write(event.text);
|
|
@@ -58,39 +61,48 @@ import { OpenAICompatibleProvider } from '@wrongstack/providers';
|
|
|
58
61
|
const groq = new OpenAICompatibleProvider({
|
|
59
62
|
id: 'groq',
|
|
60
63
|
apiKey: process.env.GROQ_API_KEY!,
|
|
61
|
-
|
|
62
|
-
modelId: 'llama-3.3-70b-versatile',
|
|
64
|
+
baseUrl: 'https://api.groq.com/openai/v1',
|
|
63
65
|
capabilities: { tools: true, vision: false, maxContext: 128_000 },
|
|
64
66
|
});
|
|
67
|
+
|
|
68
|
+
const result = await groq.complete(
|
|
69
|
+
{
|
|
70
|
+
model: 'llama-3.3-70b-versatile',
|
|
71
|
+
messages: [{ role: 'user', content: 'hello' }],
|
|
72
|
+
maxTokens: 512,
|
|
73
|
+
},
|
|
74
|
+
{ signal: new AbortController().signal },
|
|
75
|
+
);
|
|
65
76
|
```
|
|
66
77
|
|
|
67
78
|
## Wire-format adapter (declarative)
|
|
68
79
|
|
|
69
|
-
For a new provider that doesn't fit one of the existing presets, write a `WireFormatConfig` and plug it into `
|
|
80
|
+
For a new provider that doesn't fit one of the existing presets, write a `WireFormatConfig` and plug it into `WireFormatProvider`. See [docs/provider-author-guide.md](../../docs/provider-author-guide.md) for the full spec.
|
|
70
81
|
|
|
71
82
|
```ts
|
|
72
|
-
import {
|
|
73
|
-
import type { WireFormatConfig } from '@wrongstack/core';
|
|
83
|
+
import { WireFormatProvider, type WireFormatConfig } from '@wrongstack/providers';
|
|
74
84
|
|
|
75
85
|
const myWire: WireFormatConfig = {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
id: 'myprovider',
|
|
87
|
+
family: 'openai-compatible',
|
|
88
|
+
capabilities: { tools: true, parallelTools: true, vision: false, streaming: true, promptCache: false, systemPrompt: true, jsonMode: false, maxContext: 32_000, cacheControl: 'none' },
|
|
89
|
+
defaultBaseUrl: 'https://api.myprovider.com/v1',
|
|
90
|
+
buildUrl: (baseUrl) => `${baseUrl.replace(/\/+$/, '')}/chat/completions`,
|
|
91
|
+
buildHeaders: (apiKey) => ({ authorization: `Bearer ${apiKey}` }),
|
|
92
|
+
buildBody: (req) => ({ model: req.model, messages: req.messages, max_tokens: req.maxTokens, stream: true }),
|
|
93
|
+
createStreamState: (fallbackModel) => ({ model: fallbackModel, started: false }),
|
|
94
|
+
parseStreamEvent: () => [],
|
|
95
|
+
finalizeStream: () => [{ type: 'message_stop', stopReason: 'end_turn', usage: { input: 0, output: 0 } }],
|
|
80
96
|
};
|
|
81
97
|
|
|
82
|
-
const provider = new
|
|
83
|
-
id: 'myprovider',
|
|
98
|
+
const provider = new WireFormatProvider(myWire, {
|
|
84
99
|
apiKey: '…',
|
|
85
|
-
modelId: 'my-model-1',
|
|
86
|
-
wire: myWire,
|
|
87
|
-
capabilities: { tools: true, maxContext: 32_000 },
|
|
88
100
|
});
|
|
89
101
|
```
|
|
90
102
|
|
|
91
103
|
## Tool input parsing (`parseToolInput`)
|
|
92
104
|
|
|
93
|
-
|
|
105
|
+
Anthropic/OpenAI-style stream parsers and the aggregate path run tool-call JSON through one canonical helper: [`_tool-input.ts`](src/_tool-input.ts). It guarantees the agent always receives a `Record<string, unknown>` for `tool_use.input`, never a parse-error or `null`. Invalid or non-object inputs are wrapped under `{ __raw: ... }` instead of crashing the provider runner.
|
|
94
106
|
|
|
95
107
|
## Capabilities
|
|
96
108
|
|
package/dist/index.d.ts
CHANGED
|
@@ -320,16 +320,18 @@ interface MistralStreamState {
|
|
|
320
320
|
name?: string;
|
|
321
321
|
partial: string;
|
|
322
322
|
emittedStart: boolean;
|
|
323
|
+
emittedArgLength: number;
|
|
323
324
|
}>;
|
|
324
325
|
}
|
|
325
326
|
declare const mistralWireFormat: WireFormatConfig<MistralStreamState>;
|
|
326
327
|
|
|
327
|
-
type BlockKind = 'text' | 'tool_use' | 'unknown';
|
|
328
|
+
type BlockKind = 'text' | 'tool_use' | 'thinking' | 'unknown';
|
|
328
329
|
interface AnthropicStreamState {
|
|
329
330
|
model: string;
|
|
330
331
|
usage: Usage;
|
|
331
332
|
stopReason: StopReason;
|
|
332
333
|
started: boolean;
|
|
334
|
+
stopped: boolean;
|
|
333
335
|
blocks: Map<number, {
|
|
334
336
|
kind: BlockKind;
|
|
335
337
|
id?: string;
|
|
@@ -347,9 +349,11 @@ interface OpenAIStreamState {
|
|
|
347
349
|
textOpen: boolean;
|
|
348
350
|
thinkingOpen: boolean;
|
|
349
351
|
toolByIndex: Map<number, {
|
|
350
|
-
id
|
|
351
|
-
name
|
|
352
|
+
id?: string;
|
|
353
|
+
name?: string;
|
|
352
354
|
argBuf: string;
|
|
355
|
+
emittedStart: boolean;
|
|
356
|
+
emittedArgLength: number;
|
|
353
357
|
}>;
|
|
354
358
|
finalEmitted: boolean;
|
|
355
359
|
}
|
package/dist/index.js
CHANGED
|
@@ -554,6 +554,7 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
554
554
|
let usage = { input: 0, output: 0 };
|
|
555
555
|
let stopReason = "end_turn";
|
|
556
556
|
let started = false;
|
|
557
|
+
let stopped = false;
|
|
557
558
|
for await (const msg of parseSSE(body)) {
|
|
558
559
|
if (!msg.data || msg.data === "[DONE]") continue;
|
|
559
560
|
const parsed = safeParse(msg.data);
|
|
@@ -634,6 +635,7 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
634
635
|
break;
|
|
635
636
|
}
|
|
636
637
|
case "message_stop":
|
|
638
|
+
stopped = true;
|
|
637
639
|
yield { type: "message_stop", stopReason, usage };
|
|
638
640
|
break;
|
|
639
641
|
case "error": {
|
|
@@ -644,7 +646,7 @@ async function* parseAnthropicStream(body, fallbackModel) {
|
|
|
644
646
|
}
|
|
645
647
|
}
|
|
646
648
|
}
|
|
647
|
-
if (started) {
|
|
649
|
+
if (started && !stopped) {
|
|
648
650
|
yield { type: "message_stop", stopReason, usage };
|
|
649
651
|
}
|
|
650
652
|
}
|
|
@@ -1086,17 +1088,33 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
1086
1088
|
for (const tc of choice.delta.tool_calls) {
|
|
1087
1089
|
const idx = tc.index ?? 0;
|
|
1088
1090
|
let entry = toolByIndex.get(idx);
|
|
1089
|
-
if (!entry
|
|
1090
|
-
entry = {
|
|
1091
|
+
if (!entry) {
|
|
1092
|
+
entry = {
|
|
1093
|
+
id: tc.id,
|
|
1094
|
+
name: tc.function?.name,
|
|
1095
|
+
argBuf: "",
|
|
1096
|
+
emittedStart: false,
|
|
1097
|
+
emittedArgLength: 0
|
|
1098
|
+
};
|
|
1091
1099
|
toolByIndex.set(idx, entry);
|
|
1092
|
-
|
|
1100
|
+
} else {
|
|
1101
|
+
if (tc.id && !entry.id) entry.id = tc.id;
|
|
1102
|
+
if (tc.function?.name && !entry.name) entry.name = tc.function.name;
|
|
1093
1103
|
}
|
|
1094
|
-
if (
|
|
1104
|
+
if (tc.function?.arguments) {
|
|
1095
1105
|
entry.argBuf += tc.function.arguments;
|
|
1106
|
+
}
|
|
1107
|
+
if (!entry.emittedStart && entry.id && entry.name) {
|
|
1108
|
+
entry.emittedStart = true;
|
|
1109
|
+
yield { type: "tool_use_start", id: entry.id, name: entry.name };
|
|
1110
|
+
}
|
|
1111
|
+
if (entry.emittedStart && entry.id && entry.emittedArgLength < entry.argBuf.length) {
|
|
1112
|
+
const partial = entry.argBuf.slice(entry.emittedArgLength);
|
|
1113
|
+
entry.emittedArgLength = entry.argBuf.length;
|
|
1096
1114
|
yield {
|
|
1097
1115
|
type: "tool_use_input_delta",
|
|
1098
1116
|
id: entry.id,
|
|
1099
|
-
partial
|
|
1117
|
+
partial
|
|
1100
1118
|
};
|
|
1101
1119
|
}
|
|
1102
1120
|
}
|
|
@@ -1106,10 +1124,11 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
1106
1124
|
}
|
|
1107
1125
|
const u = obj["usage"];
|
|
1108
1126
|
if (u) {
|
|
1109
|
-
const
|
|
1110
|
-
const
|
|
1127
|
+
const hasDeepSeekCacheFields = u.prompt_cache_hit_tokens !== void 0 || u.prompt_cache_miss_tokens !== void 0;
|
|
1128
|
+
const cached = u.prompt_tokens_details?.cached_tokens ?? u.prompt_cache_hit_tokens ?? 0;
|
|
1129
|
+
const promptTotal = u.prompt_tokens ?? (hasDeepSeekCacheFields ? (u.prompt_cache_hit_tokens ?? 0) + (u.prompt_cache_miss_tokens ?? 0) : usage.input + cached);
|
|
1111
1130
|
usage = {
|
|
1112
|
-
input: Math.max(0, promptTotal - cached),
|
|
1131
|
+
input: u.prompt_cache_miss_tokens ?? Math.max(0, promptTotal - cached),
|
|
1113
1132
|
output: u.completion_tokens ?? usage.output,
|
|
1114
1133
|
cacheRead: cached || usage.cacheRead
|
|
1115
1134
|
};
|
|
@@ -1119,6 +1138,10 @@ async function* parseOpenAIStream(body, fallbackModel) {
|
|
|
1119
1138
|
yield { type: "thinking_stop" };
|
|
1120
1139
|
}
|
|
1121
1140
|
for (const entry of toolByIndex.values()) {
|
|
1141
|
+
if (!entry.id || !entry.name) continue;
|
|
1142
|
+
if (!entry.emittedStart) {
|
|
1143
|
+
yield { type: "tool_use_start", id: entry.id, name: entry.name };
|
|
1144
|
+
}
|
|
1122
1145
|
const input = parseToolInput(entry.argBuf);
|
|
1123
1146
|
yield { type: "tool_use_stop", id: entry.id, input };
|
|
1124
1147
|
}
|
|
@@ -1237,16 +1260,31 @@ var mistralWireFormat = defineWireFormat({
|
|
|
1237
1260
|
defaultBaseUrl: "https://api.mistral.ai/v1",
|
|
1238
1261
|
buildUrl: (base) => `${base.replace(/\/+$/, "")}/chat/completions`,
|
|
1239
1262
|
buildHeaders: (apiKey) => ({ authorization: `Bearer ${apiKey}` }),
|
|
1240
|
-
buildBody: (req) =>
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1263
|
+
buildBody: (req) => {
|
|
1264
|
+
const body = {
|
|
1265
|
+
model: req.model,
|
|
1266
|
+
messages: messagesToOpenAI(stripCacheControl(req.system), req.messages, {}),
|
|
1267
|
+
max_tokens: req.maxTokens,
|
|
1268
|
+
stream: true
|
|
1269
|
+
};
|
|
1270
|
+
if (req.tools && req.tools.length > 0) {
|
|
1271
|
+
body["tools"] = toolsToOpenAI(req.tools);
|
|
1272
|
+
if (req.toolChoice) {
|
|
1273
|
+
if (typeof req.toolChoice === "string") {
|
|
1274
|
+
body["tool_choice"] = req.toolChoice === "required" ? "required" : req.toolChoice;
|
|
1275
|
+
} else {
|
|
1276
|
+
body["tool_choice"] = {
|
|
1277
|
+
type: "function",
|
|
1278
|
+
function: { name: req.toolChoice.name }
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (req.temperature !== void 0) body["temperature"] = req.temperature;
|
|
1284
|
+
if (req.topP !== void 0) body["top_p"] = req.topP;
|
|
1285
|
+
if (req.stopSequences) body["stop"] = req.stopSequences;
|
|
1286
|
+
return body;
|
|
1287
|
+
},
|
|
1250
1288
|
createStreamState: (fallbackModel) => ({
|
|
1251
1289
|
model: fallbackModel,
|
|
1252
1290
|
started: false,
|
|
@@ -1270,25 +1308,38 @@ var mistralWireFormat = defineWireFormat({
|
|
|
1270
1308
|
for (const tc of choice?.delta?.tool_calls ?? []) {
|
|
1271
1309
|
let block = state.toolCalls.get(tc.index);
|
|
1272
1310
|
if (!block) {
|
|
1273
|
-
block = {
|
|
1311
|
+
block = {
|
|
1312
|
+
id: tc.id,
|
|
1313
|
+
name: tc.function?.name,
|
|
1314
|
+
partial: "",
|
|
1315
|
+
emittedStart: false,
|
|
1316
|
+
emittedArgLength: 0
|
|
1317
|
+
};
|
|
1274
1318
|
state.toolCalls.set(tc.index, block);
|
|
1275
1319
|
} else {
|
|
1276
1320
|
if (tc.id && !block.id) block.id = tc.id;
|
|
1277
1321
|
if (tc.function?.name && !block.name) block.name = tc.function.name;
|
|
1278
1322
|
}
|
|
1323
|
+
const arg = tc.function?.arguments;
|
|
1324
|
+
if (arg) {
|
|
1325
|
+
block.partial += arg;
|
|
1326
|
+
}
|
|
1279
1327
|
if (!block.emittedStart && block.id && block.name) {
|
|
1280
1328
|
block.emittedStart = true;
|
|
1281
1329
|
out.push({ type: "tool_use_start", id: block.id, name: block.name });
|
|
1282
1330
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
block.
|
|
1286
|
-
out.push({ type: "tool_use_input_delta", id: block.id, partial
|
|
1331
|
+
if (block.emittedStart && block.id && block.emittedArgLength < block.partial.length) {
|
|
1332
|
+
const partial = block.partial.slice(block.emittedArgLength);
|
|
1333
|
+
block.emittedArgLength = block.partial.length;
|
|
1334
|
+
out.push({ type: "tool_use_input_delta", id: block.id, partial });
|
|
1287
1335
|
}
|
|
1288
1336
|
}
|
|
1289
1337
|
if (choice?.finish_reason) {
|
|
1290
1338
|
for (const block of state.toolCalls.values()) {
|
|
1291
|
-
if (block.id) {
|
|
1339
|
+
if (block.id && block.name) {
|
|
1340
|
+
if (!block.emittedStart) {
|
|
1341
|
+
out.push({ type: "tool_use_start", id: block.id, name: block.name });
|
|
1342
|
+
}
|
|
1292
1343
|
out.push({
|
|
1293
1344
|
type: "tool_use_stop",
|
|
1294
1345
|
id: block.id,
|
|
@@ -1313,13 +1364,21 @@ function mapStopReason(reason) {
|
|
|
1313
1364
|
case "tool_calls":
|
|
1314
1365
|
return "tool_use";
|
|
1315
1366
|
case "length":
|
|
1367
|
+
case "model_length":
|
|
1316
1368
|
return "max_tokens";
|
|
1317
1369
|
case "stop":
|
|
1318
|
-
return "
|
|
1370
|
+
return "end_turn";
|
|
1319
1371
|
default:
|
|
1320
1372
|
return "end_turn";
|
|
1321
1373
|
}
|
|
1322
1374
|
}
|
|
1375
|
+
function stripCacheControl(system) {
|
|
1376
|
+
if (!system) return void 0;
|
|
1377
|
+
return system.map((b) => {
|
|
1378
|
+
const { cache_control: _cc, ...rest } = b;
|
|
1379
|
+
return rest;
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1323
1382
|
|
|
1324
1383
|
// src/presets/anthropic.ts
|
|
1325
1384
|
init_tool_input();
|
|
@@ -1362,6 +1421,7 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1362
1421
|
usage: { input: 0, output: 0 },
|
|
1363
1422
|
stopReason: "end_turn",
|
|
1364
1423
|
started: false,
|
|
1424
|
+
stopped: false,
|
|
1365
1425
|
blocks: /* @__PURE__ */ new Map()
|
|
1366
1426
|
}),
|
|
1367
1427
|
parseStreamEvent: (msg, state) => {
|
|
@@ -1397,6 +1457,9 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1397
1457
|
}
|
|
1398
1458
|
} else if (cb?.type === "text") {
|
|
1399
1459
|
state.blocks.set(index, { kind: "text", partial: "" });
|
|
1460
|
+
} else if (cb?.type === "thinking" || cb?.type === "redacted_thinking") {
|
|
1461
|
+
state.blocks.set(index, { kind: "thinking", partial: "" });
|
|
1462
|
+
out.push({ type: "thinking_start" });
|
|
1400
1463
|
} else {
|
|
1401
1464
|
state.blocks.set(index, { kind: "unknown", partial: "" });
|
|
1402
1465
|
}
|
|
@@ -1414,6 +1477,10 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1414
1477
|
block.partial += delta.partial_json;
|
|
1415
1478
|
out.push({ type: "tool_use_input_delta", id: block.id, partial: delta.partial_json });
|
|
1416
1479
|
}
|
|
1480
|
+
} else if (delta.type === "thinking_delta" && typeof delta.thinking === "string") {
|
|
1481
|
+
out.push({ type: "thinking_delta", text: delta.thinking });
|
|
1482
|
+
} else if (delta.type === "signature_delta" && typeof delta.signature === "string") {
|
|
1483
|
+
out.push({ type: "thinking_signature", signature: delta.signature });
|
|
1417
1484
|
}
|
|
1418
1485
|
break;
|
|
1419
1486
|
}
|
|
@@ -1423,6 +1490,8 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1423
1490
|
if (block?.kind === "tool_use" && block.id) {
|
|
1424
1491
|
const input = parseToolInput(block.partial);
|
|
1425
1492
|
out.push({ type: "tool_use_stop", id: block.id, input });
|
|
1493
|
+
} else if (block?.kind === "thinking") {
|
|
1494
|
+
out.push({ type: "thinking_stop" });
|
|
1426
1495
|
}
|
|
1427
1496
|
break;
|
|
1428
1497
|
}
|
|
@@ -1438,6 +1507,7 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1438
1507
|
break;
|
|
1439
1508
|
}
|
|
1440
1509
|
case "message_stop":
|
|
1510
|
+
state.stopped = true;
|
|
1441
1511
|
out.push({ type: "message_stop", stopReason: state.stopReason, usage: state.usage });
|
|
1442
1512
|
break;
|
|
1443
1513
|
case "error": {
|
|
@@ -1450,7 +1520,7 @@ var anthropicWireFormat = defineWireFormat({
|
|
|
1450
1520
|
return out;
|
|
1451
1521
|
},
|
|
1452
1522
|
finalizeStream: (state) => {
|
|
1453
|
-
if (state.started) {
|
|
1523
|
+
if (state.started && !state.stopped) {
|
|
1454
1524
|
return [{ type: "message_stop", stopReason: state.stopReason, usage: state.usage }];
|
|
1455
1525
|
}
|
|
1456
1526
|
return [];
|
|
@@ -1474,7 +1544,7 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1474
1544
|
buildBody: (req) => {
|
|
1475
1545
|
const body = {
|
|
1476
1546
|
model: req.model,
|
|
1477
|
-
messages: messagesToOpenAI(
|
|
1547
|
+
messages: messagesToOpenAI(stripCacheControl2(req.system), req.messages, {}),
|
|
1478
1548
|
max_tokens: req.maxTokens,
|
|
1479
1549
|
stream: true,
|
|
1480
1550
|
stream_options: { include_usage: true }
|
|
@@ -1544,18 +1614,34 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1544
1614
|
for (const tc of choice.delta.tool_calls) {
|
|
1545
1615
|
const idx = tc.index ?? 0;
|
|
1546
1616
|
let entry = state.toolByIndex.get(idx);
|
|
1547
|
-
if (!entry
|
|
1548
|
-
entry = {
|
|
1617
|
+
if (!entry) {
|
|
1618
|
+
entry = {
|
|
1619
|
+
id: tc.id,
|
|
1620
|
+
name: tc.function?.name,
|
|
1621
|
+
argBuf: "",
|
|
1622
|
+
emittedStart: false,
|
|
1623
|
+
emittedArgLength: 0
|
|
1624
|
+
};
|
|
1549
1625
|
state.toolByIndex.set(idx, entry);
|
|
1626
|
+
} else {
|
|
1627
|
+
if (tc.id && !entry.id) entry.id = tc.id;
|
|
1628
|
+
if (tc.function?.name && !entry.name) entry.name = tc.function.name;
|
|
1629
|
+
}
|
|
1630
|
+
if (tc.function?.arguments) {
|
|
1631
|
+
entry.argBuf += tc.function.arguments;
|
|
1632
|
+
}
|
|
1633
|
+
if (!entry.emittedStart && entry.id && entry.name) {
|
|
1634
|
+
entry.emittedStart = true;
|
|
1550
1635
|
state.textOpen = false;
|
|
1551
1636
|
out.push({ type: "tool_use_start", id: entry.id, name: entry.name });
|
|
1552
1637
|
}
|
|
1553
|
-
if (entry &&
|
|
1554
|
-
entry.argBuf
|
|
1638
|
+
if (entry.emittedStart && entry.id && entry.emittedArgLength < entry.argBuf.length) {
|
|
1639
|
+
const partial = entry.argBuf.slice(entry.emittedArgLength);
|
|
1640
|
+
entry.emittedArgLength = entry.argBuf.length;
|
|
1555
1641
|
out.push({
|
|
1556
1642
|
type: "tool_use_input_delta",
|
|
1557
1643
|
id: entry.id,
|
|
1558
|
-
partial
|
|
1644
|
+
partial
|
|
1559
1645
|
});
|
|
1560
1646
|
}
|
|
1561
1647
|
}
|
|
@@ -1565,10 +1651,11 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1565
1651
|
}
|
|
1566
1652
|
const u = obj["usage"];
|
|
1567
1653
|
if (u) {
|
|
1568
|
-
const
|
|
1569
|
-
const
|
|
1654
|
+
const hasDeepSeekCacheFields = u.prompt_cache_hit_tokens !== void 0 || u.prompt_cache_miss_tokens !== void 0;
|
|
1655
|
+
const cached = u.prompt_tokens_details?.cached_tokens ?? u.prompt_cache_hit_tokens ?? 0;
|
|
1656
|
+
const promptTotal = u.prompt_tokens ?? (hasDeepSeekCacheFields ? (u.prompt_cache_hit_tokens ?? 0) + (u.prompt_cache_miss_tokens ?? 0) : state.usage.input + cached);
|
|
1570
1657
|
state.usage = {
|
|
1571
|
-
input: Math.max(0, promptTotal - cached),
|
|
1658
|
+
input: u.prompt_cache_miss_tokens ?? Math.max(0, promptTotal - cached),
|
|
1572
1659
|
output: u.completion_tokens ?? state.usage.output,
|
|
1573
1660
|
cacheRead: cached || state.usage.cacheRead
|
|
1574
1661
|
};
|
|
@@ -1584,6 +1671,10 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1584
1671
|
out.push({ type: "thinking_stop" });
|
|
1585
1672
|
}
|
|
1586
1673
|
for (const entry of state.toolByIndex.values()) {
|
|
1674
|
+
if (!entry.id || !entry.name) continue;
|
|
1675
|
+
if (!entry.emittedStart) {
|
|
1676
|
+
out.push({ type: "tool_use_start", id: entry.id, name: entry.name });
|
|
1677
|
+
}
|
|
1587
1678
|
const input = parseToolInput(entry.argBuf);
|
|
1588
1679
|
out.push({ type: "tool_use_stop", id: entry.id, input });
|
|
1589
1680
|
}
|
|
@@ -1593,7 +1684,7 @@ var openaiWireFormat = defineWireFormat({
|
|
|
1593
1684
|
return out;
|
|
1594
1685
|
}
|
|
1595
1686
|
});
|
|
1596
|
-
function
|
|
1687
|
+
function stripCacheControl2(system) {
|
|
1597
1688
|
if (!system) return void 0;
|
|
1598
1689
|
return system.map((b) => {
|
|
1599
1690
|
const { cache_control: _cc, ...rest } = b;
|