genaicode 2.0.0 → 2.1.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/CHANGELOG.md +37 -0
- package/README.md +102 -1
- package/dist/core/client.d.ts +9 -3
- package/dist/core/client.js +69 -0
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.d.ts +38 -0
- package/dist/core/errors.js +118 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/middleware.d.ts +43 -0
- package/dist/core/middleware.js +173 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/plugins.d.ts +8 -1
- package/dist/core/plugins.js +25 -1
- package/dist/core/plugins.js.map +1 -1
- package/dist/core/result.d.ts +2 -2
- package/dist/core/result.js +5 -1
- package/dist/core/result.js.map +1 -1
- package/dist/core/stream.d.ts +11 -0
- package/dist/core/stream.js +93 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/types.d.ts +50 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.js +63 -1
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/fixtures/multimodal-tool-roundtrip.d.ts +4 -0
- package/dist/providers/fixtures/multimodal-tool-roundtrip.js +32 -0
- package/dist/providers/fixtures/multimodal-tool-roundtrip.js.map +1 -0
- package/dist/providers/google.js +62 -0
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai-converter.d.ts +18 -1
- package/dist/providers/openai-converter.js +82 -0
- package/dist/providers/openai-converter.js.map +1 -1
- package/dist/providers/openai.js +17 -1
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/providers.js.map +1 -1
- package/docs/pivot.md +30 -14
- package/docs/provider-packages.md +60 -0
- package/docs/retry.md +62 -0
- package/docs/semver.md +55 -0
- package/package.json +3 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.1.0 — 2026-07-25
|
|
4
|
+
|
|
5
|
+
Publishes the Phase 3–4 work already on `master`. npm `2.0.0` shipped the 2.0
|
|
6
|
+
kernel and provider adapters only; this minor adds the remaining public surface
|
|
7
|
+
documented in the README and [semver policy](docs/semver.md).
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Provider-neutral streaming (`StreamEvent`, `.stream()` / `.streamText()`,
|
|
12
|
+
native streams for OpenAI / Anthropic / Google with generate→stream fallback)
|
|
13
|
+
- Built-in middleware: `timingPlugin`, `rateLimitPlugin`, `cachePlugin`,
|
|
14
|
+
`fallbackPlugin`, `fallbackProvider`
|
|
15
|
+
- Retry helpers: `classifyError`, `isRetryable`, `withRetry` (+ [docs/retry.md](docs/retry.md))
|
|
16
|
+
- `ProviderCapabilities` on `ModelProvider`
|
|
17
|
+
- Compatibility fixtures for multimodal and tool-call round trips
|
|
18
|
+
- Framework examples under `examples/` (HTTP handler, queue worker, cron job)
|
|
19
|
+
- Written guidance: [docs/semver.md](docs/semver.md),
|
|
20
|
+
[docs/provider-packages.md](docs/provider-packages.md)
|
|
21
|
+
|
|
22
|
+
### Notes
|
|
23
|
+
|
|
24
|
+
- Additive API only; no breaking changes from `2.0.0`.
|
|
25
|
+
- Retries remain opt-in application policy (no hidden retries in core).
|
|
26
|
+
- Provider SDKs stay bundled behind `genaicode/providers` for 2.x.
|
|
27
|
+
|
|
28
|
+
## 2.0.0 — 2026-07-24
|
|
29
|
+
|
|
30
|
+
Major pivot from coding agent to backend LLM toolkit.
|
|
31
|
+
|
|
32
|
+
- `genaicode()` client, immutable request builders, conversation chains
|
|
33
|
+
- `PromptItem` IR and prompt/result helpers
|
|
34
|
+
- OpenAI, OpenAI-compatible, Anthropic, Gemini, and Vertex adapters
|
|
35
|
+
- `GenAIPlugin` middleware contract
|
|
36
|
+
- Coding-agent CLI/UI/tools removed; `npx genaicode` prints migration guidance
|
|
37
|
+
(1.x remains on the `1.x` branch / `genaicode@1`)
|
package/README.md
CHANGED
|
@@ -129,6 +129,22 @@ for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
|
129
129
|
|
|
130
130
|
The application owns validation, attempt limits, and failure policy.
|
|
131
131
|
|
|
132
|
+
## Schema adapters
|
|
133
|
+
|
|
134
|
+
`json(...)` and `parseJsonResult(...)` accept either a parser function or a schema adapter
|
|
135
|
+
with a `parse(value)` method. This keeps schema validation library-agnostic:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const value = await ai('Return {"count": 3}.').json({
|
|
139
|
+
parse(input) {
|
|
140
|
+
if (typeof input !== 'object' || input === null || typeof input.count !== 'number') {
|
|
141
|
+
throw new Error('Invalid shape');
|
|
142
|
+
}
|
|
143
|
+
return input;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
132
148
|
## PromptItem: the portable prompt IR
|
|
133
149
|
|
|
134
150
|
`PromptItem` is GenAIcode's provider-neutral intermediate representation:
|
|
@@ -184,6 +200,68 @@ const calls = await ai('What is the weather in Warsaw?')
|
|
|
184
200
|
GenAIcode normalizes tool calls but deliberately does not execute them. The application
|
|
185
201
|
owns permissions, retries, and side effects.
|
|
186
202
|
|
|
203
|
+
## Streaming
|
|
204
|
+
|
|
205
|
+
Providers that support native streaming expose a provider-neutral `StreamEvent` IR.
|
|
206
|
+
Request builders and chains offer `.stream()` and `.streamText()`. If a provider has no
|
|
207
|
+
`stream` method, GenAIcode synthesizes a short stream from `generate`.
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
for await (const event of ai('Write a haiku about queues.').stream()) {
|
|
211
|
+
if (event.type === 'text-delta') process.stdout.write(event.text);
|
|
212
|
+
if (event.type === 'done') console.log('\n', event.result.usage);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Built-in adapters declare capability metadata:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
ai.provider.capabilities;
|
|
220
|
+
// { streaming: true, tools: true, images: 'input', systemPrompt: true }
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Middleware
|
|
224
|
+
|
|
225
|
+
Hook-style plugins remain the extension point. Built-in helpers cover common backend
|
|
226
|
+
needs without restoring a global registry:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import {
|
|
230
|
+
cachePlugin,
|
|
231
|
+
fallbackPlugin,
|
|
232
|
+
genaicode,
|
|
233
|
+
rateLimitPlugin,
|
|
234
|
+
timingPlugin,
|
|
235
|
+
} from 'genaicode';
|
|
236
|
+
import { anthropic, openai } from 'genaicode/providers';
|
|
237
|
+
|
|
238
|
+
const ai = genaicode(openai({ model: 'your-model-name' }), {
|
|
239
|
+
plugins: [
|
|
240
|
+
timingPlugin(),
|
|
241
|
+
rateLimitPlugin({ concurrency: 2, minIntervalMs: 50 }),
|
|
242
|
+
cachePlugin({ maxEntries: 64 }),
|
|
243
|
+
fallbackPlugin({ providers: [anthropic({ model: 'your-claude-model' })] }),
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Retries
|
|
249
|
+
|
|
250
|
+
Retries stay in application code. Use `classifyError`, `isRetryable`, and `withRetry`
|
|
251
|
+
when you want shared classification without hidden policy:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import { withRetry } from 'genaicode';
|
|
255
|
+
|
|
256
|
+
const text = await withRetry(() => ai('Summarize the deploy notes.').text(), {
|
|
257
|
+
attempts: 3,
|
|
258
|
+
delayMs: 250,
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
See [retry guidance](docs/retry.md), [semver policy](docs/semver.md), and the
|
|
263
|
+
[provider package evaluation](docs/provider-packages.md).
|
|
264
|
+
|
|
187
265
|
## Providers
|
|
188
266
|
|
|
189
267
|
Models are provided in the adapter, through `.model(...)`, or with environment variables:
|
|
@@ -248,6 +326,24 @@ const provider: ModelProvider = {
|
|
|
248
326
|
All Anthropic, Google, and OpenAI conversion functions are public from
|
|
249
327
|
`genaicode/providers`, so gateways and tests can reuse them without instantiating clients.
|
|
250
328
|
|
|
329
|
+
## Provider E2E tests
|
|
330
|
+
|
|
331
|
+
Run real-provider E2E tests locally with:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm run test:e2e
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
These tests are credential-gated and run only when provider-specific environment variables
|
|
338
|
+
are set:
|
|
339
|
+
|
|
340
|
+
- OpenAI: `OPENAI_API_KEY`, `OPENAI_MODEL`
|
|
341
|
+
- Anthropic: `ANTHROPIC_API_KEY`, `ANTHROPIC_MODEL`
|
|
342
|
+
- Gemini: `GEMINI_API_KEY`, `GEMINI_MODEL`
|
|
343
|
+
|
|
344
|
+
CI/CD is configured in `.github/workflows/provider-e2e.yaml`. Each provider runs in its own
|
|
345
|
+
job and only starts when both required secrets are configured in GitHub Actions.
|
|
346
|
+
|
|
251
347
|
## Plugins and hooks
|
|
252
348
|
|
|
253
349
|
A provider plugin no longer needs registration in global configuration. It exports the
|
|
@@ -259,6 +355,7 @@ import type { ModelProvider } from 'genaicode';
|
|
|
259
355
|
|
|
260
356
|
export const bedrock = (options: BedrockOptions): ModelProvider => ({
|
|
261
357
|
name: 'bedrock',
|
|
358
|
+
capabilities: { streaming: false, tools: true, systemPrompt: true },
|
|
262
359
|
async generate(request) {
|
|
263
360
|
// Convert PromptItem[], call Bedrock, and return GenerationResult.
|
|
264
361
|
return { parts: [{ type: 'text', text: 'response' }] };
|
|
@@ -267,7 +364,8 @@ export const bedrock = (options: BedrockOptions): ModelProvider => ({
|
|
|
267
364
|
```
|
|
268
365
|
|
|
269
366
|
Hook-style plugins use middleware. They can observe or rewrite requests and results,
|
|
270
|
-
handle errors, implement caches or fallbacks, and intentionally short-circuit a call
|
|
367
|
+
handle errors, implement caches or fallbacks, and intentionally short-circuit a call.
|
|
368
|
+
Optional `stream` middleware follows the same registration order.
|
|
271
369
|
|
|
272
370
|
```ts
|
|
273
371
|
import { definePlugin, genaicode } from 'genaicode';
|
|
@@ -294,6 +392,9 @@ Plugins run in registration order, and each plugin may call `next()` once. This
|
|
|
294
392
|
extension mechanism compatible with npm packages and ordinary imports without restoring
|
|
295
393
|
the 1.x runtime TypeScript loader or process-global plugin registry.
|
|
296
394
|
|
|
395
|
+
Framework-shaped examples live under `examples/` (`http-handler`, `queue-worker`,
|
|
396
|
+
`cron-job`).
|
|
397
|
+
|
|
297
398
|
## Design boundaries
|
|
298
399
|
|
|
299
400
|
- Backend library, not a coding agent.
|
package/dist/core/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type GenAIPlugin } from './plugins.js';
|
|
2
|
-
import type { GenerationDefaults, GenerationRequest, GenerationResult, ModelProvider, PromptInput, PromptItem, ToolCall, ToolChoice, ToolDefinition } from './types.js';
|
|
2
|
+
import type { GenerationDefaults, GenerationRequest, GenerationResult, JsonResultParser, ModelProvider, PromptInput, PromptItem, StreamEvent, ToolCall, ToolChoice, ToolDefinition } from './types.js';
|
|
3
3
|
export interface RequestBuilder {
|
|
4
4
|
system(text: string): RequestBuilder;
|
|
5
5
|
user(input: PromptInput): RequestBuilder;
|
|
@@ -11,16 +11,22 @@ export interface RequestBuilder {
|
|
|
11
11
|
signal(signal: AbortSignal): RequestBuilder;
|
|
12
12
|
run(): Promise<GenerationResult>;
|
|
13
13
|
text(): Promise<string>;
|
|
14
|
-
json<T = unknown>(parse?:
|
|
14
|
+
json<T = unknown>(parse?: JsonResultParser<T>): Promise<T>;
|
|
15
15
|
toolCalls(): Promise<ToolCall[]>;
|
|
16
|
+
/** Provider-neutral streaming events (native when available, synthesized otherwise). */
|
|
17
|
+
stream(): AsyncIterable<StreamEvent>;
|
|
18
|
+
/** Convenience: yield only text deltas. */
|
|
19
|
+
streamText(): AsyncIterable<string>;
|
|
16
20
|
inspect(): GenerationRequest;
|
|
17
21
|
}
|
|
18
22
|
export type ConfigureRequest = (request: RequestBuilder) => RequestBuilder;
|
|
19
23
|
export interface Conversation {
|
|
20
24
|
ask(input: PromptInput, configure?: ConfigureRequest): Promise<GenerationResult>;
|
|
21
25
|
text(input: PromptInput, configure?: ConfigureRequest): Promise<string>;
|
|
22
|
-
json<T = unknown>(input: PromptInput, parse?:
|
|
26
|
+
json<T = unknown>(input: PromptInput, parse?: JsonResultParser<T>, configure?: ConfigureRequest): Promise<T>;
|
|
23
27
|
toolCalls(input: PromptInput, configure?: ConfigureRequest): Promise<ToolCall[]>;
|
|
28
|
+
stream(input: PromptInput, configure?: ConfigureRequest): AsyncIterable<StreamEvent>;
|
|
29
|
+
streamText(input: PromptInput, configure?: ConfigureRequest): AsyncIterable<string>;
|
|
24
30
|
history(): PromptItem[];
|
|
25
31
|
reset(...initial: PromptInput[]): void;
|
|
26
32
|
}
|
package/dist/core/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assistant, prompt, system, toPromptItems } from './prompt.js';
|
|
2
2
|
import { withPlugins } from './plugins.js';
|
|
3
3
|
import { parseJsonResult, resultText, resultToPromptItem, resultToolCalls } from './result.js';
|
|
4
|
+
import { providerStream, streamTextDeltas } from './stream.js';
|
|
4
5
|
class RequestBuilderImpl {
|
|
5
6
|
provider;
|
|
6
7
|
state;
|
|
@@ -67,6 +68,12 @@ class RequestBuilderImpl {
|
|
|
67
68
|
async toolCalls() {
|
|
68
69
|
return resultToolCalls(await this.run());
|
|
69
70
|
}
|
|
71
|
+
stream() {
|
|
72
|
+
return providerStream(this.provider, this.inspect());
|
|
73
|
+
}
|
|
74
|
+
streamText() {
|
|
75
|
+
return streamTextDeltas(this.stream());
|
|
76
|
+
}
|
|
70
77
|
}
|
|
71
78
|
class ConversationImpl {
|
|
72
79
|
createRequest;
|
|
@@ -100,6 +107,68 @@ class ConversationImpl {
|
|
|
100
107
|
async toolCalls(input, configure) {
|
|
101
108
|
return resultToolCalls(await this.ask(input, configure));
|
|
102
109
|
}
|
|
110
|
+
stream(input, configure = (request) => request) {
|
|
111
|
+
return this.iterateStream(input, configure);
|
|
112
|
+
}
|
|
113
|
+
async *iterateStream(input, configure) {
|
|
114
|
+
let release = () => undefined;
|
|
115
|
+
const gate = new Promise((resolve) => {
|
|
116
|
+
release = resolve;
|
|
117
|
+
});
|
|
118
|
+
const previous = this.queue;
|
|
119
|
+
this.queue = previous.then(() => gate);
|
|
120
|
+
await previous;
|
|
121
|
+
try {
|
|
122
|
+
const additions = toPromptItems(input);
|
|
123
|
+
const generation = this.generation;
|
|
124
|
+
const events = configure(this.createRequest(this.items, additions)).stream();
|
|
125
|
+
let text = '';
|
|
126
|
+
const toolCalls = [];
|
|
127
|
+
const images = [];
|
|
128
|
+
let usage;
|
|
129
|
+
let doneResult;
|
|
130
|
+
for await (const event of events) {
|
|
131
|
+
yield event;
|
|
132
|
+
switch (event.type) {
|
|
133
|
+
case 'text-delta':
|
|
134
|
+
text += event.text;
|
|
135
|
+
break;
|
|
136
|
+
case 'tool-call':
|
|
137
|
+
toolCalls.push(event.toolCall);
|
|
138
|
+
break;
|
|
139
|
+
case 'image':
|
|
140
|
+
images.push({ type: 'image', image: event.image });
|
|
141
|
+
break;
|
|
142
|
+
case 'usage':
|
|
143
|
+
usage = event.usage;
|
|
144
|
+
break;
|
|
145
|
+
case 'done':
|
|
146
|
+
doneResult = event.result;
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const result = doneResult ??
|
|
153
|
+
{
|
|
154
|
+
parts: [
|
|
155
|
+
...(text ? [{ type: 'text', text }] : []),
|
|
156
|
+
...toolCalls.map((toolCall) => ({ type: 'toolCall', toolCall })),
|
|
157
|
+
...images,
|
|
158
|
+
],
|
|
159
|
+
usage,
|
|
160
|
+
};
|
|
161
|
+
if (generation === this.generation) {
|
|
162
|
+
this.items = [...this.items, ...additions, resultToPromptItem(result)];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
release();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
streamText(input, configure) {
|
|
170
|
+
return streamTextDeltas(this.stream(input, configure));
|
|
171
|
+
}
|
|
103
172
|
history() {
|
|
104
173
|
return this.items.map((item) => ({ ...item }));
|
|
105
174
|
}
|
package/dist/core/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ErrorClass = 'transient' | 'permanent' | 'unknown';
|
|
2
|
+
export interface ClassifiedError {
|
|
3
|
+
class: ErrorClass;
|
|
4
|
+
retryable: boolean;
|
|
5
|
+
reason: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
code?: string;
|
|
8
|
+
cause: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Classify a provider/SDK error for application-owned retry loops.
|
|
12
|
+
*
|
|
13
|
+
* GenAIcode does not retry automatically. Use this helper (or your own policy)
|
|
14
|
+
* inside ordinary application control flow. See docs/retry.md.
|
|
15
|
+
*/
|
|
16
|
+
export declare function classifyError(error: unknown): ClassifiedError;
|
|
17
|
+
export declare function isRetryable(error: unknown): boolean;
|
|
18
|
+
export interface RetryOptions {
|
|
19
|
+
attempts?: number;
|
|
20
|
+
/** Base delay in ms; doubles each attempt. Defaults to 250. */
|
|
21
|
+
delayMs?: number;
|
|
22
|
+
/** Max delay cap in ms. Defaults to 5000. */
|
|
23
|
+
maxDelayMs?: number;
|
|
24
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
25
|
+
onRetry?: (info: {
|
|
26
|
+
attempt: number;
|
|
27
|
+
error: unknown;
|
|
28
|
+
delayMs: number;
|
|
29
|
+
}) => void;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Explicit retry helper for application code. Not wired into the client by default.
|
|
34
|
+
*
|
|
35
|
+
* Idempotency: only wrap operations that are safe to repeat (most pure generation
|
|
36
|
+
* calls are; tool side effects are not unless the application makes them idempotent).
|
|
37
|
+
*/
|
|
38
|
+
export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
function readStatus(error) {
|
|
2
|
+
if (!error || typeof error !== 'object')
|
|
3
|
+
return undefined;
|
|
4
|
+
const candidate = error;
|
|
5
|
+
for (const value of [candidate.status, candidate.statusCode, candidate.response?.status]) {
|
|
6
|
+
if (typeof value === 'number')
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
function readCode(error) {
|
|
12
|
+
if (!error || typeof error !== 'object')
|
|
13
|
+
return undefined;
|
|
14
|
+
const code = error.code;
|
|
15
|
+
return typeof code === 'string' ? code : undefined;
|
|
16
|
+
}
|
|
17
|
+
function messageOf(error) {
|
|
18
|
+
if (error instanceof Error)
|
|
19
|
+
return error.message;
|
|
20
|
+
return String(error);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Classify a provider/SDK error for application-owned retry loops.
|
|
24
|
+
*
|
|
25
|
+
* GenAIcode does not retry automatically. Use this helper (or your own policy)
|
|
26
|
+
* inside ordinary application control flow. See docs/retry.md.
|
|
27
|
+
*/
|
|
28
|
+
export function classifyError(error) {
|
|
29
|
+
const status = readStatus(error);
|
|
30
|
+
const code = readCode(error);
|
|
31
|
+
const message = messageOf(error).toLowerCase();
|
|
32
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
33
|
+
return { class: 'permanent', retryable: false, reason: 'aborted', cause: error };
|
|
34
|
+
}
|
|
35
|
+
if (code === 'ECONNRESET' || code === 'ETIMEDOUT' || code === 'ECONNREFUSED' || code === 'ENOTFOUND') {
|
|
36
|
+
return { class: 'transient', retryable: true, reason: `network:${code}`, code, cause: error };
|
|
37
|
+
}
|
|
38
|
+
if (status === 408 || status === 425 || status === 429 || (status !== undefined && status >= 500)) {
|
|
39
|
+
return {
|
|
40
|
+
class: 'transient',
|
|
41
|
+
retryable: true,
|
|
42
|
+
reason: `http:${status}`,
|
|
43
|
+
status,
|
|
44
|
+
code,
|
|
45
|
+
cause: error,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (status !== undefined && status >= 400 && status < 500) {
|
|
49
|
+
return {
|
|
50
|
+
class: 'permanent',
|
|
51
|
+
retryable: false,
|
|
52
|
+
reason: `http:${status}`,
|
|
53
|
+
status,
|
|
54
|
+
code,
|
|
55
|
+
cause: error,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (message.includes('rate limit') ||
|
|
59
|
+
message.includes('timeout') ||
|
|
60
|
+
message.includes('temporar') ||
|
|
61
|
+
message.includes('unavailable') ||
|
|
62
|
+
message.includes('overloaded')) {
|
|
63
|
+
return { class: 'transient', retryable: true, reason: 'message-heuristic', status, code, cause: error };
|
|
64
|
+
}
|
|
65
|
+
if (message.includes('invalid') ||
|
|
66
|
+
message.includes('authentication') ||
|
|
67
|
+
message.includes('unauthorized') ||
|
|
68
|
+
message.includes('permission') ||
|
|
69
|
+
message.includes('not found')) {
|
|
70
|
+
return { class: 'permanent', retryable: false, reason: 'message-heuristic', status, code, cause: error };
|
|
71
|
+
}
|
|
72
|
+
return { class: 'unknown', retryable: false, reason: 'unclassified', status, code, cause: error };
|
|
73
|
+
}
|
|
74
|
+
export function isRetryable(error) {
|
|
75
|
+
return classifyError(error).retryable;
|
|
76
|
+
}
|
|
77
|
+
function sleep(ms, signal) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
if (signal?.aborted) {
|
|
80
|
+
reject(signal.reason instanceof Error ? signal.reason : new DOMException('Aborted', 'AbortError'));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const timer = setTimeout(resolve, ms);
|
|
84
|
+
signal?.addEventListener('abort', () => {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
reject(signal.reason instanceof Error ? signal.reason : new DOMException('Aborted', 'AbortError'));
|
|
87
|
+
}, { once: true });
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Explicit retry helper for application code. Not wired into the client by default.
|
|
92
|
+
*
|
|
93
|
+
* Idempotency: only wrap operations that are safe to repeat (most pure generation
|
|
94
|
+
* calls are; tool side effects are not unless the application makes them idempotent).
|
|
95
|
+
*/
|
|
96
|
+
export async function withRetry(operation, options = {}) {
|
|
97
|
+
const attempts = Math.max(1, options.attempts ?? 3);
|
|
98
|
+
const delayMs = options.delayMs ?? 250;
|
|
99
|
+
const maxDelayMs = options.maxDelayMs ?? 5000;
|
|
100
|
+
const shouldRetry = options.shouldRetry ?? ((error) => isRetryable(error));
|
|
101
|
+
let lastError;
|
|
102
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
103
|
+
try {
|
|
104
|
+
return await operation();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
lastError = error;
|
|
108
|
+
if (attempt >= attempts || !shouldRetry(error, attempt)) {
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
const wait = Math.min(maxDelayMs, delayMs * 2 ** (attempt - 1));
|
|
112
|
+
options.onRetry?.({ attempt, error, delayMs: wait });
|
|
113
|
+
await sleep(wait, options.signal);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { GenerationRequest, ModelProvider } from './types.js';
|
|
2
|
+
import { type GenAIPlugin } from './plugins.js';
|
|
3
|
+
export interface TimingPluginOptions {
|
|
4
|
+
onTiming?: (info: {
|
|
5
|
+
plugin: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
durationMs: number;
|
|
8
|
+
ok: boolean;
|
|
9
|
+
}) => void;
|
|
10
|
+
}
|
|
11
|
+
/** Observability middleware: records wall-clock duration around each generate call. */
|
|
12
|
+
export declare function timingPlugin(options?: TimingPluginOptions): GenAIPlugin;
|
|
13
|
+
export interface RateLimitPluginOptions {
|
|
14
|
+
/** Maximum concurrent in-flight generate calls. Defaults to 1. */
|
|
15
|
+
concurrency?: number;
|
|
16
|
+
/** Minimum delay between starting successive calls, in milliseconds. */
|
|
17
|
+
minIntervalMs?: number;
|
|
18
|
+
}
|
|
19
|
+
/** Simple concurrency / interval limiter. Does not talk to external rate-limit stores. */
|
|
20
|
+
export declare function rateLimitPlugin(options?: RateLimitPluginOptions): GenAIPlugin;
|
|
21
|
+
export interface CachePluginOptions {
|
|
22
|
+
/** Stable cache key. Defaults to a JSON serialization of the request (excluding signal). */
|
|
23
|
+
key?: (request: GenerationRequest) => string;
|
|
24
|
+
maxEntries?: number;
|
|
25
|
+
}
|
|
26
|
+
/** In-memory response cache. Intentionally short-circuits `next` on hit. */
|
|
27
|
+
export declare function cachePlugin(options?: CachePluginOptions): GenAIPlugin;
|
|
28
|
+
export interface FallbackPluginOptions {
|
|
29
|
+
/** Additional providers tried after the primary provider fails. */
|
|
30
|
+
providers: readonly ModelProvider[];
|
|
31
|
+
/** Decide whether an error should trigger fallback. Defaults to always. */
|
|
32
|
+
shouldFallback?: (error: unknown, attempt: number) => boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fallback middleware: on primary failure, try alternate providers in order.
|
|
36
|
+
* Each alternate receives the same GenerationRequest.
|
|
37
|
+
*/
|
|
38
|
+
export declare function fallbackPlugin(options: FallbackPluginOptions): GenAIPlugin;
|
|
39
|
+
/**
|
|
40
|
+
* Compose multiple providers into one ModelProvider that tries each until one succeeds.
|
|
41
|
+
* Prefer this when there is no single "primary" provider wired through plugins.
|
|
42
|
+
*/
|
|
43
|
+
export declare function fallbackProvider(providers: readonly ModelProvider[], name?: string): ModelProvider;
|