@namzu/openrouter 2.1.0 → 2.2.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 CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 70f23bb: A driver can now say how large a model's context window is, and the kernel
8
+ ranks that above its hand-maintained table.
9
+
10
+ That table was the only source below an explicit host config, and its own
11
+ header records what it cost: every Claude entry carried 200k including the
12
+ 1M-window models, so those runs compacted at roughly 14% full and threw
13
+ away the prompt-cache prefix to do it. Every model release drifts it again
14
+ until somebody edits it — while the OpenRouter driver was already parsing
15
+ the vendor's real `context_length` and discarding it, because there was no
16
+ member to return it through.
17
+
18
+ `LLMProvider.resolveContextWindow?(model, signal)` is three-state like
19
+ `effortLevelsFor`: absent means this driver cannot answer, a resolved
20
+ `undefined` means it asked and does not know, a number is the answer. A
21
+ driver resolving `undefined` falls through to the TABLE, not to the
22
+ assumed default — asking must never be worse than not asking.
23
+
24
+ Resolved once per run, at the door. Both consumers are synchronous and in
25
+ the hot loop, so this can never become an await inside it. A driver that
26
+ rejects or hangs does not fail the run: the window is an optimisation over
27
+ a working default.
28
+
29
+ `ResolvedContextWindow['source']` and the `windowSource` on
30
+ `token_usage_updated` gain `'provider'`, ranked between `'config'` and
31
+ `'model-table'`, so a host can see which route a number came from.
32
+
33
+ Also fixes a hole this exposed: `withProviderRetry` and
34
+ `withProviderFallback` forwarded `listModels`, `healthCheck` and
35
+ `doctorCheck` but not `effortLevelsFor`. A dropped optional member does not
36
+ fail — it reads as "this driver cannot answer" — and retry is on by
37
+ default, so a driver's declared effort levels were invisible on
38
+ essentially every run.
39
+
3
40
  ## 2.1.0
4
41
 
5
42
  ### Minor Changes
package/README.md CHANGED
@@ -1,6 +1,52 @@
1
- # @namzu/openrouter
1
+ <!-- okf
2
+ type: Reference
3
+ title: "@namzu/openrouter"
4
+ description: >-
5
+ The OpenRouter driver for @namzu/sdk. Speaks OpenRouter's OpenAI-compatible
6
+ Chat Completions wire over native fetch with no runtime dependencies, maps
7
+ tool use, and answers the kernel's context-window question from the vendor's
8
+ own catalogue rather than from a hand-kept table.
9
+ tags: [readme, package, provider, openrouter]
10
+ timestamp: 2026-08-17T00:00:00Z
11
+ status: active
12
+ diataxis: reference
13
+ -->
2
14
 
3
- OpenRouter LLM provider for [`@namzu/sdk`](https://www.npmjs.com/package/@namzu/sdk). Thin `fetch`-based wrapper around OpenRouter's **OpenAI-compatible Chat Completions API** (chat + streaming) with full tool-use support, conformant to the `LLMProvider` contract. Gives you access to 200+ models — Claude, GPT-4, Llama, Mixtral, Gemini, and more — through a single unified API and billing account.
15
+ <div align="center">
16
+
17
+ <h1>@namzu/openrouter</h1>
18
+
19
+ **The OpenRouter driver for [`@namzu/sdk`](https://www.npmjs.com/package/@namzu/sdk).**
20
+
21
+ [![License: FSL-1.1-MIT](https://img.shields.io/badge/license-FSL--1.1--MIT-blue.svg)](https://github.com/cogitave/namzu/blob/main/LICENSE.md)
22
+ [![npm](https://img.shields.io/npm/v/@namzu/openrouter.svg?label=%40namzu%2Fopenrouter)](https://www.npmjs.com/package/@namzu/openrouter)
23
+
24
+ [Install](#install) · [Use it](#use-it) · [Models](#models-and-the-window) · [Credentials](#credentials-and-attribution) · [Config](#configuration) · [Capabilities](#capabilities) · [Health](#health) · [Errors](#errors)
25
+
26
+ </div>
27
+
28
+ ---
29
+
30
+ ## What this is
31
+
32
+ One driver, one wire. `OpenRouterProvider` implements the kernel's
33
+ `LLMProvider` contract against OpenRouter's OpenAI-compatible Chat Completions
34
+ endpoint, and it sends exactly one request: `POST /chat/completions` with
35
+ `stream: true`. There is no non-streaming path, because the contract has no
36
+ non-streaming method — `chatStream` is the single model entry point, and a
37
+ caller who wants the whole answer collects the stream.
38
+
39
+ The transport is native `fetch` and nothing else. This package declares no
40
+ runtime dependencies at all: no vendor SDK, no HTTP client, no JSON tooling.
41
+ `@namzu/sdk` is a peer dependency (`>=1.3.0`), so your lockfile owns the kernel
42
+ version rather than this package.
43
+
44
+ What it buys over a driver bound to one vendor is the aggregation: OpenRouter
45
+ fronts hundreds of models from a dozen vendors behind one key and one bill, and
46
+ switching between them is a change to the `model` string rather than to which
47
+ package is installed. That also makes it the driver where a static model table
48
+ goes stale fastest, which is why nothing about the catalogue is hardcoded here
49
+ — see [Models and the window](#models-and-the-window).
4
50
 
5
51
  ## Install
6
52
 
@@ -8,63 +54,174 @@ OpenRouter LLM provider for [`@namzu/sdk`](https://www.npmjs.com/package/@namzu/
8
54
  pnpm add @namzu/sdk @namzu/openrouter
9
55
  ```
10
56
 
11
- `@namzu/openrouter` declares `@namzu/sdk` as a peer dependency. Install both. The provider has **zero runtime dependencies** — it talks to OpenRouter with native `fetch`.
12
-
13
- ## Usage
57
+ ## Use it
14
58
 
15
59
  ```ts
16
60
  import { ProviderRegistry } from '@namzu/sdk'
17
61
  import { registerOpenRouter } from '@namzu/openrouter'
18
62
 
19
- // Register once at app startup.
20
- registerOpenRouter()
63
+ registerOpenRouter() // once, at startup
21
64
 
22
- // Fully typed via module augmentation: ProviderConfigRegistry['openrouter'].
23
- const { provider, capabilities } = ProviderRegistry.create({
65
+ const { provider } = ProviderRegistry.create({
24
66
  type: 'openrouter',
25
- apiKey: process.env.OPENROUTER_API_KEY!,
26
- siteUrl: 'https://myapp.example', // optional — shown on OpenRouter analytics
27
- siteName: 'My App', // optional — shown on OpenRouter analytics
67
+ apiKey: process.env.OPENROUTER_API_KEY ?? '',
68
+ siteUrl: 'https://example.com', // optional
69
+ siteName: 'Example', // optional
28
70
  })
29
71
 
30
- const response = await provider.chat({
31
- model: 'anthropic/claude-sonnet-4',
72
+ for await (const chunk of provider.chatStream({
73
+ model: 'anthropic/claude-opus-5',
32
74
  messages: [{ role: 'user', content: 'Hello' }],
75
+ })) {
76
+ if (chunk.delta.content) process.stdout.write(chunk.delta.content)
77
+ }
78
+ ```
79
+
80
+ `registerOpenRouter()` also carries the module augmentation that adds
81
+ `'openrouter'` to the kernel's config union, so `ProviderRegistry.create({ type:
82
+ 'openrouter', … })` narrows to `OpenRouterProviderConfig` and a typo in the
83
+ config is a compile error. Call it twice and it throws `DuplicateProviderError`;
84
+ pass `{ replace: true }` when you mean to take the slot over.
85
+
86
+ `create()` hands back the driver's capability declaration alongside it, which is
87
+ the same object as [`OPENROUTER_CAPABILITIES`](#capabilities):
88
+
89
+ ```ts
90
+ const { provider, capabilities } = ProviderRegistry.create({
91
+ type: 'openrouter',
92
+ apiKey: process.env.OPENROUTER_API_KEY ?? '',
33
93
  })
34
94
  ```
35
95
 
36
- Streaming:
96
+ When you want the aggregated response rather than the deltas, collect the same
97
+ stream:
37
98
 
38
99
  ```ts
39
- for await (const chunk of provider.chatStream({
40
- model: 'openai/gpt-4o',
41
- messages: [{ role: 'user', content: 'Tell me a story' }],
42
- })) {
43
- if (chunk.delta.content) process.stdout.write(chunk.delta.content)
44
- }
100
+ import { collectChatCompletion } from '@namzu/sdk'
101
+
102
+ const response = await collectChatCompletion(
103
+ provider.chatStream({
104
+ model: 'anthropic/claude-opus-5',
105
+ messages: [{ role: 'user', content: 'Hello' }],
106
+ }),
107
+ )
108
+
109
+ console.log(response.message.content)
110
+ console.log(response.usage.totalTokens)
45
111
  ```
46
112
 
47
- ## Authentication
113
+ The terminal agent constructs this driver for you: `@namzu/cli` lists
114
+ `openrouter` among the provider types it can build, reads `OPENROUTER_API_KEY`
115
+ from the environment, and defaults to `https://openrouter.ai/api/v1` and the
116
+ model `anthropic/claude-opus-5`.
48
117
 
49
- Get an API key at [openrouter.ai/keys](https://openrouter.ai/keys). Pass it to the provider via the `apiKey` field, or read it from `process.env.OPENROUTER_API_KEY` in your app before constructing the config.
118
+ `listModels`, `resolveContextWindow`, `probeCredential` and `healthCheck` are
119
+ **optional** members of `LLMProvider`, so a caller holding the interface has to
120
+ guard them. The snippets below hold the class instead, where they are ordinary
121
+ methods:
50
122
 
51
- ## Models
123
+ ```ts
124
+ import { OpenRouterProvider } from '@namzu/openrouter'
52
125
 
53
- OpenRouter exposes 200+ models from every major vendor under one unified API. See the [OpenRouter model catalog](https://openrouter.ai/models) for the full list and current pricing. Identifiers follow the `vendor/model-name` pattern:
126
+ const driver = new OpenRouterProvider({
127
+ apiKey: process.env.OPENROUTER_API_KEY ?? '',
128
+ })
129
+ ```
54
130
 
55
- - `anthropic/claude-sonnet-4`
56
- - `anthropic/claude-haiku-4`
57
- - `openai/gpt-4o`
58
- - `openai/gpt-4o-mini`
59
- - `meta-llama/llama-3.3-70b-instruct`
60
- - `mistralai/mixtral-8x22b-instruct`
61
- - `google/gemini-pro-1.5`
131
+ ## Models and the window
62
132
 
63
- Pricing is per-million tokens on OpenRouter's catalog — the provider's `listModels()` returns live pricing pulled from the `/models` endpoint.
133
+ Model ids follow OpenRouter's `vendor/model-name` pattern —
134
+ `anthropic/claude-opus-5` — and the authority on which ones exist today is the
135
+ vendor, not this package. There is no hardcoded catalogue here to go stale.
64
136
 
65
- ## Base URL override
137
+ ```ts
138
+ await driver.listModels()
139
+ // id, name, contextWindow, maxOutputTokens, inputPrice, outputPrice,
140
+ // supportsToolUse, supportsStreaming
141
+ ```
142
+
143
+ `listModels()` returns exactly what `GET /models` sent, with no fallback list
144
+ behind it: `contextWindow` is the catalogue's `context_length`,
145
+ `maxOutputTokens` is `top_provider.max_completion_tokens` where the vendor
146
+ states one and `4096` where it does not, and `inputPrice` / `outputPrice` are
147
+ the catalogue's per-token prices scaled to per-million. If the listing call
148
+ fails, it throws rather than substituting a menu.
149
+
150
+ `resolveContextWindow(model)` answers the kernel's own question — how large is
151
+ this model's context — from that same listing. It matters because the fallback
152
+ below it is a hand-maintained prefix table, and this is the driver a hand-kept
153
+ table is least able to keep up with. The kernel's precedence is: a window you
154
+ configured, then the driver's answer, then the table, then the default.
155
+
156
+ ```ts
157
+ await driver.resolveContextWindow('anthropic/claude-opus-5')
158
+ // the vendor's own context_length, or undefined
159
+ ```
160
+
161
+ `undefined` for a model the listing does not contain, deliberately, rather than
162
+ a guess: "I asked and it is not there" leaves the table exactly as authoritative
163
+ as it was, while a substituted number would present a guess as a vendor answer.
164
+ The listing is resolved once per process, because several hundred models is a
165
+ real payload and a window does not change under a running run. A **failure** is
166
+ not cached — the next run asks again rather than inheriting one bad minute
167
+ forever.
168
+
169
+ ## Credentials and attribution
170
+
171
+ `apiKey` is required and the constructor throws when it is empty. This driver
172
+ does not read the key from the environment itself — pass it, from wherever your
173
+ host keeps secrets. (`@namzu/cli` is the thing in this repository that reads
174
+ `OPENROUTER_API_KEY`; the library leaves that choice to you.)
175
+
176
+ `siteUrl` and `siteName` are optional and are sent verbatim as the
177
+ `HTTP-Referer` and `X-Title` headers, which is how OpenRouter attributes traffic
178
+ to an application. Omit them and the headers are not sent at all.
179
+
180
+ Every request also carries one `User-Agent` from the kernel's
181
+ `attributionHeaders()` — `namzu/<version> (+https://github.com/cogitave/namzu)`
182
+ — so a provider reading its own logs can tell this kernel's traffic apart from a
183
+ browser's. It is one header and only one, by design.
184
+
185
+ `probeCredential()` asks whether the key works, and it asks the endpoint that
186
+ can answer:
187
+
188
+ ```ts
189
+ await driver.probeCredential() // resolves if the key is accepted, throws if not
190
+ ```
191
+
192
+ It calls `GET /key`, which requires the credential. The obvious alternative was
193
+ measured and does not work: `/models` does not authenticate, so **any** string
194
+ whatsoever — a typo, the wrong clipboard entry, a revoked key — came back with
195
+ the full catalogue and was reported as verified. Nothing was wrong with the
196
+ menu; a menu was simply never evidence about a key. The thrown error carries the
197
+ HTTP `status`, so a caller can separate a genuine `401` from a timeout that
198
+ taught it nothing.
66
199
 
67
- The OpenRouter endpoint defaults to `https://openrouter.ai/api/v1`. Override via the `baseUrl` config field or the `OPENROUTER_BASE_URL` environment variable — useful for OpenRouter-compatible self-hosted gateways.
200
+ ## Configuration
201
+
202
+ | Option | Default | Notes |
203
+ |---|---|---|
204
+ | `apiKey` | — | required; the constructor throws on an empty string |
205
+ | `baseUrl` | `OPENROUTER_BASE_URL`, else `https://openrouter.ai/api/v1` | any OpenAI-compatible endpoint |
206
+ | `siteUrl` | — | sent as `HTTP-Referer` |
207
+ | `siteName` | — | sent as `X-Title` |
208
+ | `timeout` | `120_000` | per-request timeout in ms |
209
+
210
+ That is the whole of `OpenRouterConfig`. `OpenRouterProviderConfig` is the same
211
+ shape plus the `type: 'openrouter'` discriminator the registry narrows on.
212
+
213
+ Two details about the defaults are worth knowing before you debug them. The
214
+ `OPENROUTER_BASE_URL` fallback is read **once, at module load**, into a module
215
+ constant — setting it after this package has been imported changes nothing, so
216
+ set it before the process starts or pass `baseUrl` explicitly. And `timeout`
217
+ does not replace the caller's cancellation: it is composed with
218
+ `params.signal`, so whichever fires first tears the request down and a Stop
219
+ still stops the turn mid-stream.
220
+
221
+ Because the wire is the OpenAI Chat Completions dialect, pointing `baseUrl` at
222
+ another server that speaks it works. If that is the whole reason you are here —
223
+ a self-hosted inference server rather than OpenRouter — `@namzu/http` is the
224
+ driver built for it and ships today.
68
225
 
69
226
  ## Capabilities
70
227
 
@@ -75,17 +232,92 @@ import { OPENROUTER_CAPABILITIES } from '@namzu/openrouter'
75
232
  // supportsTools: true,
76
233
  // supportsStreaming: true,
77
234
  // supportsFunctionCalling: true,
235
+ // supportsVision: false,
236
+ // supportsDocuments: false,
78
237
  // }
79
238
  ```
80
239
 
81
- ## OpenAI compatibility
240
+ These describe what this **driver** does, not what OpenRouter could do, and the
241
+ runtime reads them before the request is built — it warns, or fails under
242
+ `strictCapabilities`, rather than letting content vanish quietly. So the two
243
+ `false` entries are load-bearing: this driver's message translation maps role
244
+ and content, plus the tool-call fields on assistant and tool turns, and nothing
245
+ else. A user message's image or document `attachments` are not mapped and never
246
+ reach the model.
247
+
248
+ Tool schemas pass through as the kernel built them, along with `toolChoice` and
249
+ `parallelToolCalls`. `enforceToolInputSchema` is a kernel-internal hint rather
250
+ than a wire field, and it is deliberately dropped instead of being serialised
251
+ into the request body.
252
+
253
+ The rest of `ChatCompletionParams` maps straight onto the OpenAI-dialect names:
254
+ `temperature`, `maxTokens` → `max_tokens`, `topP`, `topK`, `frequencyPenalty`,
255
+ `presencePenalty`, `repetitionPenalty`, `stop`, `responseFormat` →
256
+ `response_format`, and `cacheControl` → `cache_control`. A field you do not set
257
+ is not sent.
258
+
259
+ Token usage comes back on the chunk that carries it, and the cache counts are
260
+ read from whichever shape the upstream model used: `cachedTokens` from
261
+ `prompt_tokens_details.cached_tokens` or `cache_read_input_tokens`, and
262
+ `cacheWriteTokens` from `cache_creation_input_tokens`. Both are `0` when the
263
+ vendor reports neither, which is the honest answer rather than an absent one.
264
+
265
+ Extended thinking and `effort` are not implemented here, and they are
266
+ **refused** rather than dropped — setting `thinking: { type: 'enabled' }`,
267
+ `thinking: { type: 'adaptive' }` or any `effort` throws before the request is
268
+ built. `thinking: { type: 'disabled' }` passes, because asking for nothing is
269
+ something this driver can honour. A silently ignored `effort` would return an
270
+ ordinary completion indistinguishable from the model's default, including on the
271
+ bill.
272
+
273
+ ## Health
274
+
275
+ ```ts
276
+ await driver.healthCheck() // boolean
277
+ ```
278
+
279
+ One `GET /models` with a five-second timeout, reduced to a single bit, and it
280
+ never throws — an unreachable service returns `false` rather than raising. Read
281
+ it as "is this endpoint answering", not as "is my key good": that endpoint does
282
+ not authenticate. [`probeCredential()`](#credentials-and-attribution) is the one
283
+ that answers the credential question.
284
+
285
+ ## Errors
286
+
287
+ Every failure this driver raises is a `ProviderRequestError` from `@namzu/sdk`,
288
+ classified into the kernel's own kinds — `throttle`, `network`, `auth`,
289
+ `context_overflow`, `bad_request`, `server` — so a caller can decide whether to
290
+ retry, compact or give up without parsing a vendor payload.
291
+
292
+ | What happened | `kind` |
293
+ |---|---|
294
+ | `401` / `403` | `auth` |
295
+ | `429` | `throttle`, with `retryAfterMs` parsed from the `retry-after` header |
296
+ | `5xx` | `server` |
297
+ | `4xx` whose body says the prompt is too long | `context_overflow` |
298
+ | any other `4xx` | `bad_request` |
299
+ | `fetch` itself rejected | `network`, unless the rejection names its own kind |
82
300
 
83
- Because OpenRouter speaks the OpenAI Chat Completions dialect, this provider can also target any OpenAI-compatible endpoint (vLLM, LM Studio, Groq, local OpenAI-compat gateways) by passing `baseUrl` pointing at the alternate endpoint. For a zero-config generic OpenAI-compatible client, use the forthcoming `@namzu/http` package instead.
301
+ The error body is read to classify and is never interpolated into the thrown
302
+ message. That is not hygiene, it is a fix: the body used to be pasted into the
303
+ message verbatim, which is how a credential the upstream echoed back reached
304
+ every log that recorded the failure — proven with a planted fake token. What
305
+ survives is the vendor's own `error.message`, truncated and with
306
+ credential-shaped substrings replaced by a `[REDACTED:…]` marker, on the error's
307
+ `detail` field. The vendor error is not attached as `cause` either.
84
308
 
85
- ## Observability
309
+ OpenRouter also reports some failures **after** a `200`, as an `error` field
310
+ inside a stream frame. Those are read and raised too, because ignoring them
311
+ makes a failed stream look like a clean end of turn. A frame that will not parse
312
+ raises as `server` without keeping the frame, since a JSON parse error quotes
313
+ the source text it choked on.
86
314
 
87
- This package ships without observability hooks in `0.1.x`. OpenTelemetry span emission and structured logging are roadmapped for the forthcoming `@namzu/telemetry` package — a separate opt-in dependency that wraps any `LLMProvider` to emit GenAI semantic-convention spans. Track progress in the [Namzu roadmap](https://github.com/cogitave/namzu).
315
+ `params.signal` is composed with the request timeout and re-checked between
316
+ reads, so a Stop tears the in-flight response body down mid-turn, and it is the
317
+ caller's own abort reason that surfaces — not a `network` classification
318
+ manufactured from it.
88
319
 
89
320
  ## License
90
321
 
91
- FSL-1.1-MIT. Same as `@namzu/sdk`.
322
+ FSL-1.1-MIT, converting to MIT two years after each release. Same as
323
+ `@namzu/sdk`.
package/dist/client.d.ts CHANGED
@@ -33,6 +33,30 @@ export declare class OpenRouterProvider implements LLMProvider {
33
33
  * key is genuinely refused.
34
34
  */
35
35
  probeCredential(): Promise<void>;
36
+ /**
37
+ * The vendor's own `context_length` for this model.
38
+ *
39
+ * This driver already parsed the number and threw it away: `listModels`
40
+ * maps it into `contextWindow` and nothing downstream ever asked. The
41
+ * kernel meanwhile fell back to a hand-maintained prefix table whose own
42
+ * header records what that costs — every Claude entry carried 200k
43
+ * including the 1M-window models, so those runs compacted at roughly 14%
44
+ * full. OpenRouter fronts hundreds of models from a dozen vendors, so it
45
+ * is the driver where a static table drifts fastest.
46
+ *
47
+ * `undefined` for a model the listing does not contain, rather than a
48
+ * guess: "I asked and it is not there" leaves the table exactly as
49
+ * authoritative as it was, while a substituted number would present a
50
+ * guess as a vendor answer.
51
+ *
52
+ * Cached for the process, because a listing of several hundred models is
53
+ * a real payload and a model's window does not change under a running
54
+ * run. A failure is NOT cached — the next run asks again rather than
55
+ * inheriting one bad minute forever.
56
+ */
57
+ resolveContextWindow(model: string, signal?: AbortSignal): Promise<number | undefined>;
58
+ /** Resolved once per process; see the note on `resolveContextWindow`. */
59
+ private contextWindows?;
36
60
  listModels(): Promise<ModelInfo[]>;
37
61
  healthCheck(): Promise<boolean>;
38
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,WAAW,EAGX,MAAM,YAAY,CAAA;AASnB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAwClD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,oBAOrC,CAAA;AAED,qBAAa,kBAAmB,YAAW,WAAW;IACrD,QAAQ,CAAC,EAAE,gBAAe;IAC1B,QAAQ,CAAC,IAAI,gBAAe;IAC5B,QAAQ,CAAC,YAAY,uBAA0B;IAE/C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAQ;gBAEX,MAAM,EAAE,gBAAgB;IAQpC,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,gBAAgB;IAqCjB,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,aAAa,CAAC,WAAW,CAAC;IAmI3E;;;;;;;;;;;;;OAaG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAWhC,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IA+BlC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAWrC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,WAAW,EAGX,MAAM,YAAY,CAAA;AAUnB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAwClD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,oBAOrC,CAAA;AAED,qBAAa,kBAAmB,YAAW,WAAW;IACrD,QAAQ,CAAC,EAAE,gBAAe;IAC1B,QAAQ,CAAC,IAAI,gBAAe;IAC5B,QAAQ,CAAC,YAAY,uBAA0B;IAE/C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAQ;gBAEX,MAAM,EAAE,gBAAgB;IAQpC,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,gBAAgB;IAqCjB,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,aAAa,CAAC,WAAW,CAAC;IAmI3E;;;;;;;;;;;;;OAaG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtC;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA0B5F,yEAAyE;IACzE,OAAO,CAAC,cAAc,CAAC,CAA8B;IAE/C,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IA+BlC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAWrC"}
package/dist/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ProviderRequestError, assertThinkingUnsupported, isCallerAbortError, isProviderRequestError, providerHttpError, providerVendorError, } from '@namzu/sdk';
2
+ import { attributionHeaders } from '@namzu/sdk';
2
3
  const OPENROUTER_BASE_URL = process.env.OPENROUTER_BASE_URL ?? 'https://openrouter.ai/api/v1';
3
4
  function parseUsage(raw) {
4
5
  if (!raw) {
@@ -52,6 +53,10 @@ export class OpenRouterProvider {
52
53
  }
53
54
  getHeaders() {
54
55
  const headers = {
56
+ // First, so anything a host sets below still wins. Attribution is
57
+ // what this kernel says about itself; a host overriding it has a
58
+ // reason and is not to be argued with.
59
+ ...attributionHeaders(),
55
60
  Authorization: `Bearer ${this.config.apiKey}`,
56
61
  'Content-Type': 'application/json',
57
62
  };
@@ -261,6 +266,49 @@ export class OpenRouterProvider {
261
266
  throw err;
262
267
  }
263
268
  }
269
+ /**
270
+ * The vendor's own `context_length` for this model.
271
+ *
272
+ * This driver already parsed the number and threw it away: `listModels`
273
+ * maps it into `contextWindow` and nothing downstream ever asked. The
274
+ * kernel meanwhile fell back to a hand-maintained prefix table whose own
275
+ * header records what that costs — every Claude entry carried 200k
276
+ * including the 1M-window models, so those runs compacted at roughly 14%
277
+ * full. OpenRouter fronts hundreds of models from a dozen vendors, so it
278
+ * is the driver where a static table drifts fastest.
279
+ *
280
+ * `undefined` for a model the listing does not contain, rather than a
281
+ * guess: "I asked and it is not there" leaves the table exactly as
282
+ * authoritative as it was, while a substituted number would present a
283
+ * guess as a vendor answer.
284
+ *
285
+ * Cached for the process, because a listing of several hundred models is
286
+ * a real payload and a model's window does not change under a running
287
+ * run. A failure is NOT cached — the next run asks again rather than
288
+ * inheriting one bad minute forever.
289
+ */
290
+ async resolveContextWindow(model, signal) {
291
+ const pending = this.contextWindows ??
292
+ (async () => {
293
+ const models = await this.listModels();
294
+ return new Map(models
295
+ .filter((m) => typeof m.contextWindow === 'number')
296
+ .map((m) => [m.id, m.contextWindow]));
297
+ })().catch((err) => {
298
+ // Not cached. A listing endpoint that was down for a minute must
299
+ // not leave every later run answering from that minute.
300
+ this.contextWindows = undefined;
301
+ throw err;
302
+ });
303
+ this.contextWindows = pending;
304
+ const windows = await pending;
305
+ if (signal?.aborted)
306
+ return undefined;
307
+ const reported = windows.get(model);
308
+ return typeof reported === 'number' && reported > 0 ? reported : undefined;
309
+ }
310
+ /** Resolved once per process; see the note on `resolveContextWindow`. */
311
+ contextWindows;
264
312
  async listModels() {
265
313
  const response = await fetch(`${this.baseUrl}/models`, {
266
314
  headers: this.getHeaders(),
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/openrouter",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "OpenRouter LLM provider for @namzu/sdk. Access to 200+ models (Claude, GPT-4, Llama, Mixtral) via OpenRouter's unified API.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "type": "module",
@@ -52,7 +52,7 @@
52
52
  "@types/node": "^22.19.17",
53
53
  "typescript": "^5.5.0",
54
54
  "vitest": "^3.2.6",
55
- "@namzu/sdk": "^18.1.0"
55
+ "@namzu/sdk": "^28.0.0"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsc --build",
package/src/client.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  providerHttpError,
16
16
  providerVendorError,
17
17
  } from '@namzu/sdk'
18
+ import { attributionHeaders } from '@namzu/sdk'
18
19
  import type { OpenRouterConfig } from './types.js'
19
20
 
20
21
  const OPENROUTER_BASE_URL = process.env.OPENROUTER_BASE_URL ?? 'https://openrouter.ai/api/v1'
@@ -88,6 +89,10 @@ export class OpenRouterProvider implements LLMProvider {
88
89
 
89
90
  private getHeaders(): Record<string, string> {
90
91
  const headers: Record<string, string> = {
92
+ // First, so anything a host sets below still wins. Attribution is
93
+ // what this kernel says about itself; a host overriding it has a
94
+ // reason and is not to be argued with.
95
+ ...attributionHeaders(),
91
96
  Authorization: `Bearer ${this.config.apiKey}`,
92
97
  'Content-Type': 'application/json',
93
98
  }
@@ -317,6 +322,56 @@ export class OpenRouterProvider implements LLMProvider {
317
322
  }
318
323
  }
319
324
 
325
+ /**
326
+ * The vendor's own `context_length` for this model.
327
+ *
328
+ * This driver already parsed the number and threw it away: `listModels`
329
+ * maps it into `contextWindow` and nothing downstream ever asked. The
330
+ * kernel meanwhile fell back to a hand-maintained prefix table whose own
331
+ * header records what that costs — every Claude entry carried 200k
332
+ * including the 1M-window models, so those runs compacted at roughly 14%
333
+ * full. OpenRouter fronts hundreds of models from a dozen vendors, so it
334
+ * is the driver where a static table drifts fastest.
335
+ *
336
+ * `undefined` for a model the listing does not contain, rather than a
337
+ * guess: "I asked and it is not there" leaves the table exactly as
338
+ * authoritative as it was, while a substituted number would present a
339
+ * guess as a vendor answer.
340
+ *
341
+ * Cached for the process, because a listing of several hundred models is
342
+ * a real payload and a model's window does not change under a running
343
+ * run. A failure is NOT cached — the next run asks again rather than
344
+ * inheriting one bad minute forever.
345
+ */
346
+ async resolveContextWindow(model: string, signal?: AbortSignal): Promise<number | undefined> {
347
+ const pending =
348
+ this.contextWindows ??
349
+ (async () => {
350
+ const models = await this.listModels()
351
+ return new Map<string, number>(
352
+ models
353
+ .filter(
354
+ (m): m is typeof m & { contextWindow: number } => typeof m.contextWindow === 'number',
355
+ )
356
+ .map((m) => [m.id, m.contextWindow]),
357
+ )
358
+ })().catch((err: unknown) => {
359
+ // Not cached. A listing endpoint that was down for a minute must
360
+ // not leave every later run answering from that minute.
361
+ this.contextWindows = undefined
362
+ throw err
363
+ })
364
+ this.contextWindows = pending
365
+
366
+ const windows = await pending
367
+ if (signal?.aborted) return undefined
368
+ const reported = windows.get(model)
369
+ return typeof reported === 'number' && reported > 0 ? reported : undefined
370
+ }
371
+
372
+ /** Resolved once per process; see the note on `resolveContextWindow`. */
373
+ private contextWindows?: Promise<Map<string, number>>
374
+
320
375
  async listModels(): Promise<ModelInfo[]> {
321
376
  const response = await fetch(`${this.baseUrl}/models`, {
322
377
  headers: this.getHeaders(),