@collieai/sdk
v1.0.0
Published
Node/TypeScript SDK for CollieAi — safe customer-owned LLM streaming and input moderation.
Downloads
310
Readme
@collieai/sdk
Node/TypeScript SDK for CollieAi — safe customer-owned LLM streaming and pre-generation input moderation. You run your own model; the SDK checks the prompt before you call it and lets you stream back only CollieAi-released text — never raw model output. Mirrors the Python SDK.
Status: 0.1.0. Input moderation, streaming preflight,
protectStream/protectBuffered, the low-level session, SSE delivery (session.streamEvents
- browser stream tokens), and provider adapters (
@collieai/sdk/adapters/*). Zero runtime dependencies (uses the globalfetch).
Install
npm install @collieai/sdkQuick start
import { CollieClient } from "@collieai/sdk";
const collie = new CollieClient({
apiKey: "clai_...",
baseUrl: "https://app.collieai.io",
projectId: "project_123",
});Check an input before calling your LLM
const result = await collie.moderate.input({ prompt: userPrompt });
if (result.blocked) return result.blockMessage ?? "Input blocked by policy.";A policy block is a normal result (result.blocked === true), not an error.
Stream safely (Express)
protectStream checks the input, calls your LLM only if it passes, batches
the output, and yields only safe events. Pass a factory — a zero-arg function
returning your stream — not an already-started stream.
import { openaiFactory } from "@collieai/sdk/adapters/openai"; // optional helper
const factory = openaiFactory(openai, {
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
});
for await (const event of collie.streaming.protectStream({ input: prompt, rawStreamFactory: factory })) {
if (event.type === "delta") res.write(event.text); // forward ONLY safe text
else if (event.type === "blocked" || event.type === "input_blocked") {
res.write(event.blockMessage ?? "Blocked by policy.");
break;
}
}See examples/express.ts and
examples/next-route.ts.
Choose the UX up front (preflight)
const cap = await collie.streaming.preflight(); // cached until cap.validUntil
if (cap.recommendedClientBehavior === "stream") { /* protectStream */ }
else if (cap.recommendedClientBehavior === "buffer_then_show") {
const r = await collie.streaming.protectBuffered({ input: prompt, rawStreamFactory: factory });
} else throw new Error(cap.reasonDetail ?? cap.reason ?? "unavailable");Or pass requireStreaming: true to protectStream — it preflights and throws
BufferedFallbackRequired / a PreflightError before calling your LLM.
Relay to a browser (SSE)
import { toSse } from "@collieai/sdk";
for await (const event of session.streamEvents()) { // auto-resumes from Last-Event-ID
if (event.type === "interrupted") continue; // reconnecting; nothing to forward
res.write(toSse(event)); // SSE bytes for text/event-stream
if (event.type === "blocked" || event.type === "finished") break;
}For direct browser subscription, mint a short-lived, job-scoped token
(const st = await session.mintStreamToken()) and open new EventSource(st.url).
Errors
Catch typed errors (all extend CollieError): ChunkRetryExhausted,
ChunkPolicyChanged, ChunkQuotaExceeded, ChunkSessionUnrecoverable,
ChunkStreamingUnsupported, BufferedFallbackRequired, ProjectNotFound /
PlanNotEntitled / … (PreflightError), ProviderStreamFactoryRequired,
ConcurrentSessionUseError, ModerationError, CollieConnectionError,
CollieApiError.
Develop
npm install
npm run typecheck # tsc --noEmit
npm test # vitest
npm run build # tsc -> dist/