@providerkit/core 0.1.0 → 0.3.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/README.md +35 -158
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +8 -0
- package/dist/context.js.map +1 -1
- package/dist/errors.d.ts +36 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +75 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/key-pool.d.ts +60 -0
- package/dist/key-pool.d.ts.map +1 -0
- package/dist/key-pool.js +235 -0
- package/dist/key-pool.js.map +1 -0
- package/dist/providers/anthropic.d.ts +10 -6
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +30 -14
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/gemini.d.ts +40 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +303 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/openai.d.ts +38 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +122 -16
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/responses.d.ts +38 -0
- package/dist/providers/responses.d.ts.map +1 -0
- package/dist/providers/responses.js +341 -0
- package/dist/providers/responses.js.map +1 -0
- package/dist/rate-limit.d.ts +29 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +194 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/transport.d.ts +18 -5
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +61 -35
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/dist/zod.d.ts +8 -1
- package/dist/zod.d.ts.map +1 -1
- package/dist/zod.js +9 -2
- package/dist/zod.js.map +1 -1
- package/package.json +2 -2
- package/src/context.ts +7 -0
- package/src/errors.ts +82 -2
- package/src/index.ts +4 -0
- package/src/key-pool.ts +272 -0
- package/src/providers/anthropic.ts +41 -20
- package/src/providers/gemini.ts +386 -0
- package/src/providers/openai.ts +153 -16
- package/src/providers/responses.ts +455 -0
- package/src/rate-limit.ts +217 -0
- package/src/transport.ts +61 -35
- package/src/types.ts +19 -2
- package/src/zod.ts +12 -2
package/dist/transport.d.ts
CHANGED
|
@@ -20,12 +20,25 @@ export declare function retryAfterFromHeaders(headers: Headers, now?: number): n
|
|
|
20
20
|
/** POST and parse one JSON response. For the endpoints that do not stream. */
|
|
21
21
|
export declare function postJson<T = unknown>(opts: RequestInit_): Promise<T>;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Yield each `data:` payload of an SSE body, trimmed — plus the bare JSON
|
|
24
|
+
* object a vendor appends outside the framing, which is only ever an error
|
|
25
|
+
* (see `payloadOf`).
|
|
24
26
|
*
|
|
25
|
-
* Frames are split on the blank line the spec requires, so a payload
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* Frames are split on the blank line the spec requires, so a payload containing
|
|
28
|
+
* a bare newline survives; `[DONE]` is swallowed here rather than in every
|
|
29
|
+
* adapter. CRLF is normalized — some gateways send it, and a `\r` left on the
|
|
30
|
+
* end of a JSON payload is a parse error nobody enjoys debugging.
|
|
31
|
+
*
|
|
32
|
+
* Exported apart from `streamSse` because the envelope above it is the half an
|
|
33
|
+
* adopting app most often cannot take: an app with its own translated error
|
|
34
|
+
* copy, its own log levels, or its own auth refresh has to keep building the
|
|
35
|
+
* request and reading the failure itself. Framing is the half nobody should
|
|
36
|
+
* write twice — hand it a `res.body` and keep your own envelope.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseSseStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string>;
|
|
39
|
+
/**
|
|
40
|
+
* POST an SSE request and stream its payloads: the envelope (auth, the
|
|
41
|
+
* classified error, the retry hints) plus `parseSseStream`.
|
|
29
42
|
*/
|
|
30
43
|
export declare function streamSse(opts: RequestInit_): AsyncGenerator<string>;
|
|
31
44
|
//# sourceMappingURL=transport.d.ts.map
|
package/dist/transport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,yEAAyE;AACzE,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,SAAS,CA6B5F;AAoCD,8EAA8E;AAC9E,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAI1E;AAED
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,yEAAyE;AACzE,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,SAAS,CA6B5F;AAoCD,8EAA8E;AAC9E,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAI1E;AAwBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAuB,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CA8B9F;AAED;;;GAGG;AACH,wBAAuB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAW3E"}
|
package/dist/transport.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Adapters keep only their per-event mapping; everything about being an HTTP
|
|
6
6
|
// client lives here once.
|
|
7
|
-
import {
|
|
7
|
+
import { classifyHttp, isTransportFailure, ProviderError } from "./errors.js";
|
|
8
8
|
/** Join a base URL and a path without doubling or dropping the slash. */
|
|
9
9
|
export function apiUrl(baseUrl, path) {
|
|
10
10
|
return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
|
@@ -53,7 +53,7 @@ export function retryAfterFromHeaders(headers, now = Date.now()) {
|
|
|
53
53
|
/** Turn a non-2xx response into the classified error every caller branches on. */
|
|
54
54
|
async function errorFor(provider, res) {
|
|
55
55
|
const text = await res.text().catch(() => "");
|
|
56
|
-
const kind =
|
|
56
|
+
const kind = classifyHttp(res.status, text);
|
|
57
57
|
const message = text
|
|
58
58
|
? `${provider} ${res.status}: ${text.slice(0, 500)}`
|
|
59
59
|
: `${provider} ${res.status} ${res.statusText}`;
|
|
@@ -91,49 +91,58 @@ export async function postJson(opts) {
|
|
|
91
91
|
throw await errorFor(opts.provider, res);
|
|
92
92
|
return (await res.json());
|
|
93
93
|
}
|
|
94
|
+
/** Pull the `data:` payload out of one SSE frame, joining continuation lines
|
|
95
|
+
* the way the spec says to. Returns null for a comment or a frame carrying
|
|
96
|
+
* only an `event:` name. */
|
|
97
|
+
function payloadOf(frame) {
|
|
98
|
+
const parts = [];
|
|
99
|
+
for (const line of frame.split("\n")) {
|
|
100
|
+
if (!line.startsWith("data:"))
|
|
101
|
+
continue;
|
|
102
|
+
parts.push(line.slice(5).replace(/^ /, ""));
|
|
103
|
+
}
|
|
104
|
+
// Gemini abandons the framing to report a mid-stream failure: the
|
|
105
|
+
// google.rpc.Status is appended as a bare JSON object with no `data:` on
|
|
106
|
+
// it. Dropped here it never reaches an adapter, and a 429 or a 503 that
|
|
107
|
+
// lands after the headers reads as an empty, successful turn. Requiring an
|
|
108
|
+
// object keeps comments and `event:`-only frames returning null.
|
|
109
|
+
if (parts.length === 0) {
|
|
110
|
+
const bare = frame.trim();
|
|
111
|
+
return bare.startsWith("{") ? bare : null;
|
|
112
|
+
}
|
|
113
|
+
const payload = parts.join("\n").trim();
|
|
114
|
+
return payload.length > 0 ? payload : null;
|
|
115
|
+
}
|
|
94
116
|
/**
|
|
95
|
-
*
|
|
117
|
+
* Yield each `data:` payload of an SSE body, trimmed — plus the bare JSON
|
|
118
|
+
* object a vendor appends outside the framing, which is only ever an error
|
|
119
|
+
* (see `payloadOf`).
|
|
96
120
|
*
|
|
97
|
-
* Frames are split on the blank line the spec requires, so a payload
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
121
|
+
* Frames are split on the blank line the spec requires, so a payload containing
|
|
122
|
+
* a bare newline survives; `[DONE]` is swallowed here rather than in every
|
|
123
|
+
* adapter. CRLF is normalized — some gateways send it, and a `\r` left on the
|
|
124
|
+
* end of a JSON payload is a parse error nobody enjoys debugging.
|
|
125
|
+
*
|
|
126
|
+
* Exported apart from `streamSse` because the envelope above it is the half an
|
|
127
|
+
* adopting app most often cannot take: an app with its own translated error
|
|
128
|
+
* copy, its own log levels, or its own auth refresh has to keep building the
|
|
129
|
+
* request and reading the failure itself. Framing is the half nobody should
|
|
130
|
+
* write twice — hand it a `res.body` and keep your own envelope.
|
|
101
131
|
*/
|
|
102
|
-
export async function*
|
|
103
|
-
const
|
|
104
|
-
if (!res.ok)
|
|
105
|
-
throw await errorFor(opts.provider, res);
|
|
106
|
-
// A 2xx with no body at all is an upstream anomaly, not a request we got
|
|
107
|
-
// wrong — worth the same retry a 5xx gets.
|
|
108
|
-
if (!res.body) {
|
|
109
|
-
throw new ProviderError(opts.provider, "overload", `${opts.provider}: empty response body`, {
|
|
110
|
-
status: res.status,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
const reader = res.body.getReader();
|
|
132
|
+
export async function* parseSseStream(body) {
|
|
133
|
+
const reader = body.getReader();
|
|
114
134
|
const decoder = new TextDecoder();
|
|
115
135
|
let buffer = "";
|
|
116
|
-
/** Pull the `data:` payload out of one SSE frame, joining continuation
|
|
117
|
-
* lines the way the spec says to. Returns null for a comment or a frame
|
|
118
|
-
* carrying only an `event:` name. */
|
|
119
|
-
function payloadOf(frame) {
|
|
120
|
-
const parts = [];
|
|
121
|
-
for (const line of frame.split("\n")) {
|
|
122
|
-
if (!line.startsWith("data:"))
|
|
123
|
-
continue;
|
|
124
|
-
parts.push(line.slice(5).replace(/^ /, ""));
|
|
125
|
-
}
|
|
126
|
-
if (parts.length === 0)
|
|
127
|
-
return null;
|
|
128
|
-
const payload = parts.join("\n").trim();
|
|
129
|
-
return payload.length > 0 ? payload : null;
|
|
130
|
-
}
|
|
131
136
|
try {
|
|
132
137
|
for (;;) {
|
|
133
138
|
const { done, value } = await reader.read();
|
|
134
139
|
if (done)
|
|
135
140
|
break;
|
|
136
|
-
|
|
141
|
+
// Normalized on the BUFFER, not on the decoded read: a network read can
|
|
142
|
+
// end between the CR and the LF, and normalizing each read separately
|
|
143
|
+
// leaves that CR stranded on the end of a payload — a JSON parse error
|
|
144
|
+
// that only ever reproduces under a particular packet split.
|
|
145
|
+
buffer = (buffer + decoder.decode(value, { stream: true })).replace(/\r\n/g, "\n");
|
|
137
146
|
let boundary = buffer.indexOf("\n\n");
|
|
138
147
|
while (boundary !== -1) {
|
|
139
148
|
const frame = buffer.slice(0, boundary);
|
|
@@ -154,4 +163,21 @@ export async function* streamSse(opts) {
|
|
|
154
163
|
reader.releaseLock();
|
|
155
164
|
}
|
|
156
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* POST an SSE request and stream its payloads: the envelope (auth, the
|
|
168
|
+
* classified error, the retry hints) plus `parseSseStream`.
|
|
169
|
+
*/
|
|
170
|
+
export async function* streamSse(opts) {
|
|
171
|
+
const res = await send(opts);
|
|
172
|
+
if (!res.ok)
|
|
173
|
+
throw await errorFor(opts.provider, res);
|
|
174
|
+
// A 2xx with no body at all is an upstream anomaly, not a request we got
|
|
175
|
+
// wrong — worth the same retry a 5xx gets.
|
|
176
|
+
if (!res.body) {
|
|
177
|
+
throw new ProviderError(opts.provider, "overload", `${opts.provider}: empty response body`, {
|
|
178
|
+
status: res.status,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
yield* parseSseStream(res.body);
|
|
182
|
+
}
|
|
157
183
|
//# sourceMappingURL=transport.js.map
|
package/dist/transport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,0BAA0B;AAC1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,0BAA0B;AAC1B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAa9E,yEAAyE;AACzE,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,IAAY;IAClD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACtE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,yEAAyE;IACzE,KAAK,MAAM,IAAI,IAAI;QACjB,mCAAmC;QACnC,oCAAoC;QACpC,kCAAkC;QAClC,4BAA4B;QAC5B,0BAA0B;QAC1B,mBAAmB;KACpB,EAAE,CAAC;QACF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,wEAAwE;YACxE,6DAA6D;YAC7D,MAAM,EAAE,GAAG,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3E,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,EAAE,CAAC;QACxB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,kFAAkF;AAClF,KAAK,UAAU,QAAQ,CAAC,QAAgB,EAAE,GAAa;IACrD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI;QAClB,CAAC,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;QACpD,CAAC,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;IAClD,OAAO,IAAI,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;QAChD,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC;QAChD,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,SAAS;KACxC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,IAAkB;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC;IACnD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;YAC7B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;YAChE,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YAC3E,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,mEAAmE;QACnE,2DAA2D;QAC3D,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC;YAAE,MAAM,GAAG,CAAC;QAChE,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,oBAAoB,IAAI,CAAC,GAAG,EAAE,EAAE;YAChF,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAc,IAAkB;IAC5D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;AACjC,CAAC;AAED;;6BAE6B;AAC7B,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QACxC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,kEAAkE;IAClE,yEAAyE;IACzE,wEAAwE;IACxE,2EAA2E;IAC3E,iEAAiE;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,cAAc,CAAC,IAAgC;IACpE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,wEAAwE;YACxE,sEAAsE;YACtE,uEAAuE;YACvE,6DAA6D;YAC7D,MAAM,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAEnF,IAAI,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACtC,OAAO,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBACvB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;gBACxC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;gBACpC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;gBACjC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,QAAQ;oBAAE,MAAM,OAAO,CAAC;gBAC5D,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QACD,wEAAwE;QACxE,gEAAgE;QAChE,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,CAAC;IACrD,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,SAAS,CAAC,IAAkB;IACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtD,yEAAyE;IACzE,2CAA2C;IAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,QAAQ,uBAAuB,EAAE;YAC1F,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -56,6 +56,16 @@ export type ChatMessage = {
|
|
|
56
56
|
* unsupported. `stripReasoning` below is that rule, once.
|
|
57
57
|
*/
|
|
58
58
|
reasoning?: string;
|
|
59
|
+
/**
|
|
60
|
+
* OpenRouter's normalized reasoning payload, arriving on the stream and
|
|
61
|
+
* riding back UNMODIFIED on the next turn's assistant message.
|
|
62
|
+
*
|
|
63
|
+
* Opaque on purpose — the same contract as Gemini's `thoughtSignature`,
|
|
64
|
+
* and for the same reason: it is the provider's own record of how it got
|
|
65
|
+
* here, and reading, reshaping or dropping it costs the model its
|
|
66
|
+
* continuity across a tool round. Absent on every other dialect.
|
|
67
|
+
*/
|
|
68
|
+
reasoningDetails?: unknown[];
|
|
59
69
|
toolCalls?: ToolCall[];
|
|
60
70
|
} | {
|
|
61
71
|
role: "tool";
|
|
@@ -104,6 +114,9 @@ export interface ProviderChunk {
|
|
|
104
114
|
type: "delta" | "usage" | "finish";
|
|
105
115
|
content?: string;
|
|
106
116
|
reasoning?: string;
|
|
117
|
+
/** OpenRouter's normalized reasoning payload — hand it back on the next
|
|
118
|
+
* turn's assistant message verbatim. See ChatMessage.reasoningDetails. */
|
|
119
|
+
reasoningDetails?: unknown[];
|
|
107
120
|
toolCalls?: ToolCallDelta[];
|
|
108
121
|
usage?: TokenUsage;
|
|
109
122
|
finishReason?: FinishReason;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,mDAAoD,CAAC;AACzE,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAEvD;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;kDACkD;AAClD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/C;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB;gEAC4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB,CAAC;AAEN,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB;;iFAE6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;IAC1B;8EAC0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,UAIzB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;0DAC0D;AAC1D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;2CAEuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,YAAY,CACV,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,IAAI,CAAC,EAAE,aAAa,GACnB,aAAa,CAAC,aAAa,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;kEACkE;AAClE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAgBrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,mDAAoD,CAAC;AACzE,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAEvD;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;kDACkD;AAClD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/C;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB;gEAC4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB,CAAC;AAEN,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB;;iFAE6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;IAC1B;8EAC0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,UAIzB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;0DAC0D;AAC1D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;2CAEuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,YAAY,CACV,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,IAAI,CAAC,EAAE,aAAa,GACnB,aAAa,CAAC,aAAa,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;kEACkE;AAClE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAgBrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAU9E;AAED,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEjD"}
|
package/dist/types.js
CHANGED
|
@@ -62,9 +62,14 @@ export async function drainStream(stream, model) {
|
|
|
62
62
|
*/
|
|
63
63
|
export function stripReasoning(messages) {
|
|
64
64
|
return messages.map((message) => {
|
|
65
|
-
if (message.role !== "assistant"
|
|
65
|
+
if (message.role !== "assistant")
|
|
66
66
|
return message;
|
|
67
|
-
|
|
67
|
+
if (message.reasoning === undefined && message.reasoningDetails === undefined)
|
|
68
|
+
return message;
|
|
69
|
+
// Both halves go. `reasoningDetails` is the same chain of thought in the
|
|
70
|
+
// provider's own words, so leaving it behind carries into a thinking-off
|
|
71
|
+
// turn exactly what stripping `reasoning` was meant to keep out.
|
|
72
|
+
const { reasoning: _text, reasoningDetails: _payload, ...rest } = message;
|
|
68
73
|
return rest;
|
|
69
74
|
});
|
|
70
75
|
}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,0BAA0B;AAE1B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AAGzE,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,0BAA0B;AAE1B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AAGzE,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AA4GD,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC,WAAW,EAAE,CAAC;IACd,iBAAiB,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC;CAChB,CAAC;AA6DF;kEACkE;AAClE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoC,EACpC,KAAa;IAEb,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,KAAK,GAAe,WAAW,CAAC;IACpC,IAAI,YAAY,GAAwB,IAAI,CAAC;IAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,OAAO;gBAAE,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC;YACzC,IAAI,KAAK,CAAC,SAAS;gBAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACpD,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACjD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACzD,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgC;IAC7D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,OAAO,CAAC;QACjD,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAC9F,yEAAyE;QACzE,yEAAyE;QACzE,iEAAiE;QACjE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,OAAO,QAAQ,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC"}
|
package/dist/zod.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type Tool, type ToolContext } from "./tools.ts";
|
|
3
3
|
import type { JsonObjectSchema } from "./types.ts";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* A zod schema as the JSON Schema every provider's tool contract wants.
|
|
6
|
+
*
|
|
7
|
+
* `$schema` is dropped. zod emits the dialect URI at the root, and a provider
|
|
8
|
+
* validating a tool's `parameters` against its own supported subset — OpenAI
|
|
9
|
+
* under `strict: true`, Gemini's `parametersJsonSchema` — rejects the whole
|
|
10
|
+
* tool over that one key, with a message that names neither zod nor the field.
|
|
11
|
+
*/
|
|
5
12
|
export declare function toJsonObjectSchema(schema: z.ZodType, label?: string): JsonObjectSchema;
|
|
6
13
|
export interface ZodToolSpec<I, O> {
|
|
7
14
|
name: string;
|
package/dist/zod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAc,KAAK,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAc,KAAK,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,SAAW,GAAG,gBAAgB,CAYxF;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAyBjE"}
|
package/dist/zod.js
CHANGED
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { defineTool } from "./tools.js";
|
|
8
8
|
import { clampToSchema } from "./schema.js";
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* A zod schema as the JSON Schema every provider's tool contract wants.
|
|
11
|
+
*
|
|
12
|
+
* `$schema` is dropped. zod emits the dialect URI at the root, and a provider
|
|
13
|
+
* validating a tool's `parameters` against its own supported subset — OpenAI
|
|
14
|
+
* under `strict: true`, Gemini's `parametersJsonSchema` — rejects the whole
|
|
15
|
+
* tool over that one key, with a message that names neither zod nor the field.
|
|
16
|
+
*/
|
|
10
17
|
export function toJsonObjectSchema(schema, label = "schema") {
|
|
11
|
-
const json = z.toJSONSchema(schema, { io: "input" });
|
|
18
|
+
const { $schema: _dialect, ...json } = z.toJSONSchema(schema, { io: "input" });
|
|
12
19
|
if (json.type !== "object") {
|
|
13
20
|
// Every provider requires an object at the top level of a tool's
|
|
14
21
|
// parameters; a bare string or array is rejected at the wire, far from
|
package/dist/zod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,wEAAwE;AACxE,2EAA2E;AAC3E,uDAAuD;AACvD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAA+B,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C
|
|
1
|
+
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@providerkit/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The layer under your agent loop: one seam for every LLM provider, plus the failure handling you only learn in production.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"author": "Gustavo
|
|
7
|
+
"author": "Gustavo Salomé",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
package/src/context.ts
CHANGED
|
@@ -56,6 +56,13 @@ export function conversationTokens(messages: readonly ChatMessage[]): number {
|
|
|
56
56
|
* that is not a guess. Estimate only when there is no reported count yet.
|
|
57
57
|
*/
|
|
58
58
|
export function needsCompaction(inputTokens: number, contextWindow: number): boolean {
|
|
59
|
+
// A window at or below the reserve puts the threshold at zero or less, and
|
|
60
|
+
// every turn — including one that has not reported usage yet — then reads as
|
|
61
|
+
// already full. That loops: folding a history this side of its first answer
|
|
62
|
+
// changes nothing, so the next check says the same thing. Small windows are
|
|
63
|
+
// not hypothetical; a caller that learns a real ceiling from a rejection
|
|
64
|
+
// (rather than guessing one) can legitimately arrive here with 8k.
|
|
65
|
+
if (inputTokens <= 0) return false;
|
|
59
66
|
return inputTokens >= contextWindow - CONTEXT_RESERVE_TOKENS;
|
|
60
67
|
}
|
|
61
68
|
|
package/src/errors.ts
CHANGED
|
@@ -221,6 +221,12 @@ export function isTransportFailure(err: unknown): boolean {
|
|
|
221
221
|
const message = readString(current, "message");
|
|
222
222
|
if (name === "APIConnectionError" || name === "APIConnectionTimeoutError") return true;
|
|
223
223
|
if (code !== undefined && TRANSPORT_CODES.has(code)) return true;
|
|
224
|
+
// undici — Node's fetch, and Bun's — parks the real reason in `code` while
|
|
225
|
+
// the thrown error says only "terminated", which is the most common way a
|
|
226
|
+
// stream dies mid-body. Its whole family shares one prefix; enumerating
|
|
227
|
+
// them ages badly, the prefix does not. UND_ERR_ABORTED is the caller's
|
|
228
|
+
// Stop wearing the same prefix, and is never ours to retry.
|
|
229
|
+
if (code?.startsWith("UND_ERR_") && code !== "UND_ERR_ABORTED") return true;
|
|
224
230
|
// A bare TypeError is also what a real bug throws ("x is not a function"),
|
|
225
231
|
// so the MESSAGE is checked, not just the type — misfiling one of those
|
|
226
232
|
// would retry a genuine bug three times and hide it.
|
|
@@ -274,7 +280,6 @@ const QUOTA_PATTERNS: readonly RegExp[] = [
|
|
|
274
280
|
/upgrade your plan/i,
|
|
275
281
|
/quota\b[^.]{0,40}\b(?:exhausted|exceeded|will be refreshed)/i,
|
|
276
282
|
/balance (?:is )?(?:too low|not enough|insufficient)/i,
|
|
277
|
-
/per\s*day|PerDay|insufficient_quota|billing/i,
|
|
278
283
|
/余额不足/,
|
|
279
284
|
/欠费/,
|
|
280
285
|
/额度(?:不足|已用完)/,
|
|
@@ -300,6 +305,21 @@ const CONTENT_PATTERNS: readonly RegExp[] = [
|
|
|
300
305
|
/safety|PROHIBITED_CONTENT|blocked|refusal/i,
|
|
301
306
|
];
|
|
302
307
|
|
|
308
|
+
/**
|
|
309
|
+
* A throttle said in words rather than in a 429.
|
|
310
|
+
*
|
|
311
|
+
* Every other kind has body evidence; rate had only the status, which is
|
|
312
|
+
* exactly the evidence an in-band failure lacks — an SSE response is already
|
|
313
|
+
* 200 when the throttle lands, so the reason arrives as a payload with no
|
|
314
|
+
* status line at all. Checked below the status branches, so it only ever
|
|
315
|
+
* catches what would otherwise fall through to "unknown".
|
|
316
|
+
*/
|
|
317
|
+
const RATE_PATTERNS: readonly RegExp[] = [
|
|
318
|
+
/rate[_\s-]?limit/i,
|
|
319
|
+
/too many requests/i,
|
|
320
|
+
/RESOURCE_EXHAUSTED/,
|
|
321
|
+
];
|
|
322
|
+
|
|
303
323
|
/** Theirs and temporary, said in words rather than a status. Gemini reports
|
|
304
324
|
* UNAVAILABLE/INTERNAL in the body; gateways say "capacity". */
|
|
305
325
|
const OVERLOAD_PATTERNS: readonly RegExp[] = [
|
|
@@ -320,6 +340,21 @@ const matches = (patterns: readonly RegExp[], text: string): boolean =>
|
|
|
320
340
|
* entitlement beats quota beats auth — each earlier category's fix is useless
|
|
321
341
|
* for the later ones.
|
|
322
342
|
*/
|
|
343
|
+
/**
|
|
344
|
+
* The kind of a failure that arrived as an HTTP response — a status and a body,
|
|
345
|
+
* with nothing thrown.
|
|
346
|
+
*
|
|
347
|
+
* `classify` below is for a caught error, and it reads `status` and the body
|
|
348
|
+
* text off that error when they are not passed separately. A response has no
|
|
349
|
+
* error object, so callers were inventing one to fill the slot: a bare body
|
|
350
|
+
* string, the same text twice, a `{ status, error }` literal. All three are
|
|
351
|
+
* inert — nothing on them can satisfy `isAbort` or `isTransportFailure` — so
|
|
352
|
+
* they were three spellings of `undefined`.
|
|
353
|
+
*/
|
|
354
|
+
export function classifyHttp(status: number | undefined, body: string): ErrorKind {
|
|
355
|
+
return classify(undefined, status, body);
|
|
356
|
+
}
|
|
357
|
+
|
|
323
358
|
export function classify(err: unknown, status?: number, body?: string): ErrorKind {
|
|
324
359
|
if (isAbort(err)) return "aborted";
|
|
325
360
|
if (isTransportFailure(err)) return "network";
|
|
@@ -346,8 +381,11 @@ export function classify(err: unknown, status?: number, body?: string): ErrorKin
|
|
|
346
381
|
if (matches(CONTENT_PATTERNS, text)) return "content";
|
|
347
382
|
// 529 is Anthropic's own "overloaded". 409 is how several gateways say
|
|
348
383
|
// "the model is still loading" — both are worth another attempt.
|
|
349
|
-
|
|
384
|
+
// 425 Too Early: the upstream is asking us to replay, not telling us we were
|
|
385
|
+
// wrong. Left as a plain 4xx it reads as `invalid` and is never retried.
|
|
386
|
+
if (code === 529 || code === 409 || code === 425) return "overload";
|
|
350
387
|
if (code !== undefined && code >= 500) return "overload";
|
|
388
|
+
if (matches(RATE_PATTERNS, text)) return "rate";
|
|
351
389
|
if (matches(OVERLOAD_PATTERNS, text)) return "overload";
|
|
352
390
|
if (/timed out|timeout/i.test(text)) return "timeout";
|
|
353
391
|
if (code !== undefined && code >= 400) return "invalid";
|
|
@@ -380,6 +418,48 @@ export function parseRetryAfterMs(err: unknown, body?: string): number | undefin
|
|
|
380
418
|
return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());
|
|
381
419
|
}
|
|
382
420
|
|
|
421
|
+
/**
|
|
422
|
+
* A failure the backend reports INSIDE an already-200 stream.
|
|
423
|
+
*
|
|
424
|
+
* The transport classified everything that failed before the body opened; this
|
|
425
|
+
* is the rest, and every streaming shape has the same hole. An SSE response
|
|
426
|
+
* commits to 200 the moment its headers go out, so a throttle, an overload, or
|
|
427
|
+
* a prompt found too long after the fact arrives as a payload in the body
|
|
428
|
+
* rather than as a status line. Left unread it matches no branch an adapter
|
|
429
|
+
* models, the loop skips it, and the turn ends as a successful zero-token
|
|
430
|
+
* completion: retry sees nothing to retry, and a key pool never rotates off an
|
|
431
|
+
* exhausted key.
|
|
432
|
+
*
|
|
433
|
+
* `error` is the vendor's own payload, whatever shape it came in — the numeric
|
|
434
|
+
* HTTP `code` Gemini and OpenRouter use, the slug OpenAI and Anthropic put in
|
|
435
|
+
* `code`/`type`, the canonical `status` name. The whole thing serializes into
|
|
436
|
+
* the searchable body, so RetryInfo's `retryDelay` is honoured wherever it sits.
|
|
437
|
+
*
|
|
438
|
+
* `unknown` is floored to "overload" rather than kept: a stream that dies after
|
|
439
|
+
* its headers is by construction a transient upstream fault, and "unknown" is
|
|
440
|
+
* never retried. Everything the body DOES name keeps its own kind — which is
|
|
441
|
+
* what tells the caller to wait, rotate a key, or compact instead of retrying
|
|
442
|
+
* a failure that will repeat.
|
|
443
|
+
*/
|
|
444
|
+
export function streamError(provider: string, error: unknown): ProviderError {
|
|
445
|
+
const body = JSON.stringify(error ?? {}) ?? "";
|
|
446
|
+
const status = readNumber(error, "code") ?? readNumber(error, "status");
|
|
447
|
+
const code =
|
|
448
|
+
readString(error, "code") ?? readString(error, "status") ?? readString(error, "type");
|
|
449
|
+
const kind = classifyHttp(status, body);
|
|
450
|
+
return new ProviderError(
|
|
451
|
+
provider,
|
|
452
|
+
kind === "unknown" ? "overload" : kind,
|
|
453
|
+
`${provider} stream error: ${readString(error, "message") ?? code ?? "no reason given"}`,
|
|
454
|
+
{
|
|
455
|
+
...(status !== undefined ? { status } : {}),
|
|
456
|
+
...(code ? { code } : {}),
|
|
457
|
+
retryAfterMs: parseRetryAfterMs(error, body),
|
|
458
|
+
body: body.slice(0, 2_000),
|
|
459
|
+
},
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
383
463
|
/** The loggable surface of a failure — so a dead run never reads
|
|
384
464
|
* "400 status code (no body)". */
|
|
385
465
|
export function describeProviderError(err: unknown): Record<string, unknown> {
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
export * from "./types.ts";
|
|
2
2
|
export * from "./errors.ts";
|
|
3
3
|
export * from "./retry.ts";
|
|
4
|
+
export * from "./key-pool.ts";
|
|
4
5
|
export * from "./watchdog.ts";
|
|
5
6
|
export * from "./usage.ts";
|
|
6
7
|
export * from "./transport.ts";
|
|
8
|
+
export * from "./rate-limit.ts";
|
|
7
9
|
export * from "./tool-args.ts";
|
|
8
10
|
export * from "./tools.ts";
|
|
9
11
|
export * from "./schema.ts";
|
|
10
12
|
export * from "./context.ts";
|
|
11
13
|
export * from "./providers/anthropic.ts";
|
|
12
14
|
export * from "./providers/openai.ts";
|
|
15
|
+
export * from "./providers/responses.ts";
|
|
16
|
+
export * from "./providers/gemini.ts";
|