@agentskit/adapters 0.17.4 → 0.18.0

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.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@agentskit/core');
4
+ var net = require('@agentskit/net');
4
5
 
5
6
  // src/stream-errors.ts
6
7
  function isAbortError(err) {
@@ -238,27 +239,75 @@ function generic(config) {
238
239
  }
239
240
  };
240
241
  }
241
-
242
- // src/stream-lines.ts
243
- async function* readSSELines(stream) {
244
- const reader = stream.getReader();
245
- const decoder = new TextDecoder();
246
- let buffer = "";
242
+ var DEFAULT_RETRY = {
243
+ maxAttempts: 3,
244
+ baseDelayMs: 500,
245
+ maxDelayMs: 8e3,
246
+ jitter: true,
247
+ retryOn: ({ error, response }) => {
248
+ if (response) return [408, 429, 500, 502, 503, 504].includes(response.status);
249
+ if (isAbortError(error)) return false;
250
+ return true;
251
+ }
252
+ };
253
+ var RetryableResponse = class extends Error {
254
+ constructor(response, retryAfterMs) {
255
+ super(`HTTP ${response.status}`);
256
+ this.response = response;
257
+ this.retryAfterMs = retryAfterMs;
258
+ }
259
+ };
260
+ async function fetchWithRetry(doFetch, signal, retryOpt = {}) {
261
+ const opts = { ...DEFAULT_RETRY, ...retryOpt };
262
+ const maxAttempts = Math.floor(opts.maxAttempts);
263
+ if (!Number.isFinite(maxAttempts) || maxAttempts < 1) {
264
+ throw new core.AdapterError({
265
+ code: core.ErrorCodes.AK_CONFIG_INVALID,
266
+ message: "Retry maxAttempts must be finite and at least 1 after flooring"
267
+ });
268
+ }
269
+ if (signal.aborted) throw new DOMException("Aborted", "AbortError");
247
270
  try {
248
- while (true) {
249
- const { done, value } = await reader.read();
250
- if (done) break;
251
- buffer += decoder.decode(value, { stream: true });
252
- const lines = buffer.split("\n");
253
- buffer = lines.pop() ?? "";
254
- for (const line of lines) {
255
- if (!line.startsWith("data: ")) continue;
256
- const data = line.slice(6).trim();
257
- if (data) yield data;
271
+ return await net.retry(async ({ attempt }) => {
272
+ let response;
273
+ try {
274
+ response = await doFetch(signal);
275
+ } catch (error) {
276
+ if (signal.aborted) throw new DOMException("Aborted", "AbortError");
277
+ throw error;
258
278
  }
259
- }
260
- } finally {
261
- reader.releaseLock();
279
+ if (response.ok || attempt >= maxAttempts || !opts.retryOn({ response, attempt })) return response;
280
+ const retryAfter = net.parseRetryAfter(response.headers.get("retry-after"));
281
+ await cancelBody(response.body);
282
+ throw new RetryableResponse(
283
+ response,
284
+ retryAfter === void 0 ? void 0 : Math.min(retryAfter, opts.maxDelayMs)
285
+ );
286
+ }, {
287
+ retries: maxAttempts - 1,
288
+ minDelayMs: opts.baseDelayMs,
289
+ maxDelayMs: opts.maxDelayMs,
290
+ jitter: opts.jitter ? "full" : "none",
291
+ shouldRetry: (error, attempt) => {
292
+ if (error instanceof RetryableResponse) return true;
293
+ if (isAbortError(error)) return false;
294
+ return opts.retryOn({ error, attempt });
295
+ },
296
+ delayFor: (error) => error instanceof RetryableResponse ? error.retryAfterMs : void 0,
297
+ onRetry: ({ error, attempt, delayMs }) => {
298
+ retryOpt.onRetry?.({
299
+ attempt,
300
+ delayMs,
301
+ reason: error instanceof Error ? error.message : String(error)
302
+ });
303
+ },
304
+ sleep: retryOpt.sleep ? (ms, retrySignal) => abortableSleep(ms, retrySignal ?? signal, retryOpt.sleep) : net.sleep,
305
+ signal
306
+ });
307
+ } catch (error) {
308
+ if (signal.aborted) throw new DOMException("Aborted", "AbortError");
309
+ if (error instanceof RetryableResponse) return error.response;
310
+ throw error;
262
311
  }
263
312
  }
264
313
  async function* readNDJSONLines(stream) {
@@ -268,8 +317,12 @@ async function* readNDJSONLines(stream) {
268
317
  try {
269
318
  while (true) {
270
319
  const { done, value } = await reader.read();
271
- if (done) break;
272
- buffer += decoder.decode(value, { stream: true });
320
+ buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });
321
+ if (done) {
322
+ const trimmed = buffer.trim();
323
+ if (trimmed) yield trimmed;
324
+ break;
325
+ }
273
326
  const lines = buffer.split("\n");
274
327
  buffer = lines.pop() ?? "";
275
328
  for (const line of lines) {
@@ -281,8 +334,6 @@ async function* readNDJSONLines(stream) {
281
334
  reader.releaseLock();
282
335
  }
283
336
  }
284
-
285
- // src/openai-stream.ts
286
337
  var SUCCESS_FINISH_REASONS = /* @__PURE__ */ new Set(["stop", "tool_calls", "function_call"]);
287
338
  async function* parseOpenAIStream(stream) {
288
339
  const pendingToolCalls = /* @__PURE__ */ new Map();
@@ -314,7 +365,7 @@ async function* parseOpenAIStream(stream) {
314
365
  pendingToolCalls.clear();
315
366
  return true;
316
367
  };
317
- for await (const data of readSSELines(stream)) {
368
+ for await (const { data } of net.parseSSE(stream)) {
318
369
  if (data === "[DONE]") {
319
370
  if (finishReason !== void 0 && !SUCCESS_FINISH_REASONS.has(finishReason)) {
320
371
  pendingToolCalls.clear();
@@ -436,7 +487,7 @@ async function* parseAnthropicStream(stream) {
436
487
  };
437
488
  return true;
438
489
  };
439
- for await (const data of readSSELines(stream)) {
490
+ for await (const { data } of net.parseSSE(stream)) {
440
491
  if (data === "[DONE]") continue;
441
492
  try {
442
493
  const event = JSON.parse(data);
@@ -517,7 +568,7 @@ var GEMINI_SUCCESS_FINISH = /* @__PURE__ */ new Set([
517
568
  ]);
518
569
  async function* parseGeminiStream(stream) {
519
570
  let finishReason;
520
- for await (const data of readSSELines(stream)) {
571
+ for await (const { data } of net.parseSSE(stream)) {
521
572
  try {
522
573
  const event = JSON.parse(data);
523
574
  if (event.usageMetadata) {
@@ -634,70 +685,6 @@ async function* parseOllamaStream(stream) {
634
685
  }
635
686
  yield { type: "done" };
636
687
  }
637
- var DEFAULT_RETRY = {
638
- maxAttempts: 3,
639
- baseDelayMs: 500,
640
- maxDelayMs: 8e3,
641
- jitter: true,
642
- retryOn: ({ error, response }) => {
643
- if (response) {
644
- return [408, 429, 500, 502, 503, 504].includes(response.status);
645
- }
646
- if (isAbortError(error)) return false;
647
- return true;
648
- }
649
- };
650
- function defaultSleep(ms) {
651
- return new Promise((resolve2) => setTimeout(resolve2, ms));
652
- }
653
- function computeDelay(attempt, opts) {
654
- const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1));
655
- if (!opts.jitter) return exp;
656
- return Math.floor(Math.random() * exp);
657
- }
658
- function parseRetryAfter(value, maxDelayMs) {
659
- if (!value) return void 0;
660
- const n = Number(value);
661
- if (Number.isFinite(n) && n >= 0) return Math.min(n * 1e3, maxDelayMs);
662
- const date = Date.parse(value);
663
- if (!Number.isNaN(date)) return Math.min(maxDelayMs, Math.max(0, date - Date.now()));
664
- return void 0;
665
- }
666
- async function fetchWithRetry(doFetch, signal, retryOpt = {}) {
667
- const opts = {
668
- ...DEFAULT_RETRY,
669
- ...retryOpt
670
- };
671
- const sleep = retryOpt.sleep ?? defaultSleep;
672
- let lastError;
673
- for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
674
- if (signal.aborted) throw new DOMException("Aborted", "AbortError");
675
- try {
676
- const response = await doFetch(signal);
677
- if (response.ok) return response;
678
- if (attempt >= opts.maxAttempts || !opts.retryOn({ response, attempt })) {
679
- return response;
680
- }
681
- const retryAfterMs = parseRetryAfter(response.headers.get("retry-after"), opts.maxDelayMs);
682
- const delay = retryAfterMs ?? computeDelay(attempt, opts);
683
- retryOpt.onRetry?.({ attempt, delayMs: delay, reason: `HTTP ${response.status}` });
684
- await cancelBody(response.body);
685
- await abortableSleep(delay, signal, sleep);
686
- } catch (err) {
687
- lastError = err;
688
- if (isAbortError(err)) throw err;
689
- if (attempt >= opts.maxAttempts || !opts.retryOn({ error: err, attempt })) throw err;
690
- const delay = computeDelay(attempt, opts);
691
- retryOpt.onRetry?.({
692
- attempt,
693
- delayMs: delay,
694
- reason: err instanceof Error ? err.message : String(err)
695
- });
696
- await abortableSleep(delay, signal, sleep);
697
- }
698
- }
699
- throw lastError ?? new Error("fetchWithRetry: exhausted attempts");
700
- }
701
688
  function chunkText(text, targetSize = 32) {
702
689
  if (text.length <= targetSize) return [text];
703
690
  const out = [];
@@ -714,14 +701,14 @@ function chunkText(text, targetSize = 32) {
714
701
  return out;
715
702
  }
716
703
  function simulateStream(doFetch, extractText, errorLabel, options = {}) {
717
- const { chunkSize = 32, delayMs = 8, retry } = options;
704
+ const { chunkSize = 32, delayMs = 8, retry: retry2 } = options;
718
705
  let abortController = new AbortController();
719
706
  return {
720
707
  stream: async function* () {
721
708
  const controller = abortController;
722
709
  if (!controller) return;
723
710
  try {
724
- const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
711
+ const response = await fetchWithRetry(doFetch, controller.signal, retry2 ?? {});
725
712
  if (!response.ok) {
726
713
  await cancelBody(response.body);
727
714
  yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
@@ -741,7 +728,7 @@ function simulateStream(doFetch, extractText, errorLabel, options = {}) {
741
728
  for (const chunk of chunks) {
742
729
  if (abortController === null || controller.signal.aborted) return;
743
730
  if (delayMs > 0) {
744
- await abortableSleep(delayMs, controller.signal, defaultSleep);
731
+ await abortableSleep(delayMs, controller.signal, net.sleep);
745
732
  }
746
733
  yield { type: "text", content: chunk };
747
734
  }
@@ -760,14 +747,14 @@ function simulateStream(doFetch, extractText, errorLabel, options = {}) {
760
747
  }
761
748
 
762
749
  // src/stream-source.ts
763
- function createStreamSource(doFetch, parse, errorLabel, retry) {
750
+ function createStreamSource(doFetch, parse, errorLabel, retry2) {
764
751
  let abortController = new AbortController();
765
752
  return {
766
753
  stream: async function* () {
767
754
  const controller = abortController;
768
755
  if (!controller) return;
769
756
  try {
770
- const response = await fetchWithRetry(doFetch, controller.signal, retry ?? {});
757
+ const response = await fetchWithRetry(doFetch, controller.signal, retry2 ?? {});
771
758
  if (!response.ok) {
772
759
  await cancelBody(response.body);
773
760
  yield adapterErrorChunk(`${errorLabel} error: ${response.status}`);
@@ -929,7 +916,7 @@ function toGeminiContents(messages) {
929
916
 
930
917
  // src/anthropic.ts
931
918
  function anthropic(config) {
932
- const { apiKey, model, baseUrl = "https://api.anthropic.com", maxTokens = 4096, retry } = config;
919
+ const { apiKey, model, baseUrl = "https://api.anthropic.com", maxTokens = 4096, retry: retry2 } = config;
933
920
  return {
934
921
  capabilities: {
935
922
  streaming: true,
@@ -964,7 +951,7 @@ function anthropic(config) {
964
951
  }),
965
952
  parseAnthropicStream,
966
953
  "Anthropic API",
967
- retry
954
+ retry2
968
955
  );
969
956
  }
970
957
  };
@@ -972,7 +959,7 @@ function anthropic(config) {
972
959
 
973
960
  // src/openai.ts
974
961
  function openai(config) {
975
- const { apiKey, model, baseUrl = "https://api.openai.com", retry } = config;
962
+ const { apiKey, model, baseUrl = "https://api.openai.com", retry: retry2 } = config;
976
963
  const apiRoot = baseUrl.replace(/\/v1\/?$/, "");
977
964
  const isCanonicalOpenAI = (() => {
978
965
  try {
@@ -1022,7 +1009,7 @@ function openai(config) {
1022
1009
  }),
1023
1010
  parseOpenAIStream,
1024
1011
  "OpenAI API",
1025
- retry
1012
+ retry2
1026
1013
  );
1027
1014
  }
1028
1015
  };
@@ -1030,7 +1017,7 @@ function openai(config) {
1030
1017
 
1031
1018
  // src/gemini.ts
1032
1019
  function gemini(config) {
1033
- const { apiKey, model, baseUrl = "https://generativelanguage.googleapis.com", retry } = config;
1020
+ const { apiKey, model, baseUrl = "https://generativelanguage.googleapis.com", retry: retry2 } = config;
1034
1021
  return {
1035
1022
  capabilities: {
1036
1023
  streaming: true,
@@ -1066,7 +1053,7 @@ function gemini(config) {
1066
1053
  ),
1067
1054
  parseGeminiStream,
1068
1055
  "Gemini API",
1069
- retry
1056
+ retry2
1070
1057
  );
1071
1058
  }
1072
1059
  };
@@ -1087,7 +1074,7 @@ var grok = createOpenAICompatibleAdapter("https://api.x.ai");
1087
1074
 
1088
1075
  // src/ollama.ts
1089
1076
  function ollama(config) {
1090
- const { model, baseUrl = "http://localhost:11434", retry } = config;
1077
+ const { model, baseUrl = "http://localhost:11434", retry: retry2 } = config;
1091
1078
  return {
1092
1079
  capabilities: {
1093
1080
  streaming: true,
@@ -1113,7 +1100,7 @@ function ollama(config) {
1113
1100
  }),
1114
1101
  parseOllamaStream,
1115
1102
  "Ollama API",
1116
- retry
1103
+ retry2
1117
1104
  );
1118
1105
  }
1119
1106
  };
@@ -1207,8 +1194,6 @@ function langgraph(config) {
1207
1194
  mode: "events"
1208
1195
  });
1209
1196
  }
1210
-
1211
- // src/vercel-ai.ts
1212
1197
  var UI_STREAM_HEADER = "x-vercel-ai-ui-message-stream";
1213
1198
  async function* parseVercelTextStream(stream) {
1214
1199
  const reader = stream.getReader();
@@ -1226,7 +1211,7 @@ async function* parseVercelTextStream(stream) {
1226
1211
  yield { type: "done" };
1227
1212
  }
1228
1213
  async function* parseVercelUiMessageStreamV1(stream) {
1229
- for await (const data of readSSELines(stream)) {
1214
+ for await (const { data } of net.parseSSE(stream)) {
1230
1215
  if (data === "[DONE]") {
1231
1216
  yield { type: "done" };
1232
1217
  return;
@@ -1268,7 +1253,7 @@ async function* parseVercelStream(stream, response) {
1268
1253
  yield* parseVercelTextStream(stream);
1269
1254
  }
1270
1255
  function vercelAI(config) {
1271
- const { api, headers = {}, retry } = config;
1256
+ const { api, headers = {}, retry: retry2 } = config;
1272
1257
  return {
1273
1258
  capabilities: {
1274
1259
  // Vercel AI routes can do any of these — whether they do depends on
@@ -1289,7 +1274,7 @@ function vercelAI(config) {
1289
1274
  }),
1290
1275
  parseVercelStream,
1291
1276
  "API",
1292
- retry
1277
+ retry2
1293
1278
  );
1294
1279
  }
1295
1280
  };
@@ -1382,7 +1367,7 @@ var cerebrasAdapter = cerebras;
1382
1367
  // src/azure-openai.ts
1383
1368
  var DEFAULT_API_VERSION = "2024-10-21";
1384
1369
  function azureOpenAI(config) {
1385
- const { apiKey, endpoint, deployment, apiVersion = DEFAULT_API_VERSION, retry } = config;
1370
+ const { apiKey, endpoint, deployment, apiVersion = DEFAULT_API_VERSION, retry: retry2 } = config;
1386
1371
  const includeUsage = config.includeUsage ?? true;
1387
1372
  const url = `${endpoint.replace(/\/$/, "")}/openai/deployments/${encodeURIComponent(deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
1388
1373
  return {
@@ -1419,7 +1404,7 @@ function azureOpenAI(config) {
1419
1404
  }),
1420
1405
  parseOpenAIStream,
1421
1406
  "Azure OpenAI API",
1422
- retry
1407
+ retry2
1423
1408
  );
1424
1409
  }
1425
1410
  };
@@ -1572,7 +1557,7 @@ var qwen = bail;
1572
1557
 
1573
1558
  // src/vertex.ts
1574
1559
  function vertex(config) {
1575
- const { project, region, model, accessToken, publisher = "google", retry } = config;
1560
+ const { project, region, model, accessToken, publisher = "google", retry: retry2 } = config;
1576
1561
  const url = `https://${region}-aiplatform.googleapis.com/v1/projects/${project}/locations/${region}/publishers/${publisher}/models/${model}:streamGenerateContent?alt=sse`;
1577
1562
  return {
1578
1563
  capabilities: {
@@ -1610,7 +1595,7 @@ function vertex(config) {
1610
1595
  },
1611
1596
  parseGeminiStream,
1612
1597
  "Vertex AI",
1613
- retry
1598
+ retry2
1614
1599
  );
1615
1600
  }
1616
1601
  };