@yourgpt/llm-sdk 2.1.4-alpha.2 → 2.1.5

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.
Files changed (49) hide show
  1. package/dist/adapters/index.d.mts +3 -2
  2. package/dist/adapters/index.d.ts +3 -2
  3. package/dist/{types-DoZX2k3v.d.mts → base-5n-UuPfS.d.mts} +1 -353
  4. package/dist/{types-DtPQaoJi.d.ts → base-Di31iy_8.d.ts} +1 -353
  5. package/dist/fallback/index.d.mts +96 -0
  6. package/dist/fallback/index.d.ts +96 -0
  7. package/dist/fallback/index.js +284 -0
  8. package/dist/fallback/index.mjs +280 -0
  9. package/dist/index.d.mts +5 -2
  10. package/dist/index.d.ts +5 -2
  11. package/dist/providers/anthropic/index.d.mts +2 -1
  12. package/dist/providers/anthropic/index.d.ts +2 -1
  13. package/dist/providers/azure/index.d.mts +2 -1
  14. package/dist/providers/azure/index.d.ts +2 -1
  15. package/dist/providers/google/index.d.mts +2 -1
  16. package/dist/providers/google/index.d.ts +2 -1
  17. package/dist/providers/ollama/index.d.mts +3 -2
  18. package/dist/providers/ollama/index.d.ts +3 -2
  19. package/dist/providers/openai/index.d.mts +2 -1
  20. package/dist/providers/openai/index.d.ts +2 -1
  21. package/dist/providers/openrouter/index.d.mts +2 -1
  22. package/dist/providers/openrouter/index.d.ts +2 -1
  23. package/dist/providers/xai/index.d.mts +2 -1
  24. package/dist/providers/xai/index.d.ts +2 -1
  25. package/dist/types-BQl1suAv.d.mts +212 -0
  26. package/dist/types-C0vLXzuw.d.ts +355 -0
  27. package/dist/types-CNL8ZRne.d.ts +212 -0
  28. package/dist/types-VDgiUvH2.d.mts +355 -0
  29. package/package.json +7 -1
  30. package/dist/adapters/index.js.map +0 -1
  31. package/dist/adapters/index.mjs.map +0 -1
  32. package/dist/index.js.map +0 -1
  33. package/dist/index.mjs.map +0 -1
  34. package/dist/providers/anthropic/index.js.map +0 -1
  35. package/dist/providers/anthropic/index.mjs.map +0 -1
  36. package/dist/providers/azure/index.js.map +0 -1
  37. package/dist/providers/azure/index.mjs.map +0 -1
  38. package/dist/providers/google/index.js.map +0 -1
  39. package/dist/providers/google/index.mjs.map +0 -1
  40. package/dist/providers/ollama/index.js.map +0 -1
  41. package/dist/providers/ollama/index.mjs.map +0 -1
  42. package/dist/providers/openai/index.js.map +0 -1
  43. package/dist/providers/openai/index.mjs.map +0 -1
  44. package/dist/providers/openrouter/index.js.map +0 -1
  45. package/dist/providers/openrouter/index.mjs.map +0 -1
  46. package/dist/providers/xai/index.js.map +0 -1
  47. package/dist/providers/xai/index.mjs.map +0 -1
  48. package/dist/yourgpt/index.js.map +0 -1
  49. package/dist/yourgpt/index.mjs.map +0 -1
@@ -0,0 +1,284 @@
1
+ 'use strict';
2
+
3
+ // src/fallback/errors.ts
4
+ var FallbackExhaustedError = class extends Error {
5
+ constructor(failures) {
6
+ const summary = failures.map((f) => `${f.provider}/${f.model}: ${f.error.message}`).join("; ");
7
+ super(
8
+ `All ${failures.length} model(s) in the fallback chain failed. ${summary}`
9
+ );
10
+ this.name = "FallbackExhaustedError";
11
+ this.failures = failures;
12
+ Object.setPrototypeOf(this, new.target.prototype);
13
+ }
14
+ };
15
+
16
+ // src/fallback/routing-store.ts
17
+ var MemoryRoutingStore = class {
18
+ constructor() {
19
+ this._map = /* @__PURE__ */ new Map();
20
+ }
21
+ async get(key) {
22
+ return this._map.get(key);
23
+ }
24
+ async set(key, value) {
25
+ this._map.set(key, value);
26
+ }
27
+ };
28
+
29
+ // src/fallback/chain.ts
30
+ var ROUND_ROBIN_KEY = "ygpt_fallback_rr_index";
31
+ function defaultIsRetryable(error) {
32
+ if (typeof error === "object" && error !== null) {
33
+ const ctorName = error.constructor?.name ?? "";
34
+ if (ctorName === "APIUserAbortError") return false;
35
+ if (ctorName === "APIConnectionError") return true;
36
+ if (ctorName === "APIConnectionTimeoutError") return true;
37
+ const status = error.status ?? error.statusCode;
38
+ if (typeof status === "number") {
39
+ if (status === 429) return true;
40
+ if (status >= 500) return true;
41
+ if (status >= 400) return false;
42
+ }
43
+ }
44
+ if (error instanceof Error) {
45
+ const msg = error.message;
46
+ if (/the operation was aborted/i.test(msg)) return false;
47
+ if (/the user aborted a request/i.test(msg)) return false;
48
+ if (/\b4[0-9]{2}\b/.test(msg) && !/\b429\b/.test(msg)) return false;
49
+ if (/\b429\b/.test(msg)) return true;
50
+ if (/rate[\s_-]?limit/i.test(msg)) return true;
51
+ if (/too many requests/i.test(msg)) return true;
52
+ if (/quota exceeded/i.test(msg)) return true;
53
+ if (/\b5[0-9]{2}\b/.test(msg)) return true;
54
+ if (/internal server error/i.test(msg)) return true;
55
+ if (/service unavailable/i.test(msg)) return true;
56
+ if (/bad gateway/i.test(msg)) return true;
57
+ if (/gateway timeout/i.test(msg)) return true;
58
+ if (/overloaded/i.test(msg)) return true;
59
+ if (/^connection error\.?$/i.test(msg)) return true;
60
+ if (/^request timed out\.?$/i.test(msg)) return true;
61
+ if (/timed?\s*out/i.test(msg)) return true;
62
+ if (/timeout/i.test(msg)) return true;
63
+ if (/fetch failed/i.test(msg)) return true;
64
+ if (/ECONNREFUSED/.test(msg)) return true;
65
+ if (/ECONNRESET/.test(msg)) return true;
66
+ if (/ETIMEDOUT/.test(msg)) return true;
67
+ if (/ENOTFOUND/.test(msg)) return true;
68
+ if (/ENETUNREACH/.test(msg)) return true;
69
+ if (/EHOSTUNREACH/.test(msg)) return true;
70
+ }
71
+ return false;
72
+ }
73
+ function calcDelay(base, attempt, backoff) {
74
+ if (backoff === "fixed") return base;
75
+ return base * Math.pow(2, attempt - 1);
76
+ }
77
+ function sleep(ms) {
78
+ return new Promise((resolve) => setTimeout(resolve, ms));
79
+ }
80
+ var FallbackChain = class {
81
+ constructor(config) {
82
+ if (config.models.length === 0) {
83
+ throw new Error("FallbackChain requires at least one model.");
84
+ }
85
+ this._config = {
86
+ models: config.models,
87
+ strategy: config.strategy ?? "priority",
88
+ store: config.store ?? new MemoryRoutingStore(),
89
+ retries: config.retries ?? 0,
90
+ retryDelay: config.retryDelay ?? 500,
91
+ retryBackoff: config.retryBackoff ?? "exponential",
92
+ onFallback: config.onFallback,
93
+ onRetry: config.onRetry,
94
+ retryableErrors: config.retryableErrors
95
+ };
96
+ }
97
+ get provider() {
98
+ return "fallback-chain";
99
+ }
100
+ get model() {
101
+ return this._config.models.map((m) => `${m.provider}/${m.model}`).join(",");
102
+ }
103
+ async _startIndex() {
104
+ if (this._config.strategy !== "round-robin") return 0;
105
+ const stored = await this._config.store.get(ROUND_ROBIN_KEY);
106
+ return typeof stored === "number" ? stored % this._config.models.length : 0;
107
+ }
108
+ async _advanceIndex(successfulIndex) {
109
+ if (this._config.strategy !== "round-robin") return;
110
+ const next = (successfulIndex + 1) % this._config.models.length;
111
+ await this._config.store.set(ROUND_ROBIN_KEY, next);
112
+ }
113
+ _isRetryable(error) {
114
+ return this._config.retryableErrors ? this._config.retryableErrors(error) : defaultIsRetryable(error);
115
+ }
116
+ /**
117
+ * Try streaming from a single adapter, with per-model retries.
118
+ *
119
+ * Returns an async generator that either:
120
+ * - yields all chunks on success, then returns
121
+ * - throws the final error if all retries exhausted or error is non-retryable
122
+ *
123
+ * The `retriesAttempted` out-param is filled via the returned object so callers
124
+ * can record it in FallbackFailure.
125
+ */
126
+ async *_streamWithRetries(adapter, request, out) {
127
+ const { retries, retryDelay, retryBackoff, onRetry } = this._config;
128
+ const maxAttempts = retries + 1;
129
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
130
+ let contentStarted = false;
131
+ let failureError = null;
132
+ try {
133
+ for await (const chunk of adapter.stream(request)) {
134
+ if (chunk.type === "error") {
135
+ if (!contentStarted) {
136
+ const msg = chunk.message ?? "Unknown error";
137
+ failureError = new Error(msg);
138
+ break;
139
+ }
140
+ yield chunk;
141
+ return;
142
+ }
143
+ if (chunk.type === "message:start") continue;
144
+ contentStarted = true;
145
+ yield chunk;
146
+ }
147
+ } catch (error) {
148
+ if (contentStarted) throw error;
149
+ if (!this._isRetryable(error)) throw error;
150
+ failureError = error instanceof Error ? error : new Error(String(error));
151
+ }
152
+ if (failureError === null) return;
153
+ if (!this._isRetryable(failureError)) throw failureError;
154
+ out.retriesAttempted = attempt - 1;
155
+ if (attempt < maxAttempts) {
156
+ const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
157
+ const retryInfo = {
158
+ model: adapter.model,
159
+ provider: adapter.provider,
160
+ error: failureError,
161
+ retryAttempt: attempt,
162
+ maxRetries: retries,
163
+ delayMs
164
+ };
165
+ onRetry?.(retryInfo);
166
+ await sleep(delayMs);
167
+ continue;
168
+ }
169
+ out.retriesAttempted = retries;
170
+ throw failureError;
171
+ }
172
+ }
173
+ async *stream(request) {
174
+ const { models, onFallback } = this._config;
175
+ const startIndex = await this._startIndex();
176
+ const failures = [];
177
+ for (let i = 0; i < models.length; i++) {
178
+ const index = (startIndex + i) % models.length;
179
+ const adapter = models[index];
180
+ const out = { retriesAttempted: 0 };
181
+ try {
182
+ yield* this._streamWithRetries(adapter, request, out);
183
+ await this._advanceIndex(index);
184
+ return;
185
+ } catch (error) {
186
+ if (!this._isRetryable(error)) throw error;
187
+ const failure = {
188
+ model: adapter.model,
189
+ provider: adapter.provider,
190
+ error: error instanceof Error ? error : new Error(String(error)),
191
+ attempt: i + 1,
192
+ retriesAttempted: out.retriesAttempted
193
+ };
194
+ failures.push(failure);
195
+ const nextOffset = i + 1;
196
+ if (nextOffset < models.length && onFallback) {
197
+ const nextIndex = (startIndex + nextOffset) % models.length;
198
+ onFallback({
199
+ attemptedModel: adapter.model,
200
+ nextModel: models[nextIndex].model,
201
+ error: failure.error,
202
+ attempt: failure.attempt
203
+ });
204
+ }
205
+ }
206
+ }
207
+ throw new FallbackExhaustedError(failures);
208
+ }
209
+ async complete(request) {
210
+ const { models, onFallback, retries, retryDelay, retryBackoff, onRetry } = this._config;
211
+ const startIndex = await this._startIndex();
212
+ const failures = [];
213
+ for (let i = 0; i < models.length; i++) {
214
+ const index = (startIndex + i) % models.length;
215
+ const adapter = models[index];
216
+ if (!adapter.complete) {
217
+ failures.push({
218
+ model: adapter.model,
219
+ provider: adapter.provider,
220
+ error: new Error(
221
+ `Adapter ${adapter.provider}/${adapter.model} does not implement complete()`
222
+ ),
223
+ attempt: i + 1,
224
+ retriesAttempted: 0
225
+ });
226
+ continue;
227
+ }
228
+ const maxAttempts = retries + 1;
229
+ let lastError = null;
230
+ let retriesAttempted = 0;
231
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
232
+ try {
233
+ const result = await adapter.complete(request);
234
+ await this._advanceIndex(index);
235
+ return result;
236
+ } catch (error) {
237
+ if (!this._isRetryable(error)) throw error;
238
+ lastError = error instanceof Error ? error : new Error(String(error));
239
+ retriesAttempted = attempt - 1;
240
+ if (attempt < maxAttempts) {
241
+ const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
242
+ onRetry?.({
243
+ model: adapter.model,
244
+ provider: adapter.provider,
245
+ error: lastError,
246
+ retryAttempt: attempt,
247
+ maxRetries: retries,
248
+ delayMs
249
+ });
250
+ await sleep(delayMs);
251
+ }
252
+ }
253
+ }
254
+ const failure = {
255
+ model: adapter.model,
256
+ provider: adapter.provider,
257
+ error: lastError,
258
+ attempt: i + 1,
259
+ retriesAttempted
260
+ };
261
+ failures.push(failure);
262
+ const nextOffset = i + 1;
263
+ if (nextOffset < models.length && onFallback) {
264
+ const nextIndex = (startIndex + nextOffset) % models.length;
265
+ onFallback({
266
+ attemptedModel: adapter.model,
267
+ nextModel: models[nextIndex].model,
268
+ error: failure.error,
269
+ attempt: failure.attempt
270
+ });
271
+ }
272
+ }
273
+ throw new FallbackExhaustedError(failures);
274
+ }
275
+ };
276
+ function createFallbackChain(config) {
277
+ return new FallbackChain(config);
278
+ }
279
+
280
+ exports.FallbackExhaustedError = FallbackExhaustedError;
281
+ exports.MemoryRoutingStore = MemoryRoutingStore;
282
+ exports.createFallbackChain = createFallbackChain;
283
+ //# sourceMappingURL=index.js.map
284
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,280 @@
1
+ // src/fallback/errors.ts
2
+ var FallbackExhaustedError = class extends Error {
3
+ constructor(failures) {
4
+ const summary = failures.map((f) => `${f.provider}/${f.model}: ${f.error.message}`).join("; ");
5
+ super(
6
+ `All ${failures.length} model(s) in the fallback chain failed. ${summary}`
7
+ );
8
+ this.name = "FallbackExhaustedError";
9
+ this.failures = failures;
10
+ Object.setPrototypeOf(this, new.target.prototype);
11
+ }
12
+ };
13
+
14
+ // src/fallback/routing-store.ts
15
+ var MemoryRoutingStore = class {
16
+ constructor() {
17
+ this._map = /* @__PURE__ */ new Map();
18
+ }
19
+ async get(key) {
20
+ return this._map.get(key);
21
+ }
22
+ async set(key, value) {
23
+ this._map.set(key, value);
24
+ }
25
+ };
26
+
27
+ // src/fallback/chain.ts
28
+ var ROUND_ROBIN_KEY = "ygpt_fallback_rr_index";
29
+ function defaultIsRetryable(error) {
30
+ if (typeof error === "object" && error !== null) {
31
+ const ctorName = error.constructor?.name ?? "";
32
+ if (ctorName === "APIUserAbortError") return false;
33
+ if (ctorName === "APIConnectionError") return true;
34
+ if (ctorName === "APIConnectionTimeoutError") return true;
35
+ const status = error.status ?? error.statusCode;
36
+ if (typeof status === "number") {
37
+ if (status === 429) return true;
38
+ if (status >= 500) return true;
39
+ if (status >= 400) return false;
40
+ }
41
+ }
42
+ if (error instanceof Error) {
43
+ const msg = error.message;
44
+ if (/the operation was aborted/i.test(msg)) return false;
45
+ if (/the user aborted a request/i.test(msg)) return false;
46
+ if (/\b4[0-9]{2}\b/.test(msg) && !/\b429\b/.test(msg)) return false;
47
+ if (/\b429\b/.test(msg)) return true;
48
+ if (/rate[\s_-]?limit/i.test(msg)) return true;
49
+ if (/too many requests/i.test(msg)) return true;
50
+ if (/quota exceeded/i.test(msg)) return true;
51
+ if (/\b5[0-9]{2}\b/.test(msg)) return true;
52
+ if (/internal server error/i.test(msg)) return true;
53
+ if (/service unavailable/i.test(msg)) return true;
54
+ if (/bad gateway/i.test(msg)) return true;
55
+ if (/gateway timeout/i.test(msg)) return true;
56
+ if (/overloaded/i.test(msg)) return true;
57
+ if (/^connection error\.?$/i.test(msg)) return true;
58
+ if (/^request timed out\.?$/i.test(msg)) return true;
59
+ if (/timed?\s*out/i.test(msg)) return true;
60
+ if (/timeout/i.test(msg)) return true;
61
+ if (/fetch failed/i.test(msg)) return true;
62
+ if (/ECONNREFUSED/.test(msg)) return true;
63
+ if (/ECONNRESET/.test(msg)) return true;
64
+ if (/ETIMEDOUT/.test(msg)) return true;
65
+ if (/ENOTFOUND/.test(msg)) return true;
66
+ if (/ENETUNREACH/.test(msg)) return true;
67
+ if (/EHOSTUNREACH/.test(msg)) return true;
68
+ }
69
+ return false;
70
+ }
71
+ function calcDelay(base, attempt, backoff) {
72
+ if (backoff === "fixed") return base;
73
+ return base * Math.pow(2, attempt - 1);
74
+ }
75
+ function sleep(ms) {
76
+ return new Promise((resolve) => setTimeout(resolve, ms));
77
+ }
78
+ var FallbackChain = class {
79
+ constructor(config) {
80
+ if (config.models.length === 0) {
81
+ throw new Error("FallbackChain requires at least one model.");
82
+ }
83
+ this._config = {
84
+ models: config.models,
85
+ strategy: config.strategy ?? "priority",
86
+ store: config.store ?? new MemoryRoutingStore(),
87
+ retries: config.retries ?? 0,
88
+ retryDelay: config.retryDelay ?? 500,
89
+ retryBackoff: config.retryBackoff ?? "exponential",
90
+ onFallback: config.onFallback,
91
+ onRetry: config.onRetry,
92
+ retryableErrors: config.retryableErrors
93
+ };
94
+ }
95
+ get provider() {
96
+ return "fallback-chain";
97
+ }
98
+ get model() {
99
+ return this._config.models.map((m) => `${m.provider}/${m.model}`).join(",");
100
+ }
101
+ async _startIndex() {
102
+ if (this._config.strategy !== "round-robin") return 0;
103
+ const stored = await this._config.store.get(ROUND_ROBIN_KEY);
104
+ return typeof stored === "number" ? stored % this._config.models.length : 0;
105
+ }
106
+ async _advanceIndex(successfulIndex) {
107
+ if (this._config.strategy !== "round-robin") return;
108
+ const next = (successfulIndex + 1) % this._config.models.length;
109
+ await this._config.store.set(ROUND_ROBIN_KEY, next);
110
+ }
111
+ _isRetryable(error) {
112
+ return this._config.retryableErrors ? this._config.retryableErrors(error) : defaultIsRetryable(error);
113
+ }
114
+ /**
115
+ * Try streaming from a single adapter, with per-model retries.
116
+ *
117
+ * Returns an async generator that either:
118
+ * - yields all chunks on success, then returns
119
+ * - throws the final error if all retries exhausted or error is non-retryable
120
+ *
121
+ * The `retriesAttempted` out-param is filled via the returned object so callers
122
+ * can record it in FallbackFailure.
123
+ */
124
+ async *_streamWithRetries(adapter, request, out) {
125
+ const { retries, retryDelay, retryBackoff, onRetry } = this._config;
126
+ const maxAttempts = retries + 1;
127
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
128
+ let contentStarted = false;
129
+ let failureError = null;
130
+ try {
131
+ for await (const chunk of adapter.stream(request)) {
132
+ if (chunk.type === "error") {
133
+ if (!contentStarted) {
134
+ const msg = chunk.message ?? "Unknown error";
135
+ failureError = new Error(msg);
136
+ break;
137
+ }
138
+ yield chunk;
139
+ return;
140
+ }
141
+ if (chunk.type === "message:start") continue;
142
+ contentStarted = true;
143
+ yield chunk;
144
+ }
145
+ } catch (error) {
146
+ if (contentStarted) throw error;
147
+ if (!this._isRetryable(error)) throw error;
148
+ failureError = error instanceof Error ? error : new Error(String(error));
149
+ }
150
+ if (failureError === null) return;
151
+ if (!this._isRetryable(failureError)) throw failureError;
152
+ out.retriesAttempted = attempt - 1;
153
+ if (attempt < maxAttempts) {
154
+ const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
155
+ const retryInfo = {
156
+ model: adapter.model,
157
+ provider: adapter.provider,
158
+ error: failureError,
159
+ retryAttempt: attempt,
160
+ maxRetries: retries,
161
+ delayMs
162
+ };
163
+ onRetry?.(retryInfo);
164
+ await sleep(delayMs);
165
+ continue;
166
+ }
167
+ out.retriesAttempted = retries;
168
+ throw failureError;
169
+ }
170
+ }
171
+ async *stream(request) {
172
+ const { models, onFallback } = this._config;
173
+ const startIndex = await this._startIndex();
174
+ const failures = [];
175
+ for (let i = 0; i < models.length; i++) {
176
+ const index = (startIndex + i) % models.length;
177
+ const adapter = models[index];
178
+ const out = { retriesAttempted: 0 };
179
+ try {
180
+ yield* this._streamWithRetries(adapter, request, out);
181
+ await this._advanceIndex(index);
182
+ return;
183
+ } catch (error) {
184
+ if (!this._isRetryable(error)) throw error;
185
+ const failure = {
186
+ model: adapter.model,
187
+ provider: adapter.provider,
188
+ error: error instanceof Error ? error : new Error(String(error)),
189
+ attempt: i + 1,
190
+ retriesAttempted: out.retriesAttempted
191
+ };
192
+ failures.push(failure);
193
+ const nextOffset = i + 1;
194
+ if (nextOffset < models.length && onFallback) {
195
+ const nextIndex = (startIndex + nextOffset) % models.length;
196
+ onFallback({
197
+ attemptedModel: adapter.model,
198
+ nextModel: models[nextIndex].model,
199
+ error: failure.error,
200
+ attempt: failure.attempt
201
+ });
202
+ }
203
+ }
204
+ }
205
+ throw new FallbackExhaustedError(failures);
206
+ }
207
+ async complete(request) {
208
+ const { models, onFallback, retries, retryDelay, retryBackoff, onRetry } = this._config;
209
+ const startIndex = await this._startIndex();
210
+ const failures = [];
211
+ for (let i = 0; i < models.length; i++) {
212
+ const index = (startIndex + i) % models.length;
213
+ const adapter = models[index];
214
+ if (!adapter.complete) {
215
+ failures.push({
216
+ model: adapter.model,
217
+ provider: adapter.provider,
218
+ error: new Error(
219
+ `Adapter ${adapter.provider}/${adapter.model} does not implement complete()`
220
+ ),
221
+ attempt: i + 1,
222
+ retriesAttempted: 0
223
+ });
224
+ continue;
225
+ }
226
+ const maxAttempts = retries + 1;
227
+ let lastError = null;
228
+ let retriesAttempted = 0;
229
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
230
+ try {
231
+ const result = await adapter.complete(request);
232
+ await this._advanceIndex(index);
233
+ return result;
234
+ } catch (error) {
235
+ if (!this._isRetryable(error)) throw error;
236
+ lastError = error instanceof Error ? error : new Error(String(error));
237
+ retriesAttempted = attempt - 1;
238
+ if (attempt < maxAttempts) {
239
+ const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
240
+ onRetry?.({
241
+ model: adapter.model,
242
+ provider: adapter.provider,
243
+ error: lastError,
244
+ retryAttempt: attempt,
245
+ maxRetries: retries,
246
+ delayMs
247
+ });
248
+ await sleep(delayMs);
249
+ }
250
+ }
251
+ }
252
+ const failure = {
253
+ model: adapter.model,
254
+ provider: adapter.provider,
255
+ error: lastError,
256
+ attempt: i + 1,
257
+ retriesAttempted
258
+ };
259
+ failures.push(failure);
260
+ const nextOffset = i + 1;
261
+ if (nextOffset < models.length && onFallback) {
262
+ const nextIndex = (startIndex + nextOffset) % models.length;
263
+ onFallback({
264
+ attemptedModel: adapter.model,
265
+ nextModel: models[nextIndex].model,
266
+ error: failure.error,
267
+ attempt: failure.attempt
268
+ });
269
+ }
270
+ }
271
+ throw new FallbackExhaustedError(failures);
272
+ }
273
+ };
274
+ function createFallbackChain(config) {
275
+ return new FallbackChain(config);
276
+ }
277
+
278
+ export { FallbackExhaustedError, MemoryRoutingStore, createFallbackChain };
279
+ //# sourceMappingURL=index.mjs.map
280
+ //# sourceMappingURL=index.mjs.map
package/dist/index.d.mts CHANGED
@@ -1,10 +1,13 @@
1
1
  import { G as GenerateTextParams, a as GenerateTextResult, S as StreamTextParams, b as StreamTextResult, T as ToolContext, c as Tool, d as StorageAdapter, e as StorageMessage } from './types-CR8mi9I0.mjs';
2
2
  export { A as AssistantMessage, C as CoreMessage, w as DEFAULT_CAPABILITIES, D as DoGenerateParams, f as DoGenerateResult, E as ErrorChunk, F as FilePart, s as FinishChunk, u as FinishReason, m as GenerateStep, I as ImagePart, L as LanguageModel, M as ModelCapabilities, R as ResponseOptions, v as StorageFile, o as StreamChunk, n as StreamPart, g as SystemMessage, p as TextDeltaChunk, j as TextPart, t as TokenUsage, k as ToolCall, q as ToolCallChunk, h as ToolMessage, l as ToolResult, r as ToolResultChunk, i as UserContentPart, U as UserMessage } from './types-CR8mi9I0.mjs';
3
3
  import { z } from 'zod';
4
- import { A as AIProvider, a as ActionDefinition, T as ToolDefinition, b as ToolProfile, K as KnowledgeBaseConfig, W as WebSearchConfig, L as LLMAdapter, D as DoneEventMessage, S as StreamEvent, c as ToolCallInfo, d as TokenUsageRaw, P as ProviderToolRuntimeOptions, M as Message, e as ToolResponse } from './types-DoZX2k3v.mjs';
5
- export { f as AdapterFactory, h as AnthropicProviderConfig, I as AnthropicProviderToolOptions, m as AnthropicTool, o as AnthropicToolResult, E as AnthropicToolSelectionHints, n as AnthropicToolUse, i as AzureProviderConfig, B as BaseProviderConfig, C as ChatCompletionRequest, J as Citation, t as GeminiFunctionCall, s as GeminiFunctionDeclaration, u as GeminiFunctionResponse, G as GoogleProviderConfig, v as LLMConfig, k as OllamaModelOptions, j as OllamaProviderConfig, O as OpenAIProviderConfig, H as OpenAIProviderToolOptions, p as OpenAITool, q as OpenAIToolCall, r as OpenAIToolResult, z as OpenAIToolSelectionHints, g as ProviderCapabilities, l as ProviderFormatter, y as ToolExecution, w as ToolLocation, F as ToolNativeProviderHints, U as UnifiedToolCall, x as UnifiedToolResult, X as XAIProviderConfig } from './types-DoZX2k3v.mjs';
4
+ import { A as ActionDefinition, T as ToolDefinition, a as ToolProfile, K as KnowledgeBaseConfig, W as WebSearchConfig, L as LLMAdapter, D as DoneEventMessage, S as StreamEvent, b as ToolCallInfo, c as TokenUsageRaw, P as ProviderToolRuntimeOptions, M as Message, d as ToolResponse } from './base-5n-UuPfS.mjs';
5
+ export { e as AdapterFactory, m as AnthropicProviderToolOptions, j as AnthropicToolSelectionHints, C as ChatCompletionRequest, n as Citation, f as LLMConfig, l as OpenAIProviderToolOptions, O as OpenAIToolSelectionHints, i as ToolExecution, g as ToolLocation, k as ToolNativeProviderHints, U as UnifiedToolCall, h as UnifiedToolResult } from './base-5n-UuPfS.mjs';
6
+ import { A as AIProvider } from './types-VDgiUvH2.mjs';
7
+ export { a as AnthropicProviderConfig, f as AnthropicTool, h as AnthropicToolResult, g as AnthropicToolUse, b as AzureProviderConfig, B as BaseProviderConfig, m as GeminiFunctionCall, l as GeminiFunctionDeclaration, n as GeminiFunctionResponse, G as GoogleProviderConfig, d as OllamaModelOptions, c as OllamaProviderConfig, O as OpenAIProviderConfig, i as OpenAITool, j as OpenAIToolCall, k as OpenAIToolResult, P as ProviderCapabilities, e as ProviderFormatter, X as XAIProviderConfig } from './types-VDgiUvH2.mjs';
6
8
  import * as hono from 'hono';
7
9
  import { Hono } from 'hono';
10
+ export { F as FallbackChainConfig, c as FallbackFailure, d as FallbackInfo, b as RetryBackoff, e as RetryInfo, R as RoutingStore, a as RoutingStrategy } from './types-BQl1suAv.mjs';
8
11
 
9
12
  /**
10
13
  * generateText - Generate text using a language model
package/dist/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import { G as GenerateTextParams, a as GenerateTextResult, S as StreamTextParams, b as StreamTextResult, T as ToolContext, c as Tool, d as StorageAdapter, e as StorageMessage } from './types-CR8mi9I0.js';
2
2
  export { A as AssistantMessage, C as CoreMessage, w as DEFAULT_CAPABILITIES, D as DoGenerateParams, f as DoGenerateResult, E as ErrorChunk, F as FilePart, s as FinishChunk, u as FinishReason, m as GenerateStep, I as ImagePart, L as LanguageModel, M as ModelCapabilities, R as ResponseOptions, v as StorageFile, o as StreamChunk, n as StreamPart, g as SystemMessage, p as TextDeltaChunk, j as TextPart, t as TokenUsage, k as ToolCall, q as ToolCallChunk, h as ToolMessage, l as ToolResult, r as ToolResultChunk, i as UserContentPart, U as UserMessage } from './types-CR8mi9I0.js';
3
3
  import { z } from 'zod';
4
- import { A as AIProvider, a as ActionDefinition, T as ToolDefinition, b as ToolProfile, K as KnowledgeBaseConfig, W as WebSearchConfig, L as LLMAdapter, D as DoneEventMessage, S as StreamEvent, c as ToolCallInfo, d as TokenUsageRaw, P as ProviderToolRuntimeOptions, M as Message, e as ToolResponse } from './types-DtPQaoJi.js';
5
- export { f as AdapterFactory, h as AnthropicProviderConfig, I as AnthropicProviderToolOptions, m as AnthropicTool, o as AnthropicToolResult, E as AnthropicToolSelectionHints, n as AnthropicToolUse, i as AzureProviderConfig, B as BaseProviderConfig, C as ChatCompletionRequest, J as Citation, t as GeminiFunctionCall, s as GeminiFunctionDeclaration, u as GeminiFunctionResponse, G as GoogleProviderConfig, v as LLMConfig, k as OllamaModelOptions, j as OllamaProviderConfig, O as OpenAIProviderConfig, H as OpenAIProviderToolOptions, p as OpenAITool, q as OpenAIToolCall, r as OpenAIToolResult, z as OpenAIToolSelectionHints, g as ProviderCapabilities, l as ProviderFormatter, y as ToolExecution, w as ToolLocation, F as ToolNativeProviderHints, U as UnifiedToolCall, x as UnifiedToolResult, X as XAIProviderConfig } from './types-DtPQaoJi.js';
4
+ import { A as ActionDefinition, T as ToolDefinition, a as ToolProfile, K as KnowledgeBaseConfig, W as WebSearchConfig, L as LLMAdapter, D as DoneEventMessage, S as StreamEvent, b as ToolCallInfo, c as TokenUsageRaw, P as ProviderToolRuntimeOptions, M as Message, d as ToolResponse } from './base-Di31iy_8.js';
5
+ export { e as AdapterFactory, m as AnthropicProviderToolOptions, j as AnthropicToolSelectionHints, C as ChatCompletionRequest, n as Citation, f as LLMConfig, l as OpenAIProviderToolOptions, O as OpenAIToolSelectionHints, i as ToolExecution, g as ToolLocation, k as ToolNativeProviderHints, U as UnifiedToolCall, h as UnifiedToolResult } from './base-Di31iy_8.js';
6
+ import { A as AIProvider } from './types-C0vLXzuw.js';
7
+ export { a as AnthropicProviderConfig, f as AnthropicTool, h as AnthropicToolResult, g as AnthropicToolUse, b as AzureProviderConfig, B as BaseProviderConfig, m as GeminiFunctionCall, l as GeminiFunctionDeclaration, n as GeminiFunctionResponse, G as GoogleProviderConfig, d as OllamaModelOptions, c as OllamaProviderConfig, O as OpenAIProviderConfig, i as OpenAITool, j as OpenAIToolCall, k as OpenAIToolResult, P as ProviderCapabilities, e as ProviderFormatter, X as XAIProviderConfig } from './types-C0vLXzuw.js';
6
8
  import * as hono from 'hono';
7
9
  import { Hono } from 'hono';
10
+ export { F as FallbackChainConfig, c as FallbackFailure, d as FallbackInfo, b as RetryBackoff, e as RetryInfo, R as RoutingStore, a as RoutingStrategy } from './types-CNL8ZRne.js';
8
11
 
9
12
  /**
10
13
  * generateText - Generate text using a language model
@@ -1,6 +1,7 @@
1
1
  import { L as LanguageModel } from '../../types-CR8mi9I0.mjs';
2
- import { h as AnthropicProviderConfig, A as AIProvider } from '../../types-DoZX2k3v.mjs';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-VDgiUvH2.mjs';
3
3
  import 'zod';
4
+ import '../../base-5n-UuPfS.mjs';
4
5
 
5
6
  /**
6
7
  * Anthropic Provider - Modern Pattern
@@ -1,6 +1,7 @@
1
1
  import { L as LanguageModel } from '../../types-CR8mi9I0.js';
2
- import { h as AnthropicProviderConfig, A as AIProvider } from '../../types-DtPQaoJi.js';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-C0vLXzuw.js';
3
3
  import 'zod';
4
+ import '../../base-Di31iy_8.js';
4
5
 
5
6
  /**
6
7
  * Anthropic Provider - Modern Pattern
@@ -1,4 +1,5 @@
1
- import { i as AzureProviderConfig, A as AIProvider } from '../../types-DoZX2k3v.mjs';
1
+ import { b as AzureProviderConfig, A as AIProvider } from '../../types-VDgiUvH2.mjs';
2
+ import '../../base-5n-UuPfS.mjs';
2
3
  import '../../types-CR8mi9I0.mjs';
3
4
  import 'zod';
4
5
 
@@ -1,4 +1,5 @@
1
- import { i as AzureProviderConfig, A as AIProvider } from '../../types-DtPQaoJi.js';
1
+ import { b as AzureProviderConfig, A as AIProvider } from '../../types-C0vLXzuw.js';
2
+ import '../../base-Di31iy_8.js';
2
3
  import '../../types-CR8mi9I0.js';
3
4
  import 'zod';
4
5
 
@@ -1,6 +1,7 @@
1
1
  import { L as LanguageModel } from '../../types-CR8mi9I0.mjs';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-DoZX2k3v.mjs';
2
+ import { G as GoogleProviderConfig, A as AIProvider } from '../../types-VDgiUvH2.mjs';
3
3
  import 'zod';
4
+ import '../../base-5n-UuPfS.mjs';
4
5
 
5
6
  /**
6
7
  * Google Provider - OpenAI-Compatible
@@ -1,6 +1,7 @@
1
1
  import { L as LanguageModel } from '../../types-CR8mi9I0.js';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-DtPQaoJi.js';
2
+ import { G as GoogleProviderConfig, A as AIProvider } from '../../types-C0vLXzuw.js';
3
3
  import 'zod';
4
+ import '../../base-Di31iy_8.js';
4
5
 
5
6
  /**
6
7
  * Google Provider - OpenAI-Compatible
@@ -1,5 +1,6 @@
1
- import { j as OllamaProviderConfig, A as AIProvider } from '../../types-DoZX2k3v.mjs';
2
- export { k as OllamaModelOptions } from '../../types-DoZX2k3v.mjs';
1
+ import { c as OllamaProviderConfig, A as AIProvider } from '../../types-VDgiUvH2.mjs';
2
+ export { d as OllamaModelOptions } from '../../types-VDgiUvH2.mjs';
3
+ import '../../base-5n-UuPfS.mjs';
3
4
  import '../../types-CR8mi9I0.mjs';
4
5
  import 'zod';
5
6
 
@@ -1,5 +1,6 @@
1
- import { j as OllamaProviderConfig, A as AIProvider } from '../../types-DtPQaoJi.js';
2
- export { k as OllamaModelOptions } from '../../types-DtPQaoJi.js';
1
+ import { c as OllamaProviderConfig, A as AIProvider } from '../../types-C0vLXzuw.js';
2
+ export { d as OllamaModelOptions } from '../../types-C0vLXzuw.js';
3
+ import '../../base-Di31iy_8.js';
3
4
  import '../../types-CR8mi9I0.js';
4
5
  import 'zod';
5
6