Skip to content

TypeScript SDK reference ​

@dotcraft/sdk is the Node.js SDK for AppServer applications. Start with the Quickstart for installation and a first run.

Package ​

FieldValue
Package@dotcraft/sdk
Module formatESM
RuntimeNode.js 20+

The package is published on npm. Runtime entry points belong in Node.js or Electron Main, not in browser or Electron Renderer code.

Entry points ​

Entry pointPublic surface
@dotcraft/sdkDotCraft, threads, runs, callbacks, input helpers, approval decisions, and high-level errors.
@dotcraft/sdk/contractsGenerated DTOs, method maps, registries, and protocol metadata.
@dotcraft/sdk/wireDotCraftWireClient, transports, lifecycle state, timeouts, typed methods, and raw extension APIs.
@dotcraft/sdk/hubHub discovery, AppServer management, process policy, events, and structured errors.
@dotcraft/sdk/app-bindingApp Binding handoff and result helpers.
@dotcraft/sdk/dynamic-toolsRuntime Dynamic Tool authoring helpers.
@dotcraft/sdk/testingTransport and protocol test surface.
@dotcraft/sdk/metaSDK, contract, protocol, and contract-hash metadata.

Contracts has no Node.js, WebSocket, or runtime I/O dependency, so Renderer code may import it for types.

Avatar package ​

@dotcraft/avatar/react provides the React 19 Avatar component for DotCraft's name-derived visual identity. Pass name and size, with optional state, motion, paused, eventSequence, and label props. Its ComposerMascot component accepts the host's applied light or dark theme through the optional theme prop, which defaults to dark. The framework-neutral package root exports deriveAppearance, which trims and NFC-normalizes the name before deriving an appearance. The same normalized name produces the same identity; an empty name produces the original DotCraft appearance.

An appearance fills five independent slots (head, face, hand, back, skin) from a registry of collectible items, each with a rarity from Common to Legendary and a series. Items that share a mounting zone never appear together; equip(appearance, slot, id) changes one slot and clears conflicting ones. Item effects such as the Holographic or Chrome skins animate only at 44px and above with motion enabled, and avatars at 20px and below keep just the head and back silhouettes. Render an explicit appearance with AppearanceAvatar from @dotcraft/avatar/react.

High-level API ​

TaskAPI
ConnectDotCraft.local(), DotCraft.localChat(), DotCraft.remote()
Closedotcraft.close()
Threadsthreads.getOrCreate(), start(), resume(), list(), listPage(), read(), listTurns(), listItems()
Runrun(), runStreamed(), enqueue(), interrupt()
Thread statesnapshot(), refresh(), subscribe(), unsubscribe(), setMode(), archive(), delete()
Modelsmodels.list()
MCP runtimemcpRuntime.listStatus(), readResource(), callTool(), loginOAuth(), reload()
App BindingappBindings
Runtime toolsonToolCall()

Configure approvalHandler and userInputHandler in local or remote connection options. See Threads & runs and Tools & approvals for task flows.

Connect ​

MethodRequired optionConnection ownership
DotCraft.local(options)workspacePathUses Hub to ensure the workspace AppServer, then connects to it.
DotCraft.localChat(options?)NoneUses Hub to ensure the default Chat workspace AppServer.
DotCraft.remote(options)url; optional tokenConnects directly to an existing AppServer WebSocket.

All three option types accept client identity, approval and user-input handlers, and additional capabilities. Local options also accept executable selection, binary-match policy, Hub timeout, and home-directory overrides.

Option typeFields
DotCraftLocalOptionsRequired workspacePath; optional clientName, clientVersion, clientTitle, executable, expectedExecutable, binaryMatchPolicy, hubStartupTimeoutMs, homeDir, handlers, and capabilities.
DotCraftLocalChatOptionsThe local fields except workspacePath.
DotCraftRemoteOptionsRequired url; optional token, client identity, handlers, and capabilities.

A remote url points at the AppServer WebSocket endpoint, whose path ends in /ws. Pass the token in the token option instead of embedding it in the URL, and keep both out of logs. See AppServer mode for how the server listens.

Threads and runs ​

ThreadManager exposes these high-level operations:

ts
getOrCreate(options?: GetOrCreateThreadOptions): Promise<DotCraftThread>;
start(options?: StartThreadOptions): Promise<DotCraftThread>;
resume(threadId: string, options?: ResumeThreadOptions): Promise<DotCraftThread>;
list(options?: ListThreadOptions): Promise<ThreadSummary[]>;
listPage(options?: ListThreadOptions): Promise<ThreadListResult>;
read(threadId: string): Promise<SessionThread>;
listTurns(threadId: string, options?: ThreadHistoryPageOptions): Promise<ThreadTurnsListResult>;
listItems(threadId: string, options?: ThreadItemPageOptions): Promise<ThreadItemsListResult>;

Start options contain identity fields, display name, history mode, configuration, Runtime Dynamic Tools, and additional context. Resume options only rebind dynamic tools and additional context. List options add identity/workspace scope, archived filtering, text query, limit, and cursor.

read() and a Thread handle's refresh() return the current Thread header without persisted Turns or Items. listTurns() reads Turn metadata; listItems() reads Items across the Thread or for the optional turnId. Both accept cursor, limit, and sortDirection, and return data plus an opaque nextCursor; listTurns() also returns a backwardsCursor that reads outward from the first returned Turn in either direction. Thread handles expose the same two pagination methods without the threadId argument.

run() and runStreamed() accept text, InputPart[], or { input, sender }. Run options are sender, collectRawEvents, abortSignal, and enqueueIfBusy. A buffered result contains thread, optional terminal turn, merged text, items, optional usage, optional raw events, and any queued-input result.

Models, MCP, and App Binding ​

ManagerOperations
modelslist() returns the model catalog visible to this AppServer.
mcpRuntimelistStatus(), readResource(), callTool(), loginOAuth(), reload().
appBindingsApp discovery, connection, surfaces, thread bindings, channel bindings, and principal operations.

The TypeScript high-level surface lists models but does not currently provide a model-configuration convenience method. Use the typed Wire request map for thread/config/update when an application must change the complete thread configuration, and preserve fields it does not own. See MCP runtime and DotCraft App for task-oriented flows.

The MCP manager signatures are:

ts
listStatus(params?: McpServerStatusListParams): Promise<McpServerStatusListResult>;
readResource(params: McpServerResourceReadParams): Promise<McpServerResourceReadResult>;
callTool(params: McpServerToolCallParams): Promise<McpServerToolCallResult>;
loginOAuth(params: McpServerOAuthLoginParams): Promise<McpServerOAuthLoginResult>;
reload(): Promise<McpServerReloadResult>;

Callbacks and Runtime Dynamic Tools ​

ts
type ApprovalHandler =
  (request: Record<string, unknown>) => Promise<ApprovalDecision> | ApprovalDecision;
type UserInputHandler =
  (request: Record<string, unknown>) => Promise<Record<string, unknown>> | Record<string, unknown>;
type DynamicToolHandler =
  (request: DynamicToolCallRequest) => Promise<DynamicToolCallResult> | DynamicToolCallResult;

thread.onToolCall(namespace: string | null, name: string, handler: DynamicToolHandler): Unsubscribe;

Handlers execute in the application process. Register them before starting work that can call the tool, validate arguments in the handler, and dispose registrations when their owning scope ends.

Typed and raw Wire API ​

Use the typed method map for cataloged AppServer methods:

ts
const result = await wire.request("thread/list", params);
const dispose = wire.on("thread/started", ({ thread }) => console.log(thread.id));

Use raw APIs only for third-party or not-yet-cataloged extensions:

ts
const value = await wire.requestRaw("ext/example/read", { id: "42" });
const dispose = wire.onRaw("ext/example/changed", console.log);

DotCraftWireClient owns JSON-RPC and connection state. It does not approve requests, answer user input, or rebuild thread and tool resources.

Connection lifecycle ​

Wire state is connecting, initializing, ready, disconnected, reconnecting, reconnectError, or closed.

  • Local and remote high-level connections reconnect automatically.
  • Raw Wire connections do not reconnect unless autoReconnect is enabled.
  • Ordinary requests default to a 30-second timeout.
  • Reconnect uses exponential backoff and queues at most 1024 new calls.
  • In-flight calls fail and are never replayed.
  • Initialization completes before queued calls are released.
  • Handler registrations survive reconnect. Thread subscriptions, active runs, and runtime tool resources do not.

Reconnect does not rebuild those resources for the application. Read or resume the thread, subscribe again, and re-register runtime tool handlers before continuing.

Closing a local high-level client closes its WebSocket connection. It does not stop Hub or the Hub-managed AppServer.

Errors ​

All SDK errors derive from DotCraftError and carry a stable code.

ErrorCondition
JsonRpcErrorAppServer returned a JSON-RPC error. Preserves rpcCode and data.
InitializationErrorConnection initialization failed.
TurnInProgressErrorThe thread already has an active turn.
ThreadNotFoundError / ThreadNotActiveErrorThe target thread is missing or cannot run.
TurnFailedError / TurnCancelledErrorA buffered run reached a failed or cancelled terminal state.
ProtocolViolationErrorA known message does not match its contract.

JsonRpcError and the transport-level errors TransportError, TransportClosed, RequestTimeoutError, and ReconnectQueueFullError are exported from the Wire entry point.

Hub API ​

HubClient discovers or starts Hub, validates the local lock, resolves a workspace AppServer, and supports ensure, restart, stop, list, status, events, and shutdown operations.

Hub errors preserve code, message, and details. Do not log Hub tokens or full token-bearing WebSocket URLs.