@absolutejs/ai 0.0.49 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -78,3 +78,120 @@ completion. Payload types are exported (`AISSECompletePayload`,
78
78
  The default (HTML) path is unchanged for the built-in HTMX/default UI, except an
79
79
  abort now renders the (previously unused) `canceled` renderer instead of a
80
80
  misleading usage chip.
81
+
82
+ ## OpenRouter
83
+
84
+ `@absolutejs/ai/openrouter` uses the shared provider contract and
85
+ OpenAI-compatible stream parser while adding OpenRouter-specific routing,
86
+ attribution, cost metadata, and local model-policy enforcement.
87
+
88
+ ```ts
89
+ import { openrouter } from "@absolutejs/ai/openrouter";
90
+
91
+ const provider = openrouter({
92
+ apiKey: process.env.OPENROUTER_API_KEY,
93
+ appName: "My AbsoluteJS App",
94
+ appUrl: "https://example.com",
95
+ // Exact IDs and namespace wildcards are supported. A disallowed model fails
96
+ // locally before any request reaches OpenRouter.
97
+ allowedModels: ["anthropic/*", "google/*", "mistralai/*", "openai/*"],
98
+ // This becomes provider.only, so OpenRouter cannot select another inference
99
+ // provider during fallback.
100
+ allowedProviders: ["anthropic", "google-vertex", "mistral", "openai"],
101
+ routing: {
102
+ dataCollection: "deny",
103
+ maxPrice: { prompt: 3, completion: 15 },
104
+ requireParameters: true,
105
+ sort: "price",
106
+ zdr: true,
107
+ },
108
+ });
109
+ ```
110
+
111
+ The adapter intentionally has no built-in geopolitical model list. Applications
112
+ must define their own explicit `allowedModels` and `allowedProviders` policy.
113
+ Avoid `openrouter/auto` unless it is deliberately present in that model policy.
114
+
115
+ Provider usage callbacks include OpenRouter's reported `costCredits`,
116
+ `upstreamInferenceCostCredits`, cache-read/write token counts, and reasoning
117
+ tokens when those fields are present in the final streaming usage message.
118
+ Hosted-tool counters are exposed as `serverToolUse`.
119
+
120
+ OpenRouter-specific features are available per request without weakening the
121
+ portable provider contract:
122
+
123
+ ```ts
124
+ await generateAI({
125
+ provider,
126
+ model: "anthropic/claude-sonnet-4.6",
127
+ messages,
128
+ providerOptions: {
129
+ openrouter: {
130
+ fallbackModels: ["openai/gpt-5.2"],
131
+ sessionId: conversationId, // sticky routing improves prompt-cache hits
132
+ serviceTier: "flex", // cheaper, slower capacity when available
133
+ responseCache: { enabled: true, ttlSeconds: 300 },
134
+ serverTools: [
135
+ { type: "openrouter:web_search", parameters: { max_results: 3 } },
136
+ ],
137
+ maxToolCalls: 5,
138
+ stopServerToolsWhen: [{ type: "max_cost", value: 0.02 }],
139
+ },
140
+ },
141
+ });
142
+ ```
143
+
144
+ Other typed request options include presets, plugins, per-call provider routing,
145
+ message transforms, reasoning visibility, verbosity, user attribution, and an
146
+ `extraBody` escape hatch for new OpenRouter parameters. The escape hatch cannot
147
+ replace models, fallbacks, providers, presets, messages, plugins, or tools; those
148
+ fields use policy-aware typed options instead.
149
+
150
+ URL images and PDFs, base64 audio, and URL/base64 video inputs use the ordinary
151
+ AbsoluteJS content-block contract. URL citations are emitted as `citation`
152
+ chunks. The final `done` chunk includes the generation ID, resolved model,
153
+ selected inference provider, service tier, cache headers, and OpenRouter router
154
+ metadata when reported.
155
+
156
+ ### OpenRouter platform client
157
+
158
+ `createOpenRouterClient()` covers model/provider discovery, embeddings,
159
+ reranking, image generation, Responses, speech, transcription, video jobs,
160
+ batches, presets, credits, key metadata, and generation metadata. Its typed
161
+ operations enforce the same model allowlist. `request()` and `requestRaw()` are
162
+ forward-compatible access to new or administrative OpenRouter endpoints.
163
+
164
+ ```ts
165
+ import { createOpenRouterClient } from "@absolutejs/ai/openrouter";
166
+
167
+ const openrouterClient = createOpenRouterClient({
168
+ apiKey: process.env.OPENROUTER_API_KEY,
169
+ allowedModels: ["anthropic/*", "google/*", "mistralai/*", "openai/*"],
170
+ });
171
+
172
+ const models = await openrouterClient.listModels({
173
+ supported_parameters: "tools",
174
+ });
175
+ const embedding = await openrouterClient.createEmbedding({
176
+ model: "openai/text-embedding-3-small",
177
+ input: "AbsoluteJS supports OpenRouter",
178
+ });
179
+ const reranked = await openrouterClient.rerank({
180
+ model: "openai/text-embedding-3-small",
181
+ query: "cost controls",
182
+ documents: ["response caching", "CSS layout"],
183
+ });
184
+ ```
185
+
186
+ For a strict model-origin policy, also assign an OpenRouter key/workspace
187
+ guardrail with the same model allowlist. Provider allowlists restrict where a
188
+ model runs; they do not identify who developed it. Presets and router aliases
189
+ must be explicitly allowed, because their resolved model is controlled outside
190
+ the request. The raw client is intentionally unopinionated and should be limited
191
+ to trusted server-side administration code. OpenRouter's official SDK can be
192
+ used alongside this package for its complete organization, SSO, SCIM, BYOK, and
193
+ analytics type surface.
194
+
195
+ Use `openrouterResponses(config)` when an AbsoluteJS agent should stream through
196
+ OpenRouter's stateless Responses API instead of Chat Completions. It accepts the
197
+ same model/provider policies and `providerOptions.openrouter` controls.