@rouvanpm/rouva 0.2.7 → 0.2.9

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
@@ -107,19 +107,25 @@ Unsupported OpenAI options (`response_format`, `logit_bias`, `n > 1`, the legacy
107
107
 
108
108
  ## Unlisted models
109
109
 
110
- Model IDs beyond the typed union also work when pinned — dated snapshots (`gpt-4o-mini-2024-07-18`), fine-tunes (`ft:gpt-4o-mini:…`), and newly released models are matched to their provider by naming convention and forwarded as-is. Until the gateway's pricing registry knows them, the dashboard records their token counts with zero cost.
110
+ Dated snapshots (`gpt-4o-mini-2024-07-18`) and fine-tunes (`ft:gpt-4o-mini:…`) work when pinned — they are matched to their provider by naming convention and forwarded as-is. Until the gateway's pricing registry knows them, the dashboard records their token counts with zero cost.
111
+
112
+ Models not recognised by the gateway return a `400` immediately:
113
+
114
+ ```json
115
+ { "error": "Model \"<id>\" is not supported. See rouva.io/docs for the supported model list." }
116
+ ```
111
117
 
112
118
  ## OpenAI-compatible endpoint
113
119
 
114
120
  Using the OpenAI SDK (or LangChain, the Vercel AI SDK, …) instead of this one? The gateway is also served at `POST /v1/chat/completions` — point `baseURL` at `https://app.rouva.io/v1` with your `rva_` key and it behaves exactly like OpenAI: `model` is required, responses are buffered JSON unless `stream: true`, and only OpenAI-format providers are available (use this SDK or the native endpoint for Anthropic models).
115
121
 
116
- Non-tools requests on `/v1` always honor the named model exactly. **Tools requests on `/v1` benefit from within-provider intelligent routing** when Intelligent Routing is enabled in your dashboard — Rouva picks the cheapest capable model within the same provider, using the named `model` as a cost ceiling. The provider never changes (tool schemas are provider-specific), and `response.model` reflects the model that actually served the request. Turn Intelligent Routing off in dashboard Settings → Gateway to always pin the exact model.
122
+ Intelligent routing applies to `/v1` too — Rouva may substitute a cheaper model within the same provider using your requested model as a cost ceiling. For tool call requests specifically, routing only considers non-reasoning models (reasoning models add unpredictable hidden token costs on tool dispatch). To pin a model exactly, disable Intelligent Routing in your dashboard under **Settings**.
117
123
 
118
124
  ## Tool use
119
125
 
120
126
  Tools are forwarded to your target provider verbatim — define them in the **provider's own format** (OpenAI `{ type: "function", function: {...} }` or Anthropic `{ name, description, input_schema }`) and pin the matching `model`. Tool schemas are provider-specific, so `model` is required and the gateway returns a 400 without it.
121
127
 
122
- When using the `/v1` endpoint (OpenAI SDK, LangChain, Vercel AI SDK, …) with Intelligent Routing enabled, tools requests are routed to the cheapest capable model within the same provider — see [OpenAI-compatible endpoint](#openai-compatible-endpoint) for details. On the native SDK endpoint (`/api/gateway/messages`), the named model is always honored exactly.
128
+ On the native endpoint (`/api/gateway/messages`), the pinned model is always honored exactly — no substitution. On the `/v1` endpoint with Intelligent Routing enabled, Rouva may route to a cheaper non-reasoning model within the same provider. Disable Intelligent Routing in **Settings** to pin the exact model on `/v1`.
123
129
 
124
130
  ```typescript
125
131
  const res = await rouva.chat.completions.create({
@@ -161,7 +167,19 @@ Responses are normalized to the OpenAI shape regardless of provider: Anthropic `
161
167
 
162
168
  **Don't branch on `finish_reason` to detect tool calls** — check for the presence of `message.tool_calls` instead. `finish_reason` follows each provider's own semantics, and OpenAI notably returns `"stop"` (not `"tool_calls"`) when `tool_choice` forces a specific function. The SDK passes OpenAI's values through unchanged so behavior matches calling OpenAI directly.
163
169
 
164
- Tools requests record usage and cost. Savings are recorded when within-provider routing substitutes a cheaper model on `/v1`. Tools responses are not quality-scored or served from the semantic cache.
170
+ Tools requests record usage and cost but no savings, and are not quality-scored or served from the semantic cache.
171
+
172
+ ## Cost optimisations
173
+
174
+ Rouva applies several cost-saving layers automatically on every non-tools request — no configuration required.
175
+
176
+ **Semantic cache (A)** — repeated or semantically similar prompts are served from cache without hitting the upstream provider. Cache hits record zero cost and appear in your dashboard with a `semantic_cache_hit` flag.
177
+
178
+ **Prompt caching (B)** — Anthropic requests automatically include cache-control headers on large system prompts and conversation prefixes, reducing input token costs on repeated turns.
179
+
180
+ **Conversation summarisation (C2)** — long Anthropic conversations are summarised by a cheap model before forwarding, compressing the context window and reducing input tokens. The summarisation cost is included in the request's spend snapshot. Only runs when the conversation exceeds ~2,000 tokens of non-system content and the request is not a tools request.
181
+
182
+ All three are skipped for tools requests, which are forwarded verbatim.
165
183
 
166
184
  ## Options
167
185
 
package/dist/index.d.mts CHANGED
@@ -56,7 +56,7 @@ type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral'
56
56
  * as-is. Until the gateway's registry knows their pricing, such requests are
57
57
  * logged with token counts but zero cost.
58
58
  */
59
- type RouvaModel = 'claude-opus-4-6' | 'claude-opus-4-7' | 'claude-opus-4-8' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001' | 'claude-fable-5' | 'gpt-5-nano' | 'gpt-5-mini' | 'gpt-5' | 'gpt-5.6' | 'gpt-4.1-nano' | 'gpt-4.1-mini' | 'gpt-4.1' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-2.5-flash' | 'gemini-2.5-pro' | 'deepseek-v4-flash' | 'deepseek-v4-flash-think' | 'deepseek-v4-pro' | 'mistral-small-latest' | 'mistral-large-latest' | 'kimi-k2.6' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'grok-4.5' | 'glm-4.7-flash' | 'glm-5.2' | (string & {});
59
+ type RouvaModel = 'claude-opus-4-6' | 'claude-opus-4-7' | 'claude-opus-4-8' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001' | 'claude-fable-5' | 'gpt-5-nano' | 'gpt-5-mini' | 'gpt-5.4-mini' | 'gpt-5' | 'gpt-5.6' | 'gpt-4.1-nano' | 'gpt-4.1-mini' | 'gpt-4.1' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-2.5-flash' | 'gemini-2.5-pro' | 'deepseek-v4-flash' | 'deepseek-v4-flash-think' | 'deepseek-v4-pro' | 'mistral-small-latest' | 'mistral-large-latest' | 'kimi-k2.6' | 'kimi-k3' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'grok-4.5' | 'glm-4.7-flash' | 'glm-5.2' | (string & {});
60
60
  /** Anthropic-style text block — the array form of the `system` param */
61
61
  interface SystemTextBlock {
62
62
  type: 'text';
package/dist/index.d.ts CHANGED
@@ -56,7 +56,7 @@ type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral'
56
56
  * as-is. Until the gateway's registry knows their pricing, such requests are
57
57
  * logged with token counts but zero cost.
58
58
  */
59
- type RouvaModel = 'claude-opus-4-6' | 'claude-opus-4-7' | 'claude-opus-4-8' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001' | 'claude-fable-5' | 'gpt-5-nano' | 'gpt-5-mini' | 'gpt-5' | 'gpt-5.6' | 'gpt-4.1-nano' | 'gpt-4.1-mini' | 'gpt-4.1' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-2.5-flash' | 'gemini-2.5-pro' | 'deepseek-v4-flash' | 'deepseek-v4-flash-think' | 'deepseek-v4-pro' | 'mistral-small-latest' | 'mistral-large-latest' | 'kimi-k2.6' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'grok-4.5' | 'glm-4.7-flash' | 'glm-5.2' | (string & {});
59
+ type RouvaModel = 'claude-opus-4-6' | 'claude-opus-4-7' | 'claude-opus-4-8' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001' | 'claude-fable-5' | 'gpt-5-nano' | 'gpt-5-mini' | 'gpt-5.4-mini' | 'gpt-5' | 'gpt-5.6' | 'gpt-4.1-nano' | 'gpt-4.1-mini' | 'gpt-4.1' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-2.5-flash' | 'gemini-2.5-pro' | 'deepseek-v4-flash' | 'deepseek-v4-flash-think' | 'deepseek-v4-pro' | 'mistral-small-latest' | 'mistral-large-latest' | 'kimi-k2.6' | 'kimi-k3' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'grok-4.5' | 'glm-4.7-flash' | 'glm-5.2' | (string & {});
60
60
  /** Anthropic-style text block — the array form of the `system` param */
61
61
  interface SystemTextBlock {
62
62
  type: 'text';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rouvanpm/rouva",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Official Node.js SDK for Rouva — managed AI gateway with intelligent routing and spend tracking",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",