Published package: @surrealdb/spectron, a typed REST client for the Spectron end-user API. It uses platform fetch, ships no runtime dependencies, and aligns with Spectron’s OpenAPI specification.
npm: The client is published under the
@surrealdbscope (@surrealdb/spectron), so no third party can squat the namespace. The bare namespectronon npm is unrelated.
Installation
npm install @surrealdb/spectron
# or: pnpm / yarn / bun add @surrealdb/spectronNode.js 18+ or a modern bundler for browser use.
Client construction
import { Spectron } from "@surrealdb/spectron";
const client = new Spectron({
endpoint: process.env.SPECTRON_ENDPOINT!,
context: "acme-prod",
apiKey: process.env.SPECTRON_API_KEY!,
});The client is async-only (all methods return Promises). It is pinned to one context and calls /api/v1/{context}/….
| Option | Default | Description |
|---|---|---|
context | required | Context id. |
endpoint | required | Spectron host URL. |
apiKey | required | Bearer token. |
timeout | 30000 | Milliseconds per request. |
maxRetries | 3 | Retries for GETs and idempotent writes. |
Scope
On the wire, scope is a ScopeSet: an ordered array of slash-path strings (for example ["org/acme/user/alice"]). Register paths before first use; see Contexts and scope.
The TypeScript client accepts a path string or an array of paths, and both serialise to the wire ScopeSet.
Remember and recall
await client.remember("Alice was promoted to CTO.", {
infer: "full",
scope: ["org/acme/user/alice"],
});
await client.rememberMany([
{ role: "user", content: "I was promoted to CTO." },
{ role: "assistant", content: "Congratulations!" },
], { scope: ["org/acme/user/alice"] });
const hits = await client.recall("What is Alice's role?", { k: 10 });
const block = await client.context("What is Alice's role?", { k: 10 });remember and rememberMany attach an Idempotency-Key header for safe retries within a 30-second window.
Documents and chat
const doc = await client.documents.upload({
file: documentFile,
title: "Returns policy",
scope: ["org/acme/team/eng"],
labels: ["team=eng"],
});
await client.chat("Summarise what you know about Alice", {
scope: ["user/alice"],
});
const stream = await client.chat("Tell me a story", { stream: true });
for await (const chunk of stream) {
process.stdout.write(chunk.delta);
}Other verbs and namespaces
Top-level: forget, consolidate, reflect, elaborate, state, profile, inspect, audit, fsck, health.
Namespaces: client.documents (including keywords), client.sessions, client.entities, client.scopes, client.principals, client.traces, client.lifecycle.
→ Full tables: JavaScript SDK reference
Errors and retries
The client throws typed errors so you can branch on failure precisely.
import {
AuthError,
ConnectionError,
NotFoundError,
RateLimitError,
ScopeError,
ServerError,
SpectronError,
ValidationError,
} from "@surrealdb/spectron";
try {
const hits = await client.recall("what is my name?", { scope: ["user/alice"] });
} catch (err) {
if (err instanceof AuthError) { /* 401 */ }
else if (err instanceof ScopeError) { /* 403 */ }
else if (err instanceof NotFoundError) { /* 404 */ }
else if (err instanceof ValidationError) { /* 400 / 422 */ }
else if (err instanceof RateLimitError) { console.log(err.retryAfter); }
else if (err instanceof ServerError) { /* 5xx after retries */ }
else if (err instanceof ConnectionError) { /* network / timeout */ }
else if (err instanceof SpectronError) { /* other */ }
}| Exception | HTTP | When it occurs |
|---|---|---|
SpectronError | n/a | Base class |
AuthError | 401 | Invalid or missing API key |
ScopeError | 403 | Scope or principal denial |
NotFoundError | 404 | Resource not found |
ValidationError | 400 / 422 | Malformed request |
RateLimitError | 429 | Rate or token budget exceeded (retryAfter when provided) |
ServerError | 5xx | Server error, retried for idempotent calls |
ConnectionError | n/a | Network failure or timeout |
GET requests and idempotent writes (remember, rememberMany) retry automatically on connection errors and 5xx responses: up to maxRetries attempts (default 3) with 250 ms, 500 ms, 1000 ms backoff. Other writes and 4xx responses are not retried. Tune or disable on the constructor:
const client = new Spectron({ ..., maxRetries: 0, timeout: 10000 });The default timeout is 30,000 ms; streaming chat disables the read timeout while tokens arrive. On a 429, read RateLimitError.retryAfter and back off before retrying manually. All errors follow RFC 7807 Problem Details.
Vercel AI SDK adapter
npm install @surrealdb/vercel-ai