@semiont/sdk
v0.5.26
Published
Semiont SDK — SemiontClient, namespaces, session/browser, state units, and the bus-request/cache helpers. Transport-agnostic; pair with @semiont/http-transport (HttpTransport) or @semiont/make-meaning (LocalTransport) for the wire.
Maintainers
Readme
@semiont/sdk
The TypeScript SDK for Semiont — a programmable surface for collaborative knowledge work. A browser app where humans annotate and link, an AI agent that gathers context and generates grounded answers, a daemon that ingests sources, a one-shot query script: all reach the same verb namespaces, the same collaboration primitives, the same lifecycle observables. Humans and AI agents are peers — the SDK does not distinguish.
📖 New here? Start with the Introduction
The orientation chapter: what Semiont is, the domain vocabulary, and the three ideas the API falls out of — written for people who build web apps, assuming nothing about AI apps. Then the Developer Guide is the road: task-ordered recipes — connect → ingest → enrich → gather → generate (grounded Q&A with inline citations) → annotate → react live → tear down — each a short explanation plus the exact SDK lines. This README is the map. For protocol-level framing (the eight flows, the core tenets), see
docs/protocol/README.md; daemon authors also want the skill packs.
Four ideas that hold the surface together
1. Eight verbs
Every operation belongs to one of eight flows — verbs describing what a participant does with a shared corpus. Learn them once and the surface stays small.
| Verb | What it does | Example methods |
|---|---|---|
| browse | Navigate, read, observe — including who's here to collaborate | browse.resource, browse.annotations, browse.agents, browse.click |
| bind | Resolve ambiguous references to specific resources | bind.body, bind.initiate |
| yield | Introduce new resources — uploaded or generated from gathered context | yield.resource, yield.fromResource, yield.fromAnnotation |
| mark | Add structured metadata to resources | mark.annotation, mark.assist, mark.updateEntityTypes, mark.archive |
| frame | Define and evolve the schema vocabulary (entity types, tag schemas) | frame.addEntityTypes, frame.addTagSchema |
| gather | Assemble grounding context around a resource or an annotation | gather.resource, gather.annotation |
| match | Search the corpus for candidate resources | match.search |
| beckon | Coordinate attention across participants | beckon.hover, beckon.sparkle |
Each flow is a namespace on SemiontClient (client.mark.X(...)); the verb is the unit of
mental model. Frame is the schema-layer flow — the others operate within the vocabulary it
manages. Per-flow contracts: docs/protocol/flows.
2. One call, two ways to consume
Every long-lived value is an Observable with an explicit one-shot path — from the same
call, take the value once or keep it live:
const resource = await client.browse.resource(rId).fresh(); // one-shot fresh read — no rxjs import
client.browse.resource(rId).subscribe((st) => { // live — same call, typed states
if (st.status === 'ready') render(st.value); // pending | ready | failed
});
const found = await client.match.search(rId, refId, ctx); // bounded streams ARE awaitableMethods return one of: Promise<T> (atomic backend ops), StreamObservable /
UploadObservable (bounded progress — thenable, await resolves the final value),
CacheObservable (live queries — .subscribe(...) for CacheState emissions,
.fresh() for the explicit network read; deliberately NOT thenable, so a cache read can
never silently become a round trip), or void (collaboration signals — below). The
per-method table and the .run() rule for progress-plus-result live in
docs/REACTIVE-MODEL.md.
3. Collaboration primitives
The void-returning signals are protocol-level coordination, not browser-app fluff: a human
hovers an annotation (beckon.hover(id)) and an AI agent across the bus reacts; an agent
sparkles an annotation and the human's UI lights up. Observers reach the same signals via
session.subscribe(channel, handler) or client.bus.get(channel).
4. Transport agnosticism
SemiontClient is built against the ITransport / IContentTransport contracts from
@semiont/core, not any particular wire — the same surface runs over HTTP or in-process. The
HTTP adapter is re-exported here for convenience; the in-process transport is
LocalTransport from @semiont/make-meaning.
What's in the box
SemiontClient— the verb-oriented coordinator: the eight flow namespaces, plusjob(always present) andauth/admin(present when constructed with backend operations).- Session layer —
SemiontSession(per-KB auth, proactive token refresh, lifecycle),SemiontBrowser(multi-KB orchestration),SessionStorageadapters, and thehttpKbhelper for endpoint shapes. - Flow state machines — closure-based factories (
createMarkStateUnit,…Gather…,…Match…,…Yield…,…Beckon…) wrapping each long-running flow withloading$/error$/ progress observables; UI-shape-agnostic (docs/STATE-UNITS.md). WorkerBus— the transport-neutral bus interface worker adapters consume (the adapters live with their domains:@semiont/jobs,@semiont/make-meaning).- KB discovery — the consumer side of the launcher's published KB view:
httpDiscovery(polls the Browser origin'sDISCOVERY_URL_PATHwith ETag/304),textDiscovery(bring-your-own IO — the sdk never importsfs), andsubscribeDiscovery(a polling diff stream with a typed absent-vs-managed state). Descriptors only; auth stays per-KB. Types (DiscoveredKB,DiscoveryDocument) come from@semiont/core's generated schema. - Helpers & types — the cache primitive behind live queries
(
docs/CACHE-SEMANTICS.md),createSearchPipeline, branded ids, and the unified error hierarchy (SemiontError,BusRequestError) re-exported so you catch every SDK error from one package. (The request/reply primitive itself,busRequest, lives in@semiont/core.)
This is everything a non-web consumer (TUI, mobile, daemon, agent) needs — nothing
page-shaped. Page-level state machines and components, including the embeddable
ResourceViewer, live in @semiont/react-ui.
Install & connect
npm install @semiont/sdkOne-shot script — credentials-first, one line:
import { SemiontClient } from '@semiont/sdk';
const semiont = await SemiontClient.signInHttp({
baseUrl: 'http://localhost:4000',
email: '[email protected]',
password: 'pwd',
});
const resources = await semiont.browse.resources({ limit: 10 }).fresh();
semiont.dispose();Long-running script — SemiontSession adds proactive refresh, storage, and disposal; kb.id
is the storage key, so distinct scripts use distinct ids:
import { SemiontSession, InMemorySessionStorage, httpKb } from '@semiont/sdk';
const session = await SemiontSession.signInHttp({
kb: httpKb({ id: 'my-watcher', label: 'My Watcher', email: '[email protected]',
host: 'localhost', port: 4000, protocol: 'http' }),
storage: new InMemorySessionStorage(),
baseUrl: 'http://localhost:4000',
email: '[email protected]',
password: 'pwd',
});
const resources = await session.client.browse.resources({ limit: 10 }).fresh();
await session.dispose();Already hold a token? SemiontClient.fromHttp({ baseUrl, token }) /
SemiontSession.fromHttp(...) skip the auth round-trip. In-process (CLI, tests, embedded) —
same surface, no network:
import { SemiontClient } from '@semiont/sdk';
import { startMakeMeaning, LocalTransport, LocalContentTransport } from '@semiont/make-meaning';
const ks = await startMakeMeaning(project, config, eventBus, logger);
const client = new SemiontClient(
new LocalTransport({ knowledgeSystem: ks.knowledgeSystem, eventBus, userId }),
new LocalContentTransport(ks.knowledgeSystem),
);From here, the Developer Guide takes over — every recipe assumes exactly this setup.
Documentation
The full map — every doc's role, and a reading order by audience — is
docs/README.md.
docs/DEVELOPER-GUIDE.md— start here to build. Task-ordered recipes, connect through teardown.docs/Usage.md— per-namespace API tour with concrete examples, plus SSE and error handling.docs/REACTIVE-MODEL.md— the Promise-shape-over-Observable design.docs/STATE-UNITS.md— the state-unit pattern and its enforced axioms.docs/CACHE-SEMANTICS.md— the cache primitive's behavioral contract (B1–B16).docs/protocol/TRANSPORT-CONTRACT.md— what everyITransportmust honor; HTTP specifics in TRANSPORT-HTTP.md. New transports implement the@semiont/coreinterfaces directly — no inheritance fromHttpTransport.
License
Apache-2.0 — see LICENSE.
Related packages
@semiont/core— domain types,ITransportcontract,busRequest, OpenAPI-derived schemas@semiont/http-transport— HTTP transport (HttpTransport,HttpContentTransport)@semiont/make-meaning— in-process transport (LocalTransport) and the actor model behind it@semiont/observability— OpenTelemetry tracing the SDK propagates across the bus@semiont/react-ui— the embeddableResourceViewer(bring-your-own-session) plus React hooks (useResourceLoader,useMediaToken,useObservable) and the webSessionStorage; its docs cross-link the Developer Guide
