TypeScript SDK
What the SDK ships, how the subpath exports map to source modules, and where to start reading.
docs/build/10-sdk.mdxOn this page
The @octostaff/sdk package is the shared, framework-agnostic contract layer
between the Bubble service and its consumers: the Bubble wire protocol types
and the thread assembler that turns events into Bubble messages. Everything else
that used to live here — taskqueue, model-stream, stream, env/auth helpers,
agent-thread types — has moved into the package that actually uses it.
Subpath Exports
| Subpath | What lives there | Doc page |
|---|---|---|
@octostaff/sdk | Bubble wire types plus shared runtime codecs for HTTP request/response bodies and both WebSocket directions. | Artifact Protocol |
@octostaff/sdk/types | Core Bubble event/principal/authz types plus post-assembled BubbleMessage contracts and synthesized data-part types. | Thread Assembler |
@octostaff/sdk/assembler | Stateful translator from BubbleSequencedEvent[] to BubbleMessage[] for assistant-ui-style renderers. | Thread Assembler |
@octostaff/sdk/client | Validated HTTP/WS client, reconnect and polling lifecycle, durable consumer cursors, and async-iterable subscriptions. | Client contract below |
@octostaff/sdk/amphibian | Shared bot runtime plus the harness-neutral local Bubble tool catalog used by scuba adapters. | Local Bubble tools below |
The root export is the Bubble protocol surface; the assembler lives under
its own subpath because it pulls in ai as a peer dependency for the
post-assembled message reducer, which not every consumer needs.
src/protocol/core-codecs.ts is the runtime boundary shared by both peers: Bubble
verifies client-authored HTTP bodies and WebSocket frames with it and validates
server frames before serialization; BubbleConnection validates server HTTP
responses and WebSocket frames before exposing them to consumers.
Where to Start Reading
If you are…
- …rendering a Bubble thread in a React UI: read Thread Assembler. The package's public surface is small (one configured assembler, one stateful thread assembler, and native-part handlers) but the design space it covers — message grouping, segment rules, and idempotency — has a learning curve.
- …emitting Bubble events from a service: read the Bubble Events doc for the wire schema; the SDK just types it.
- …writing a new transport or storage adapter that needs to walk a
Bubble backlog and hand off to assistant-ui: the
thread assembler doc covers the
MessageFormatItemchaining shape. - …connecting to Bubble: construct
BubbleConnectionfrom@octostaff/sdk/client. It startsidle, opens WebSocket lazily, exposes connection-wide failures throughonError, and becomes terminal afterclose(). Public discovery (listAuthenticators,getServerInfo) needs no token; protected calls fail withBubbleClientErrorwhen credentials are absent. - …storing or transferring artifacts: read
Artifact Protocol for the global
/v1/artifactsroutes, explicit access scopes, and staged transfer flow.
Local Bubble Tools
@octostaff/sdk/amphibian exports one curated, harness-neutral tool catalog.
LOCAL_BUBBLE_TOOL_DESCRIPTORS is the schema surface, and
runLocalBubbleTool dispatches a validated call through the amphibian's own
authenticated BubbleApi. Artifact tools share the catalog with four
thread-oriented operations:
browse_threadpages lossless events and participant context;open_subthreadcreates an idempotent agent-only child;search_principalsresolves an exact principal before mutation; andinvite_to_threadadds one principal asmember.
Thread ids are optional where the active thread is the natural default. An explicit id does not widen authority: Bubble still evaluates the caller's current read, child-create, grant-management, discoverability, and invite privacy rights. A harness adapter is responsible only for translating the descriptors, supplying active-thread/tool-call correlation, and rendering the harness-neutral result.
Client Contract
- HTTP and WebSocket responses are runtime-decoded before entering application
state. Every failure is a
BubbleClientError; branch onkindfor local lifecycle/transport failures andcodefor Bubble protocol failures. - Unacknowledged
appendEventcalls preserve registration order with cursor frames until socket handoff, but handoff is not a persistence acknowledgement. Pass{ ack: true }when persistence or the assignedseqis required. HTTP acknowledgements are not ordered against earlier fire-and-forget WebSocket writes; use one transport when persistence order matters. subscribeThreadList,subscribeGrants, andsubscribePresencefan multiple local listeners onto the protocol's singleton subscription. Their iterable adapters share{ opened, changes(), close() }semantics.close()aborts in-flight HTTP, stops reconnect/polling, rejects queued work, and terminates subscriptions. A closed connection cannot be reused.
Layout
packages/sdk-typescript/
├── docs/
│ ├── 00-overview.mdx # this page
│ ├── 10-artifact-protocol.mdx # Artifact HTTP/SDK contract
│ └── 15-assembler.mdx # Thread Assembler
└── src/
├── identity/ # bubble authenticator dispatch
├── protocol/ # HTTP/WS shapes + bidirectional runtime codecs
├── types/ # bubble event / principal / authz / message types
├── client/ # connection, consumers, subscriptions, polling
│ └── transport/ # HTTP, WebSocket, outbound queue, Node adapter
├── index.ts # root barrel re-exporting all of the above
└── assembler/ # event → BubbleMessage translator
├── assembler.ts # configured assembler + thread lifecycle
├── run-segment.ts # RunSegment class
├── tool-parts.ts # event-neutral AI SDK tool-part traversal
├── chunk-helpers.ts # internal chunk utilities
├── segment-reducer.ts # persistent AI SDK reducer stream
├── event-handlers/ # semantic event families
├── native-part-handlers/ # core bubble-v1 families
├── contracts.ts # public composition contracts
└── index.ts # slim public entrypoint