Types
Every request and response is typed from the OpenAPI spec. Field names are the API's wire names, so a response object matches the JSON exactly.
Request and response types are generated from the same OpenAPI spec the API reference is built from, and re-exported from the package root:
import type { Session, SessionRecord } from '@ellipsis-dev/sdk';
function summarize(session: Session): string {
return `${session.id} ${session.status}`;
}Field names are the API's wire names, so a response object matches the JSON on the wire exactly: session_state, not sessionState. Only the SDK's own surface uses camelCase, which is why handle.send() takes idempotencyKey while sessions.sendMessage() takes idempotency_key.
Responses are envelopes
A response type wraps the resource rather than being it. sessions.get() returns a SessionResponse whose session is the Session:
const response = await client.sessions.get('session_7Hq2mX4p');
const session = response.session;Destructuring at the call site is usually shorter:
const { session } = await client.sessions.get('session_7Hq2mX4p');The session handle unwraps this for you: handle.session is already a Session. Each operation's exact response type is named on its API reference page.
Optional means possibly undefined or null
A field the API may omit is typed optional, and a nullable one includes null. With strictNullChecks on, the compiler makes you handle it:
if (session.surface) {
console.log(session.surface.status);
}Open vocabularies are strings
Fields whose value set grows without a contract change are typed string, even where the known values are documented: a record's source, an error code, a delta's kind. New values ship on a routine release, so a union type would turn an additive server change into a broken build. Handle the values you know and fall through on the rest.
Closed vocabularies keep their union. A new value in one of those is a real contract change and should redden your build, which is the point.
Frames and store types
Stream frame types live in the same public surface, so a frame handler can be typed without importing from a subpath:
import type { StreamFrame, DeltaFrame } from '@ellipsis-dev/sdk';StreamFrame is the open union: the seven known frames plus an unknown-shape escape hatch. Narrow it on frame.type.