libfx API reference
This page documents the JavaScript API in libfx@0.0.10. The TypeScript interfaces below describe the API; they are not types exported by the package. For setup and examples, see the Node SDK or WebAssembly SDK.
API index
| Function or method | Returns | Purpose |
|---|---|---|
createFxAgent(options) | Promise<Agent> | Create one conversation. |
agent.prompt(input, options?) | Turn | Run a prompt and stream events. |
agent.checkpoint() | Promise<Uint8Array> | Export conversation history and usage. |
agent.close() | Promise<void> | Stop the agent and release its runtime. |
| Function or method | Returns | Purpose |
|---|---|---|
turn.cancel() | void | Cancel the active turn. |
| Function or method | Returns | Purpose |
|---|---|---|
createFxTerminal(options) | Promise<TerminalRuntime> | Start the interactive terminal. |
terminal.write(data) | void | Send terminal input. |
terminal.resize() | void | Notify fx of a size change. |
terminal.abort() | void | Stop the terminal and release listeners. |
| Function or method | Returns | Purpose |
|---|---|---|
createMcpAdapter(client, options?) | Promise<McpAdapter> | Convert an MCP client's tools and context. |
mcp.close() | Promise<void> | Close the adapter and its client. |
| Function or method | Returns | Purpose |
|---|---|---|
createSkillsAdapter(records) | SkillsAdapter | Convert loaded skill records. |
loadSkillFile(path, options?) | Promise<SkillRecord> | Read one skill file in Node or Bun. |
| Function or method | Returns | Purpose |
|---|---|---|
listModels(options) | Promise<string[]> | List available language-model IDs. |
getBackendInfo(options?) | Promise<BackendInfo> | Check backend availability in Node. |
supportsJspi() | boolean | Check WebAssembly JSPI support. |
xtermAdapter(term) | TerminalAdapter | Connect an xterm.js instance. |
encodeXtermKeyEvent(event) | string | null | Encode special terminal keys. |
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
| Interface | Describes |
|---|---|
AgentOptions | Credentials, model, instructions, tools, and checkpoint input. |
Agent | The conversation's methods. |
PromptInput and PromptOptions | Text, resources, and cancellation. |
Turn | An event stream, result promise, and cancel method. |
TurnEvent | Text, reasoning, and tool events. |
TurnResult and Usage | Stop reason and token counts. |
HostTool | A tool's schema and execution callback. |
DiagnosticEvent | Runtime diagnostics sent to onEvent. |
BackendInfo | Selected backend and attempted alternatives. |
TerminalOptions | Terminal adapter, configuration, and stores. |
TerminalRuntime | Terminal readiness, exit, and control methods. |
TerminalAdapter | Input, output, and geometry supplied by your UI. |
McpAdapter | Adapted tools, instructions, and cleanup. |
SkillRecord and SkillsAdapter | Loaded 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.
AgentOptions
interface AgentOptions {
apiKey: string
model?: string
instructions?: string | string[]
tools?: HostTool[]
checkpoint?: Bytes
fetch?: Fetch
onEvent?: (event: DiagnosticEvent) => void
wasm?: WasmSource | URL | Promise<Response | Bytes | WebAssembly.Module>
backend?: Backend
nativeAddon?: string | URL | object | false
}
| Option | Required | Default | Behavior |
|---|---|---|---|
apiKey | Yes | None | AI Gateway credential. Non-empty string, at most 64 KiB of UTF-8. |
model | No | fx's built-in model | Model ID, at most 1 KiB of UTF-8. |
instructions | No | No system message | Complete system instructions. An array joins non-empty entries with blank lines. At most 64 KiB of UTF-8 after joining. |
tools | No | [] | Up to 64 explicit host tools. No CLI tools are enabled automatically. |
checkpoint | No | New conversation | Opaque bytes from agent.checkpoint(). The input is copied. |
fetch | No | globalThis.fetch | Host-controlled HTTP transport. Preserve the supplied AbortSignal. |
onEvent | No | None | Synchronous diagnostic callback. Model output is on the Turn stream instead. |
wasm | No for package wrappers | Packaged fx-core.wasm | WebAssembly asset to load when using that backend. |
backend | No | 'auto' | Node-only backend selection. 'native' fails instead of falling back; 'wasm' requires JSPI. |
nativeAddon | No | Packaged platform addon | Node-only custom addon module, path, or URL. false disables native loading. Treat this as trusted application configuration. |
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.
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 this schema.')
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: 'resource'; resource: { uri: string; text?: string } }
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. Image and audio prompt blocks are not supported.
const turn = agent.prompt([
{ type: 'text', text: 'Summarize this file.' },
{
type: 'resource',
resource: {
uri: 'file:///workspace/schema.sql',
text: 'CREATE TABLE users (id INTEGER PRIMARY KEY);',
},
},
], { signal: controller.signal })
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. 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. Protect stored checkpoints as conversation data.
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>
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.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: 'tool_start'; id: string; name: string }
| {
type: 'tool_end'
id: string
name: string
content?: string
isError: boolean
}
| Event | Fields | Meaning |
|---|---|---|
text_delta | delta | Append this text to the answer. |
reasoning_delta | delta | Reasoning text when the provider supplies it. |
tool_start | id, name | A tool call started. |
tool_end | id, name, content?, isError | A tool call completed or failed. Match it to its start by id. |
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 reason | Meaning |
|---|---|
end_turn | The turn ended normally. |
max_output_tokens | The response reached its output-token limit. |
max_model_turns | The turn reached its model-step limit. |
refused | The model refused the request. |
cancelled | The 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 }>
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, with PNG, JPEG, GIF, and WebP 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. Keep tool results small and honor context.signal.
TerminalRuntime
interface TerminalRuntime {
interactive: Promise<void>
exited: Promise<number>
write(data: string | Uint8Array): void
resize(): void
abort(): void
}
| Member | Behavior |
|---|---|
interactive | Resolves after the terminal reaches its input loop and optional adapter drain() finishes. Rejects if fx exits before reaching that loop or draining fails. |
exited | Resolves 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
}
| Option | Default | Behavior |
|---|---|---|
terminal | Required | UI adapter for input, output, and size. |
env | {} | Terminal environment, including AI_GATEWAY_API_KEY when supplying a credential directly. |
args | [] | Terminal CLI arguments, such as ['--resume', 'last']. |
fetch | globalThis.fetch | Host HTTP transport. |
onEvent | None | Diagnostic callback. |
interruptKey | '\x03' (Ctrl+C) | String input containing this key also cancels active host effects. '' disables this detection. |
wasm | Packaged fx-term.wasm | Terminal WebAssembly asset; required with the direct libfx/wasm entry. |
backend | 'auto' | Node-only selection. The package has no native terminal, so 'native' fails. |
nativeAddon | Packaged platform addon | Node-only override for a custom addon. |
Stores, openUrl, workspace | Not supplied | Optional terminal host integrations listed below. |
Store methods can return their value directly or in a promise. See Terminal embedding for method signatures and revision rules:
| Interface | Contract |
|---|---|
ConfigStore | get(id) and set(id, value) |
PromptHistoryStore | load, append, and clear |
SessionStore | load, commit, list, and remove |
OAuthSessionStore | load, commit, and remove |
WorkspaceAdapter | info, 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? }).
| Option | Default | Behavior |
|---|---|---|
prefix | '' | Prefix for model-facing tool names; letters, digits, underscores, and hyphens only. |
resources | [] | Resource URIs whose text is added to instructions. |
prompts | [] | Prompt 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 code | Meaning |
|---|---|
LIBFX_UNSUPPORTED_PLATFORM | No packaged native addon supports this platform and architecture. |
LIBFX_NATIVE_ARTIFACT_MISSING | The selected native file is absent. |
LIBFX_NATIVE_LOAD_FAILED | Node could not load the addon. |
LIBFX_NATIVE_API_MISMATCH | The addon API revision is incompatible. |
LIBFX_NATIVE_SURFACE_MISSING | The addon does not implement the requested agent or terminal. |
LIBFX_NATIVE_DISABLED | nativeAddon: false disabled native loading. |
LIBFX_JSPI_UNAVAILABLE | The runtime has no JSPI support. |
LIBFX_WASM_LOAD_FAILED | The 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. Availability does not guarantee a later initialization or prompt will succeed.
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.
| Event | Additional fields |
|---|---|
runtime.start, runtime.ready | Terminal events include surface: 'terminal'. |
runtime.exit | code; terminal events also include surface. |
transport.start | attempt, method, endpoint, model when selected. |
transport.response | attempt, status, elapsedMs, requestId, generationId, model, provider. Header-derived values can be null or absent. |
transport.error | attempt, elapsedMs, error (error name). |
transport.retry | attempt, nextAttempt, elapsedMs, error. |
output.backpressure | bufferedBytes, bufferedEvents. |
output.discarded | reason, bytes. |
acp.send, acp.receive | message, the protocol payload. |
terminal.resize, terminal.size | cols, rows. |
terminal.cleanup_error | source, 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. Do not log the entire diagnostic stream as if it were free of sensitive data.
Errors
| Operation | Failure behavior |
|---|---|
createFxAgent, createFxTerminal | Reject on invalid options, unavailable backend, asset failure, or initialization failure. |
agent.prompt | Throws for invalid input, a closed agent, or a concurrent prompt. |
Turn iteration and turn.result | Reject on transport, decoding, or runtime failure. Normal cancellation resolves with stopReason: 'cancelled'. |
agent.checkpoint | Rejects during an active turn, after close, or if export fails. |
listModels | Rejects invalid options, HTTP errors, malformed data, or size limits. |
getBackendInfo | Rejects invalid options; expected backend-loading failures are returned in attempts. |
| Host tool callback | A thrown error is sent to the model as a failed tool result. |
The Node factories may report LIBFX_JSPI_REQUIRED when no native backend can be used and JSPI is unavailable, or LIBFX_NATIVE_UNAVAILABLE for a missing native surface. Loading and initialization errors can retain their original codes. These factory errors are distinct from the reason codes returned by getBackendInfo().
Advanced testing
Most applications should leave model-request routing at its default. 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. Use only trusted application configuration. For production network policy or a proxy, provide a trusted fetch implementation and preserve cancellation.