API reference

JavaScript API reference for libfx@0.0.13. The TypeScript interfaces below describe the API; the package does not export them as types. Start with Quick start, or see WebAssembly for browser setup.

API index

Agent

Function or methodDescriptionReturns
createFxAgent(options)Create one conversation.Promise<Agent>
agent.prompt(input, options?)Run a prompt and stream events.Turn
agent.checkpoint()Export conversation history and usage.Promise<Uint8Array>
agent.close()Stop the agent and release its runtime.Promise<void>

Turn

Function or methodDescriptionReturns
turn.steer(input)Send follow-up instructions to a running turn.Promise<void>
turn.cancel()Cancel the active turn.void

TerminalRuntime

Function or methodDescriptionReturns
createFxTerminal(options)Start the interactive terminal.Promise<TerminalRuntime>
terminal.write(data)Send terminal input.void
terminal.resize()Notify fx of a size change.void
terminal.abort()Stop the terminal and release listeners.void

McpAdapter

Function or methodDescriptionReturns
createMcpAdapter(client, options?)Convert an MCP client's tools and context.Promise<McpAdapter>
mcp.close()Close the adapter and its client.Promise<void>

SkillsAdapter

Function or methodDescriptionReturns
createSkillsAdapter(records)Convert loaded skill records.SkillsAdapter
loadSkillFile(path, options?)Read one skill file in Node or Bun.Promise<SkillRecord>

Helpers

Function or methodDescriptionReturns
listModels(options)List available language-model IDs.Promise<string[]>
getBackendInfo(options?)Check backend availability in Node.Promise<BackendInfo>
supportsJspi()Check WebAssembly JSPI support.boolean
xtermAdapter(term)Connect an xterm.js instance.TerminalAdapter
encodeXtermKeyEvent(event)Encode special terminal keys.string | null

Imports

import {
  createFxAgent,
  createFxTerminal,
  listModels,
  supportsJspi,
  xtermAdapter,
  encodeXtermKeyEvent,
} from 'libfx'

import { getBackendInfo } from 'libfx/node'
import { createMcpAdapter } from 'libfx/mcp'
import { createSkillsAdapter } from 'libfx/skills'
import { loadSkillFile } from 'libfx/skills/node'

libfx selects the Node or browser entry point for your environment. libfx/node uses a native addon when available; libfx/browser always uses WebAssembly. libfx/wasm exposes the WebAssembly host layer directly and requires an explicit wasm asset. getBackendInfo() is Node-only. CommonJS applications can use require('libfx') or require('libfx/node').

The main entry points also export fxSdkApiVersion, currently 2. The Node and browser wrappers export libfxApiVersion, also 2. These identify API revisions, not the npm package version.

Interfaces

InterfaceDescription
AgentOptionsCredentials, model, instructions, tools, and checkpoint input.
AgentThe conversation's methods.
PromptInput and PromptOptionsText, images, resources, and cancellation.
TurnStream events, steer, cancel, and await a result.
TurnEventText, reasoning, tool, and steering events.
TurnResult and UsageStop reason and token counts.
HostToolA tool's schema and execution callback.
DiagnosticEventRuntime diagnostics sent to onEvent.
BackendInfoSelected backend and attempted alternatives.
TerminalOptionsTerminal adapter, configuration, and stores.
TerminalRuntimeTerminal readiness, exit, and control methods.
TerminalAdapterInput, output, and geometry supplied by your UI.
McpAdapterAdapted tools, instructions, and cleanup.
SkillRecord and SkillsAdapterLoaded skill text, resources, and tools.

Shared notation used below:

type MaybePromise<T> = T | Promise<T>
type Bytes = ArrayBuffer | ArrayBufferView
type Fetch = typeof globalThis.fetch
type Backend = 'auto' | 'native' | 'wasm'
type WasmSource = string | Response | Bytes | WebAssembly.Module

For wasm, the browser accepts a URL string, response, bytes, or compiled module. Node also accepts a filesystem path or a URL object. A promise resolving to a response, bytes, or compiled module is accepted. The package wrappers supply their own assets when you omit wasm.

Agent

interface Agent {
  prompt(input: PromptInput, options?: PromptOptions): Turn
  checkpoint(): Promise<Uint8Array>
  close(): Promise<void>
}

An agent has no createSession(), setModel(), or history property. To change creation options, save a checkpoint and restore it into a new agent with those options.

createFxAgent

createFxAgent(options: AgentOptions): Promise<Agent>

Creates one in-memory conversation. On Node, the default backend tries the native addon and falls back to WebAssembly. Browser agents require JSPI. The promise resolves after initialization and any checkpoint restore finish. A named model.effort, model.fast: true, or model.ultrafast: true also checks the model catalog; unsupported settings reject creation.

AgentOptions

interface ModelOptions {
  id: string
  effort?: string
  fast?: boolean
  ultrafast?: boolean
}

interface AgentOptions {
  apiKey: string
  model?: string | ModelOptions
  effort?: string
  fast?: boolean
  ultrafast?: boolean
  instructions?: string | string[]
  tools?: (HostTool | ProviderTool)[]
  checkpoint?: Bytes
  fetch?: Fetch
  onEvent?: (event: DiagnosticEvent) => void
  resizeImage?: (
    image: { bytes: Uint8Array; mimeType: string },
  ) => MaybePromise<{ bytes: Bytes; mimeType: string }>
  wasm?: WasmSource | URL | Promise<Response | Bytes | WebAssembly.Module>
  backend?: Backend
  nativeAddon?: string | URL | object | false
}
OptionDescriptionRequiredDefault
apiKeyAI Gateway credential. Non-empty string, at most 64 KiB of UTF-8.YesNone
modelModel ID or an object containing id, effort, fast, and ultrafast. The ID is at most 1 KiB of UTF-8.Nofx's built-in model
model.effortReasoning level supported by the selected model; 'default' uses the model default.NoModel default
model.fastUse the fast lane when supported by the selected model.Nofalse
model.ultrafastRequest the higher-priced OpenAI Ultrafast tier for a catalog-verified eligible Gateway model. Strict boolean; creation rejects unsupported models.Nofalse
instructionsComplete system instructions. An array joins non-empty entries with blank lines. At most 64 KiB of UTF-8 after joining.NoNo system message
toolsUp to 64 host tools or provider tools. No CLI tools are enabled automatically.No[]
checkpointOpaque bytes from agent.checkpoint(). The input is copied.NoNew conversation
fetchHost-controlled HTTP transport. Preserve the supplied AbortSignal.NoglobalThis.fetch
onEventSynchronous diagnostic callback. Model output is on the Turn stream instead.NoNone
resizeImagePrepare prompt image bytes before sending. Return bytes and their MIME type. Does not run on tool images or reference-only blocks.NoSend eligible images unchanged
wasmWebAssembly asset to load when using that backend.No for package wrappersPackaged fx-core.wasm
backendNode-only backend selection. 'native' fails instead of falling back; 'wasm' requires JSPI.No'auto'
nativeAddonNode-only custom addon module, path, or URL. false disables native loading.NoPackaged platform addon

Do not pass env: the agent rejects it. Terminal settings, session stores, and CLI permission modes are not agent configuration. Your application supplies tools, authorizes their actions, and stores checkpoints.

String model IDs remain supported. Top-level effort and fast are deprecated and work only with a string model or no model; they cannot be mixed with a model object. Top-level ultrafast is also accepted with a string or omitted model, but not alongside a model object.

Invalid options reject creation. Missing JSPI, asset-loading failures, incompatible addons, and invalid checkpoints can also reject the promise. See Errors and Advanced testing.

agent.prompt

agent.prompt(input: PromptInput, options?: PromptOptions): Turn

Starts a turn in the conversation and returns a Turn immediately, not a promise. Read events with for await, then await turn.result.

import { createFxAgent } from 'libfx'

const agent = await createFxAgent({ apiKey: process.env.AI_GATEWAY_API_KEY })
try {
  const turn = agent.prompt('Explain how a database index speeds up a query.')
  for await (const event of turn) {
    if (event.type === 'text_delta') process.stdout.write(event.delta)
  }
  const result = await turn.result
  console.log(result.stopReason, result.usage)
} finally {
  await agent.close()
}

PromptInput and PromptOptions

type PromptInput = string | PromptBlock[]
type PromptBlock =
  | { type: 'text'; text: string }
  | { type: 'image'; data: string | Bytes; mimeType: ImageMimeType; sourceRef?: string }
  | { type: 'image'; data: Blob | File; mimeType?: ImageMimeType; sourceRef?: string }
  | { type: 'image'; mimeType: ImageMimeType; sourceRef: string }
  | { type: 'resource'; resource: { uri: string; text?: string } }

type ImageMimeType = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp'

interface PromptOptions {
  signal?: AbortSignal
}

A string is equivalent to one text block. For a resource, pass its text explicitly; the URI identifies the resource and does not grant file access. A flat resource block with uri and text alongside type is also accepted. Audio prompt blocks are not supported.

For images, pass raw bytes or canonical base64 with an explicit mimeType, or a Blob or File with a supported, non-empty type. Each prompt accepts up to 8 images, with at most 3.75 MiB of raw data per image and 6 MiB total. Text, encoded images, and metadata must fit within an 8 MiB frame. The bytes must match the claimed type.

sourceRef identifies a host-owned original; it does not grant access or fetch the image. It must be non-empty, at most 512 UTF-8 bytes, and contain no ASCII control characters. Referenced images that exceed the limits can be sent as references without data. See Images for preprocessing and recovery.

Raw bytes are copied before prompt() returns. Invalid Base64 throws synchronously. Blob reads and resizeImage preparation happen after prompt() returns; failures reject turn.result, and cancellation or close prevents dispatch.

import { createFxAgent } from 'libfx'

const controller = new AbortController()
const agent = await createFxAgent({ apiKey: process.env.AI_GATEWAY_API_KEY })
try {
  const turn = agent.prompt([
    { type: 'text', text: 'Explain this table definition.' },
    {
      type: 'resource',
      resource: {
        uri: 'file:///workspace/schema.sql',
        text: 'CREATE TABLE users (id INTEGER PRIMARY KEY);',
      },
    },
  ], { signal: controller.signal })
  for await (const event of turn) {
    if (event.type === 'text_delta') process.stdout.write(event.delta)
  }
  await turn.result
} finally {
  await agent.close()
}

prompt() throws synchronously for malformed input, a closed agent, or another active prompt. An already-aborted signal returns a cancelled turn without making a model request or changing history. Network and runtime failures during execution reject the stream or result promise.

agent.checkpoint

agent.checkpoint(): Promise<Uint8Array>

Returns opaque, versioned conversation bytes while the agent is idle. It rejects while a prompt is active or after the agent closes. Checkpoints are limited to 4 MiB. Store the bytes without editing them and restore them only through createFxAgent({ checkpoint, ...options }).

A checkpoint contains history and usage, not credentials, model selection, instructions, tools, MCP clients, or skills. Resupply those options on restoration.

Version 2 checkpoints retain image bytes and source references within the 4 MiB limit. libfx 0.0.13 restores existing checkpoints, but older versions cannot restore new ones. Reference-only images remain host-owned; resupply the tools and storage needed to resolve them.

const checkpoint = await agent.checkpoint()
await agent.close()
const restored = await createFxAgent({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  checkpoint,
})
// Continue with restored.prompt(...), then await restored.close().

agent.close

agent.close(): Promise<void>

Cancels an active turn, releases blocked output, and waits for the runtime to exit. Repeated calls are safe. The agent cannot be prompted or checkpointed afterward. Closing an agent does not close host-owned database connections or MCP clients.

Turn

interface Turn extends AsyncIterable<TurnEvent> {
  result: Promise<TurnResult>
  steer(input: string | { type: 'text'; text: string }[]): Promise<void>
  cancel(): void
}

A turn permits one event consumer. Read the stream even when you only need the result:

const turn = agent.prompt('Summarize the discussion.')
for await (const _ of turn) {}
const result = await turn.result

A slow reader pauses output production instead of growing an unlimited queue. Awaiting only turn.result can stall while unread events wait to be consumed. Breaking out of the iterator cancels the turn. Do not start another prompt until the current one settles.

turn.steer

turn.steer(input: string | { type: 'text'; text: string }[]): Promise<void>

Sends follow-up instructions to a running turn. The agent applies them at the next model boundary, preserving the in-flight response and completed tool work. A user_message event marks when the instructions enter the conversation.

await turn.steer('Keep the public API backward compatible.')

Steering accepts text only and rejects after the turn finishes. Each message can contain up to 64 KiB of UTF-8 text; pending messages are limited to 64 messages and 1 MiB total.

turn.cancel

turn.cancel(): void

Requests cancellation without waiting for completion. It aborts model requests and the signals passed to host tools. Continue draining the stream and await turn.result to observe completion. Calling cancel() again, or after the turn finishes, has no effect.

const controller = new AbortController()
const turn = agent.prompt('Review the schema.', { signal: controller.signal })
controller.abort() // Equivalent to requesting cancellation with turn.cancel().
for await (const _ of turn) {}
console.log((await turn.result).stopReason)

Cancellation stops waiting for tool callbacks; it cannot stop JavaScript work that ignores its signal. Late tool results and rejections are ignored.

TurnEvent

type TurnEvent =
  | { type: 'text_delta'; delta: string }
  | { type: 'reasoning_delta'; delta: string }
  | { type: 'user_message'; text: string }
  | {
      type: 'tool_start'
      id: string
      name: string
      input?: unknown
      inputPreview?: string
      inputTruncated?: boolean
    }
  | {
      type: 'tool_end'
      id: string
      name: string
      content?: string
      isError: boolean
    }
EventDescriptionFields
text_deltaAppend this text to the answer.delta
reasoning_deltaReasoning text when the provider supplies it.delta
user_messageSteering instructions entered the conversation.text
tool_startA tool call started. Large inputs use a preview.id, name, input?, inputPreview?, inputTruncated?
tool_endA tool call completed or failed. Match it to its start by id.id, name, content?, isError

tool_end.content is the available text result, not the original JavaScript return value. There is no separate final-result event; use turn.result after reading the stream.

TurnResult and Usage

interface TurnResult {
  stopReason: StopReason
  usage: Usage
}

type StopReason =
  | 'end_turn'
  | 'max_output_tokens'
  | 'max_model_turns'
  | 'refused'
  | 'cancelled'

interface Usage {
  inputTokens?: number
  outputTokens?: number
  cacheReadTokens?: number
  cacheWriteTokens?: number
  reasoningTokens?: number
}
Stop reasonDescription
end_turnThe turn ended normally.
max_output_tokensThe response reached its output-token limit.
max_model_turnsThe turn reached its model-step limit.
refusedThe model refused the request.
cancelledThe turn was cancelled.

usage is always an object. Its fields are optional: missing counts are omitted, not replaced with zero. A prompt cancelled before it starts returns { stopReason: 'cancelled', usage: {} }. Transport or decoding failures reject rather than returning a successful result with missing output.

HostTool

type JsonValue =
  | string | number | boolean | null
  | JsonValue[]
  | { [key: string]: JsonValue }

interface HostTool {
  name: string
  description: string
  inputSchema: Record<string, JsonValue>
  execute(
    input: unknown,
    context: { signal: AbortSignal },
  ): MaybePromise<JsonValue | undefined | RichToolResult>
}

interface RichToolResult {
  type: 'libfx.tool-result'
  text: string
  images: Array<{ type: 'image'; mimeType: string; data?: string; sourceRef?: string }>
  isError?: boolean
}

Tool names must be unique, contain 1–64 letters, digits, underscores, or hyphens, and have a JSON-serializable object schema. Your callback must validate and authorize actions before executing them.

Strings return as text. Other ordinary results are JSON-encoded; undefined becomes "null". A thrown error becomes a failed tool result with its message. Use RichToolResult for image results: data is base64, or omit it and supply a host-owned sourceRef. Tool images do not accept raw bytes or Blobs and do not run resizeImage. PNG, JPEG, GIF, and WebP are supported for image-capable models. Other models receive an omission notice. Ordinary objects are not interpreted as images.

Up to eight images are allowed, each with at most 5 MiB of base64 data and an 8 MiB serialized rich-result limit. The host-tool response frame has an 8 MiB limit. Honor context.signal to stop cancelled work.

ProviderTool

interface ProviderTool {
  name: 'web_search'
  providerExecuted: true
}

Add { name: 'web_search', providerExecuted: true } to tools for web search through AI Gateway. The SDK supplies its schema; omit execute. Calls produce the same tool_start and tool_end events as host tools, and results stay in conversation history and checkpoints.

web_search is the only supported provider tool in libfx 0.0.13.

TerminalRuntime

interface TerminalRuntime {
  interactive: Promise<void>
  exited: Promise<number>
  write(data: string | Uint8Array): void
  resize(): void
  abort(): void
}
MemberDescription
interactiveResolves after the terminal reaches its input loop and optional adapter drain() finishes. Rejects if fx exits before reaching that loop or draining fails.
exitedResolves with the exit code. An explicit abort uses 130.
write(data)Sends text or bytes as input. Ctrl+C string input also cancels host effects; it does not immediately destroy the runtime.
resize()Wakes fx to read the adapter's current cols and rows. It takes no dimensions.
abort()Stops the runtime and releases data, key, and resize subscriptions. Returns immediately; await exited for the exit code.

createFxTerminal

createFxTerminal(options: TerminalOptions): Promise<TerminalRuntime>

Starts the interactive terminal, not a headless Agent. The packaged terminal uses WebAssembly on both Node and browsers and requires JSPI. Await runtime.interactive before sending input.

TerminalOptions

interface TerminalOptions {
  terminal: TerminalAdapter
  env?: Record<string, string>
  args?: string[]
  fetch?: Fetch
  onEvent?: (event: DiagnosticEvent) => void
  interruptKey?: string
  wasm?: WasmSource | URL | Promise<Response | Bytes | WebAssembly.Module>
  backend?: Backend
  nativeAddon?: string | URL | object | false
  configStore?: ConfigStore
  promptHistoryStore?: PromptHistoryStore
  sessionStore?: SessionStore
  oauthSessionStore?: OAuthSessionStore
  openUrl?: (url: string) => MaybePromise<boolean>
  workspace?: WorkspaceAdapter
}
OptionDescriptionDefault
terminalUI adapter for input, output, and size.Required
envTerminal environment, including AI_GATEWAY_API_KEY when supplying a credential directly.{}
argsTerminal CLI arguments, such as ['--resume', 'last'].[]
fetchHost HTTP transport.globalThis.fetch
onEventDiagnostic callback.None
interruptKeyString input containing this key also cancels active host effects. '' disables this detection.'\x03' (Ctrl+C)
wasmTerminal WebAssembly asset; required with the direct libfx/wasm entry.Packaged fx-term.wasm
backendNode-only selection. The package has no native terminal, so 'native' fails.'auto'
nativeAddonNode-only override for a custom addon.Packaged platform addon
Stores, openUrl, workspaceOptional terminal host integrations listed below.Not supplied

Store methods can return their value directly or in a promise. See Terminal embedding for method signatures and revision rules:

InterfaceContract
ConfigStoreget(id) and set(id, value)
PromptHistoryStoreload, append, and clear
SessionStoreload, commit, list, and remove
OAuthSessionStoreload, commit, and remove
WorkspaceAdapterinfo, permission, and exec

These stores do not configure a headless agent. Use agent creation options and checkpoints instead.

TerminalAdapter

interface TerminalAdapter {
  readonly cols: number
  readonly rows: number
  write(bytes: Uint8Array): void
  onData(callback: (data: string) => void): () => void
  onResize(callback: () => void): () => void
  onKeyData?(callback: (data: string) => void): () => void
  drain?(): MaybePromise<void>
}

Subscription methods return unsubscribe functions. Keep dimensions current before emitting a resize. Use drain() when your UI needs to flush pending output before the terminal is considered interactive. The standard xterm adapter handles the subscriptions for you.

McpAdapter

createMcpAdapter

From libfx/mcp:

createMcpAdapter(client: McpClient, options?: McpOptions): Promise<McpAdapter>

interface McpOptions {
  prefix?: string
  resources?: string[]
  prompts?: Array<string | { name: string; arguments?: Record<string, string> }>
}

interface McpAdapter {
  tools: HostTool[]
  instructions: string
  close(): Promise<void>
}

McpClient is your already-connected MCP TypeScript SDK v1 client. It must implement listTools() and callTool(params, resultSchema?, options?). Resource options also require readResource({ uri }); prompt options require getPrompt({ name, arguments? }).

OptionDescriptionDefault
prefixPrefix for model-facing tool names; letters, digits, underscores, and hyphens only.''
resourcesResource URIs whose text is added to instructions.[]
promptsPrompt names or name/arguments objects whose text is added to instructions.[]

Creation lists tools, follows pagination, and fetches the requested context. More than 64 tools, invalid or repeated cursors, duplicate original tool names, or instructions larger than 64 KiB fail creation. Tool names are normalized for model APIs; calls to the client retain the original names. Non-text prompt/resource context is replaced with an omission notice.

Pass adapter.tools and adapter.instructions into createFxAgent(). Tool cancellation reaches the client's third callTool argument as { signal }. adapter.close() calls client.close() if supplied, once. Close the agent first. The host chooses and authenticates the client and remains responsible for transport setup.

SkillsAdapter

createSkillsAdapter

From libfx/skills, also re-exported by libfx/skills/node:

createSkillsAdapter(records: SkillRecord[]): SkillsAdapter

interface SkillRecord {
  name: string
  description?: string
  instructions: string
  resources?: Array<{ uri: string; text: string }>
  tools?: HostTool[]
}

interface SkillsAdapter {
  instructions: string
  tools: HostTool[]
}

Combines up to 64 loaded records into instructions and a tool array. Skill names must be unique. Resource text is included directly; this function does not fetch resources or read files. Invalid records, duplicate names, or combined instructions larger than 64 KiB throw. Pass the returned fields into createFxAgent({ apiKey, ...skills }).

loadSkillFile

From libfx/skills/node, for Node or Bun:

loadSkillFile(path: string, options?: LoadSkillOptions): Promise<SkillRecord>

interface LoadSkillOptions {
  readFile?: (path: string, encoding: 'utf8') => MaybePromise<string>
  resources?: Array<{ uri: string; text: string }>
  tools?: HostTool[]
}

Reads one file as UTF-8 using Node's readFile, or the supplied function. It reads simple name: value and description: value frontmatter and returns the remaining text as instructions. Without a name, it uses the filename without .md. It is not a general YAML parser and does not scan directories or load referenced files. File errors and unterminated frontmatter reject the promise.

Helpers

listModels

listModels(options: ListModelsOptions): Promise<string[]>

interface ListModelsOptions {
  apiKey: string
  fetch?: Fetch
}

Returns sorted, unique language-model IDs. apiKey is required; fetch defaults to the global implementation. This performs one Gateway catalog request without creating an agent or loading a native or WebAssembly runtime.

The promise rejects on invalid options, a failed HTTP response, malformed catalog data, or a catalog exceeding 4 MiB or 10,000 entries. Agent creation does not call this function automatically.

getBackendInfo

Node-only, from libfx or libfx/node:

getBackendInfo(options?: BackendInfoOptions): Promise<BackendInfo>

interface BackendInfoOptions {
  surface?: 'agent' | 'terminal'
  backend?: Backend
  nativeAddon?: string | URL | object | false
  wasm?: WasmSource | URL | Promise<Response | Bytes | WebAssembly.Module>
}

surface defaults to 'agent' and backend to 'auto'. Asset options have the same meaning as factory options. No credentials are required. Unknown options reject with TypeError.

BackendInfo

interface BackendInfo {
  surface: 'agent' | 'terminal'
  backend: 'native' | 'wasm-jspi' | 'unavailable'
  attempts: BackendAttempt[]
}

interface BackendAttempt {
  backend: 'native' | 'wasm-jspi'
  available: boolean
  reason: null | {
    code: string
    message: string
    causeCode?: string | number
  }
}

Attempts appear in selection order and stop at the first available backend. A successful attempt has reason: null. Expected loading failures resolve with an unavailable result rather than rejecting.

Reason codeDescription
LIBFX_UNSUPPORTED_PLATFORMNo packaged native addon supports this platform and architecture.
LIBFX_NATIVE_ARTIFACT_MISSINGThe selected native file is absent.
LIBFX_NATIVE_LOAD_FAILEDNode could not load the addon.
LIBFX_NATIVE_API_MISMATCHThe addon API revision is incompatible.
LIBFX_NATIVE_SURFACE_MISSINGThe addon does not implement the requested agent or terminal.
LIBFX_NATIVE_DISABLEDnativeAddon: false disabled native loading.
LIBFX_JSPI_UNAVAILABLEThe runtime has no JSPI support.
LIBFX_WASM_LOAD_FAILEDThe WebAssembly asset could not load or compile.

The probe loads the native module or compiles WebAssembly. It does not start an agent, validate credentials, or make a model request. A remote WebAssembly asset can still cause a network request.

supportsJspi

supportsJspi(): boolean

Checks for WebAssembly.Suspending and WebAssembly.promising. It does not load WebAssembly. Use this feature check before creating a browser agent or terminal; native Node agents do not require JSPI.

xtermAdapter

xtermAdapter(term: import('@xterm/xterm').Terminal): TerminalAdapter

Wraps an xterm.js terminal and forwards input, output, geometry, and resize notifications. It installs a custom key handler for fx-specific key encodings when xterm supports that hook. The host still owns opening and disposing the xterm.js instance.

encodeXtermKeyEvent

encodeXtermKeyEvent(event: KeyboardEvent): string | null

Returns an escape sequence for Shift+Enter and supported Meta+Backspace or Meta+arrow key combinations. Returns null for keys it does not handle, non-keydown events, or Alt/Ctrl combinations. null means the terminal should use its normal handling.

DiagnosticEvent

onEvent receives runtime diagnostics, not the TurnEvent stream:

interface DiagnosticEvent {
  type: string
  timestamp: number
  [detail: string]: unknown
}

timestamp is milliseconds from performance.now(), not a Unix timestamp. The callback runs synchronously; exceptions thrown by it are ignored. Treat event-specific fields as diagnostics rather than the answer/result API.

EventAdditional fields
runtime.start, runtime.readyTerminal events include surface: 'terminal'.
runtime.exitcode; terminal events also include surface.
transport.startattempt, method, endpoint, model when selected.
transport.responseattempt, status, elapsedMs, requestId, generationId, model, provider. Header-derived values can be null or absent.
transport.activityattempt, chunkBytes, totalBytes; emitted as response bytes arrive, at most once per 250 ms.
transport.errorattempt, elapsedMs, error (error name).
transport.retryattempt, nextAttempt, elapsedMs, error.
output.backpressurebufferedBytes, bufferedEvents.
output.discardedreason, bytes.
acp.send, acp.receivemessage, the protocol payload.
terminal.resize, terminal.sizecols, rows.
terminal.cleanup_errorsource, error.

Terminal adapters also emit config/history restore, update, and error diagnostics. Transport metadata omits credentials and raw headers, but protocol messages can contain prompts, instructions, tool content, and checkpoint data.

Errors

OperationFailure behavior
createFxAgent, createFxTerminalReject on invalid options, unavailable backend, asset failure, or initialization failure.
agent.promptThrows for invalid input, a closed agent, or a concurrent prompt.
Turn iteration and turn.resultReject on transport, decoding, or runtime failure. Normal cancellation resolves with stopReason: 'cancelled'.
agent.checkpointRejects during an active turn, after close, or if export fails.
listModelsRejects invalid options, HTTP errors, malformed data, or size limits.
getBackendInfoRejects invalid options; expected backend-loading failures are returned in attempts.
Host tool callbackA thrown error is sent to the model as a failed tool result.

On Node, createFxAgent() and createFxTerminal() may report LIBFX_JSPI_REQUIRED when no native backend can be used and JSPI is unavailable, or LIBFX_NATIVE_UNAVAILABLE when the addon cannot provide the requested agent or terminal. Loading and initialization errors can retain their original codes. These creation errors differ from the reason codes returned by getBackendInfo().

Unsupported model settings reject creation with LIBFX_MODEL_UNSUPPORTED_EFFORT, LIBFX_MODEL_UNSUPPORTED_FAST, or LIBFX_MODEL_UNSUPPORTED_ULTRAFAST, plus model and capability fields. Ultrafast rejection uses capability: 'ultrafast'. The effort and Fast codes replace LIBFX_UNSUPPORTED_EFFORT and LIBFX_UNSUPPORTED_FAST, including for legacy top-level options.

An older native addon without Ultrafast support rejects an explicitly supplied option with LIBFX_NATIVE_CAPABILITY_UNAVAILABLE; the automatic backend can fall back to a supporting WebAssembly build. Upgrade the package or custom assets instead of assuming the option was ignored.

Advanced testing

gatewayChatUrl?: string is a low-level agent option for testing against a local Gateway-compatible HTTP server, not a general provider base URL. It changes where model inference requests are sent; it does not change listModels().

The only accepted destinations are the canonical Gateway inference URL and HTTP on localhost, 127.0.0.1, or [::1] with an explicit port. URLs with embedded credentials or fragments are rejected. To proxy requests, provide fetch and preserve cancellation.