@polyweave/xai (1.0.8)
Installation
@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/npm install @polyweave/xai@1.0.8"@polyweave/xai": "1.0.8"About this package
@polyweave/xai
xAI (Grok) adapter for Polyweave — chat, image generation, 1M token context window, dynamic pricing.
Synopsis
import { createXAIAdapter } from '@polyweave/xai';
import { createTextFrame, createImageFrame, createParamFrame, createFrameSink } from '@polyweave/core';
var adapter = createXAIAdapter({ apiKey: process.env.XAI_API_KEY, model: 'grok-4.3' });
adapter.source.pipe(createFrameSink(function(frame) {
if (frame.type === 'TEXT') console.log(frame.content.text);
if (frame.type === 'IMAGE') console.log('Image:', frame.content.url);
if (frame.type === 'RECEIPT') console.log('Cost:', frame.content.usage.totalCost);
}));
adapter.sink.write(createTextFrame('What is the meaning of life?'));
// Image generation via task PARAM
adapter.sink.write(createParamFrame('task', 'generation'));
adapter.sink.write(createParamFrame('image_model', 'grok-imagine-image'));
adapter.sink.write(createTextFrame('A futuristic city at sunset'));
Install
npm install @polyweave/xai
Why
Grok models offer a 1M token context window, native image generation (grok-imagine-image), reasoning capabilities (grok-4.20-reasoning), multi-agent support (grok-4.20-multi-agent), and a models API endpoint that publishes live pricing data. The adapter unifies Grok's OpenAI-compatible chat API and image generation API under the standard Polyweave frame protocol, enabling budget control, cost estimation, dynamic pricing refresh, and topology scanning alongside other providers without special-casing the integration layer.
API
createXAIAdapter(config)
Creates a frame duplex adapter for xAI/Grok. Returns an IFrameDuplex with source, sink, setReady, and name.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
config.apiKey |
string |
No | process.env.XAI_API_KEY |
xAI API bearer token |
config.baseURL |
string |
No | https://api.x.ai/v1 |
API base URL override |
config.model |
string |
No | grok-4.3 |
Default model for TEXT frames (can be overridden via PARAM) |
config.budget |
number |
No | 0 |
Hard cap in USD. When cumulative spend reaches this, incoming TEXT/IMAGE/AUDIO frames are rejected with ERROR(BUDGET_EXCEEDED) + END |
config.name |
string |
No | null |
Logical name for the node, exposed on the duplex for topology identification |
config.timeout |
number |
No | 120000 |
HTTP request timeout in milliseconds |
Return value: IFrameDuplex — a bidirectional frame stream.
Properties on the returned duplex:
.source— readable frame source (receives output frames from the adapter).sink— writable frame sink (send input frames to the adapter).setReady(key)— provide the API key after construction; flushes buffered frames.name— logical name (config.name)
Frame Protocol
Frames flowing into the adapter sink trigger provider API calls. Frames emitted from the adapter source are responses.
| Input frame | Action |
|---|---|
TEXT |
Appends to conversation, sends POST /v1/chat/completions (streaming) |
IMAGE |
Vision mode (sent as image_url in chat) unless task PARAM is generation/generate, which routes to POST /v1/images/generations |
AUDIO |
Emits ERROR('Grok voice API not yet implemented in adapter') — voice is unsupported |
PARAM |
Accumulates into adapter config. key=apiKey triggers setReady; key=budget sets the budget cap |
COST_CHECK |
Enters dry-run mode. Buffers subsequent content frames, calls costEstimator.estimate(), emits a COST frame with bounds/accuracy, then END. If maxBudget is exceeded, emits ERROR(BUDGET_EXCEEDED) + END instead |
START |
Ignored (passthrough placeholder) |
END |
Ignored (passthrough placeholder) |
TOPOLOGY_SCAN |
Emits TOPOLOGY_REPORT describing the adapter node (receives/generates/types/state/path), then forwards the scan frame |
| Output frame | Trigger |
|---|---|
TEXT |
Chat content deltas (streaming) or full completion body (batch) |
IMAGE |
One per generated image from POST /v1/images/generations |
TOOL_CALL |
Tool call chunks from stream or complete calls from batch response |
RECEIPT |
Cost receipt. Progressive receipts every 50 output tokens during streaming; final receipt at end from usage data |
COST |
Estimated cost from COST_CHECK dry-run, containing bounds, accuracy, estimateSource, forwardEstimate, inputBounds, maxOutputTokens |
ERROR |
Errors (see Error Conditions below) followed by END |
END |
Always emitted after each request completes (including errors) |
PARAM Keys
All PARAM keys accumulate into the adapter's internal params object and are used in API requests.
| Key | Type | Default | Description |
|---|---|---|---|
model |
string |
grok-4.3 |
Chat model ID |
image_model |
string |
grok-imagine-image |
Image generation model ID |
max_tokens |
number |
1024 |
Max completion tokens |
temperature |
number |
undefined | Sampling temperature |
stream |
boolean |
true |
Enable SSE streaming for chat |
system |
string |
undefined | System prompt (sent as messages[0] with role=system) |
tools |
object[] |
undefined | Tool definitions for function calling |
tool_choice |
string |
undefined | Tool choice constraint |
size |
string |
1024x1024 |
Image generation size |
n |
number |
1 |
Number of images to generate |
prompt |
string |
undefined | Fallback prompt for image generation (overridden by TEXT frame content) |
task |
string |
undefined | Routing hint: generation/generate → image gen; otherwise vision mode |
budget |
number |
0 |
Set or override budget cap at runtime |
apiKey |
string |
undefined | Set or override API key at runtime (triggers setReady) |
Error Conditions
Every error emits an ERROR frame immediately followed by an END frame with metadata.error: true.
| Condition | Error Message | Error Code | When |
|---|---|---|---|
| Budget exhausted | 'Budget exceeded' |
BUDGET_EXCEEDED |
budgetTotal > 0 && totalSpent >= budgetTotal — rejected at frame entry before any API call |
| COST_CHECK estimate exceeds maxBudget | 'Estimated cost exceeds budget' |
BUDGET_EXCEEDED |
Dry-run estimate > costCheckOptions.maxBudget |
| COST_CHECK budget exceeded in estimator | 'Est cost exceeds budget' |
BUDGET_EXCEEDED |
costEstimator.checkBudget() returns withinBudget: false |
| IMAGE frame missing url/data | 'IMAGE frame requires url, data, or b64_json' |
ADAPTER_ERROR |
IMAGE with no url, data, or b64_json content |
| AUDIO frame received | 'Grok voice API not yet implemented in adapter — use xAI HTTP endpoints directly' |
ADAPTER_ERROR |
AUDIO/voice is unimplemented |
| HTTP 4xx/5xx from API | API error message (from response.error.message) or 'HTTP ' + statusCode |
ADAPTER_ERROR |
Response statusCode >= 400 from either chat or image endpoint |
| Network error | err.message (e.g. ECONNREFUSED) |
ADAPTER_ERROR |
req.on('error', ...) fires |
| Request timeout | 'Request timeout' |
ADAPTER_ERROR |
req.on('timeout', ...) fires |
| JSON parse failure | 'Parse: ' + err.message |
ADAPTER_ERROR |
API response body is not valid JSON |
| Stream error | 'Stream error' or API error from SSE chunk |
ADAPTER_ERROR |
Streaming SSE event.error is present |
| Sink paused or ended | None (frame dropped) | — | duplex.sink.paused or duplex.sink.ended — frame is silently ignored |
| Missing API key | Frames buffered | — | Frames enqueue in frameBuffer until setReady(key) is called |
Tests
npm test
Runs rigor.test.js (property-based cost verification: pricing table oracle, non-negative costs, zero-cost at zero tokens) and smoke.test.js (construction with defaults/config, setReady presence, TEXT frame buffering when not ready).
Requirements
- Node.js 22 or later (as per
enginesfield inpackage.json) - ESM only (
"type": "module") - Peer dependencies:
@polyweave/core,@polyweave/costs
Dependencies
Development Dependencies
| ID | Version |
|---|---|
| @polyweave/core | * |
| @polyweave/costs | * |
| @rigor/core | * |
Peer Dependencies
| ID | Version |
|---|---|
| @polyweave/core | * |
| @polyweave/costs | * |
| @polyweave/errors | * |