@agentskit/adapters 0.13.12 → 0.13.16
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 -3
- package/dist/catalog/index.cjs +197 -60
- package/dist/catalog/index.cjs.map +1 -1
- package/dist/catalog/index.d.cts +1 -1
- package/dist/catalog/index.d.ts +1 -1
- package/dist/catalog/index.js +2 -1
- package/dist/catalog/index.js.map +1 -1
- package/dist/{chunk-77QS3QRT.js → chunk-4KZTWGRB.js} +249 -119
- package/dist/chunk-4KZTWGRB.js.map +1 -0
- package/dist/chunk-627FHZZY.js +101 -0
- package/dist/chunk-627FHZZY.js.map +1 -0
- package/dist/chunk-6CIB2QCH.js +81 -0
- package/dist/chunk-6CIB2QCH.js.map +1 -0
- package/dist/createAdapter-C-pKR1aO.d.cts +19 -0
- package/dist/createAdapter-C-pKR1aO.d.ts +19 -0
- package/dist/createAdapter.cjs +138 -15
- package/dist/createAdapter.cjs.map +1 -1
- package/dist/createAdapter.d.cts +1 -1
- package/dist/createAdapter.d.ts +1 -1
- package/dist/createAdapter.js +2 -1
- package/dist/index.cjs +1090 -319
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -13
- package/dist/index.d.ts +33 -13
- package/dist/index.js +686 -191
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
- package/dist/chunk-6FPLWOVE.js +0 -26
- package/dist/chunk-6FPLWOVE.js.map +0 -1
- package/dist/chunk-77QS3QRT.js.map +0 -1
- package/dist/createAdapter-Dfnf3Iio.d.cts +0 -14
- package/dist/createAdapter-Dfnf3Iio.d.ts +0 -14
|
@@ -1,39 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const output = [];
|
|
5
|
-
for (const message of messages) {
|
|
6
|
-
if (message.role === "tool") {
|
|
7
|
-
const id = message.toolCallId;
|
|
8
|
-
if (!id || !knownToolCallIds.has(id)) continue;
|
|
9
|
-
output.push({
|
|
10
|
-
role: "tool",
|
|
11
|
-
content: message.content,
|
|
12
|
-
tool_call_id: id
|
|
13
|
-
});
|
|
14
|
-
continue;
|
|
15
|
-
}
|
|
16
|
-
if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
|
|
17
|
-
for (const tc of message.toolCalls) knownToolCallIds.add(tc.id);
|
|
18
|
-
output.push({
|
|
19
|
-
role: "assistant",
|
|
20
|
-
content: message.content || null,
|
|
21
|
-
tool_calls: message.toolCalls.map((tc) => ({
|
|
22
|
-
id: tc.id,
|
|
23
|
-
type: "function",
|
|
24
|
-
function: {
|
|
25
|
-
name: tc.name,
|
|
26
|
-
arguments: typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args ?? {})
|
|
27
|
-
}
|
|
28
|
-
}))
|
|
29
|
-
});
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (message.role === "assistant" && !message.content) continue;
|
|
33
|
-
output.push({ role: message.role, content: message.content });
|
|
34
|
-
}
|
|
35
|
-
return output;
|
|
36
|
-
}
|
|
1
|
+
import { adapterErrorChunk, parseCompleteToolArgs, cancelBody, abortableSleep, isAbortError } from './chunk-6CIB2QCH.js';
|
|
2
|
+
|
|
3
|
+
// src/stream-lines.ts
|
|
37
4
|
async function* readSSELines(stream) {
|
|
38
5
|
const reader = stream.getReader();
|
|
39
6
|
const decoder = new TextDecoder();
|
|
@@ -75,23 +42,61 @@ async function* readNDJSONLines(stream) {
|
|
|
75
42
|
reader.releaseLock();
|
|
76
43
|
}
|
|
77
44
|
}
|
|
45
|
+
|
|
46
|
+
// src/openai-stream.ts
|
|
47
|
+
var SUCCESS_FINISH_REASONS = /* @__PURE__ */ new Set(["stop", "tool_calls", "function_call"]);
|
|
78
48
|
async function* parseOpenAIStream(stream) {
|
|
79
49
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
50
|
+
let finishReason;
|
|
51
|
+
const terminalError = (message, extra) => {
|
|
52
|
+
const chunk = adapterErrorChunk(message);
|
|
53
|
+
return {
|
|
54
|
+
...chunk,
|
|
55
|
+
metadata: { ...chunk.metadata, ...extra, finishReason }
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const flushToolCalls = function* () {
|
|
59
|
+
for (const [, toolCall] of pendingToolCalls) {
|
|
60
|
+
const parsed = parseCompleteToolArgs(toolCall.args);
|
|
61
|
+
if (!parsed.ok) {
|
|
62
|
+
pendingToolCalls.clear();
|
|
63
|
+
yield {
|
|
64
|
+
type: "error",
|
|
65
|
+
content: parsed.error.message,
|
|
66
|
+
metadata: { error: parsed.error, finishReason }
|
|
67
|
+
};
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
yield {
|
|
71
|
+
type: "tool_call",
|
|
72
|
+
toolCall: { id: toolCall.id, name: toolCall.name, args: parsed.args }
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
pendingToolCalls.clear();
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
80
78
|
for await (const data of readSSELines(stream)) {
|
|
81
79
|
if (data === "[DONE]") {
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
if (finishReason !== void 0 && !SUCCESS_FINISH_REASONS.has(finishReason)) {
|
|
81
|
+
pendingToolCalls.clear();
|
|
82
|
+
yield terminalError(
|
|
83
|
+
`OpenAI stream ended with non-success finish reason "${finishReason}".`,
|
|
84
|
+
{ finishReason }
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
84
87
|
}
|
|
85
|
-
|
|
88
|
+
if (!(yield* flushToolCalls())) return;
|
|
86
89
|
yield { type: "done" };
|
|
87
90
|
return;
|
|
88
91
|
}
|
|
89
92
|
try {
|
|
90
93
|
const event = JSON.parse(data);
|
|
91
94
|
const delta = event.choices?.[0]?.delta;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
const candidateFinishReason = event.choices?.find(
|
|
96
|
+
(choice) => typeof choice.finish_reason === "string"
|
|
97
|
+
)?.finish_reason;
|
|
98
|
+
if (typeof candidateFinishReason === "string") finishReason = candidateFinishReason;
|
|
99
|
+
if (typeof delta?.content === "string") yield { type: "text", content: delta.content };
|
|
95
100
|
if (Array.isArray(delta?.tool_calls)) {
|
|
96
101
|
for (const toolCall of delta.tool_calls) {
|
|
97
102
|
const index = toolCall.index ?? 0;
|
|
@@ -120,18 +125,87 @@ async function* parseOpenAIStream(stream) {
|
|
|
120
125
|
} catch {
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
if (finishReason !== void 0 && !SUCCESS_FINISH_REASONS.has(finishReason)) {
|
|
129
|
+
pendingToolCalls.clear();
|
|
130
|
+
yield terminalError(
|
|
131
|
+
`OpenAI stream ended with non-success finish reason "${finishReason}".`,
|
|
132
|
+
{ finishReason }
|
|
133
|
+
);
|
|
134
|
+
return;
|
|
125
135
|
}
|
|
126
|
-
|
|
136
|
+
if (!finishReason) {
|
|
137
|
+
pendingToolCalls.clear();
|
|
138
|
+
yield terminalError("OpenAI stream ended before a terminal marker.");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!(yield* flushToolCalls())) return;
|
|
127
142
|
yield { type: "done" };
|
|
128
143
|
}
|
|
144
|
+
|
|
145
|
+
// src/utils.ts
|
|
146
|
+
function toProviderMessages(messages) {
|
|
147
|
+
const knownToolCallIds = /* @__PURE__ */ new Set();
|
|
148
|
+
const output = [];
|
|
149
|
+
for (const message of messages) {
|
|
150
|
+
if (message.role === "tool") {
|
|
151
|
+
const id = message.toolCallId;
|
|
152
|
+
if (!id || !knownToolCallIds.has(id)) continue;
|
|
153
|
+
output.push({
|
|
154
|
+
role: "tool",
|
|
155
|
+
content: message.content,
|
|
156
|
+
tool_call_id: id
|
|
157
|
+
});
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (message.role === "assistant" && message.toolCalls && message.toolCalls.length > 0) {
|
|
161
|
+
for (const tc of message.toolCalls) knownToolCallIds.add(tc.id);
|
|
162
|
+
output.push({
|
|
163
|
+
role: "assistant",
|
|
164
|
+
content: message.content || null,
|
|
165
|
+
tool_calls: message.toolCalls.map((tc) => ({
|
|
166
|
+
id: tc.id,
|
|
167
|
+
type: "function",
|
|
168
|
+
function: {
|
|
169
|
+
name: tc.name,
|
|
170
|
+
arguments: typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args ?? {})
|
|
171
|
+
}
|
|
172
|
+
}))
|
|
173
|
+
});
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (message.role === "assistant" && !message.content) continue;
|
|
177
|
+
output.push({ role: message.role, content: message.content });
|
|
178
|
+
}
|
|
179
|
+
return output;
|
|
180
|
+
}
|
|
129
181
|
async function* parseAnthropicStream(stream) {
|
|
130
182
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
183
|
+
let sawMessageStop = false;
|
|
184
|
+
const emitToolCall = function* (tc) {
|
|
185
|
+
const parsed = parseCompleteToolArgs(tc.args);
|
|
186
|
+
if (!parsed.ok) {
|
|
187
|
+
yield {
|
|
188
|
+
type: "error",
|
|
189
|
+
content: parsed.error.message,
|
|
190
|
+
metadata: { error: parsed.error }
|
|
191
|
+
};
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
yield {
|
|
195
|
+
type: "tool_call",
|
|
196
|
+
toolCall: { id: tc.id, name: tc.name, args: parsed.args }
|
|
197
|
+
};
|
|
198
|
+
return true;
|
|
199
|
+
};
|
|
131
200
|
for await (const data of readSSELines(stream)) {
|
|
132
201
|
if (data === "[DONE]") continue;
|
|
133
202
|
try {
|
|
134
203
|
const event = JSON.parse(data);
|
|
204
|
+
if (event.type === "error") {
|
|
205
|
+
const msg = event.error?.message ?? event.error?.type ?? "Anthropic stream error";
|
|
206
|
+
yield adapterErrorChunk(String(msg));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
135
209
|
if (event.type === "content_block_delta" && event.delta?.type === "text_delta" && event.delta?.text) {
|
|
136
210
|
yield { type: "text", content: event.delta.text };
|
|
137
211
|
} else if (event.type === "content_block_delta" && event.delta?.type === "input_json_delta") {
|
|
@@ -143,22 +217,18 @@ async function* parseAnthropicStream(stream) {
|
|
|
143
217
|
} else if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
|
|
144
218
|
const index = event.index ?? 0;
|
|
145
219
|
pendingToolCalls.set(index, {
|
|
146
|
-
id: event.content_block.id
|
|
147
|
-
name: event.content_block.name,
|
|
220
|
+
id: event.content_block.id ?? `tool-${index}`,
|
|
221
|
+
name: event.content_block.name ?? "unknown",
|
|
148
222
|
args: ""
|
|
149
223
|
});
|
|
150
224
|
} else if (event.type === "content_block_stop") {
|
|
151
225
|
const index = event.index ?? 0;
|
|
152
226
|
const tc = pendingToolCalls.get(index);
|
|
153
227
|
if (tc) {
|
|
154
|
-
yield {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
name: tc.name,
|
|
159
|
-
args: tc.args || "{}"
|
|
160
|
-
}
|
|
161
|
-
};
|
|
228
|
+
if (!(yield* emitToolCall(tc))) {
|
|
229
|
+
pendingToolCalls.clear();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
162
232
|
pendingToolCalls.delete(index);
|
|
163
233
|
}
|
|
164
234
|
} else if (event.type === "message_delta" && event.usage) {
|
|
@@ -180,8 +250,12 @@ async function* parseAnthropicStream(stream) {
|
|
|
180
250
|
}
|
|
181
251
|
};
|
|
182
252
|
} else if (event.type === "message_stop") {
|
|
253
|
+
sawMessageStop = true;
|
|
183
254
|
for (const [, tc] of pendingToolCalls) {
|
|
184
|
-
yield
|
|
255
|
+
if (!(yield* emitToolCall(tc))) {
|
|
256
|
+
pendingToolCalls.clear();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
185
259
|
}
|
|
186
260
|
pendingToolCalls.clear();
|
|
187
261
|
yield { type: "done" };
|
|
@@ -190,13 +264,20 @@ async function* parseAnthropicStream(stream) {
|
|
|
190
264
|
} catch {
|
|
191
265
|
}
|
|
192
266
|
}
|
|
193
|
-
for (const [, tc] of pendingToolCalls) {
|
|
194
|
-
yield { type: "tool_call", toolCall: { id: tc.id, name: tc.name, args: tc.args || "{}" } };
|
|
195
|
-
}
|
|
196
267
|
pendingToolCalls.clear();
|
|
268
|
+
if (!sawMessageStop) {
|
|
269
|
+
yield adapterErrorChunk("Anthropic stream ended before message_stop");
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
197
272
|
yield { type: "done" };
|
|
198
273
|
}
|
|
274
|
+
var GEMINI_SUCCESS_FINISH = /* @__PURE__ */ new Set([
|
|
275
|
+
"STOP",
|
|
276
|
+
"stop",
|
|
277
|
+
"FINISH_REASON_STOP"
|
|
278
|
+
]);
|
|
199
279
|
async function* parseGeminiStream(stream) {
|
|
280
|
+
let finishReason;
|
|
200
281
|
for await (const data of readSSELines(stream)) {
|
|
201
282
|
try {
|
|
202
283
|
const event = JSON.parse(data);
|
|
@@ -210,19 +291,33 @@ async function* parseGeminiStream(stream) {
|
|
|
210
291
|
}
|
|
211
292
|
};
|
|
212
293
|
}
|
|
213
|
-
const
|
|
294
|
+
const candidate = event.candidates?.[0];
|
|
295
|
+
if (typeof candidate?.finishReason === "string") {
|
|
296
|
+
finishReason = candidate.finishReason;
|
|
297
|
+
}
|
|
298
|
+
const parts = candidate?.content?.parts;
|
|
214
299
|
if (!Array.isArray(parts)) continue;
|
|
215
300
|
for (const part of parts) {
|
|
216
301
|
if (typeof part.text === "string" && part.text) {
|
|
217
302
|
yield { type: "text", content: part.text };
|
|
218
303
|
} else if (part.functionCall) {
|
|
219
304
|
const fc = part.functionCall;
|
|
305
|
+
const args = typeof fc.args === "string" ? fc.args : JSON.stringify(fc.args ?? {});
|
|
306
|
+
const parsed = parseCompleteToolArgs(args);
|
|
307
|
+
if (!parsed.ok) {
|
|
308
|
+
yield {
|
|
309
|
+
type: "error",
|
|
310
|
+
content: parsed.error.message,
|
|
311
|
+
metadata: { error: parsed.error }
|
|
312
|
+
};
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
220
315
|
yield {
|
|
221
316
|
type: "tool_call",
|
|
222
317
|
toolCall: {
|
|
223
318
|
id: fc.id ?? `${fc.name}-${Date.now()}`,
|
|
224
|
-
name: fc.name,
|
|
225
|
-
args:
|
|
319
|
+
name: fc.name ?? "unknown",
|
|
320
|
+
args: parsed.args
|
|
226
321
|
}
|
|
227
322
|
};
|
|
228
323
|
}
|
|
@@ -230,9 +325,20 @@ async function* parseGeminiStream(stream) {
|
|
|
230
325
|
} catch {
|
|
231
326
|
}
|
|
232
327
|
}
|
|
328
|
+
if (!finishReason || !GEMINI_SUCCESS_FINISH.has(finishReason)) {
|
|
329
|
+
if (finishReason && !GEMINI_SUCCESS_FINISH.has(finishReason)) {
|
|
330
|
+
yield adapterErrorChunk(
|
|
331
|
+
`Gemini stream ended with non-success finish reason "${finishReason}"`
|
|
332
|
+
);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
yield adapterErrorChunk("Gemini stream ended without a successful finishReason");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
233
338
|
yield { type: "done" };
|
|
234
339
|
}
|
|
235
340
|
async function* parseOllamaStream(stream) {
|
|
341
|
+
let sawDone = false;
|
|
236
342
|
for await (const data of readNDJSONLines(stream)) {
|
|
237
343
|
try {
|
|
238
344
|
const event = JSON.parse(data);
|
|
@@ -242,18 +348,29 @@ async function* parseOllamaStream(stream) {
|
|
|
242
348
|
if (Array.isArray(event.message?.tool_calls)) {
|
|
243
349
|
for (const tc of event.message.tool_calls) {
|
|
244
350
|
if (tc?.function?.name) {
|
|
351
|
+
const args = typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments ?? {});
|
|
352
|
+
const parsed = parseCompleteToolArgs(args);
|
|
353
|
+
if (!parsed.ok) {
|
|
354
|
+
yield {
|
|
355
|
+
type: "error",
|
|
356
|
+
content: parsed.error.message,
|
|
357
|
+
metadata: { error: parsed.error }
|
|
358
|
+
};
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
245
361
|
yield {
|
|
246
362
|
type: "tool_call",
|
|
247
363
|
toolCall: {
|
|
248
364
|
id: tc.id ?? `${tc.function.name}-${Date.now()}`,
|
|
249
365
|
name: tc.function.name,
|
|
250
|
-
args:
|
|
366
|
+
args: parsed.args
|
|
251
367
|
}
|
|
252
368
|
};
|
|
253
369
|
}
|
|
254
370
|
}
|
|
255
371
|
}
|
|
256
372
|
if (event.done) {
|
|
373
|
+
sawDone = true;
|
|
257
374
|
if (typeof event.prompt_eval_count === "number" || typeof event.eval_count === "number") {
|
|
258
375
|
const promptTokens = event.prompt_eval_count ?? 0;
|
|
259
376
|
const completionTokens = event.eval_count ?? 0;
|
|
@@ -272,6 +389,10 @@ async function* parseOllamaStream(stream) {
|
|
|
272
389
|
} catch {
|
|
273
390
|
}
|
|
274
391
|
}
|
|
392
|
+
if (!sawDone) {
|
|
393
|
+
yield adapterErrorChunk("Ollama stream ended without done:true");
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
275
396
|
yield { type: "done" };
|
|
276
397
|
}
|
|
277
398
|
var DEFAULT_RETRY = {
|
|
@@ -283,7 +404,7 @@ var DEFAULT_RETRY = {
|
|
|
283
404
|
if (response) {
|
|
284
405
|
return [408, 429, 500, 502, 503, 504].includes(response.status);
|
|
285
406
|
}
|
|
286
|
-
if (error
|
|
407
|
+
if (isAbortError(error)) return false;
|
|
287
408
|
return true;
|
|
288
409
|
}
|
|
289
410
|
};
|
|
@@ -321,47 +442,23 @@ async function fetchWithRetry(doFetch, signal, retryOpt = {}) {
|
|
|
321
442
|
const retryAfterMs = parseRetryAfter(response.headers.get("retry-after"));
|
|
322
443
|
const delay = retryAfterMs ?? computeDelay(attempt, opts);
|
|
323
444
|
retryOpt.onRetry?.({ attempt, delayMs: delay, reason: `HTTP ${response.status}` });
|
|
324
|
-
await
|
|
325
|
-
|
|
326
|
-
});
|
|
445
|
+
await cancelBody(response.body);
|
|
446
|
+
await abortableSleep(delay, signal, sleep);
|
|
327
447
|
} catch (err) {
|
|
328
448
|
lastError = err;
|
|
329
|
-
if (err
|
|
449
|
+
if (isAbortError(err)) throw err;
|
|
330
450
|
if (attempt >= opts.maxAttempts || !opts.retryOn({ error: err, attempt })) throw err;
|
|
331
451
|
const delay = computeDelay(attempt, opts);
|
|
332
|
-
retryOpt.onRetry?.({
|
|
333
|
-
|
|
452
|
+
retryOpt.onRetry?.({
|
|
453
|
+
attempt,
|
|
454
|
+
delayMs: delay,
|
|
455
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
456
|
+
});
|
|
457
|
+
await abortableSleep(delay, signal, sleep);
|
|
334
458
|
}
|
|
335
459
|
}
|
|
336
460
|
throw lastError ?? new Error("fetchWithRetry: exhausted attempts");
|
|
337
461
|
}
|
|
338
|
-
function createStreamSource(doFetch, parse, errorLabel, retry) {
|
|
339
|
-
let abortController = new AbortController();
|
|
340
|
-
return {
|
|
341
|
-
stream: async function* () {
|
|
342
|
-
const controller = abortController;
|
|
343
|
-
if (!controller) return;
|
|
344
|
-
try {
|
|
345
|
-
const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
|
|
346
|
-
if (!response.ok || !response.body) {
|
|
347
|
-
yield { type: "error", content: `${errorLabel} error: ${response.status}` };
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
yield* parse(response.body);
|
|
351
|
-
} catch (err) {
|
|
352
|
-
if (err instanceof DOMException && err.name === "AbortError") return;
|
|
353
|
-
yield {
|
|
354
|
-
type: "error",
|
|
355
|
-
content: err instanceof Error ? err.message : String(err)
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
abort: () => {
|
|
360
|
-
abortController?.abort();
|
|
361
|
-
abortController = null;
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
462
|
function chunkText(text, targetSize = 32) {
|
|
366
463
|
if (text.length <= targetSize) return [text];
|
|
367
464
|
const out = [];
|
|
@@ -387,35 +484,68 @@ function simulateStream(doFetch, extractText, errorLabel, options = {}) {
|
|
|
387
484
|
try {
|
|
388
485
|
const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
|
|
389
486
|
if (!response.ok) {
|
|
390
|
-
|
|
487
|
+
await cancelBody(response.body);
|
|
488
|
+
yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
let text;
|
|
492
|
+
try {
|
|
493
|
+
text = await extractText(response);
|
|
494
|
+
} catch (err) {
|
|
495
|
+
await cancelBody(response.body);
|
|
496
|
+
if (isAbortError(err)) return;
|
|
497
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
498
|
+
yield adapterErrorChunk(message, { cause: err });
|
|
391
499
|
return;
|
|
392
500
|
}
|
|
393
|
-
const text = await extractText(response);
|
|
394
501
|
const chunks = chunkText(text, chunkSize);
|
|
395
502
|
for (const chunk of chunks) {
|
|
396
|
-
if (abortController === null) return;
|
|
503
|
+
if (abortController === null || controller.signal.aborted) return;
|
|
397
504
|
if (delayMs > 0) {
|
|
398
|
-
await
|
|
399
|
-
const timer = setTimeout(resolve, delayMs);
|
|
400
|
-
controller.signal.addEventListener(
|
|
401
|
-
"abort",
|
|
402
|
-
() => {
|
|
403
|
-
clearTimeout(timer);
|
|
404
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
405
|
-
},
|
|
406
|
-
{ once: true }
|
|
407
|
-
);
|
|
408
|
-
});
|
|
505
|
+
await abortableSleep(delayMs, controller.signal, defaultSleep);
|
|
409
506
|
}
|
|
410
507
|
yield { type: "text", content: chunk };
|
|
411
508
|
}
|
|
412
509
|
yield { type: "done" };
|
|
413
510
|
} catch (err) {
|
|
414
|
-
if (err
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
511
|
+
if (isAbortError(err)) return;
|
|
512
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
513
|
+
yield adapterErrorChunk(message, { cause: err });
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
abort: () => {
|
|
517
|
+
abortController?.abort();
|
|
518
|
+
abortController = null;
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// src/stream-source.ts
|
|
524
|
+
function createStreamSource(doFetch, parse, errorLabel, retry) {
|
|
525
|
+
let abortController = new AbortController();
|
|
526
|
+
return {
|
|
527
|
+
stream: async function* () {
|
|
528
|
+
const controller = abortController;
|
|
529
|
+
if (!controller) return;
|
|
530
|
+
try {
|
|
531
|
+
const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
|
|
532
|
+
if (!response.ok) {
|
|
533
|
+
await cancelBody(response.body);
|
|
534
|
+
yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (!response.body) {
|
|
538
|
+
yield adapterErrorChunk(`${errorLabel} error: empty response body`);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
for await (const chunk of parse(response.body, response)) {
|
|
542
|
+
if (controller.signal.aborted || abortController === null) return;
|
|
543
|
+
yield chunk;
|
|
544
|
+
}
|
|
545
|
+
} catch (err) {
|
|
546
|
+
if (isAbortError(err) || controller.signal.aborted || abortController === null) return;
|
|
547
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
548
|
+
yield adapterErrorChunk(message, { cause: err });
|
|
419
549
|
}
|
|
420
550
|
},
|
|
421
551
|
abort: () => {
|
|
@@ -482,6 +612,6 @@ function openai(config) {
|
|
|
482
612
|
};
|
|
483
613
|
}
|
|
484
614
|
|
|
485
|
-
export { chunkText, createStreamSource, fetchWithRetry, openai, parseAnthropicStream, parseGeminiStream, parseOllamaStream, parseOpenAIStream, simulateStream, toProviderMessages };
|
|
486
|
-
//# sourceMappingURL=chunk-
|
|
487
|
-
//# sourceMappingURL=chunk-
|
|
615
|
+
export { chunkText, createStreamSource, fetchWithRetry, openai, parseAnthropicStream, parseGeminiStream, parseOllamaStream, parseOpenAIStream, readSSELines, simulateStream, toProviderMessages };
|
|
616
|
+
//# sourceMappingURL=chunk-4KZTWGRB.js.map
|
|
617
|
+
//# sourceMappingURL=chunk-4KZTWGRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stream-lines.ts","../src/openai-stream.ts","../src/utils.ts","../src/stream-source.ts","../src/openai.ts"],"names":[],"mappings":"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","file":"chunk-4KZTWGRB.js","sourcesContent":["export async function* readSSELines(stream: ReadableStream): AsyncIterableIterator<string> {\n const reader = stream.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data) yield data\n }\n }\n } finally {\n reader.releaseLock()\n }\n}\n\nexport async function* readNDJSONLines(stream: ReadableStream): AsyncIterableIterator<string> {\n const reader = stream.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n const trimmed = line.trim()\n if (trimmed) yield trimmed\n }\n }\n } finally {\n reader.releaseLock()\n }\n}\n","import type { StreamChunk } from '@agentskit/core'\nimport { readSSELines } from './stream-lines'\nimport { adapterErrorChunk, parseCompleteToolArgs } from './stream-errors'\n\nconst SUCCESS_FINISH_REASONS = new Set(['stop', 'tool_calls', 'function_call'])\n\nexport async function* parseOpenAIStream(stream: ReadableStream): AsyncIterableIterator<StreamChunk> {\n const pendingToolCalls = new Map<number, { id: string; name: string; args: string }>()\n let finishReason: string | undefined\n\n const terminalError = (message: string, extra?: Record<string, unknown>): StreamChunk => {\n const chunk = adapterErrorChunk(message)\n return {\n ...chunk,\n metadata: { ...chunk.metadata, ...extra, finishReason },\n }\n }\n\n const flushToolCalls = function* (): Generator<StreamChunk, boolean> {\n for (const [, toolCall] of pendingToolCalls) {\n const parsed = parseCompleteToolArgs(toolCall.args)\n if (!parsed.ok) {\n pendingToolCalls.clear()\n yield {\n type: 'error',\n content: parsed.error.message,\n metadata: { error: parsed.error, finishReason },\n }\n return false\n }\n yield {\n type: 'tool_call',\n toolCall: { id: toolCall.id, name: toolCall.name, args: parsed.args },\n }\n }\n pendingToolCalls.clear()\n return true\n }\n\n for await (const data of readSSELines(stream)) {\n if (data === '[DONE]') {\n if (finishReason !== undefined && !SUCCESS_FINISH_REASONS.has(finishReason)) {\n pendingToolCalls.clear()\n yield terminalError(\n `OpenAI stream ended with non-success finish reason \"${finishReason}\".`,\n { finishReason },\n )\n return\n }\n if (!(yield* flushToolCalls())) return\n yield { type: 'done' }\n return\n }\n\n try {\n const event = JSON.parse(data) as {\n choices?: Array<{\n delta?: {\n content?: string\n tool_calls?: Array<{\n index?: number\n id?: string\n function?: { name?: string; arguments?: string }\n }>\n }\n finish_reason?: string\n }>\n usage?: {\n prompt_tokens?: number\n completion_tokens?: number\n total_tokens?: number\n }\n }\n const delta = event.choices?.[0]?.delta\n const candidateFinishReason = event.choices?.find(\n choice => typeof choice.finish_reason === 'string',\n )?.finish_reason\n if (typeof candidateFinishReason === 'string') finishReason = candidateFinishReason\n\n if (typeof delta?.content === 'string') yield { type: 'text', content: delta.content }\n\n if (Array.isArray(delta?.tool_calls)) {\n for (const toolCall of delta.tool_calls) {\n const index: number = toolCall.index ?? 0\n const existing = pendingToolCalls.get(index)\n if (toolCall?.function?.name) {\n pendingToolCalls.set(index, {\n id: toolCall.id ?? existing?.id ?? `tool-${index}-${Date.now()}`,\n name: toolCall.function.name,\n args: (existing?.args ?? '') + (toolCall.function.arguments ?? ''),\n })\n } else if (existing && toolCall?.function?.arguments) {\n existing.args += toolCall.function.arguments\n }\n }\n }\n\n if (event.usage) {\n yield {\n type: 'usage',\n usage: {\n promptTokens: event.usage.prompt_tokens ?? 0,\n completionTokens: event.usage.completion_tokens ?? 0,\n totalTokens: event.usage.total_tokens ?? 0,\n },\n } as StreamChunk\n }\n } catch {\n // Ignore malformed events.\n }\n }\n\n if (finishReason !== undefined && !SUCCESS_FINISH_REASONS.has(finishReason)) {\n pendingToolCalls.clear()\n yield terminalError(\n `OpenAI stream ended with non-success finish reason \"${finishReason}\".`,\n { finishReason },\n )\n return\n }\n if (!finishReason) {\n pendingToolCalls.clear()\n yield terminalError('OpenAI stream ended before a terminal marker.')\n return\n }\n\n if (!(yield* flushToolCalls())) return\n yield { type: 'done' }\n}\n","import type { Message, StreamChunk, StreamSource } from '@agentskit/core'\nimport { readNDJSONLines, readSSELines } from './stream-lines'\nimport {\n abortableSleep,\n adapterErrorChunk,\n cancelBody,\n isAbortError,\n parseCompleteToolArgs,\n} from './stream-errors'\n\nexport { parseOpenAIStream } from './openai-stream'\nexport { readNDJSONLines, readSSELines } from './stream-lines'\nexport type { StreamParser } from './stream-types'\n\nexport function toProviderMessages(messages: Message[]) {\n // Track which tool_call ids were declared by preceding assistant turns so\n // we can drop orphan tool messages — the OpenAI Chat Completions API\n // rejects a tool message whose tool_call_id isn't bound to a previous\n // assistant message.\n const knownToolCallIds = new Set<string>()\n const output: Array<Record<string, unknown>> = []\n\n for (const message of messages) {\n if (message.role === 'tool') {\n const id = message.toolCallId\n // Orphan (no id, or id not declared) — skip; it would 400 the API.\n if (!id || !knownToolCallIds.has(id)) continue\n output.push({\n role: 'tool' as const,\n content: message.content,\n tool_call_id: id,\n })\n continue\n }\n\n if (message.role === 'assistant' && message.toolCalls && message.toolCalls.length > 0) {\n for (const tc of message.toolCalls) knownToolCallIds.add(tc.id)\n output.push({\n role: 'assistant' as const,\n content: message.content || null,\n tool_calls: message.toolCalls.map(tc => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.name,\n arguments: typeof tc.args === 'string' ? tc.args : JSON.stringify(tc.args ?? {}),\n },\n })),\n })\n continue\n }\n\n // Skip assistant messages with no content AND no tool calls. These\n // happen when a turn was interrupted (Ctrl+C, crashed adapter, etc.)\n // and the placeholder assistant message never received content —\n // sending `{role:'assistant', content:''}` back to the provider either\n // 400s or confuses the model into silence on the next turn.\n if (message.role === 'assistant' && !message.content) continue\n\n output.push({ role: message.role, content: message.content })\n }\n\n return output\n}\nexport async function* parseAnthropicStream(stream: ReadableStream): AsyncIterableIterator<StreamChunk> {\n const pendingToolCalls = new Map<number, { id: string; name: string; args: string }>()\n let sawMessageStop = false\n\n const emitToolCall = function* (\n tc: { id: string; name: string; args: string },\n ): Generator<StreamChunk, boolean> {\n const parsed = parseCompleteToolArgs(tc.args)\n if (!parsed.ok) {\n yield {\n type: 'error',\n content: parsed.error.message,\n metadata: { error: parsed.error },\n }\n return false\n }\n yield {\n type: 'tool_call',\n toolCall: { id: tc.id, name: tc.name, args: parsed.args },\n }\n return true\n }\n\n for await (const data of readSSELines(stream)) {\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data) as {\n type?: string\n index?: number\n delta?: { type?: string; text?: string; partial_json?: string }\n content_block?: { type?: string; id?: string; name?: string }\n usage?: { input_tokens?: number; output_tokens?: number }\n message?: { usage?: { input_tokens?: number } }\n error?: { type?: string; message?: string }\n }\n\n if (event.type === 'error') {\n const msg =\n event.error?.message ??\n event.error?.type ??\n 'Anthropic stream error'\n yield adapterErrorChunk(String(msg))\n return\n }\n\n if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta' && event.delta?.text) {\n yield { type: 'text', content: event.delta.text }\n } else if (event.type === 'content_block_delta' && event.delta?.type === 'input_json_delta') {\n const index: number = event.index ?? 0\n const existing = pendingToolCalls.get(index)\n if (existing) {\n existing.args += event.delta.partial_json ?? ''\n }\n } else if (event.type === 'content_block_start' && event.content_block?.type === 'tool_use') {\n const index: number = event.index ?? 0\n pendingToolCalls.set(index, {\n id: event.content_block.id ?? `tool-${index}`,\n name: event.content_block.name ?? 'unknown',\n args: '',\n })\n } else if (event.type === 'content_block_stop') {\n const index: number = event.index ?? 0\n const tc = pendingToolCalls.get(index)\n if (tc) {\n if (!(yield* emitToolCall(tc))) {\n pendingToolCalls.clear()\n return\n }\n pendingToolCalls.delete(index)\n }\n } else if (event.type === 'message_delta' && event.usage) {\n yield {\n type: 'usage',\n usage: {\n promptTokens: event.usage.input_tokens ?? 0,\n completionTokens: event.usage.output_tokens ?? 0,\n totalTokens: (event.usage.input_tokens ?? 0) + (event.usage.output_tokens ?? 0),\n },\n } as StreamChunk\n } else if (event.type === 'message_start' && event.message?.usage) {\n yield {\n type: 'usage',\n usage: {\n promptTokens: event.message.usage.input_tokens ?? 0,\n completionTokens: 0,\n totalTokens: event.message.usage.input_tokens ?? 0,\n },\n } as StreamChunk\n } else if (event.type === 'message_stop') {\n sawMessageStop = true\n for (const [, tc] of pendingToolCalls) {\n if (!(yield* emitToolCall(tc))) {\n pendingToolCalls.clear()\n return\n }\n }\n pendingToolCalls.clear()\n yield { type: 'done' }\n return\n }\n } catch {\n // Ignore malformed events.\n }\n }\n\n pendingToolCalls.clear()\n if (!sawMessageStop) {\n yield adapterErrorChunk('Anthropic stream ended before message_stop')\n return\n }\n yield { type: 'done' }\n}\n\nconst GEMINI_SUCCESS_FINISH = new Set([\n 'STOP',\n 'stop',\n 'FINISH_REASON_STOP',\n])\n\nexport async function* parseGeminiStream(stream: ReadableStream): AsyncIterableIterator<StreamChunk> {\n let finishReason: string | undefined\n\n for await (const data of readSSELines(stream)) {\n try {\n const event = JSON.parse(data) as {\n usageMetadata?: {\n promptTokenCount?: number\n candidatesTokenCount?: number\n totalTokenCount?: number\n }\n candidates?: Array<{\n finishReason?: string\n content?: {\n parts?: Array<{\n text?: string\n functionCall?: { id?: string; name?: string; args?: unknown }\n }>\n }\n }>\n }\n\n if (event.usageMetadata) {\n yield {\n type: 'usage',\n usage: {\n promptTokens: event.usageMetadata.promptTokenCount ?? 0,\n completionTokens: event.usageMetadata.candidatesTokenCount ?? 0,\n totalTokens: event.usageMetadata.totalTokenCount ?? 0,\n },\n } as StreamChunk\n }\n\n const candidate = event.candidates?.[0]\n if (typeof candidate?.finishReason === 'string') {\n finishReason = candidate.finishReason\n }\n\n const parts = candidate?.content?.parts\n if (!Array.isArray(parts)) continue\n\n for (const part of parts) {\n if (typeof part.text === 'string' && part.text) {\n yield { type: 'text', content: part.text }\n } else if (part.functionCall) {\n const fc = part.functionCall\n const args =\n typeof fc.args === 'string' ? fc.args : JSON.stringify(fc.args ?? {})\n const parsed = parseCompleteToolArgs(args)\n if (!parsed.ok) {\n yield {\n type: 'error',\n content: parsed.error.message,\n metadata: { error: parsed.error },\n }\n return\n }\n yield {\n type: 'tool_call',\n toolCall: {\n id: fc.id ?? `${fc.name}-${Date.now()}`,\n name: fc.name ?? 'unknown',\n args: parsed.args,\n },\n }\n }\n }\n } catch {\n // Ignore malformed events.\n }\n }\n\n if (!finishReason || !GEMINI_SUCCESS_FINISH.has(finishReason)) {\n if (finishReason && !GEMINI_SUCCESS_FINISH.has(finishReason)) {\n yield adapterErrorChunk(\n `Gemini stream ended with non-success finish reason \"${finishReason}\"`,\n )\n return\n }\n yield adapterErrorChunk('Gemini stream ended without a successful finishReason')\n return\n }\n\n yield { type: 'done' }\n}\n\nexport async function* parseOllamaStream(stream: ReadableStream): AsyncIterableIterator<StreamChunk> {\n let sawDone = false\n\n for await (const data of readNDJSONLines(stream)) {\n try {\n const event = JSON.parse(data) as {\n message?: {\n content?: string\n tool_calls?: Array<{\n id?: string\n function?: { name?: string; arguments?: unknown }\n }>\n }\n done?: boolean\n prompt_eval_count?: number\n eval_count?: number\n }\n if (event.message?.content) {\n yield { type: 'text', content: event.message.content }\n }\n if (Array.isArray(event.message?.tool_calls)) {\n for (const tc of event.message.tool_calls) {\n if (tc?.function?.name) {\n const args =\n typeof tc.function.arguments === 'string'\n ? tc.function.arguments\n : JSON.stringify(tc.function.arguments ?? {})\n const parsed = parseCompleteToolArgs(args)\n if (!parsed.ok) {\n yield {\n type: 'error',\n content: parsed.error.message,\n metadata: { error: parsed.error },\n }\n return\n }\n yield {\n type: 'tool_call',\n toolCall: {\n id: tc.id ?? `${tc.function.name}-${Date.now()}`,\n name: tc.function.name,\n args: parsed.args,\n },\n }\n }\n }\n }\n if (event.done) {\n sawDone = true\n if (typeof event.prompt_eval_count === 'number' || typeof event.eval_count === 'number') {\n const promptTokens = event.prompt_eval_count ?? 0\n const completionTokens = event.eval_count ?? 0\n yield {\n type: 'usage',\n usage: {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n },\n } as StreamChunk\n }\n yield { type: 'done' }\n return\n }\n } catch {\n // Ignore malformed events.\n }\n }\n\n if (!sawDone) {\n yield adapterErrorChunk('Ollama stream ended without done:true')\n return\n }\n yield { type: 'done' }\n}\n\n/**\n * Retry knobs for adapter fetches. Tunable per call to createStreamSource.\n *\n * Default behavior:\n * - 3 attempts total (1 initial + 2 retries)\n * - exponential backoff: 500ms, 1000ms, 2000ms ... (capped at maxDelayMs)\n * - full jitter on each delay\n * - retry on HTTP 408, 429, 500, 502, 503, 504\n * - retry on network errors (fetch throws)\n * - DO NOT retry on 4xx other than 408/429 (those are bad requests / auth)\n * - retries only the initial fetch — never mid-stream\n * - respects Retry-After header when present\n */\nexport interface RetryOptions {\n maxAttempts?: number\n baseDelayMs?: number\n maxDelayMs?: number\n jitter?: boolean\n retryOn?: (info: { error?: unknown; response?: Response; attempt: number }) => boolean\n /** Hook for tests + logging. Called after every failed attempt. */\n onRetry?: (info: { attempt: number; delayMs: number; reason: string }) => void\n /** Sleep override for tests. Defaults to setTimeout. */\n sleep?: (ms: number) => Promise<void>\n}\n\nconst DEFAULT_RETRY: Required<Omit<RetryOptions, 'onRetry' | 'sleep' | 'retryOn'>> & {\n retryOn: NonNullable<RetryOptions['retryOn']>\n} = {\n maxAttempts: 3,\n baseDelayMs: 500,\n maxDelayMs: 8000,\n jitter: true,\n retryOn: ({ error, response }) => {\n if (response) {\n return [408, 429, 500, 502, 503, 504].includes(response.status)\n }\n if (isAbortError(error)) return false\n // Network error: TypeError from fetch, AbortError from upstream timeout, etc.\n return true\n },\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction computeDelay(attempt: number, opts: Required<Pick<RetryOptions, 'baseDelayMs' | 'maxDelayMs' | 'jitter'>>): number {\n const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1))\n if (!opts.jitter) return exp\n return Math.floor(Math.random() * exp)\n}\n\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (!value) return undefined\n const n = Number(value)\n if (!Number.isNaN(n)) return n * 1000\n const date = Date.parse(value)\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now())\n return undefined\n}\n\n/**\n * Run a fetch with retries on transient failures. Returns the final\n * Response (whether successful or not — caller decides), or throws if\n * the AbortSignal fires or all attempts fail with a thrown error.\n */\nexport async function fetchWithRetry(\n doFetch: (signal: AbortSignal) => Promise<Response>,\n signal: AbortSignal,\n retryOpt: RetryOptions = {},\n): Promise<Response> {\n const opts = {\n ...DEFAULT_RETRY,\n ...retryOpt,\n }\n const sleep = retryOpt.sleep ?? defaultSleep\n let lastError: unknown\n\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\n if (signal.aborted) throw new DOMException('Aborted', 'AbortError')\n\n try {\n const response = await doFetch(signal)\n\n // Success or non-retryable failure → return.\n if (response.ok) return response\n if (attempt >= opts.maxAttempts || !opts.retryOn({ response, attempt })) {\n return response\n }\n\n const retryAfterMs = parseRetryAfter(response.headers.get('retry-after'))\n const delay = retryAfterMs ?? computeDelay(attempt, opts)\n retryOpt.onRetry?.({ attempt, delayMs: delay, reason: `HTTP ${response.status}` })\n // Drain the body so the connection can be reused / does not leak.\n await cancelBody(response.body)\n await abortableSleep(delay, signal, sleep)\n } catch (err) {\n lastError = err\n if (isAbortError(err)) throw err\n if (attempt >= opts.maxAttempts || !opts.retryOn({ error: err, attempt })) throw err\n\n const delay = computeDelay(attempt, opts)\n retryOpt.onRetry?.({\n attempt,\n delayMs: delay,\n reason: err instanceof Error ? err.message : String(err),\n })\n await abortableSleep(delay, signal, sleep)\n }\n }\n\n // Unreachable, but the TS narrowing needs it.\n throw lastError ?? new Error('fetchWithRetry: exhausted attempts')\n}\n\n/**\n * Chunk-splitter that turns one large string into N streamable text chunks.\n * Useful when a provider returns the full response in one shot and you\n * want to feed it to a UI that expects streaming.\n *\n * Default splits by whitespace boundaries with a target chunk size of ~32\n * characters.\n */\nexport function chunkText(text: string, targetSize = 32): string[] {\n if (text.length <= targetSize) return [text]\n const out: string[] = []\n let i = 0\n while (i < text.length) {\n let end = Math.min(text.length, i + targetSize)\n // Prefer to cut on whitespace within the next few chars\n if (end < text.length) {\n const nextSpace = text.indexOf(' ', end)\n if (nextSpace !== -1 && nextSpace - end <= 8) end = nextSpace + 1\n }\n out.push(text.slice(i, end))\n i = end\n }\n return out\n}\n\n/**\n * Build a StreamSource from a non-streaming fetch. The adapter is\n * auto-completing: it fetches once, then yields the text as a sequence\n * of chunks so UIs see the same streaming shape they'd see from a\n * native streaming provider.\n *\n * Use this when you're wiring a provider that only has a non-streaming\n * endpoint but you want consumers (useChat, the runtime) to get\n * identical ergonomics.\n */\nexport function simulateStream(\n doFetch: (signal: AbortSignal) => Promise<Response>,\n extractText: (response: Response) => Promise<string>,\n errorLabel: string,\n options: { chunkSize?: number; delayMs?: number; retry?: RetryOptions } = {},\n): StreamSource {\n const { chunkSize = 32, delayMs = 8, retry } = options\n let abortController: AbortController | null = new AbortController()\n\n return {\n stream: async function* (): AsyncIterableIterator<StreamChunk> {\n const controller = abortController\n if (!controller) return\n try {\n const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {})\n\n if (!response.ok) {\n await cancelBody(response.body)\n yield adapterErrorChunk(`${errorLabel} error: ${response.status}`)\n return\n }\n\n let text: string\n try {\n text = await extractText(response)\n } catch (err) {\n await cancelBody(response.body)\n if (isAbortError(err)) return\n const message = err instanceof Error ? err.message : String(err)\n yield adapterErrorChunk(message, { cause: err })\n return\n }\n\n const chunks = chunkText(text, chunkSize)\n for (const chunk of chunks) {\n if (abortController === null || controller.signal.aborted) return\n if (delayMs > 0) {\n await abortableSleep(delayMs, controller.signal, defaultSleep)\n }\n yield { type: 'text', content: chunk }\n }\n yield { type: 'done' }\n } catch (err) {\n if (isAbortError(err)) return\n const message = err instanceof Error ? err.message : String(err)\n yield adapterErrorChunk(message, { cause: err })\n }\n },\n abort: () => {\n abortController?.abort()\n abortController = null\n },\n }\n}\n","import type { StreamChunk, StreamSource } from '@agentskit/core'\nimport { adapterErrorChunk, cancelBody, isAbortError } from './stream-errors'\nimport type { StreamParser } from './stream-types'\nimport { fetchWithRetry, type RetryOptions } from './utils'\n\nexport function createStreamSource(\n doFetch: (signal: AbortSignal) => Promise<Response>,\n parse: StreamParser,\n errorLabel: string,\n retry?: RetryOptions,\n): StreamSource {\n let abortController: AbortController | null = new AbortController()\n\n return {\n stream: async function* (): AsyncIterableIterator<StreamChunk> {\n const controller = abortController\n if (!controller) return\n try {\n const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {})\n\n if (!response.ok) {\n await cancelBody(response.body)\n yield adapterErrorChunk(`${errorLabel} error: ${response.status}`)\n return\n }\n\n if (!response.body) {\n yield adapterErrorChunk(`${errorLabel} error: empty response body`)\n return\n }\n\n for await (const chunk of parse(response.body, response)) {\n if (controller.signal.aborted || abortController === null) return\n yield chunk\n }\n } catch (err) {\n if (isAbortError(err) || controller.signal.aborted || abortController === null) return\n const message = err instanceof Error ? err.message : String(err)\n yield adapterErrorChunk(message, { cause: err })\n }\n },\n abort: () => {\n abortController?.abort()\n abortController = null\n },\n }\n}\n","import type { AdapterFactory, AdapterRequest, StreamSource } from '@agentskit/core'\nimport { parseOpenAIStream, toProviderMessages, type RetryOptions } from './utils'\nimport { createStreamSource } from './stream-source'\n\nexport interface OpenAIConfig {\n apiKey: string\n model: string\n baseUrl?: string\n retry?: RetryOptions\n /**\n * Ask the provider to include token usage in the final stream chunk via\n * `stream_options: { include_usage: true }`. Off by default because some\n * OpenAI-compatible providers (OpenRouter proxies to a long tail of\n * backends) reject unknown params with a 4xx and break the whole stream.\n * Turn this on for vanilla `api.openai.com`.\n */\n includeUsage?: boolean\n}\n\nexport function openai(config: OpenAIConfig): AdapterFactory {\n const { apiKey, model, baseUrl = 'https://api.openai.com', retry } = config\n // Normalize: many compatible endpoints are declared WITH a trailing `/v1`\n // (together, mistral, fireworks, openrouter `/api/v1`, …) while others are\n // declared without it. We always append `/v1/chat/completions`, so strip a\n // trailing `/v1` first to avoid a double `/v1/v1/...` (→ 404).\n const apiRoot = baseUrl.replace(/\\/v1\\/?$/, '')\n // Auto: on for canonical OpenAI, off for every other compatible endpoint\n // where the param is a known source of 4xx surprises.\n // Match the canonical OpenAI host exactly — a substring/prefix check\n // would also accept `https://api.openai.com.evil.test`.\n const isCanonicalOpenAI = (() => {\n try {\n return new URL(baseUrl).host === 'api.openai.com'\n } catch {\n return false\n }\n })()\n const includeUsage = config.includeUsage ?? isCanonicalOpenAI\n\n return {\n capabilities: {\n streaming: true,\n tools: true,\n // o1 / o3 models emit reasoning; older models don't. Accurate per-model\n // detection would need a model registry; 'true' is the safer default here.\n reasoning: model.startsWith('o1') || model.startsWith('o3'),\n multiModal: model.startsWith('gpt-4') || model.startsWith('o'),\n usage: true,\n },\n createSource: (request: AdapterRequest): StreamSource => {\n const body: Record<string, unknown> = {\n model,\n messages: toProviderMessages(request.messages),\n tools: request.context?.tools?.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.schema,\n },\n })),\n temperature: request.context?.temperature,\n max_tokens: request.context?.maxTokens,\n stream: true,\n }\n if (includeUsage) body.stream_options = { include_usage: true }\n\n return createStreamSource(\n (signal) => fetch(`${apiRoot}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify(body),\n signal,\n }),\n parseOpenAIStream,\n 'OpenAI API',\n retry,\n )\n },\n }\n}\n"]}
|