@rouvanpm/rouva 0.5.1 → 0.5.2

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
@@ -103,6 +103,7 @@ const res = await rouva.chat.completions.create({
103
103
  - **`top_p`** — nucleus sampling; `top_p: 1` is treated as omitted. OpenAI reasoning models don't support it: routing avoids them when it's set, and pinning one returns a 400. The gateway omits it for the Claude models that reject it (as for `temperature`).
104
104
  - **`stop`** — a string or up to 4 stop sequences (Anthropic receives them as `stop_sequences`). OpenAI and xAI reasoning models (e.g. gpt-5, grok-4.5 / 4.6 / 4.7) reject it: routing avoids them when it's set, and pinning one returns a 400.
105
105
  - **`metadata`** — up to 10 string key-value pairs (keys up to 64 characters, values up to 256, no null bytes) stored with the request's usage record; not sent to the provider.
106
+ - **`service_tier`** — `'default'` (or Anthropic's `'standard_only'`) asks the provider for its standard tier; `'auto'`, the same as leaving it out, uses your provider account's own setting. Rouva bills standard prices, so other tiers (`flex`, `priority`, `scale`) are a 400.
106
107
  - **`seed`** — best-effort deterministic sampling. Only OpenAI honors it, so it requires an OpenAI `model` and pins the request to that exact model (no routing, no fallbacks).
107
108
  - **`response_format`** — JSON mode or a JSON schema; see [Structured output](#structured-output).
108
109
  - **`reasoning_effort`** — `'none'` … `'xhigh'`, or `'max'` for Claude. Which values a model takes depends on the model; routing only picks one that takes yours; a listed OpenAI or Claude model you name that doesn't gets a 400, and other providers' models get the value as sent. On gpt-6-luna / gpt-6-sol / gpt-6.1-terra, `'none'` turns reasoning off. See [the docs](https://rouva.io/docs#reasoning-effort).
@@ -258,6 +259,8 @@ Every turn is logged as a usage snapshot in the Rouva dashboard under the shared
258
259
  | `max_tokens` | `number` | | Max tokens per turn (default: 4096) |
259
260
  | `temperature` | `number` | | Sampling temperature 0–1 |
260
261
  | `session_budget_usd` | `number` | | Hard USD cap across all turns |
262
+ | `metadata` | `Record<string, string>` | | Your labels (e.g. `customer_id`), stored with every turn's usage record |
263
+ | `service_tier` | `ServiceTier` | | `'default'` / `'standard_only'` for the standard tier, or `'auto'` |
261
264
 
262
265
  ### Result shape
263
266
 
@@ -407,7 +410,7 @@ try {
407
410
  await rouva.chat.completions.create({ messages })
408
411
  } catch (e) {
409
412
  if (e instanceof RouvaError && e.status === 429) {
410
- console.log(e.refusal) // 'key_cap' | 'member_cap' | 'rate' | … — Rouva refused before calling the provider
413
+ console.log(e.refusal) // 'key_cap' | 'plan_limit' | 'rate' | … — Rouva refused before calling the provider
411
414
  console.log(e.retryAfter) // seconds, from Retry-After
412
415
  console.log(e.error) // the gateway's message
413
416
  console.log(e.requestId) // when the request was recorded — rouva.requests.get(e.requestId)
@@ -415,7 +418,7 @@ try {
415
418
  }
416
419
  ```
417
420
 
418
- `refusal` (header `X-Rouva-Refusal`) names why Rouva itself refused the request before contacting the provider, when the gateway marks it: a monthly spend cap would be exceeded (`key_cap`, `member_cap`), the rate limit (`rate`), for spend-capped keys a model with no known price (`unpriced`) or input or a model whose cost can't be bounded (`unbounded`), or — a `504` — the request ran out of its time budget before the provider was called (`deadline`; nothing was sent, so it's safe to retry, and `retryAfter` is set). Every Rouva refusal is marked, so a `429` or `504` without `refusal` came from the provider, not from Rouva — with one exception: `rouva.run()` returns an unmarked `504` "Run deadline exceeded before completion" when the run runs out of time, because earlier turns were already billed and their tool handlers ran; check what completed before retrying it. Every call also takes `{ signal }` as a second argument to abort it.
421
+ `refusal` (header `X-Rouva-Refusal`) names why Rouva itself refused the request before contacting the provider, when the gateway marks it: a monthly spend cap would be exceeded (`key_cap`, `member_cap`, or `customer_cap` for a `metadata.customer_id` customer), the account is on the Free plan and has used its requests for the month (`plan_limit`, a `429`; `retryAfter` runs to the 1st of next month, UTC, or upgrade the plan), the rate limit (`rate`), for spend-capped keys a model with no known price (`unpriced`) or input or a model whose cost can't be bounded (`unbounded`), or — a `504` — the request ran out of its time budget before the provider was called (`deadline`; nothing was sent, so it's safe to retry, and `retryAfter` is set). Every Rouva refusal is marked, so a `429` or `504` without `refusal` came from the provider, not from Rouva — with one exception: `rouva.run()` returns an unmarked `504` "Run deadline exceeded before completion" when the run runs out of time, because earlier turns were already billed and their tool handlers ran; check what completed before retrying it. Every call also takes `{ signal }` as a second argument to abort it.
419
422
 
420
423
  ## Getting your API key
421
424
 
package/dist/index.d.mts CHANGED
@@ -50,9 +50,17 @@ interface ContentBlockMessage {
50
50
  * valid when `tools` is set on the request.
51
51
  */
52
52
  type ChatMessage = Message | AssistantToolCallMessage | ToolResultMessage | ContentBlockMessage;
53
+ /** `service_tier` values the gateway serves (see `ChatCompletionParams.service_tier`). */
54
+ type ServiceTier = 'auto' | 'default' | 'standard_only';
55
+ /**
56
+ * Why Rouva itself refused a request (`RouvaError.refusal`, header
57
+ * `X-Rouva-Refusal`). See `RouvaError.refusal` for each kind. Other strings
58
+ * are allowed so a newer gateway's kinds still type-check.
59
+ */
60
+ type RouvaRefusal = 'key_cap' | 'member_cap' | 'customer_cap' | 'plan_limit' | 'rate' | 'unpriced' | 'unbounded' | 'deadline' | (string & {});
53
61
  type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral' | 'moonshot' | 'xai' | 'zai' | 'alibaba' | 'minimax' | (string & {});
54
62
  /**
55
- * Supported models across all providers (the gateway's list as of SDK 0.5.1).
63
+ * Supported models across all providers (the gateway's list as of SDK 0.5.2).
56
64
  * Omit `model` entirely to let Rouva route to the cheapest capable model automatically.
57
65
  *
58
66
  * Other IDs are accepted by the type for forward compatibility. On
@@ -64,7 +72,7 @@ type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral'
64
72
  *
65
73
  * `'gpt-5.6'` is a deprecated alias the gateway maps to `'gpt-5.6-sol'`.
66
74
  */
67
- type RouvaModel = 'claude-fable-5-1' | 'claude-fable-5' | 'claude-opus-5-5' | 'claude-opus-5' | 'claude-opus-4-8' | 'claude-opus-4-7' | 'claude-opus-4-6' | 'claude-sonnet-5-5' | 'claude-sonnet-5' | 'claude-sonnet-4-6' | 'claude-haiku-5-5' | 'claude-haiku-4-5-20251001' | 'gpt-6-astra' | 'gpt-6.1-sol' | 'gpt-6.1-terra' | 'gpt-6-sol' | 'gpt-6-luna' | 'gpt-5.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'gpt-5.6' | 'gpt-5' | 'gpt-5.4-mini' | 'gpt-5-mini' | 'gpt-5-nano' | 'gpt-4.1' | 'gpt-4.1-mini' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-4-argon' | 'gemini-3.8-flash' | 'gemini-3.7-flash' | 'gemini-3.6-flash' | 'gemini-3.5-flash-lite' | 'gemini-2.5-pro' | 'gemini-2.5-flash' | 'deepseek-flash' | 'deepseek-flash-think' | 'deepseek-v4-pro' | 'mistral-large-latest' | 'mistral-small-latest' | 'kimi-k3.1-pro' | 'kimi-k3' | 'kimi-k2.6' | 'grok-4.7' | 'grok-4.6' | 'grok-4.5' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'glm-5.3' | 'glm-5.2' | 'glm-4.7-flash' | 'qwen3.8-omni-flash' | 'qwen3.8-flash' | 'qwen3.7-plus' | 'qwen-max' | 'qwen-plus' | 'qwen-flash' | 'MiniMax-M3.1-Flash' | 'MiniMax-M3' | (string & {});
75
+ type RouvaModel = 'claude-fable-5-1' | 'claude-fable-5' | 'claude-opus-5-5' | 'claude-opus-5' | 'claude-opus-4-8' | 'claude-opus-4-7' | 'claude-opus-4-6' | 'claude-sonnet-5-5' | 'claude-sonnet-5' | 'claude-sonnet-4-6' | 'claude-haiku-5-5' | 'claude-haiku-4-5-20251001' | 'gpt-6-astra' | 'gpt-6.1-sol' | 'gpt-6.1-terra' | 'gpt-6-sol' | 'gpt-6-luna' | 'gpt-5.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'gpt-5.6' | 'gpt-5' | 'gpt-5.4-mini' | 'gpt-5-mini' | 'gpt-5-nano' | 'gpt-4.1' | 'gpt-4.1-mini' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-4-argon' | 'gemini-3.8-flash' | 'gemini-3.7-flash' | 'gemini-3.6-flash' | 'gemini-3.5-flash-lite' | 'gemini-2.5-pro' | 'gemini-2.5-flash' | 'deepseek-flash' | 'deepseek-flash-think' | 'deepseek-v4-pro' | 'mistral-large-4' | 'mistral-large-latest' | 'mistral-small-latest' | 'kimi-k3.1-pro' | 'kimi-k3' | 'kimi-k2.6' | 'grok-4.7' | 'grok-4.6' | 'grok-4.5' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'glm-5.3' | 'glm-5.2' | 'glm-4.7-flash' | 'qwen3.8-omni-flash' | 'qwen3.8-flash' | 'qwen3.7-plus' | 'qwen-max' | 'qwen-plus' | 'qwen-flash' | 'MiniMax-M3.1-Flash' | 'MiniMax-M3' | (string & {});
68
76
  /** Anthropic-style text block — the array form of the `system` param */
69
77
  interface SystemTextBlock {
70
78
  type: 'text';
@@ -104,6 +112,15 @@ interface ChatCompletionParams {
104
112
  * characters, values up to 256 characters, no null bytes.
105
113
  */
106
114
  metadata?: Record<string, string>;
115
+ /**
116
+ * Which provider service tier to use. Rouva bills standard prices, so only
117
+ * the standard tier is served: `'default'` (OpenAI's name) or
118
+ * `'standard_only'` (Anthropic's) asks for it — sent in the dialect of
119
+ * whichever provider the request reaches; `'auto'` (the same as leaving it
120
+ * out) uses your provider account's own setting. Any other tier (`flex`,
121
+ * `priority`, `scale`, …) is a 400.
122
+ */
123
+ service_tier?: ServiceTier;
107
124
  /**
108
125
  * Sampling temperature 0–1.
109
126
  * The gateway omits it for models that only accept their default: OpenAI
@@ -444,6 +461,23 @@ interface RunParams {
444
461
  * all turns reaches this threshold.
445
462
  */
446
463
  session_budget_usd?: number;
464
+ /**
465
+ * Your own labels for the run, stored with every turn's usage record and
466
+ * not sent to the provider (e.g. `{ customer_id: 'acme' }` for the
467
+ * dashboard's Customers page and per-customer spend caps): up to 10 string
468
+ * key-value pairs, keys up to 64 characters, values up to 256 characters,
469
+ * no null bytes.
470
+ */
471
+ metadata?: Record<string, string>;
472
+ /**
473
+ * Which provider service tier to use. Rouva bills standard prices, so only
474
+ * the standard tier is served: `'default'` (OpenAI's name) or
475
+ * `'standard_only'` (Anthropic's) asks for it — sent in the dialect of
476
+ * whichever provider the request reaches; `'auto'` (the same as leaving it
477
+ * out) uses your provider account's own setting. Any other tier (`flex`,
478
+ * `priority`, `scale`, …) is a 400.
479
+ */
480
+ service_tier?: ServiceTier;
447
481
  }
448
482
  interface RunResult {
449
483
  /** Final model response text after all tool loops complete. */
@@ -587,8 +621,11 @@ declare class RouvaError extends Error {
587
621
  /**
588
622
  * Why Rouva itself refused the request before contacting the provider, when
589
623
  * the gateway marks it (header `X-Rouva-Refusal`): `"key_cap"` /
590
- * `"member_cap"` (a monthly spend cap would be exceeded), `"rate"` (rate
591
- * limit), `"unpriced"` (a capped key can't use a model with no known price),
624
+ * `"member_cap"` / `"customer_cap"` (a monthly spend cap — the key's, the
625
+ * workspace member's, or the `metadata.customer_id` customer's — would be
626
+ * exceeded), `"plan_limit"` (a 429: the account is on the Free plan and has
627
+ * used its requests for the month; `retryAfter` runs to the 1st of next
628
+ * month, UTC — or upgrade the plan), `"rate"` (rate limit), `"unpriced"` (a capped key can't use a model with no known price),
592
629
  * `"unbounded"` (a capped key can't send input, or use a model, whose cost
593
630
  * can't be bounded), `"deadline"` (a 504: the request ran out of its time
594
631
  * budget before the provider was called — nothing was sent, so it's safe to
@@ -598,7 +635,7 @@ declare class RouvaError extends Error {
598
635
  * Rouva's but deliberately unmarked: earlier turns were billed and their
599
636
  * tool handlers ran, so it must not be retried blindly.
600
637
  */
601
- readonly refusal?: string;
638
+ readonly refusal?: RouvaRefusal;
602
639
  /** Seconds to wait before retrying, from `Retry-After`, when present. */
603
640
  readonly retryAfter?: number;
604
641
  /** The gateway's error message (`error` field), when the body is JSON. */
@@ -615,4 +652,4 @@ declare class RouvaError extends Error {
615
652
  constructor(kind: 'Gateway' | 'Run' | 'Request' | 'Explain', status: number, headers: Headers, rawBody: string);
616
653
  }
617
654
 
618
- export { type AssistantToolCallMessage, type ChatCompletion, type ChatCompletionChoice, type ChatCompletionParams, type ChatCompletionUsage, type ChatMessage, type ContentBlockMessage, type ExplainOptions, type FunctionToolCall, type Message, type ReasoningEffort, type RequestOptions, type ResponseFormat, type ResponseMessage, Rouva, RouvaError, type RouvaExplainResult, type RouvaExplainedRefusal, type RouvaExplanation, type RouvaModel, type RouvaOptions, type RouvaProvider, type RouvaRequest, type RouvaRequestStatus, type RouvaResponseMeta, type RouvaRouteReason, type RouvaStream, type RunParams, type RunResult, type SystemTextBlock, type ToolResultMessage };
655
+ export { type AssistantToolCallMessage, type ChatCompletion, type ChatCompletionChoice, type ChatCompletionParams, type ChatCompletionUsage, type ChatMessage, type ContentBlockMessage, type ExplainOptions, type FunctionToolCall, type Message, type ReasoningEffort, type RequestOptions, type ResponseFormat, type ResponseMessage, Rouva, RouvaError, type RouvaExplainResult, type RouvaExplainedRefusal, type RouvaExplanation, type RouvaModel, type RouvaOptions, type RouvaProvider, type RouvaRefusal, type RouvaRequest, type RouvaRequestStatus, type RouvaResponseMeta, type RouvaRouteReason, type RouvaStream, type RunParams, type RunResult, type ServiceTier, type SystemTextBlock, type ToolResultMessage };
package/dist/index.d.ts CHANGED
@@ -50,9 +50,17 @@ interface ContentBlockMessage {
50
50
  * valid when `tools` is set on the request.
51
51
  */
52
52
  type ChatMessage = Message | AssistantToolCallMessage | ToolResultMessage | ContentBlockMessage;
53
+ /** `service_tier` values the gateway serves (see `ChatCompletionParams.service_tier`). */
54
+ type ServiceTier = 'auto' | 'default' | 'standard_only';
55
+ /**
56
+ * Why Rouva itself refused a request (`RouvaError.refusal`, header
57
+ * `X-Rouva-Refusal`). See `RouvaError.refusal` for each kind. Other strings
58
+ * are allowed so a newer gateway's kinds still type-check.
59
+ */
60
+ type RouvaRefusal = 'key_cap' | 'member_cap' | 'customer_cap' | 'plan_limit' | 'rate' | 'unpriced' | 'unbounded' | 'deadline' | (string & {});
53
61
  type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral' | 'moonshot' | 'xai' | 'zai' | 'alibaba' | 'minimax' | (string & {});
54
62
  /**
55
- * Supported models across all providers (the gateway's list as of SDK 0.5.1).
63
+ * Supported models across all providers (the gateway's list as of SDK 0.5.2).
56
64
  * Omit `model` entirely to let Rouva route to the cheapest capable model automatically.
57
65
  *
58
66
  * Other IDs are accepted by the type for forward compatibility. On
@@ -64,7 +72,7 @@ type RouvaProvider = 'anthropic' | 'openai' | 'gemini' | 'deepseek' | 'mistral'
64
72
  *
65
73
  * `'gpt-5.6'` is a deprecated alias the gateway maps to `'gpt-5.6-sol'`.
66
74
  */
67
- type RouvaModel = 'claude-fable-5-1' | 'claude-fable-5' | 'claude-opus-5-5' | 'claude-opus-5' | 'claude-opus-4-8' | 'claude-opus-4-7' | 'claude-opus-4-6' | 'claude-sonnet-5-5' | 'claude-sonnet-5' | 'claude-sonnet-4-6' | 'claude-haiku-5-5' | 'claude-haiku-4-5-20251001' | 'gpt-6-astra' | 'gpt-6.1-sol' | 'gpt-6.1-terra' | 'gpt-6-sol' | 'gpt-6-luna' | 'gpt-5.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'gpt-5.6' | 'gpt-5' | 'gpt-5.4-mini' | 'gpt-5-mini' | 'gpt-5-nano' | 'gpt-4.1' | 'gpt-4.1-mini' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-4-argon' | 'gemini-3.8-flash' | 'gemini-3.7-flash' | 'gemini-3.6-flash' | 'gemini-3.5-flash-lite' | 'gemini-2.5-pro' | 'gemini-2.5-flash' | 'deepseek-flash' | 'deepseek-flash-think' | 'deepseek-v4-pro' | 'mistral-large-latest' | 'mistral-small-latest' | 'kimi-k3.1-pro' | 'kimi-k3' | 'kimi-k2.6' | 'grok-4.7' | 'grok-4.6' | 'grok-4.5' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'glm-5.3' | 'glm-5.2' | 'glm-4.7-flash' | 'qwen3.8-omni-flash' | 'qwen3.8-flash' | 'qwen3.7-plus' | 'qwen-max' | 'qwen-plus' | 'qwen-flash' | 'MiniMax-M3.1-Flash' | 'MiniMax-M3' | (string & {});
75
+ type RouvaModel = 'claude-fable-5-1' | 'claude-fable-5' | 'claude-opus-5-5' | 'claude-opus-5' | 'claude-opus-4-8' | 'claude-opus-4-7' | 'claude-opus-4-6' | 'claude-sonnet-5-5' | 'claude-sonnet-5' | 'claude-sonnet-4-6' | 'claude-haiku-5-5' | 'claude-haiku-4-5-20251001' | 'gpt-6-astra' | 'gpt-6.1-sol' | 'gpt-6.1-terra' | 'gpt-6-sol' | 'gpt-6-luna' | 'gpt-5.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'gpt-5.6' | 'gpt-5' | 'gpt-5.4-mini' | 'gpt-5-mini' | 'gpt-5-nano' | 'gpt-4.1' | 'gpt-4.1-mini' | 'gpt-4o' | 'gpt-4o-mini' | 'gemini-4-argon' | 'gemini-3.8-flash' | 'gemini-3.7-flash' | 'gemini-3.6-flash' | 'gemini-3.5-flash-lite' | 'gemini-2.5-pro' | 'gemini-2.5-flash' | 'deepseek-flash' | 'deepseek-flash-think' | 'deepseek-v4-pro' | 'mistral-large-4' | 'mistral-large-latest' | 'mistral-small-latest' | 'kimi-k3.1-pro' | 'kimi-k3' | 'kimi-k2.6' | 'grok-4.7' | 'grok-4.6' | 'grok-4.5' | 'grok-4.3' | 'grok-4.20-0309-reasoning' | 'glm-5.3' | 'glm-5.2' | 'glm-4.7-flash' | 'qwen3.8-omni-flash' | 'qwen3.8-flash' | 'qwen3.7-plus' | 'qwen-max' | 'qwen-plus' | 'qwen-flash' | 'MiniMax-M3.1-Flash' | 'MiniMax-M3' | (string & {});
68
76
  /** Anthropic-style text block — the array form of the `system` param */
69
77
  interface SystemTextBlock {
70
78
  type: 'text';
@@ -104,6 +112,15 @@ interface ChatCompletionParams {
104
112
  * characters, values up to 256 characters, no null bytes.
105
113
  */
106
114
  metadata?: Record<string, string>;
115
+ /**
116
+ * Which provider service tier to use. Rouva bills standard prices, so only
117
+ * the standard tier is served: `'default'` (OpenAI's name) or
118
+ * `'standard_only'` (Anthropic's) asks for it — sent in the dialect of
119
+ * whichever provider the request reaches; `'auto'` (the same as leaving it
120
+ * out) uses your provider account's own setting. Any other tier (`flex`,
121
+ * `priority`, `scale`, …) is a 400.
122
+ */
123
+ service_tier?: ServiceTier;
107
124
  /**
108
125
  * Sampling temperature 0–1.
109
126
  * The gateway omits it for models that only accept their default: OpenAI
@@ -444,6 +461,23 @@ interface RunParams {
444
461
  * all turns reaches this threshold.
445
462
  */
446
463
  session_budget_usd?: number;
464
+ /**
465
+ * Your own labels for the run, stored with every turn's usage record and
466
+ * not sent to the provider (e.g. `{ customer_id: 'acme' }` for the
467
+ * dashboard's Customers page and per-customer spend caps): up to 10 string
468
+ * key-value pairs, keys up to 64 characters, values up to 256 characters,
469
+ * no null bytes.
470
+ */
471
+ metadata?: Record<string, string>;
472
+ /**
473
+ * Which provider service tier to use. Rouva bills standard prices, so only
474
+ * the standard tier is served: `'default'` (OpenAI's name) or
475
+ * `'standard_only'` (Anthropic's) asks for it — sent in the dialect of
476
+ * whichever provider the request reaches; `'auto'` (the same as leaving it
477
+ * out) uses your provider account's own setting. Any other tier (`flex`,
478
+ * `priority`, `scale`, …) is a 400.
479
+ */
480
+ service_tier?: ServiceTier;
447
481
  }
448
482
  interface RunResult {
449
483
  /** Final model response text after all tool loops complete. */
@@ -587,8 +621,11 @@ declare class RouvaError extends Error {
587
621
  /**
588
622
  * Why Rouva itself refused the request before contacting the provider, when
589
623
  * the gateway marks it (header `X-Rouva-Refusal`): `"key_cap"` /
590
- * `"member_cap"` (a monthly spend cap would be exceeded), `"rate"` (rate
591
- * limit), `"unpriced"` (a capped key can't use a model with no known price),
624
+ * `"member_cap"` / `"customer_cap"` (a monthly spend cap — the key's, the
625
+ * workspace member's, or the `metadata.customer_id` customer's — would be
626
+ * exceeded), `"plan_limit"` (a 429: the account is on the Free plan and has
627
+ * used its requests for the month; `retryAfter` runs to the 1st of next
628
+ * month, UTC — or upgrade the plan), `"rate"` (rate limit), `"unpriced"` (a capped key can't use a model with no known price),
592
629
  * `"unbounded"` (a capped key can't send input, or use a model, whose cost
593
630
  * can't be bounded), `"deadline"` (a 504: the request ran out of its time
594
631
  * budget before the provider was called — nothing was sent, so it's safe to
@@ -598,7 +635,7 @@ declare class RouvaError extends Error {
598
635
  * Rouva's but deliberately unmarked: earlier turns were billed and their
599
636
  * tool handlers ran, so it must not be retried blindly.
600
637
  */
601
- readonly refusal?: string;
638
+ readonly refusal?: RouvaRefusal;
602
639
  /** Seconds to wait before retrying, from `Retry-After`, when present. */
603
640
  readonly retryAfter?: number;
604
641
  /** The gateway's error message (`error` field), when the body is JSON. */
@@ -615,4 +652,4 @@ declare class RouvaError extends Error {
615
652
  constructor(kind: 'Gateway' | 'Run' | 'Request' | 'Explain', status: number, headers: Headers, rawBody: string);
616
653
  }
617
654
 
618
- export { type AssistantToolCallMessage, type ChatCompletion, type ChatCompletionChoice, type ChatCompletionParams, type ChatCompletionUsage, type ChatMessage, type ContentBlockMessage, type ExplainOptions, type FunctionToolCall, type Message, type ReasoningEffort, type RequestOptions, type ResponseFormat, type ResponseMessage, Rouva, RouvaError, type RouvaExplainResult, type RouvaExplainedRefusal, type RouvaExplanation, type RouvaModel, type RouvaOptions, type RouvaProvider, type RouvaRequest, type RouvaRequestStatus, type RouvaResponseMeta, type RouvaRouteReason, type RouvaStream, type RunParams, type RunResult, type SystemTextBlock, type ToolResultMessage };
655
+ export { type AssistantToolCallMessage, type ChatCompletion, type ChatCompletionChoice, type ChatCompletionParams, type ChatCompletionUsage, type ChatMessage, type ContentBlockMessage, type ExplainOptions, type FunctionToolCall, type Message, type ReasoningEffort, type RequestOptions, type ResponseFormat, type ResponseMessage, Rouva, RouvaError, type RouvaExplainResult, type RouvaExplainedRefusal, type RouvaExplanation, type RouvaModel, type RouvaOptions, type RouvaProvider, type RouvaRefusal, type RouvaRequest, type RouvaRequestStatus, type RouvaResponseMeta, type RouvaRouteReason, type RouvaStream, type RunParams, type RunResult, type ServiceTier, type SystemTextBlock, type ToolResultMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rouvanpm/rouva",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
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",