SDK
@snowluma/sdk — a typed OneBot client, independent of the SnowLuma runtime
@snowluma/sdk is a fully typed OneBot v11 client written in TypeScript. It is built for downstream consumers: you don't run SnowLuma in the same process and you don't depend on the SnowLuma runtime — the SDK just connects to any running SnowLuma instance over its OneBot HTTP / WebSocket ports.
The package installs straight from npm and shares action types with the SnowLuma core, so call parameters and return shapes can't drift across versions.
Where the ports come from
The SDK connects to the OneBot ports SnowLuma exposes: HTTP at 0.0.0.0:3000 and WebSocket at 0.0.0.0:3001 by default. The accessToken also comes from the OneBot config. Make sure those network adapters are enabled first on the Configuration page.
Install
npm install @snowluma/sdkRequires Node.js ≥ 22 (Node 24 LTS recommended). The package is pure ESM ("type": "module") and ships its own type declarations.
Supported transports
| Transport | Client class | Default endpoint |
|---|---|---|
| HTTP (POST JSON) | SnowLumaHttpClient | http://127.0.0.1:3000/ |
| WebSocket (forward / reverse, with events) | SnowLumaWebSocketClient | ws://127.0.0.1:3001/ |
Both clients extend the abstract SnowLumaApiClient base, so call() / request() and every camelCase action shortcut work identically across transports. HTTP suits plain request/response scripts; WebSocket adds realtime event delivery on top.
Constructing a client
HTTP
import { } from '@snowluma/sdk';
const = new ({
: 'http://127.0.0.1:3000/', // default
: ..,
: 30_000, // default 30s
});SnowLumaHttpClientOptions:
baseUrl?— OneBot HTTP endpoint, defaults tohttp://127.0.0.1:3000/.accessToken?— token from the OneBot config; when set, anAuthorization: Bearer <token>header is sent automatically.requestTimeoutMs?— default timeout in ms, defaults to30000.fetch?— customfetchimplementation (tests or non-standard runtimes).headers?— extra headers attached to every request.
WebSocket
import { } from '@snowluma/sdk';
const = new ({
: 'ws://127.0.0.1:3001/', // default
: ..,
: true, // enable auto-reconnect
});SnowLumaWebSocketClientOptions:
url?— OneBot WebSocket endpoint, defaults tows://127.0.0.1:3001/.accessToken?— appended to the connection URL as a query parameter.requestTimeoutMs?— default request timeout, defaults to30000.role?— role the client advertises:'Api'|'Event'|'Universal'(default'Universal').reconnect?—trueor aReconnectOptions(retries/minDelayMs/maxDelayMs) to enable auto-reconnect after an unexpected close.protocols?/webSocket?— optional subprotocols, optional customWebSocketconstructor (Node runtimes or tests).
Custom WebSocket on Node
Browsers and Node 24 ship a global WebSocket that works out of the box. To use an implementation like the ws package, pass it to the webSocket option.
The factory functions
createHttpClient(options?)andcreateWebSocketClient(options?)are equivalent tonew; use whichever you prefer.
Calling an action
Common endpoints have fully typed camelCase methods (getLoginInfo, sendGroupMessage, setGroupBan, …). Any registered action can be called via raw / rawResponse.
import { , } from '@snowluma/sdk';
const = new ({ : .. });
// Shortcut method
const = await .();
await .(123456, (`Hello from ${.}`).('all'));
// Any action: raw() returns data and throws on failure
const = await .('get_group_file_system_info', { : 123456 });
// rawResponse() keeps the full OneBot envelope (status / retcode / data / echo)
const = await .('get_status');The underlying methods:
call(action, params?, options?)— sends the action and returnsdata; throwsSnowLumaApiErrorwhenstatusisfailedorretcode !== 0.request(action, params?, options?)— returns the full response envelope and does not throw on business errors.
Every request can override behavior via RequestOptions: echo (correlation value), timeoutMs (0 disables the timeout), and signal (an AbortSignal).
const = new ();
const = .({ : 5_000, : . });
.();
await ; // throws SnowLumaAbortErrorSubscribing to events
Event subscription is a WebSocket-client capability. The client correlates API responses by echo and dispatches packets without an echo as events.
import { , } from '@snowluma/sdk';
const = new ({
: ..,
: true,
});
// Typed event helpers
.(async (, ) => {
if (. === '/ping') {
await .(('pong').(.));
}
});
.('friend', async (, ) => {
await .();
});
// Register a command
.('echo', async (, , ) => {
await .((. || 'empty'));
});
await .();Available event helpers: onMessage / onPrivateMessage / onGroupMessage / onNotice(type?) / onRequest(type?) / onMetaEvent / command(), plus the lower-level onEvent, when(predicate, handler), and use(middleware). Lifecycle events use on('open' | 'close' | 'error' | 'response' | 'raw', …). Every on / when / use returns an unsubscribe function.
The event context (ctx) has built-in shortcuts:
ctx.reply(message)— auto-replies to the private/group thread.ctx.approve()/ctx.reject(reason)— handle friend or group requests.ctx.quickOperation(operation)— calls.handle_quick_operation.ctx.stopPropagation()— stops further middleware dispatch.
Message builder
The SDK ships a chainable message builder and segment factories; send methods accept their output directly:
import { , , , } from '@snowluma/sdk';
// Chained
await .(123456, ('got it ').(10001).('/tmp/a.png'));
// Segment array
await .(123456, [.('Hello'), .('all')]);
// CQ-code round-trip
const = ([.(42), .('hi')]);
const = ('hi[CQ:at,qq=all]');Built-in segments: text, br, face, at, atAll, reply, image, record, video, json, xml, poke, forward, node, share, music, location, contact, raw. reply() may appear only once per chain.
Auto-reconnect, ack correlation, and shared types
- Ack correlation — the WebSocket client generates an
echoper request and routes the response back to the rightPromise, so concurrent requests never cross. Override the correlation value viaRequestOptions.echo. - Auto-reconnect —
reconnect: true(or aReconnectOptions) enables exponential backoff (minDelayMsdefaults to 1000,maxDelayMsto 30000). On disconnect, all pending requests reject withSnowLumaConnectionError. - Shared action types — action names, params, and result types share their source with
@snowluma/core, so the call surface always matches the server. - Unified error model — all errors extend
SnowLumaError: business failures throwSnowLumaApiError(auth-class retcodes becomeSnowLumaAuthError); transport issues throw theSnowLumaTransportErrorsubclassesSnowLumaConnectionError/SnowLumaParseError/SnowLumaTimeoutError/SnowLumaAbortError.
Subpath imports
Beyond the main entry, the package exposes per-module exports: @snowluma/sdk/client, /messages, /events, /types, /errors, /actions. Import only what you need.
See also
- Configuration — enable and secure the OneBot HTTP / WS adapters and get an
accessToken. - Developer guide — monorepo layout and runtime internals.
- MCP server — an alternative integration path for LLMs.
Was this page helpful?
Last updated on