Polyweave

@polyweave/openrouter (1.0.9)

Published 2026-07-11 15:28:51 +00:00 by Dvorak

Installation

@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/
npm install @polyweave/openrouter@1.0.9
"@polyweave/openrouter": "1.0.9"

About this package

@polyweave/openrouter

OpenRouter adapter for Polyweave — unified access to 300+ AI models from multiple providers via OpenAI-compatible API. Supports text generation, vision/multimodal, image generation, SSE streaming, tool calling, automatic model routing, and lazy cost estimation with dynamic API pricing lookup.

Synopsis

import { createOpenRouterAdapter } from '@polyweave/openrouter';

const adapter = createOpenRouterAdapter({ apiKey: 'YOUR_API_KEY' });

adapter.source.pipe(someSink);
adapter.sink.write({ type: 'PARAM', content: { key: 'model', value: 'openai/gpt-4o' } });
adapter.sink.write({ type: 'TEXT', content: { text: 'Hello!' } });

Install

npm install @polyweave/openrouter

Why

OpenRouter provides a single API key gateway to 300+ models from Anthropic, OpenAI, Google, Meta, Mistral, and others. This adapter converts the Polyweave frame protocol into OpenRouter API calls, handling model routing, automatic fallbacks, cost estimation with live API pricing lookup, streaming via SSE, tool calling, and vision support — all through a single frame duplex. No per-provider adapter switching; just send frames and receive frames.

API

createOpenRouterAdapter(config)

Returns an IFrameDuplex stream adapter (object with source and sink).

Name Type Required Default Description
config.apiKey string No process.env.OPENROUTER_API_KEY OpenRouter API key
config.baseURL string No 'https://openrouter.ai/api' API base URL path (scheme not required)
config.siteUrl string No undefined Your site URL for openrouter.ai rankings
config.siteName string No undefined Your site name for openrouter.ai rankings
config.timeout number No 120000 Request timeout in ms
config.name string No null Adapter name used in topology reports

Adaptive authentication: The API key can be provided at construction time, via the OPENROUTER_API_KEY environment variable, or at runtime via a PARAM frame with key: 'apiKey'. If no key is provided at construction, the adapter buffers frames until a key arrives.

Return value: IFrameDuplex — an object with:

  • sink — receives Polyweave frames, translates to OpenRouter HTTP calls
  • source — emits Polyweave frames from OpenRouter responses
  • setReady(key) — inject API key at runtime (flushes buffered frames)
  • resetConversation() — clear accumulated message history
  • ready (getter) — whether the adapter has an API key
  • apiKey (getter) — current API key value

Frame Protocol (Input)

Frame Type Description
PARAM Sets a configuration parameter. frame.content.key / frame.content.value. See PARAM keys table.
TEXT User text prompt. Appended to conversation as role: 'user' if metadata.role is absent.
IMAGE Image for vision or generation. Routed based on model capabilities.
TOOL_RESULT Result of a tool call. Appended to conversation as role: 'tool'.
COST_CHECK Enter dry-run estimation mode. Buffers subsequent frames, runs cost estimation, emits a COST frame with estimate.
ESTIMATED_OUTPUT Metadata frame in cost-check mode — buffered but does not trigger estimate calculation.
START Pass-through (ignored).
END Pass-through (ignored).

PARAM keys:

Key Type Default Description
apiKey string env Sets API key (triggers ready state)
model string 'openai/gpt-4o-mini' OpenRouter model ID (e.g. 'openai/gpt-4o')
max_tokens number 1024 Max output tokens
temperature number undefined Sampling temperature
top_p number undefined Nucleus sampling
top_k number undefined Top-K sampling
frequency_penalty number undefined Frequency penalty
presence_penalty number undefined Presence penalty
repetition_penalty number undefined Repetition penalty
seed number undefined Random seed
stop string[] undefined Stop sequences
messages Array undefined Pre-seeded conversation messages
system string undefined System prompt
stream boolean true for chat, false for image Enable SSE streaming
tools Array undefined Tool definitions for function calling
tool_choice string undefined Tool selection mode
response_format Object undefined Response format (e.g. JSON mode)
logprobs boolean undefined Return log probabilities
top_logprobs number undefined Top logprobs to return
transforms string[] undefined OpenRouter transforms (e.g. ['middle-out'])
models string[] undefined Fallback model list for routing
route string undefined Routing strategy ('fallback')
provider Object undefined Provider preferences (e.g. { order: ['Anthropic'] })
task string undefined Task hint: 'chat' | 'image' | 'vision' | 'embedding'
input string|string[] undefined Embedding input text(s)
dimensions number undefined Embedding output dimensions
encoding_format string undefined Embedding encoding ('float' | 'base64')
prompt string undefined Image generation prompt
num_images number 1 Number of images to generate
receipt_mode string 'final' Receipt emission: 'none' | 'final' | 'progressive'
receipt_interval number 50 Tokens between progressive receipts

Frame Protocol (Output)

Frame Type Description
TEXT Streamed or complete text response (chunks in stream mode, full response otherwise)
TOOL_CALL Tool call requested by the model
IMAGE Generated image data (base64)
RECEIPT Final receipt with usage stats (tokens, cost)
COST Cost estimate (emitted after COST_CHECK input)
ERROR Error frame with mapped error code
END End-of-response marker
META Passthrough for unknown frame types

Error Conditions

Condition ErrorFrame.code When
API error (HTTP error response) Mapped by status code (PROVIDER_ERROR, RATE_LIMITED, QUOTA_EXCEEDED, etc.) OpenRouter returns non-2xx
Network error (ECONNREFUSED, ENOTFOUND) SERVICE_UNAVAILABLE Cannot reach OpenRouter
Network error (ETIMEDOUT, ESOCKETTIMEDOUT) QUEUE_TIMEOUT Request timeout
Network error (ECONNRESET) PROVIDER_ERROR Connection reset
Budget exceeded in COST_CHECK BUDGET_EXCEEDED Estimated cost > maxBudget in COST_CHECK options
Estimation error ESTIMATION_ERROR Cost estimation fails (e.g. price fetch error on unknown model)

Error frames include streamId for correlation, and END frames are emitted after errors with metadata: { error: true, errorCode }.

fetchPricing(modelId, callback [, options])

Fetches current pricing for a specific model from the OpenRouter models API. Uses request coalescing (multiple simultaneous calls share one HTTP request) and a 1-hour in-memory cache.

Name Type Required Default Description
modelId string Yes OpenRouter model ID (e.g. 'openai/gpt-4o')
callback function Yes Callback signature: (error, pricing) => void
options.skipCache boolean No false Force fresh API fetch
options.timeout number No 10000 Request timeout in ms

pricing object (on success): { mtoksInput, mtoksOutput, perImageInput, perImageOutput, perAudioMinute, perRequest, mtoksReasoning, _source, _inputModalities, _outputModalities, _modelName, _contextLength, _fetchedAt }

Error paths: API error → fallback pricing if model in fallback table, otherwise passes error to callback. Model not found → fallback if in table, otherwise Error with code 'MODEL_NOT_FOUND'.

getCachedPricing(modelId)

Synchronous lookup of cached pricing for a model. Returns pricing object or null if not cached or TTL expired (1 hour).

clearPricingCache()

Clears all cached pricing and the full models cache. For testing and forced refresh.

getModelCapabilities(modelId, callback)

Returns { inputModalities, outputModalities, modelName, contextLength } for a model. Checks cache first, falls back to API fetch.

supportsModality(modelId, modality, direction, callback)

Name Type Required Description
modelId string Yes Model ID
modality string Yes 'text' | 'image' | 'audio' | 'video'
direction string Yes 'input' | 'output'
callback function Yes (error, supports: boolean) => void

On lookup error, assumes text-only support (returns true for 'text').

calculateCostFromPricing(pricing, params)

Calculates total cost from pricing config. Returns { totalCost, currency: 'USD', inputTokens, inputCost, outputTokens, outputCost, imageInputCount, imageInputCost, imageOutputCount, imageOutputCost, audioMinutes, audioCost, requestCost, _pricingSource }.

fetchCredits(apiKey, callback)

Fetches current credits balance from OpenRouter.

Name Type Required Description
apiKey string Yes OpenRouter API key
callback function Yes (error, credits) => void

credits object (on success): { totalCredits: number, totalUsage: number, remaining: number, raw: object }

Throws/errors if apiKey is falsy (emitted via callback as Error('API key required')), on HTTP error (≥400), on JSON parse failure, or on network error.

checkSufficientCredits(apiKey, estimatedCost, callback)

Name Type Required Description
apiKey string Yes OpenRouter API key
estimatedCost number Yes Estimated cost in USD
callback function Yes (error, result) => void

result object: { sufficient: boolean, remaining: number, estimated: number, shortfall: number, totalCredits, totalUsage, raw }

Wraps fetchCredits — propagates its error conditions.

Tests

npm test

Tests cover: adapter creation and frame routing, cost estimation with pricing fetch, PARAM accumulation, COST_CHECK dry-run mode (including budget exceeded detection), error mapping across HTTP status codes and network errors, rate limit header extraction, credits fetching and balance checking, SSE streaming, and js-rigor property tests for pricing estimatation monotonicity.

Requirements

  • Node.js >= 22.0.0
  • ESM ("type": "module")
  • @polyweave/core (peer)
  • @polyweave/errors (peer)
  • @polyweave/costs (peer)

Dependencies

Development Dependencies

ID Version
@rigor/core *

Peer Dependencies

ID Version
@polyweave/core *
@polyweave/costs *
@polyweave/errors *

Keywords

polyweave openrouter llm ai adapter
Details
npm
2026-07-11 15:28:51 +00:00
8
John Dvorak
SEE LICENSE IN LICENSE
latest
22 KiB
Assets (1)
Versions (5) View all
1.0.9 2026-07-11
1.0.6 2026-07-11
1.0.5 2026-07-10
1.0.4 2026-07-10
1.0.3 2026-07-10