Release candidate — 1.0.0-rc.6
StitchAPI
Concepts

The event stream

Why a stitch returns an async iterable of typed events — start, progress, drift, result, done — instead of Promise<bytes>.

A stitch returns an async iterable of typed events — start → progress → drift → result → done — not Promise<bytes>. Awaiting it gives you just the final value; iterating its stream gives you everything that happened on the way there.

Why it's shaped this way

A single Promise<bytes> collapses a call to two outcomes — it resolved, or it threw — and throws away the story in between: the retry that succeeded on the third attempt, the throttle that paused for 400ms, the field that silently changed shape. That story is exactly what an agent needs to reason about a call, and what an operator needs to debug one.

So a stitch is a single source that you can read at the altitude you need:

import {  } from 'stitchapi';

const  = ({ : 'https://api.example.com', : '/search' });

// Await it for just the value…
const  = await ({ : { : 'mango' } });

// …or iterate the typed event stream for everything that happened.
for await (const  of ({ : { : 'mango' } }).()) {
    if (. === 'progress') .(., .);
    if (. === 'drift')
        .(.., ..);
    if (. === 'result') .(.);
}

The events form a fixed spine — start, then any number of progress (auth, throttle, retry, pagination) and drift findings, then exactly one terminal result or error, then done. The union is discriminated on type, so narrowing one field tells the compiler the shape of the rest.

Awaiting without the throw

Awaiting collapses the stream to its terminal — the result value, or a thrown StitchError when the terminal is an error. When you'd rather branch on failure than wrap the call in try/catch, .safe() consumes the same stream and never throws: it resolves to a discriminated { ok, data, error } where error is the StitchError, or null on success.

import {  } from 'stitchapi';

const  = ({ : 'https://api.example.com', : '/search' });

const { ,  } = await ({ : { : 'mango' } }).();
if () {
    .(., .); // a StitchError
} else {
    .(); // the validated result; error is null here
}

.unwrap() is the explicit throwing twin — the value, or a thrown StitchError, exactly what awaiting the bare call does. Each also has an eager form on the stitch itself (search.safe(input) / search.unwrap(input)) that mirrors search.stream(input).

How it relates

The stream is what every cross-cutting feature reports through: retry, throttle, and auth emit progress; leveled drift emits drift. It is also the seam observability plugs into — a trace sink is just a consumer of these same events, which is how console logs, JSONL, and OTLP spans all come from one source without the call site knowing.

See also

On this page