
Product
PHP and Composer Support Is Now in Beta
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.
@opitacode/ocais
Advanced tools
OCAIS — Opita Code AI Stream. Lightweight AI streaming SDK for AWS Lambda. Zero deps, TypeScript-first, provider-agnostic.
Lightweight AI streaming SDK for AWS Lambda. Zero deps. TypeScript-first. Provider-agnostic.
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 SDK | OCAIS | |
|---|---|---|
| Bundle | ~2.8 MB | ~15 KB |
| Dependencies | 30+ transitive | 0 |
| Target | Next.js, React | AWS Lambda |
| Tool execution | Optional | First-class with execute |
| Cancellation | AbortController | AbortSignal + timeoutMs |
| Errors | Generic | Typed hierarchy |
npm install @opitacode/ocais
Some optional features require installing peer-dependencies. None are required for the core streaming API.
| Feature | Package | Install |
|---|---|---|
generateObject() (structured output via Zod) | zod | Included as a direct dependency in 3.0.1+ |
signJWT() / verifyJWT() with algorithm: "EdDSA" | @noble/ed25519 | npm install @noble/ed25519 |
passwordHash() / passwordVerify() / needsRehash() | @node-rs/argon2 | npm 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.
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);
}
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" }],
});
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();
},
);
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);
}
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 }
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
})) { ... }
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.
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)
streamText(options)| Option | Type | Required | Default | Description |
|---|---|---|---|---|
provider | Provider | ✅ | — | Provider instance (openai(), google()) |
model | string | ✅ | — | Model name (e.g. deepseek-chat, gemini-2.5-flash) |
messages | Message[] | ✅ | — | Conversation history |
system | string | — | — | System prompt |
tools | Record<string, ToolDefinition> | — | — | Tools available to the model |
temperature | number | — | — | Sampling temperature |
maxTokens | number | — | — | Max output tokens |
maxSteps | number | — | 5 | Max LLM round-trips (for tool execution) |
signal | AbortSignal | — | — | Cancel the operation |
timeoutMs | number | — | — | Throw after N milliseconds |
onStart | (ctx) => void | — | — | Called before the first request |
onComplete | (ctx) => void | — | — | Called after successful stream |
onError | (ctx) => void | — | — | Called on any error |
onAbort | () => void | — | — | Called when signal/timeout fires |
generateObject(options)Same as streamText except:
prompt: string (replaces messages + system)schema: ZodSchema (required) — validates the outputcreateSSEWriter(stream)Helper for writing to AWS Lambda's responseStream in SSE format. See Lambda example.
| Provider | Constructor | Compatible APIs |
|---|---|---|
| OpenAI-compatible | openai({ apiKey, baseURL? }) | OpenAI, DeepSeek, OpenRouter, Groq, etc. |
| Google Gemini | google({ apiKey }) | Gemini 1.5, 2.0, 2.5 |
streamObject — streaming structured output (v2.1)npm install
npm run typecheck # tsc --noEmit
npm test # node --test --experimental-strip-types tests/*.test.ts
MIT © Opita Code
FAQs
OCAIS — Opita Code AI Stream. Lightweight AI streaming SDK for AWS Lambda. Zero deps, TypeScript-first, provider-agnostic.
The npm package @opitacode/ocais receives a total of 10 weekly downloads. As such, @opitacode/ocais popularity was classified as not popular.
We found that @opitacode/ocais demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.

Research
/Security News
Three compromised Rust crates pulled in a malicious dependency that downloaded and executed cross-platform malware during Cargo builds.