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.
Files changed (44) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +102 -1
  3. package/dist/core/client.d.ts +9 -3
  4. package/dist/core/client.js +69 -0
  5. package/dist/core/client.js.map +1 -1
  6. package/dist/core/errors.d.ts +38 -0
  7. package/dist/core/errors.js +118 -0
  8. package/dist/core/errors.js.map +1 -0
  9. package/dist/core/middleware.d.ts +43 -0
  10. package/dist/core/middleware.js +173 -0
  11. package/dist/core/middleware.js.map +1 -0
  12. package/dist/core/plugins.d.ts +8 -1
  13. package/dist/core/plugins.js +25 -1
  14. package/dist/core/plugins.js.map +1 -1
  15. package/dist/core/result.d.ts +2 -2
  16. package/dist/core/result.js +5 -1
  17. package/dist/core/result.js.map +1 -1
  18. package/dist/core/stream.d.ts +11 -0
  19. package/dist/core/stream.js +93 -0
  20. package/dist/core/stream.js.map +1 -0
  21. package/dist/core/types.d.ts +50 -0
  22. package/dist/index.d.ts +6 -1
  23. package/dist/index.js +3 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/providers/anthropic.js +63 -1
  26. package/dist/providers/anthropic.js.map +1 -1
  27. package/dist/providers/fixtures/multimodal-tool-roundtrip.d.ts +4 -0
  28. package/dist/providers/fixtures/multimodal-tool-roundtrip.js +32 -0
  29. package/dist/providers/fixtures/multimodal-tool-roundtrip.js.map +1 -0
  30. package/dist/providers/google.js +62 -0
  31. package/dist/providers/google.js.map +1 -1
  32. package/dist/providers/openai-converter.d.ts +18 -1
  33. package/dist/providers/openai-converter.js +82 -0
  34. package/dist/providers/openai-converter.js.map +1 -1
  35. package/dist/providers/openai.js +17 -1
  36. package/dist/providers/openai.js.map +1 -1
  37. package/dist/providers.d.ts +1 -1
  38. package/dist/providers.js +1 -1
  39. package/dist/providers.js.map +1 -1
  40. package/docs/pivot.md +30 -14
  41. package/docs/provider-packages.md +60 -0
  42. package/docs/retry.md +62 -0
  43. package/docs/semver.md +55 -0
  44. 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.
@@ -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?: (value: unknown) => T): Promise<T>;
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?: (value: unknown) => T, configure?: ConfigureRequest): Promise<T>;
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
  }
@@ -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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
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;