Sign In

@opitacode/ocais

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opitacode/ocais

OCAIS — Opita Code AI Stream. Lightweight AI streaming SDK for AWS Lambda. Zero deps, TypeScript-first, provider-agnostic.

latest
Source
npmnpm
Version
3.0.1
Version published
Weekly downloads
14
-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

OCAIS — Opita Code AI Stream

Lightweight AI streaming SDK for AWS Lambda. Zero deps. TypeScript-first. Provider-agnostic.

License: MIT Node.js

Why OCAIS?

Other SDKs (Vercel AI SDK, LangChain) are designed for fullstack web frameworks. OCAIS is designed for a single use case: streaming AI in AWS Lambda with SSE.

Vercel AI SDKOCAIS
Bundle~2.8 MB~15 KB
Dependencies30+ transitive0
TargetNext.js, ReactAWS Lambda
Tool executionOptionalFirst-class with execute
CancellationAbortControllerAbortSignal + timeoutMs
ErrorsGenericTyped hierarchy

Install

npm install @opitacode/ocais

Peer dependencies

Some optional features require installing peer-dependencies. None are required for the core streaming API.

FeaturePackageInstall
generateObject() (structured output via Zod)zodIncluded as a direct dependency in 3.0.1+
signJWT() / verifyJWT() with algorithm: "EdDSA"@noble/ed25519npm install @noble/ed25519
passwordHash() / passwordVerify() / needsRehash()@node-rs/argon2npm install @node-rs/argon2

The provider modules (openai(), google()) and core streaming (streamText()) need only fetch, available in Node 20+. See docs/peer-deps.md for the full table.

Quick start

Streaming with DeepSeek

import { streamText, openai } from "@opitacode/ocais";

const stream = streamText({
  provider: openai({
    apiKey: process.env.DEEP_SEEK_KEY!,
    baseURL: "https://api.deepseek.com",
  }),
  model: "deepseek-chat",
  system: "You are a helpful assistant.",
  messages: [{ role: "user", content: "Hello" }],
});

for await (const chunk of stream) {
  if (chunk.type === "text") process.stdout.write(chunk.text);
}

Streaming with Google Gemini

import { streamText, google } from "@opitacode/ocais";

const stream = streamText({
  provider: google({ apiKey: process.env.API_GOOGLE_CLOUD! }),
  model: "gemini-2.5-flash",
  messages: [{ role: "user", content: "Hello" }],
});

In AWS Lambda (Function URL + SSE)

import { streamText, openai, createSSEWriter } from "@opitacode/ocais";

export const handler = awslambda.streamifyResponse(
  async (event, responseStream) => {
    const writer = createSSEWriter(responseStream);
    const body = JSON.parse(event.body || "{}");

    const stream = streamText({
      provider: openai({
        apiKey: process.env.DEEP_SEEK_KEY!,
        baseURL: "https://api.deepseek.com",
      }),
      model: "deepseek-chat",
      system: "Eres Aura, asistente de Vibe Studio.",
      messages: body.messages,
    });

    for await (const chunk of stream) {
      writer.write(chunk);
    }
    writer.done();
  },
);

Server-side tool execution (multi-step)

import { streamText, openai } from "@opitacode/ocais";

const stream = streamText({
  provider: openai({ apiKey, baseURL: "https://api.deepseek.com" }),
  model: "deepseek-chat",
  system: "You can check the weather and book flights.",
  messages: [{ role: "user", content: "Book me a flight to Bogotá" }],
  tools: {
    getWeather: {
      description: "Get weather for a city",
      parameters: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"],
      },
      execute: async ({ city }) => {
        return { temp: 22, condition: "sunny" };
      },
    },
    bookFlight: {
      description: "Book a flight",
      parameters: { type: "object", properties: { to: { type: "string" } } },
      execute: async ({ to }) => ({ confirmation: `Flight to ${to} booked` }),
    },
  },
  maxSteps: 5, // up to 5 LLM round-trips
});

for await (const chunk of stream) {
  if (chunk.type === "text") process.stdout.write(chunk.text);
  if (chunk.type === "tool-call") console.log("tool:", chunk.toolName, chunk.args);
  if (chunk.type === "tool-result") console.log("result:", chunk.result);
}

Structured output (Zod)

import { generateObject, google } from "@opitacode/ocais";
import { z } from "zod";

const { object } = await generateObject({
  provider: google({ apiKey }),
  model: "gemini-2.5-flash",
  schema: z.object({
    name: z.string(),
    age: z.number(),
  }),
  prompt: "Generate a fictional person",
});
// object: { name: string; age: number }

Cancellation

Use standard AbortSignal and/or timeoutMs. Both throw typed errors.

import { streamText, OCAISAbortError, OCAISTimeoutError } from "@opitacode/ocais";

// AbortSignal (e.g. from a request)
const controller = new AbortController();
req.on("close", () => controller.abort());

try {
  for await (const chunk of streamText({
    provider: openai({ apiKey }),
    model: "deepseek-chat",
    messages: [{ role: "user", content: "Long task" }],
    signal: controller.signal,
  })) {
    if (chunk.type === "text") process.stdout.write(chunk.text);
  }
} catch (err) {
  if (err instanceof OCAISAbortError) {
    // request was closed by client
  } else if (err instanceof OCAISTimeoutError) {
    // exceeded timeoutMs
    console.log(`Timed out after ${err.elapsedMs}ms (limit: ${err.timeoutMs}ms)`);
  } else {
    throw err;
  }
}

// Or just timeoutMs without an explicit AbortController
for await (const chunk of streamText({
  ...,
  timeoutMs: 5000, // throw OCAISTimeoutError if it takes >5s
})) { ... }

Observability

Pass lifecycle hooks to track requests without wrapping the stream:

for await (const chunk of streamText({
  provider: openai({ apiKey }),
  model: "deepseek-chat",
  messages: [{ role: "user", content: "Hi" }],
  onStart: (ctx) => {
    console.log(`[start] model=${ctx.model} tools=${ctx.toolNames?.join(",")}`);
  },
  onComplete: (ctx) => {
    console.log(
      `[complete] steps=${ctx.steps} duration=${ctx.durationMs}ms ` +
      `tokens=${ctx.usage?.totalTokens ?? "?"}`,
    );
  },
  onError: (ctx) => {
    console.error(`[error] step=${ctx.step}`, ctx.error);
  },
  onAbort: () => {
    console.warn("[abort]");
  },
})) {
  // consume
}

The lifecycle hooks (onStart, onComplete, onError, onAbort) above are the canonical observability API.

Error hierarchy

All OCAIS errors extend OCAISError for easy instanceof checks:

OCAISError (base)
├── OCAISAbortError        // user cancelled via AbortSignal
├── OCAISTimeoutError      // exceeded timeoutMs (has .timeoutMs, .elapsedMs)
├── OCAISParseError        // malformed JSON, SSE parse error (has .raw)
├── OCAISToolError         // tool execute() threw (has .toolName, .toolCallId)
└── OCAISProviderError     // provider returned non-2xx (has .provider, .status)

API Reference

streamText(options)

OptionTypeRequiredDefaultDescription
providerProviderProvider instance (openai(), google())
modelstringModel name (e.g. deepseek-chat, gemini-2.5-flash)
messagesMessage[]Conversation history
systemstringSystem prompt
toolsRecord<string, ToolDefinition>Tools available to the model
temperaturenumberSampling temperature
maxTokensnumberMax output tokens
maxStepsnumber5Max LLM round-trips (for tool execution)
signalAbortSignalCancel the operation
timeoutMsnumberThrow after N milliseconds
onStart(ctx) => voidCalled before the first request
onComplete(ctx) => voidCalled after successful stream
onError(ctx) => voidCalled on any error
onAbort() => voidCalled when signal/timeout fires

generateObject(options)

Same as streamText except:

  • prompt: string (replaces messages + system)
  • schema: ZodSchema (required) — validates the output

createSSEWriter(stream)

Helper for writing to AWS Lambda's responseStream in SSE format. See Lambda example.

Providers

ProviderConstructorCompatible APIs
OpenAI-compatibleopenai({ apiKey, baseURL? })OpenAI, DeepSeek, OpenRouter, Groq, etc.
Google Geminigoogle({ apiKey })Gemini 1.5, 2.0, 2.5

Roadmap

  • Streaming text (v1.0)
  • Server-side tool execution with multi-step (v1.0)
  • Structured output via Zod (v1.0)
  • AbortSignal + timeout + typed errors (v2.0)
  • Observability hooks (v2.0)
  • Anthropic Claude provider (v2.1)
  • streamObject — streaming structured output (v2.1)
  • Local Ollama provider (v2.1)
  • Event-based observability API (v2.1)
  • Pre-built cultural prompt helpers (v2.2)

Development

npm install
npm run typecheck   # tsc --noEmit
npm test            # node --test --experimental-strip-types tests/*.test.ts

License

MIT © Opita Code

Keywords

ai

FAQs

Package last updated on 23 Jul 2026

Related posts