@aeye/openrouter 0.4.0 → 0.5.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 (33) hide show
  1. package/README.md +152 -65
  2. package/aeye-openrouter.md +175 -161
  3. package/dist/__integration__/openrouter.integration.test.js +122 -6
  4. package/dist/__integration__/openrouter.integration.test.js.map +1 -1
  5. package/dist/__tests__/batch.test.d.ts +5 -0
  6. package/dist/__tests__/batch.test.d.ts.map +1 -0
  7. package/dist/__tests__/batch.test.js +41 -0
  8. package/dist/__tests__/batch.test.js.map +1 -0
  9. package/dist/__tests__/features.test.d.ts +5 -0
  10. package/dist/__tests__/features.test.d.ts.map +1 -0
  11. package/dist/__tests__/features.test.js +206 -0
  12. package/dist/__tests__/features.test.js.map +1 -0
  13. package/dist/__tests__/openrouter.test.js +185 -0
  14. package/dist/__tests__/openrouter.test.js.map +1 -1
  15. package/dist/__tests__/rerank-decide.test.d.ts +5 -0
  16. package/dist/__tests__/rerank-decide.test.d.ts.map +1 -0
  17. package/dist/__tests__/rerank-decide.test.js +75 -0
  18. package/dist/__tests__/rerank-decide.test.js.map +1 -0
  19. package/dist/__tests__/schema-rejection.test.d.ts +6 -0
  20. package/dist/__tests__/schema-rejection.test.d.ts.map +1 -0
  21. package/dist/__tests__/schema-rejection.test.js +39 -0
  22. package/dist/__tests__/schema-rejection.test.js.map +1 -0
  23. package/dist/openrouter.d.ts +118 -41
  24. package/dist/openrouter.d.ts.map +1 -1
  25. package/dist/openrouter.js +407 -210
  26. package/dist/openrouter.js.map +1 -1
  27. package/dist/source.d.ts +9 -4
  28. package/dist/source.d.ts.map +1 -1
  29. package/dist/source.js +45 -28
  30. package/dist/source.js.map +1 -1
  31. package/dist/types.d.ts +244 -81
  32. package/dist/types.d.ts.map +1 -1
  33. package/package.json +71 -71
@@ -1,161 +1,175 @@
1
- # @aeye/openrouter
2
-
3
- One-line purpose: OpenRouter provider for `@aeye/ai` — one API key, hundreds of models from many upstream providers (OpenAI, Anthropic, Google, Meta, Mistral, …) with provider routing, fallbacks, ZDR, reasoning, and real cost reporting. Built as a subclass of `@aeye/openai`'s `OpenAIProvider`.
4
-
5
- ## When to use
6
-
7
- - You want access to many models/providers through a single endpoint and key.
8
- - You need routing control (preferred providers, fallbacks, price/throughput/latency sorting) or Zero Data Retention.
9
- - You want a dynamic model registry with pricing/capabilities pulled from OpenRouter.
10
-
11
- Do **not** use it for image generation, image editing, transcription, speech, or embeddings — those operations are explicitly disabled (see Gotchas).
12
-
13
- ## Install / import
14
-
15
- ```bash
16
- npm install @aeye/openrouter
17
- ```
18
-
19
- `@aeye/openai`, `@aeye/ai`, `@aeye/core`, and `openai` ship as dependencies.
20
-
21
- ```typescript
22
- import {
23
- OpenRouterProvider,
24
- type OpenRouterConfig,
25
- // dynamic model registry
26
- OpenRouterModelSource,
27
- type OpenRouterSourceConfig,
28
- fetchModels,
29
- fetchZDRModels,
30
- convertOpenRouterModel,
31
- } from '@aeye/openrouter';
32
- ```
33
-
34
- The provider's registry name is `openrouter`.
35
-
36
- ## Register with an `@aeye/ai` instance
37
-
38
- ```typescript
39
- import { AI } from '@aeye/ai';
40
- import { OpenRouterProvider } from '@aeye/openrouter';
41
-
42
- const openrouter = new OpenRouterProvider({
43
- apiKey: process.env.OPENROUTER_API_KEY!,
44
- });
45
-
46
- const ai = AI.with().providers({ openrouter }).create({ /* ... */ });
47
-
48
- // Model ids use provider/model form
49
- await ai.chat.get(
50
- { messages: [{ role: 'user', content: 'Hi' }] },
51
- { metadata: { model: 'anthropic/claude-3.5-sonnet' } }
52
- );
53
-
54
- await ai.chat.get(
55
- { messages: [{ role: 'user', content: 'Hi' }] },
56
- { metadata: { model: 'google/gemini-2.0-flash' } }
57
- );
58
- ```
59
-
60
- ## Authentication / credentials
61
-
62
- - `apiKey` is required on the config (inherited from `OpenAIConfig`). Use `process.env.OPENROUTER_API_KEY`.
63
- - `createClient` sets the base URL to `https://openrouter.ai/api/v1` (override via `baseURL`).
64
- - The standalone `OpenRouterModelSource`, `fetchModels`, and `fetchZDRModels` will fall back to `process.env.OPENROUTER_API_KEY` if no key is passed.
65
- - Optional attribution headers: `defaultParams.siteUrl` → `HTTP-Referer`, `defaultParams.appName` → `X-Title`.
66
-
67
- ## Configuration (`OpenRouterConfig`)
68
-
69
- `OpenRouterConfig extends OpenAIConfig`, so all OpenAI fields apply (`apiKey`, `baseURL`, `organization`, `project`, `store`, `retry`, `retryEvents`, `hooks`, `defaultModels`). It adds `defaultParams`:
70
-
71
- ```typescript
72
- const openrouter = new OpenRouterProvider({
73
- apiKey: process.env.OPENROUTER_API_KEY!,
74
- defaultParams: {
75
- siteUrl: 'https://myapp.com', // -> HTTP-Referer
76
- appName: 'my-app', // -> X-Title
77
- providers: {
78
- order: ['Anthropic', 'OpenAI'], // preferred upstream order
79
- allowFallbacks: true, // -> allow_fallbacks
80
- requireParameters: false, // -> require_parameters
81
- dataCollection: 'deny', // 'deny' | 'allow' -> data_collection
82
- zdr: true, // zero data retention
83
- only: ['Anthropic'], // whitelist upstreams
84
- ignore: ['Together'], // blacklist upstreams
85
- quantizations: ['bf16', 'fp16'], // int4|int8|fp4|fp6|fp8|fp16|bf16|fp32|unknown
86
- sort: 'price', // 'price' | 'throughput' | 'latency'
87
- maxPrice: { prompt: 10, completion: 30, image: 0 }, // $/M tokens (image: $/image)
88
- },
89
- transforms: ['middle-out'], // context transforms
90
- },
91
- });
92
- ```
93
-
94
- `defaultParams.providers` is mapped onto OpenRouter's `provider` request object (camelCase → snake_case is handled internally).
95
-
96
- ## Provider routing
97
-
98
- ```typescript
99
- const openrouter = new OpenRouterProvider({
100
- apiKey: process.env.OPENROUTER_API_KEY!,
101
- defaultParams: {
102
- providers: {
103
- order: ['Anthropic'], // try Anthropic first
104
- allowFallbacks: true, // then fall back to others
105
- sort: 'throughput', // optimize for speed
106
- },
107
- },
108
- });
109
- ```
110
-
111
- ## Reasoning
112
-
113
- If a request sets `request.reason`, the provider emits OpenRouter's `reasoning` object (`enabled: true`, plus `effort` and `max_tokens`). Reasoning text and `reasoning_details` are parsed back onto `response.reasoning` (and streamed via chunks).
114
-
115
- ## Dynamic model registry (`OpenRouterModelSource`)
116
-
117
- Use OpenRouter as a `ModelSource` to populate the registry with live pricing, capabilities, context windows, and ZDR flags:
118
-
119
- ```typescript
120
- import { OpenRouterModelSource } from '@aeye/openrouter';
121
-
122
- const ai = AI.with()
123
- .providers({ openrouter })
124
- .create({
125
- modelSources: [
126
- new OpenRouterModelSource({
127
- apiKey: process.env.OPENROUTER_API_KEY!,
128
- includeZDR: true, // default true; fetches the ZDR endpoint too
129
- }),
130
- ],
131
- });
132
-
133
- await ai.models.refresh();
134
- ```
135
-
136
- `fetchModels(apiKey?)` and `fetchZDRModels(apiKey?)` are exported for direct use.
137
-
138
- ## Supported capabilities
139
-
140
- Capabilities depend on the selected model, but the provider class supports: **chat, streaming, tools, structured output / JSON mode, reasoning, vision** (per model). Capabilities are auto-detected from each model's input/output modalities and `supported_parameters` during model conversion.
141
-
142
- Explicitly **unsupported** (overridden to `undefined`): image generation, image generation streaming, image editing, transcription, transcription streaming, speech, embeddings.
143
-
144
- ## Cost tracking
145
-
146
- OpenRouter returns actual spend, surfaced on usage:
147
-
148
- ```typescript
149
- const response = await ai.chat.get({ messages });
150
- console.log(response.usage?.cost); // real cost reported by OpenRouter
151
- ```
152
-
153
- (Available on both non-streaming responses and streamed usage chunks.)
154
-
155
- ## Gotchas
156
-
157
- - **Chat-only provider.** `generateImage`, `editImage`, `transcribe`, `speech`, and `embed` are set to `undefined` — calling those operations on this provider will not work; use OpenAI/AWS/Replicate for them.
158
- - Model ids are `provider/model` slugs (e.g. `anthropic/claude-3.5-sonnet`), not raw OpenAI ids.
159
- - Strict/structured output behavior is inherited from `OpenAIProvider` (best-effort, silent lenient fallback), but the accepted dialects are widened here: `supportedStrictFamilies = {'openai', 'anthropic', 'google'}`, because the model id's `family/…` prefix names the upstream that actually serves the request. This applies to **tool** schemas as well as `response_format`; before 0.4.x the inherited `{'openai'}` quietly forced every non-OpenAI model's tools through LENIENT.
160
- - Assistant reasoning is split into a separate preceding message during conversion to work around OpenRouter not round-tripping reasoning attached to content — expect an extra assistant message in transformed payloads.
161
- - ZDR (`zdr: true` / `dataCollection: 'deny'`) only constrains upstreams that honor it; combine with `only`/`ignore` for strict guarantees.
1
+ # @aeye/openrouter
2
+
3
+ One-line purpose: OpenRouter provider for `@aeye/ai` — one API key, hundreds of models from many upstream providers (OpenAI, Anthropic, Google, xAI, Meta, Mistral, …) with provider routing, fallback models, plugins, server tools, ZDR, reasoning, media endpoints, and real cost reporting. Built as a subclass of `@aeye/openai`'s `OpenAIProvider`.
4
+
5
+ ## When to use
6
+
7
+ - You want access to many models/providers through a single endpoint and key.
8
+ - You need routing control (preferred providers, fallbacks, price/throughput/latency sorting) or Zero Data Retention.
9
+ - You want a dynamic model registry with pricing/capabilities pulled from OpenRouter.
10
+
11
+ It also serves image generation/editing (through chat with the image modality), speech, transcription, and embeddings (through OpenRouter's OpenAI-compatible endpoints). Image and transcription streaming are not offered; those fall back to the non-streaming methods.
12
+
13
+ ## Install / import
14
+
15
+ ```bash
16
+ npm install @aeye/openrouter
17
+ ```
18
+
19
+ `@aeye/openai`, `@aeye/ai`, `@aeye/core`, and `openai` (v7) ship as dependencies. Requires Node >= 22.
20
+
21
+ ```typescript
22
+ import {
23
+ OpenRouterProvider,
24
+ type OpenRouterConfig,
25
+ // dynamic model registry
26
+ OpenRouterModelSource,
27
+ type OpenRouterSourceConfig,
28
+ fetchModels,
29
+ fetchZDRModels,
30
+ fetchEndpointMetrics,
31
+ convertOpenRouterModel,
32
+ } from '@aeye/openrouter';
33
+ ```
34
+
35
+ The provider's registry name is `openrouter`.
36
+
37
+ ## Register with an `@aeye/ai` instance
38
+
39
+ ```typescript
40
+ import { AI } from '@aeye/ai';
41
+ import { OpenRouterProvider } from '@aeye/openrouter';
42
+
43
+ const openrouter = new OpenRouterProvider({
44
+ apiKey: process.env.OPENROUTER_API_KEY!,
45
+ });
46
+
47
+ const ai = AI.with().providers({ openrouter }).create({ /* ... */ });
48
+
49
+ // Model ids use provider/model form
50
+ await ai.chat.get(
51
+ { messages: [{ role: 'user', content: 'Hi' }] },
52
+ { metadata: { model: 'anthropic/claude-sonnet-4.5' } }
53
+ );
54
+
55
+ await ai.chat.get(
56
+ { messages: [{ role: 'user', content: 'Hi' }] },
57
+ { metadata: { model: 'google/gemini-2.5-flash' } }
58
+ );
59
+ ```
60
+
61
+ ## Authentication / credentials
62
+
63
+ - `apiKey` is required on the config (inherited from `OpenAIConfig`). Use `process.env.OPENROUTER_API_KEY`.
64
+ - `createClient` sets the base URL to `https://openrouter.ai/api/v1` (override via `baseURL`).
65
+ - The standalone `OpenRouterModelSource`, `fetchModels`, and `fetchZDRModels` will fall back to `process.env.OPENROUTER_API_KEY` if no key is passed.
66
+ - Optional attribution headers: `defaultParams.siteUrl` → `HTTP-Referer`, `defaultParams.appName` → `X-Title`.
67
+
68
+ ## Configuration (`OpenRouterConfig`)
69
+
70
+ `OpenRouterConfig extends Omit<OpenAIConfig, 'api'>`, so the OpenAI fields apply (`apiKey`, `baseURL`, `organization`, `project`, `store`, `retry`, `retryEvents`, `hooks`, `defaultModels`) except `api`: requests always go through Chat Completions. It adds `defaultParams`:
71
+
72
+ ```typescript
73
+ const openrouter = new OpenRouterProvider({
74
+ apiKey: process.env.OPENROUTER_API_KEY!,
75
+ defaultParams: {
76
+ siteUrl: 'https://myapp.com', // -> HTTP-Referer
77
+ appName: 'my-app', // -> X-Title
78
+ providers: {
79
+ order: ['Anthropic', 'OpenAI'], // preferred upstream order
80
+ allowFallbacks: true, // -> allow_fallbacks
81
+ requireParameters: false, // -> require_parameters
82
+ dataCollection: 'deny', // 'deny' | 'allow' -> data_collection
83
+ zdr: true, // zero data retention
84
+ enforceDistillableText: false, // -> enforce_distillable_text
85
+ only: ['Anthropic'], // whitelist upstreams
86
+ ignore: ['Together'], // blacklist upstreams
87
+ quantizations: ['bf16', 'fp16'], // int4|int8|fp4|mxfp4|nvfp4|fp6|fp8|mxfp8|fp16|bf16|fp32|unknown
88
+ sort: 'price', // 'price' | 'throughput' | 'latency' | 'exacto', or { by, partition: 'model' | 'none' }
89
+ preferredMinThroughput: 50, // -> preferred_min_throughput (tokens/s, median)
90
+ preferredMaxLatency: 2, // -> preferred_max_latency (seconds, median)
91
+ maxPrice: { prompt: 10, completion: 30, image: 0 }, // $/M tokens (image: $/image); also audio, request
92
+ },
93
+ fallbackModels: ['openai/gpt-5.4-mini'], // -> models
94
+ plugins: [{ id: 'response-healing' }], // file-parser | response-healing | context-compression
95
+ },
96
+ });
97
+ ```
98
+
99
+ `defaultParams.providers` is mapped onto OpenRouter's `provider` request object (camelCase → snake_case is handled internally). `transforms` is deprecated: `transforms: ['middle-out']` is sent as the `context-compression` plugin. `requireParameters` left undefined is switched on automatically for strict `json_schema` requests.
100
+
101
+ ## Provider routing
102
+
103
+ ```typescript
104
+ const openrouter = new OpenRouterProvider({
105
+ apiKey: process.env.OPENROUTER_API_KEY!,
106
+ defaultParams: {
107
+ providers: {
108
+ order: ['Anthropic'], // try Anthropic first
109
+ allowFallbacks: true, // then fall back to others
110
+ sort: 'throughput', // optimize for speed
111
+ },
112
+ },
113
+ });
114
+ ```
115
+
116
+ ## Reasoning
117
+
118
+ If a request sets `request.reason`, the provider emits OpenRouter's `reasoning` object: `enabled: true`, either `max_tokens` (from `maxTokens`) or `effort` (clamped to the model's `reasoningEfforts`), never both, plus `exclude`, `summary`, `mode`, and `context`. No separate `reasoning_effort` is sent. Reasoning text and `reasoning_details` are parsed back onto `response.reasoning` (and streamed via chunks), and replayed from assistant messages on later turns.
119
+
120
+ ## Server tools and other request features
121
+
122
+ - `hostedTools` run as OpenRouter server tools through chat: `web_search` → `openrouter:web_search` (`maxResults`, `allowedDomains`, `blockedDomains` → `excluded_domains`), `web_fetch` → `openrouter:web_fetch`, `image_generation` → `openrouter:image_generation`. `file_search`, `code_interpreter`, and `mcp` throw `ProviderError`. Calls are counted in `usage.tools`.
123
+ - `cacheBreakpoint` on content goes as `cache_control: { type: 'ephemeral' }`.
124
+ - `modalities` with `'image'` is passed through; images come back on `response.images` (streamed or not).
125
+ - `userKey` goes as `user`. `moderate` is not sent (OpenRouter ignores OpenAI's inline moderation).
126
+
127
+ ## Dynamic model registry (`OpenRouterModelSource`)
128
+
129
+ Use OpenRouter as a `ModelSource` to populate the registry with live pricing, capabilities, context windows, and ZDR flags. It lists every output modality (chat, image, speech, transcription, and embedding models); capabilities come from each modality (`vision`, `files`, `videoInput`, `hearing`, `image`, `audio`, `embedding`); pricing covers cache read/write, audio, image tokens, and web search per call; `reasoningEfforts` and `retiresAt` (from `expiration_date`) are filled in:
130
+
131
+ ```typescript
132
+ import { OpenRouterModelSource } from '@aeye/openrouter';
133
+
134
+ const ai = AI.with()
135
+ .providers({ openrouter })
136
+ .create({
137
+ modelSources: [
138
+ new OpenRouterModelSource({
139
+ apiKey: process.env.OPENROUTER_API_KEY!,
140
+ includeZDR: true, // default true; fetches the ZDR endpoint too
141
+ }),
142
+ ],
143
+ });
144
+
145
+ await ai.models.refresh();
146
+ ```
147
+
148
+ `fetchModels(apiKey?)`, `fetchZDRModels(apiKey?)`, and `fetchEndpointMetrics(modelId, apiKey?)` (best median latency in ms, throughput in tokens/s, and uptime across a model's providers) are exported for direct use.
149
+
150
+ ## Supported capabilities
151
+
152
+ Capabilities depend on the selected model, but the provider class supports: **chat, streaming, tools, hosted (server) tools, structured output / JSON mode, reasoning, vision, files, video input, image generation and editing, audio output, speech, transcription, embeddings** (per model). Capabilities are auto-detected from each model's input/output modalities and `supported_parameters` during model conversion.
153
+
154
+ Default models: `google/gemini-2.5-flash-image` (image generate/edit), `openai/gpt-5.4-mini` (image analysis), `openai/gpt-transcribe`, `openai/text-embedding-3-small`; speech and chat have none.
155
+
156
+ Not offered (overridden to `undefined`, so the non-streaming method is used): image generation streaming, image edit streaming, transcription streaming.
157
+
158
+ ## Cost tracking
159
+
160
+ OpenRouter returns actual spend, surfaced on usage:
161
+
162
+ ```typescript
163
+ const response = await ai.chat.get({ messages });
164
+ console.log(response.usage?.cost); // real cost reported by OpenRouter, including the upstream bill for BYOK requests
165
+ ```
166
+
167
+ (Available on both non-streaming responses and streamed usage chunks.)
168
+
169
+ ## Gotchas
170
+
171
+ - **Images go through chat.** `generateImage` / `editImage` send a chat request with `modalities: ['image', 'text']` (running through the chat hooks); `size` becomes an `image_config.aspect_ratio`, and an edit's `image` + `references` are sent as input images. GPT Image options such as `quality` and `outputFormat` are not sent.
172
+ - Model ids are `provider/model` slugs (e.g. `anthropic/claude-sonnet-4.5`), not raw OpenAI ids.
173
+ - Strict/structured output behavior is inherited from `OpenAIProvider` (best-effort, silent fallback to the family's non-strict descriptor), but the accepted dialects are widened here: `supportedStrictFamilies = {'openai', 'anthropic', 'google', 'xai'}`, because the model id's `family/…` prefix names the upstream that actually serves the request. This applies to **tool** schemas as well as `response_format`; before 0.4.x the inherited `{'openai'}` quietly forced every non-OpenAI model's tools through LENIENT.
174
+ - Assistant reasoning is split into a separate preceding message during conversion to work around OpenRouter not round-tripping reasoning attached to content — expect an extra assistant message in transformed payloads.
175
+ - ZDR (`zdr: true` / `dataCollection: 'deny'`) only constrains upstreams that honor it; combine with `only`/`ignore` for strict guarantees.
@@ -5,6 +5,7 @@
5
5
  * Requires OPENROUTER_API_KEY environment variable.
6
6
  */
7
7
  import { OpenRouterProvider } from '../openrouter';
8
+ import { z } from 'zod';
8
9
  import { getAPIKey, skipIfNoAPIKey } from './setup';
9
10
  const describeIntegration = skipIfNoAPIKey();
10
11
  describeIntegration('OpenRouter Integration', () => {
@@ -59,7 +60,7 @@ describeIntegration('OpenRouter Integration', () => {
59
60
  ]
60
61
  };
61
62
  // Use a free model to avoid charges
62
- const response = await executor(request, {}, { model: 'google/gemini-flash-1.5' });
63
+ const response = await executor(request, {}, { model: 'google/gemini-2.5-flash-lite' });
63
64
  expect(response.content).toBeTruthy();
64
65
  expect(typeof response.content).toBe('string');
65
66
  expect(response.finishReason).toBeTruthy();
@@ -80,7 +81,7 @@ describeIntegration('OpenRouter Integration', () => {
80
81
  };
81
82
  const chunks = [];
82
83
  let finalUsage = null;
83
- for await (const chunk of streamer(request, {}, { model: 'google/gemini-flash-1.5' })) {
84
+ for await (const chunk of streamer(request, {}, { model: 'google/gemini-2.5-flash-lite' })) {
84
85
  if (chunk.content) {
85
86
  chunks.push(chunk.content);
86
87
  }
@@ -105,7 +106,7 @@ describeIntegration('OpenRouter Integration', () => {
105
106
  };
106
107
  const ctx = {
107
108
  metadata: {
108
- model: 'google/gemini-flash-1.5'
109
+ model: 'google/gemini-2.5-flash-lite'
109
110
  }
110
111
  };
111
112
  const response = await executor(request, ctx, {});
@@ -117,8 +118,8 @@ describeIntegration('OpenRouter Integration', () => {
117
118
  const executor = provider.createExecutor();
118
119
  // Test models from different providers available on OpenRouter
119
120
  const testModels = [
120
- 'google/gemini-flash-1.5',
121
- 'meta-llama/llama-3.2-3b-instruct:free'
121
+ 'google/gemini-2.5-flash-lite',
122
+ 'openai/gpt-5.4-nano'
122
123
  ];
123
124
  for (const model of testModels) {
124
125
  try {
@@ -171,7 +172,7 @@ describeIntegration('OpenRouter Integration', () => {
171
172
  messages: [{ role: 'user', content: 'Hi' }]
172
173
  };
173
174
  // Make multiple rapid requests using free model
174
- const promises = Array(3).fill(null).map(() => executor(request, {}, { model: 'google/gemini-flash-1.5' }));
175
+ const promises = Array(3).fill(null).map(() => executor(request, {}, { model: 'google/gemini-2.5-flash-lite' }));
175
176
  // At least some should succeed
176
177
  const results = await Promise.allSettled(promises);
177
178
  const succeeded = results.filter(r => r.status === 'fulfilled').length;
@@ -200,4 +201,119 @@ describeIntegration('OpenRouter Integration', () => {
200
201
  }, 30000);
201
202
  });
202
203
  });
204
+ /**
205
+ * LIVE verification of the Google tool-schema fix (schema.ts `GOOGLE_STRICT`/
206
+ * `GOOGLE_NON_STRICT` `anyEncoding: 'unconstrained'`, and this provider's
207
+ * `supportedStrictFamilies` now including `'google'`). The unit suite
208
+ * (`__tests__/openrouter.test.ts`, `describe('OpenRouterProvider tool schema
209
+ * dialects')`) proves the WIRE SHAPE is keyword-clean; it cannot prove Gemini's
210
+ * own function-calling grammar compiler actually ACCEPTS that shape — only a
211
+ * real request against the real model can. `toolChoice: 'required'` is the
212
+ * trigger throughout (Google's function-calling mode `ANY`, which is what
213
+ * compiles the tool schemas into a decoding grammar in the first place — under
214
+ * `'auto'` no grammar is built and the pre-fix shape never 400s).
215
+ *
216
+ * `google/gemini-3-flash-preview` specifically, matching the curated
217
+ * `strictSupport` pattern (`^google\/gemini-(2\.0|2\.5|3|3\.1)`) and the exact
218
+ * model the reported regression was measured against — a cheaper/older Gemini
219
+ * could easily behave differently.
220
+ */
221
+ describeIntegration('OpenRouter — Google tool-schema fix (live)', () => {
222
+ let provider;
223
+ const model = 'google/gemini-3-flash-preview';
224
+ beforeAll(() => {
225
+ provider = new OpenRouterProvider({ apiKey: getAPIKey() });
226
+ });
227
+ /** The exact `[kind]_signature` shape from the reported 400 (product's
228
+ * `api_agent`/`code_agent`/etc.): a named field alongside an open TypeDef —
229
+ * `z.any()` is the case `GOOGLE_STRICT.anyEncoding` was fixed for. */
230
+ const signatureTool = {
231
+ name: 'api_signature',
232
+ description: 'Declare the signature of the API function.',
233
+ parameters: z.object({
234
+ signature: z.object({ name: z.string() })
235
+ .catchall(z.any())
236
+ .describe('The signature of the API function being declared.'),
237
+ }),
238
+ strict: 1,
239
+ };
240
+ /** A genuinely nested/multi-level schema with NO "any" and NO union — arrays
241
+ * of objects, an enum, an optional field — the "complex but expressible"
242
+ * case that was never broken. Included so a live failure here would mean a
243
+ * DIFFERENT regression, not the one this fix targets. */
244
+ const complexTool = {
245
+ name: 'file_ticket',
246
+ description: 'File a support ticket with structured fields.',
247
+ parameters: z.object({
248
+ title: z.string(),
249
+ priority: z.enum(['low', 'medium', 'high']),
250
+ labels: z.array(z.string()),
251
+ assignee: z.optional(z.string()),
252
+ steps: z.array(z.object({
253
+ description: z.string(),
254
+ completed: z.boolean(),
255
+ })),
256
+ }),
257
+ strict: 1,
258
+ };
259
+ /** A `z.union(...)` argument — the ONE case the fix's own report flags as a
260
+ * KNOWN, still-open gap ("Tool schemas never consult `canExpress`... a
261
+ * `z.union(...)` in a Google tool still emits `anyOf` despite
262
+ * `allowAnyOf: false`"). This is diagnostic, not a regression guard: it
263
+ * logs the real outcome rather than asserting one, so this suite stays
264
+ * green regardless and the log is what tells Phil whether that gap is
265
+ * still live against the real API. */
266
+ const unionTool = {
267
+ name: 'set_contact_method',
268
+ description: 'Record how to reach the requester.',
269
+ parameters: z.object({
270
+ contact: z.union([
271
+ z.object({ kind: z.literal('email'), address: z.string() }),
272
+ z.object({ kind: z.literal('phone'), number: z.string() }),
273
+ ]),
274
+ }),
275
+ strict: 1,
276
+ };
277
+ it('an "Any"-typed tool argument, FORCED, does not 400 — the reported regression, fixed', async () => {
278
+ const executor = provider.createExecutor();
279
+ const request = {
280
+ messages: [{ role: 'user', content: 'Declare a signature with one field "id" of type text.' }],
281
+ tools: [{ ...signatureTool }],
282
+ toolChoice: 'required',
283
+ };
284
+ const response = await executor(request, {}, { model });
285
+ expect(response.finishReason).toBeTruthy();
286
+ expect(response.toolCalls?.length ?? 0).toBeGreaterThan(0);
287
+ console.log(` tool_choice:required + Any-typed arg → ${response.toolCalls?.length} call(s), finishReason=${response.finishReason}`);
288
+ }, 30000);
289
+ it('a complex multi-level object argument, FORCED, does not 400', async () => {
290
+ const executor = provider.createExecutor();
291
+ const request = {
292
+ messages: [{ role: 'user', content: 'File a high-priority ticket titled "Printer on fire" with one step: "unplug it", not yet completed.' }],
293
+ tools: [{ ...complexTool }],
294
+ toolChoice: 'required',
295
+ };
296
+ const response = await executor(request, {}, { model });
297
+ expect(response.finishReason).toBeTruthy();
298
+ expect(response.toolCalls?.length ?? 0).toBeGreaterThan(0);
299
+ console.log(` tool_choice:required + nested object arg → ${response.toolCalls?.length} call(s), finishReason=${response.finishReason}`);
300
+ }, 30000);
301
+ it('DIAGNOSTIC (not a regression guard): a z.union(...) tool argument, FORCED — logs whether the known unaddressed gap still 400s live', async () => {
302
+ const executor = provider.createExecutor();
303
+ const request = {
304
+ messages: [{ role: 'user', content: 'Record that they reached out by email at test@example.com.' }],
305
+ tools: [{ ...unionTool }],
306
+ toolChoice: 'required',
307
+ };
308
+ try {
309
+ const response = await executor(request, {}, { model });
310
+ console.log(` UNION TOOL SUCCEEDED (unexpected — the flagged gap may not be live for this shape): ${response.toolCalls?.length} call(s)`);
311
+ }
312
+ catch (error) {
313
+ console.log(` UNION TOOL FAILED as the fix's own report predicted (known gap, not covered by this change): ${error.message}`);
314
+ }
315
+ // No assertion — this test exists to OBSERVE, not to gate. Both outcomes are informative.
316
+ expect(true).toBe(true);
317
+ }, 30000);
318
+ });
203
319
  //# sourceMappingURL=openrouter.integration.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openrouter.integration.test.js","sourceRoot":"","sources":["../../src/__integration__/openrouter.integration.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"openrouter.integration.test.js","sourceRoot":"","sources":["../../src/__integration__/openrouter.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * OpenRouter batches: requests and results go inline.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=batch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/batch.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * OpenRouter batches: requests and results go inline.
3
+ */
4
+ import { AI } from '@aeye/ai';
5
+ import { OpenRouterProvider } from '../openrouter';
6
+ const mockPost = jest.fn();
7
+ const mockGet = jest.fn();
8
+ jest.mock('openai', () => jest.fn().mockImplementation(() => ({ post: mockPost, get: mockGet })));
9
+ const ctx = { ai: AI.with().providers({}).create({}), metadata: { model: 'anthropic/claude-haiku-4.5' } };
10
+ const provider = new OpenRouterProvider({ apiKey: 'k' });
11
+ const counts = { total: 2, completed: 2, failed: 0 };
12
+ beforeEach(() => jest.clearAllMocks());
13
+ describe('batch', () => {
14
+ it('posts the requests inline', async () => {
15
+ mockPost.mockResolvedValue({ id: 'batch_1', status: 'validating', request_counts: { total: 2, completed: 0, failed: 0 }, error: null, results: null });
16
+ const job = await provider.submitBatch([
17
+ { messages: [{ role: 'user', content: 'One' }] },
18
+ { messages: [{ role: 'user', content: 'Two' }], reason: { effort: 'low' } },
19
+ ], ctx);
20
+ const [path, { body }] = mockPost.mock.calls[0];
21
+ expect(path).toBe('/batches');
22
+ expect(body).toMatchObject({ endpoint: '/v1/chat/completions', model: 'anthropic/claude-haiku-4.5' });
23
+ expect(body.requests.map((r) => r.custom_id)).toEqual(['0', '1']);
24
+ expect(body.requests[1].body.reasoning).toEqual({ enabled: true, effort: 'low' });
25
+ expect(job).toMatchObject({ id: 'batch_1', provider: 'openrouter', status: 'validating' });
26
+ });
27
+ it('reads inline results, cost included', async () => {
28
+ const body = (content) => ({ object: 'chat.completion', choices: [{ message: { content }, finish_reason: 'stop' }], usage: { prompt_tokens: 4, completion_tokens: 1, total_tokens: 5, cost: 0.0001 } });
29
+ mockGet.mockResolvedValue({
30
+ id: 'batch_1', status: 'completed', request_counts: counts, error: null,
31
+ usage: { prompt_tokens: 8, completion_tokens: 2, total_tokens: 10, cost: 0, is_byok: true, cost_details: { upstream_inference_cost: 0.00004 } },
32
+ results: [{ custom_id: '1', response: { status_code: 200, body: body('second') } }, { custom_id: '0', response: { status_code: 200, body: body('first') } }],
33
+ });
34
+ const job = await provider.getBatch({ id: 'batch_1', provider: 'openrouter', model: 'anthropic/claude-haiku-4.5', status: 'in_progress' }, ctx);
35
+ expect(mockGet.mock.calls[0][0]).toBe('/batches/batch_1');
36
+ expect(job.results?.map(r => r.response?.content)).toEqual(['first', 'second']);
37
+ expect(job.results?.[0].response?.usage?.cost).toBe(0.0001);
38
+ expect(job.cost).toBe(0.00004);
39
+ });
40
+ });
41
+ //# sourceMappingURL=batch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.test.js","sourceRoot":"","sources":["../../src/__tests__/batch.test.ts"],"names":[],"mappings":"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"}