npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ultrasafeai

v1.1.4

Published

UltrasafeAI REST API with comprehensive endpoints for AI services

Readme

UltrasafeAI TypeScript SDK

npm version License: MIT

The official TypeScript / JavaScript SDK for the UltrasafeAI API. Provides access to chat completions, vision, embeddings, reranking, image generation, speech-to-text, text-to-speech, real-time audio streaming, vector stores, assistants, threads, and more.

Works in Node.js 18+, Deno, Bun, and modern browsers via native fetch.

Base URL: https://api.us.tech/v1

Installation

npm install ultrasafeai
# or
yarn add ultrasafeai

Client Setup

The client reads ULTRASAFEAI_API_KEY from the environment automatically if apiKey is not passed.

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({
    apiKey: process.env.ULTRASAFEAI_API_KEY,
});

Options:

| Parameter | Type | Description | |---|---|---| | apiKey | string | Your UltrasafeAI API key | | environment | string \| object | Environment override | | baseUrl | string | Override the base URL | | timeoutInSeconds | number | Request timeout (default: 60) | | maxRetries | number | Max retry attempts | | fetch | FetchFunction | Custom fetch implementation |


Chat Completions

Non-Streaming

Method: client.chat.completions.create(request)
Endpoint: POST /chat/completions

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.chat.completions.create({
    model: "usf-mini",
    messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: "Hello!" }
    ]
});

console.log(response.choices[0].message.content);

Payload: CreateCompletionsRequest

| Parameter | Type | Required | Description | |---|---|---|---| | model | string | Yes | Model ID (e.g. "usf-mini") | | messages | array | Yes | Conversation history. Roles: "system", "user", "assistant", "tool" | | tools | array | No | Function or custom tools the model may call | | tool_choice | string \| object | No | "none", "auto", "required", or a specific tool | | parallel_tool_calls | boolean | No | Allow parallel tool calls (default: true) | | reasoning_effort | string | No | Controls reasoning depth: "none", "low", "medium", "high" (default: "none") | | web_search | boolean | No | Enable web search (default: false) | | response_format | object | No | {type: "text"}, {type: "json_object"}, or {type: "json_schema", json_schema: {...}} | | max_tokens | number | No | Max tokens to generate | | temperature | number | No | Sampling temperature 0–2 | | top_p | number | No | Nucleus sampling probability mass | | n | number | No | Number of completions to generate | | stop | string \| string[] | No | Stop sequences (up to 4) | | presence_penalty | number | No | Penalty for repeated tokens (-2.0 to 2.0) | | frequency_penalty | number | No | Frequency-based penalty (-2.0 to 2.0) | | seed | number | No | Seed for deterministic sampling | | store | boolean | No | Store conversation for retrieval | | conversation_id | string | No | Continue an existing stored conversation | | user | string | No | Stable end-user identifier |

Response: ChatCompletion

{
    id: "chatcmpl-abc123",
    object: "chat.completion",
    created: 1700000000,
    model: "usf-mini",
    conversation_id: "conv_xyz",       // present when store=true
    choices: [
        {
            index: 0,
            message: {
                role: "assistant",
                content: "Hello! How can I help you?",
                tool_calls: null,      // array of tool calls when finish_reason="tool_calls"
                refusal: null
            },
            finish_reason: "stop"      // "stop", "length", "tool_calls", "content_filter"
        }
    ],
    usage: {
        prompt_tokens: 12,
        completion_tokens: 10,
        total_tokens: 22
    }
}

Streaming

Method: client.chat.completions.create(request) with stream: true
Endpoint: POST /chat/completions (with stream: true)

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const stream = await client.chat.completions.create({
    model: "usf-mini",
    messages: [{ role: "user", content: "Tell me a joke" }],
    stream: true,
});

for await (const chunk of stream) {
    const delta = chunk.choices?.[0]?.delta?.content;
    if (delta) process.stdout.write(delta);
}

Payload: CreateCompletionsStreamRequest — same fields as non-streaming.

Response: Stream<ChatCompletionChunk>

Each chunk:

{
    id: "chatcmpl-abc123",
    object: "chat.completion.chunk",
    created: 1700000000,
    model: "usf-mini",
    choices: [
        {
            index: 0,
            delta: {
                role: "assistant",         // only on first chunk
                content: "Hello",          // incremental text; concatenate across chunks
                reasoning_content: null,   // chain-of-thought when available
                tool_calls: null           // incremental tool call data
            },
            finish_reason: null            // non-null only on the final chunk
        }
    ],
    usage: null  // present only on last chunk when stream_options.include_usage=true
}

Vision

Vision uses the same chat.completions.create / createStream methods. Pass an array of content parts instead of a plain string for the content field of a user message.

Non-Streaming

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.chat.completions.create({
    model: "usf-mini",
    messages: [
        {
            role: "user",
            content: [
                { type: "text", text: "What is in this image?" },
                {
                    type: "image_url",
                    image_url: { url: "https://example.com/image.jpg" }
                }
            ]
        }
    ]
});

console.log(response.choices[0].message.content);

Base64 image:

import fs from "fs";

const imageData = fs.readFileSync("image.jpg").toString("base64");

const response = await client.chat.completions.create({
    model: "usf-mini",
    messages: [
        {
            role: "user",
            content: [
                { type: "text", text: "Describe this image." },
                {
                    type: "image_url",
                    image_url: { url: `data:image/jpeg;base64,${imageData}` }
                }
            ]
        }
    ]
});

Streaming

const stream = await client.chat.completions.create({
    model: "usf-mini",
    messages: [
        {
            role: "user",
            content: [
                { type: "text", text: "What's in this image?" },
                { type: "image_url", image_url: { url: "https://example.com/image.jpg" } }
            ]
        }
    ],
    stream: true,
});

for await (const chunk of stream) {
    const delta = chunk.choices?.[0]?.delta?.content;
    if (delta) process.stdout.write(delta);
}

Content part types:

| Type | Fields | Description | |---|---|---| | "text" | text: string | Plain text content | | "image_url" | image_url: { url: string } | URL or data:image/...;base64,... string |

Response: Same ChatCompletion / ChatCompletionChunk as standard chat completions.


Embeddings

Method: client.embeddings.create(request)
Endpoint: POST /embeddings

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

// Single string
const response = await client.embeddings.create({
    model: "usf-embed",
    input: "The quick brown fox"
});

console.log(response.data[0].embedding);  // number[]

// Multiple strings
const batchResponse = await client.embeddings.create({
    model: "usf-embed",
    input: ["First sentence", "Second sentence"],
    dimensions: 512
});

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | model | string | Yes | Embedding model ID (e.g. "usf-embed") | | input | string \| string[] \| number[] \| number[][] | Yes | Text or token arrays to embed. Max 8192 tokens per input, 300k tokens total | | dimensions | number | No | Output embedding dimensions (supported on usf-embed and later) | | encoding_format | string | No | "float" (default) or "base64" | | user | string | No | End-user identifier |

Response: EmbeddingResponse

{
    object: "list",
    data: [
        {
            object: "embedding",
            index: 0,
            embedding: [0.0023, -0.0142, ...]  // number[]
        }
    ],
    model: "usf-embed",
    usage: {
        prompt_tokens: 8,
        total_tokens: 8
    }
}

Reranker

Method: client.rerank.create(request)
Endpoint: POST /rerank

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.rerank.create({
    model: "usf-rerank",
    query: "What is machine learning?",
    texts: [
        "Machine learning is a subset of AI.",
        "The weather is sunny today.",
        "Deep learning uses neural networks."
    ],
    top_n: 2
});

for (const result of response.results) {
    console.log(result.index, result.relevance_score, result.text);
}

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | model | string | Yes | Rerank model ID (e.g. "usf-rerank") | | query | string | Yes | Search query to rank documents against | | texts | string[] | Yes | Documents to rerank | | top_n | number | No | Number of top results to return |

Response:

{
    results: [
        {
            index: 0,
            relevance_score: 0.97,
            text: "Machine learning is a subset of AI."
        },
        {
            index: 2,
            relevance_score: 0.85,
            text: "Deep learning uses neural networks."
        }
    ]
}

Image Generation

Generate

Method: client.images.generate(request)
Endpoint: POST /images/generations

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.images.generate({
    model: "usf-mini-image",
    prompt: "A futuristic city at sunset",
    size: "1024x1024",
    n: 1,
    response_format: "url"
});

console.log(response.data[0].url);

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | model | string | Yes | Image model ID (e.g. "usf-mini-image") | | prompt | string | Yes | Text description of the image to generate | | size | string | No | "256x256", "512x512", "1024x1024" | | n | number | No | Number of images to generate | | response_format | string | No | "url" (default) or "b64_json" |

Response: ImageResponse

{
    created: 1700000000,
    images: [
        { url: "https://..." },      // when response_format="url"
        { b64_json: "iVBORw..." }    // when response_format="b64_json"
    ],
    data: [...]  // same contents as images; present for OpenAI-compat clients
}

Access via either field — both contain typed Image objects:

console.log(response.images[0].url);  // preferred
console.log(response.data[0].url);    // OpenAI-compat alias

Speech to Text

Method: client.audio.transcriptions.create(request)
Endpoint: POST /audio/transcribe

import fs from "fs";
import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.audio.transcriptions.create({
    file: fs.createReadStream("audio.mp3"),
    model: "usf-mini-asr",
    language: "en",
    response_format: "json"
});

console.log(response.text);

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | file | File | Yes | Audio file (mp3, mp4, wav, flac, ogg, webm, etc.) | | model | string | Yes | ASR model ID (e.g. "usf-mini-asr") | | language | string | No | ISO 639-1 language code (e.g. "en", "es") | | response_format | string | No | "json" (default), "text", "srt", "verbose_json", "vtt" |

Response: TranscriptionResponse

{
    text: "Hello, this is a transcription.",
    language: "en",
    duration: 3.5
}

Live ASR (WebSocket)

Live ASR uses a WebSocket-based client. Access it via client.audio.stream.connect().

Class: AudioStreamSession
Endpoint: wss://api.us.tech/v1/audio/stream

import { UltrasafeAI } from "ultrasafeai";
import fs from "fs";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const session = await client.audio.stream.connect({
    model: "usf-mini-asr",
    sampleRate: 16000,
    audioFormat: "pcm_s16le",
    enableVad: false,
    partialResults: true,
    interimMinDurationMs: 500,
    fullContextRetranscription: true
});

session.on("ready", (event) => {
    console.log("Connected — streaming audio");
});

session.on("transcript", (event) => {
    console.log(event.full_text);
});

session.on("close", (code, reason) => {
    console.log(`Closed: ${code} ${reason}`);
});

// Send PCM audio frames as Uint8Array or ArrayBuffer
const audioBuffer = fs.readFileSync("audio.raw");
session.send(new Uint8Array(audioBuffer));

// Close when done
session.close();

Connect options:

| Parameter | Type | Default | Description | |---|---|---|---| | model | string | "usf-mini-asr" | ASR model ID | | sampleRate | number | 16000 | Audio sample rate in Hz | | audioFormat | string | "pcm_s16le" | "pcm_s16le" or "pcm_f32le" | | enableVad | boolean | false | Enable voice activity detection | | partialResults | boolean | true | Emit partial results before segment is final | | interimMinDurationMs | number | 500 | Min audio duration (ms) before emitting interim | | fullContextRetranscription | boolean | true | Re-transcribe with full audio context for accuracy |

Session methods:

| Method | Description | |---|---| | send(audio: Uint8Array \| ArrayBufferLike) | Send a PCM audio frame | | on(event, handler) | Subscribe to a server event | | off(event, handler) | Unsubscribe from a server event | | close() | Close the session gracefully |

Session events:

| Event | Handler type | Description | |---|---|---| | ready | (event: TranscriptEvent & { type: "ready" }) => void | Server ready to receive audio | | transcript | (event: TranscriptEvent & { type: "transcript" }) => void | Transcription result (partial or final) | | speech_activity | (event: TranscriptEvent & { type: "speech_activity" }) => void | VAD speech start/end | | control | (event: TranscriptEvent & { type: "control" }) => void | Lifecycle signal (action: "stop") | | error | (event: TranscriptEvent & { type: "error" }) => void | Server-side error | | close | (code: number, reason: string) => void | Connection closed | | ws_error | (error: Error) => void | WebSocket error | | parse_error | (error: Error, raw: string) => void | A frame could not be decoded/parsed (surfaced, not swallowed) |

TranscriptEvent shape:

{
    type: "transcript",        // "ready" | "speech_activity" | "transcript" | "control" | "error"
    request_id: "req_abc",
    is_final: true,
    full_text: "Hello world this is a test",
    committed_text: "Hello world",
    segment: {
        id: 3,
        text: "this is a test",
        is_final: true,
        start: 1.2,
        end: 2.8,
        confidence: 0.95
    }
}

Vector Stores

Access: client.vectorStores

Create Vector Store

Method: client.vectorStores.create(request)
Endpoint: POST /vector_stores

import fs from "fs";
import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const store = await client.vectorStores.create({
    name: "My Knowledge Base",
    files: [fs.createReadStream("document.pdf")]
});

console.log(store.id);      // e.g. "vs_abc123"
console.log(store.status);  // poll until "ready"

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | name | string | Yes | Display name for the vector store | | files | File[] | No | Files to upload and index immediately |

Response: VectorStore

{
    id: "vs_abc123",
    object: "vector_store",
    created_at: 1700000000,
    name: "My Knowledge Base",
    status: "ready",
    file_counts: { in_progress: 0, completed: 1, failed: 0, cancelled: 0, total: 1 }
}

List Vector Stores

const response = await client.vectorStores.list({ limit: 20 });
for (const store of response.data) {
    console.log(store.id, store.name, store.status);
}

Retrieve Vector Store

const store = await client.vectorStores.retrieve("vs_abc123");
console.log(store.status);

Delete Vector Store

const result = await client.vectorStores.delete("vs_abc123");
console.log(result.deleted); // true

Search Vector Store

Method: client.vectorStores.search(vectorStoreId, request)
Endpoint: POST /vector_stores/{vector_store_id}/search

const results = await client.vectorStores.search("vs_abc123", {
    query: "What is the refund policy?"
});

for (const item of results.data) {
    console.log(item);
}

File Management

Upload File to Vector Store

const file = await client.vectorStores.uploadFile("vs_abc123", {
    file: fs.createReadStream("doc.pdf")
});

List Vector Store Files

const files = await client.vectorStores.listFiles("vs_abc123", { limit: 20 });
for (const f of files.data) {
    console.log(f.id);
}

Retrieve / Delete Vector Store File

const file = await client.vectorStores.retrieveFile("vs_abc123", "file_xyz");

const result = await client.vectorStores.deleteFile("vs_abc123", "file_xyz");
console.log(result.deleted); // true

File Batches

// Create a batch of files by ID
const batch = await client.vectorStores.createFileBatch("vs_abc123", {
    file_ids: ["file_abc", "file_def"]
});

// Retrieve batch status
const status = await client.vectorStores.retrieveFileBatch("vs_abc123", batch.id);

// Cancel a running batch
await client.vectorStores.cancelFileBatch("vs_abc123", batch.id);

// List files in a batch
const batchFiles = await client.vectorStores.listBatchFiles("vs_abc123", batch.id);

Assistants

Access: client.assistants

Create Assistant

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const assistant = await client.assistants.create({
    model: "usf-mini",
    name: "My Assistant",
    description: "A helpful customer support bot",
    instructions: "You are a customer support agent. Be concise and friendly.",
    tools: [{ type: "code_interpreter" }],
    temperature: 0.5
});

console.log(assistant.id);

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | model | string | Yes | Model ID | | name | string | No | Assistant name | | description | string | No | Short description | | instructions | string | No | System prompt / instructions | | tools | object[] | No | Tool definitions (e.g. [{ type: "code_interpreter" }]) | | tool_resources | object | No | Resources for tools | | metadata | object | No | Arbitrary key-value metadata | | temperature | number | No | Sampling temperature | | top_p | number | No | Nucleus sampling | | response_format | string | No | Response format |

Response: Assistant

{
    id: "asst_abc123",
    object: "assistant",
    created_at: 1700000000,
    name: "My Assistant",
    description: "A helpful customer support bot",
    model: "usf-mini",
    instructions: "You are a customer support agent.",
    tools: [{ type: "code_interpreter" }]
}

List Assistants

const assistants = await client.assistants.list({ limit: 20 });
for (const asst of assistants.data) {
    console.log(asst.id, asst.name);
}

Payload:

| Parameter | Type | Description | |---|---|---| | limit | number | Max items to return | | after | string | Pagination cursor |

Retrieve Assistant

const assistant = await client.assistants.retrieve("asst_abc123");
console.log(assistant.name);

Delete Assistant

const result = await client.assistants.delete("asst_abc123");
console.log(result.deleted); // true

Response: DeletedResponse

{ id: "asst_abc123", object: "assistant.deleted", deleted: true }

Threads

Access: client.threads

Create Thread

Method: client.threads.create(request)
Endpoint: POST /threads

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const thread = await client.threads.create({
    messages: [
        { role: "user", content: "Hello, I need help with my account." }
    ]
});

console.log(thread.id); // e.g. "thread_abc123"

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | messages | object[] | No | Initial messages to seed the thread | | metadata | object | No | Arbitrary key-value metadata |

Response: Thread

{
    id: "thread_abc123",
    object: "thread",
    created_at: 1700000000,
    metadata: {}
}

List Threads

const threads = await client.threads.list({ limit: 20 });
for (const t of threads.data) {
    console.log(t.id, t.created_at);
}

Retrieve Thread

const thread = await client.threads.retrieve("thread_abc123");
console.log(thread.id);

Thread Messages

Thread messages are managed via client.threads.addMessage and client.threads.listMessages.

Add Message to Thread

Method: client.threads.addMessage(threadId, request)
Endpoint: POST /threads/{thread_id}/messages

const message = await client.threads.addMessage("thread_abc123", {
    role: "user",
    content: "Can you summarize my previous question?"
});

console.log(message.id);   // e.g. "msg_xyz"
console.log(message.role); // "user"

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | role | string | Yes | Message role: "user" or "assistant" | | content | string | Yes | Text content of the message | | attachments | object[] | No | File attachments | | metadata | object | No | Arbitrary key-value metadata |

Response: Message

{
    id: "msg_xyz",
    object: "thread.message",
    created_at: 1700000000,
    thread_id: "thread_abc123",
    role: "user",
    content: [{ type: "text", text: { value: "Can you summarize my previous question?" } }]
}

List Messages in Thread

Method: client.threads.listMessages(threadId, params?)
Endpoint: GET /threads/{thread_id}/messages

const messages = await client.threads.listMessages("thread_abc123", { limit: 20 });
for (const msg of messages.data) {
    console.log(msg.role, msg.content);
}

Run Thread with Assistant

Method: client.threads.run(threadId, request)
Endpoint: POST /threads/{thread_id}/runs

const run = await client.threads.run("thread_abc123", {
    assistant_id: "asst_abc123",
    model: "usf-mini",
    instructions: "Be concise."
});

console.log(run.id);     // e.g. "run_abc"
console.log(run.status); // "queued" | "in_progress" | "completed" | "failed"

Payload:

| Parameter | Type | Required | Description | |---|---|---|---| | assistant_id | string | Yes | Assistant to use for this run | | model | string | No | Override the assistant's model | | instructions | string | No | Override the assistant's instructions | | tools | object[] | No | Override the assistant's tools | | metadata | object | No | Arbitrary key-value metadata |


Models

Access: client.models

List Models

Method: client.models.list()
Endpoint: GET /models

import { UltrasafeAI } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const response = await client.models.list();
for (const model of response.data) {
    console.log(model.id, model.type, model.description);
}

Response: ListModelsResponse

{
    object: "list",
    data: [
        {
            id: "usf-mini",
            object: "model",
            name: "USF Mini",
            type: "chat",
            description: "Fast and efficient chat model",
            is_active: true,
            created: 1700000000,
            owned_by: "ultrasafeai"
        }
    ]
}

Retrieve Model

Method: client.models.retrieve(model)
Endpoint: GET /models/{model}

const model = await client.models.retrieve("usf-mini");
console.log(model.id, model.is_active);

Response: Model

{
    id: "usf-mini",
    object: "model",
    name: "USF Mini",
    type: "chat",
    description: "Fast and efficient chat model",
    is_active: true,
    created: 1700000000,
    owned_by: "ultrasafeai"
}

Error Handling

import { UltrasafeAI, UltrasafeaiApi } from "ultrasafeai";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

try {
    const response = await client.chat.completions.create({
        model: "usf-mini",
        messages: [{ role: "user", content: "Hello" }]
    });
} catch (error) {
    if (error instanceof UltrasafeaiApi.UnauthorizedError) {
        console.error("Invalid API key:", error.message);
    } else if (error instanceof UltrasafeaiApi.BadRequestError) {
        console.error("Bad request:", error.message);
    } else {
        throw error;
    }
}

| Error class | HTTP Status | Description | |---|---|---| | UltrasafeaiApi.UnauthorizedError | 401 | Invalid or missing API key | | UltrasafeaiApi.BadRequestError | 400 | Invalid request parameters | | UltrasafeaiApiError | any | General API error with statusCode and body | | UltrasafeaiApiTimeoutError | — | Request timed out |

Accessing Raw HTTP Response

const result = await client.chat.completions.create({
    model: "usf-mini",
    messages: [{ role: "user", content: "Hello" }]
});

// Access via .withRawResponse() for headers / status
const raw = await client.chat.completions.withRawResponse().create({
    model: "usf-mini",
    messages: [{ role: "user", content: "Hello" }]
});

console.log(raw.rawResponse.status);
console.log(raw.data.choices[0].message.content);

Retries

The client automatically retries on connection errors, timeouts, and 429/5xx responses with exponential backoff. Default is 2 retries.

// Disable retries
const client = new UltrasafeAI({ apiKey: "...", maxRetries: 0 });

// Increase retries
const client = new UltrasafeAI({ apiKey: "...", maxRetries: 5 });

// Override per request
await client.chat.completions.create({ model: "usf-mini", messages: [...] }, { maxRetries: 0 });

Timeouts

Requests time out after 60 seconds by default.

// Set globally
const client = new UltrasafeAI({ apiKey: "...", timeoutInSeconds: 30 });

// Override per request
await client.chat.completions.create({ model: "usf-mini", messages: [...] }, { timeoutInSeconds: 10 });

Lib Helpers

The SDK ships ergonomics helpers as named subpath imports.


Streaming Accumulator

Import: import { ChatCompletionStream } from "ultrasafeai/lib/streaming/chat"

Wraps a raw stream: true response and accumulates deltas so you can read the final assembled message after iteration.

import { UltrasafeAI } from "ultrasafeai";
import { ChatCompletionStream } from "ultrasafeai/lib/streaming/chat";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const raw = await client.chat.completions.create({
    model: "usf-mini",
    messages: [{ role: "user", content: "Count from 1 to 5." }],
    stream: true,
});

const stream = new ChatCompletionStream(raw);

for await (const chunk of stream) {
    const delta = chunk.choices?.[0]?.delta?.content;
    if (delta) process.stdout.write(delta);
}

const completion = stream.getFinalCompletion();
console.log(completion.choices[0].finish_reason);          // "stop"
console.log(completion.choices[0].message.content);        // full assembled text

Methods:

| Method | Description | |---|---| | new ChatCompletionStream(stream) | Wrap a raw AsyncIterable of chunks | | for await (chunk of stream) | Iterate and accumulate simultaneously | | await stream.untilDone() | Drain the stream without iterating manually, returns this | | stream.getFinalCompletion() | Returns assembled { object, choices } — call after stream is consumed |


Tool Helpers

Import: import { functionTool, normalizeTool, normalizeTools } from "ultrasafeai/lib/tools"

import { functionTool, normalizeTools } from "ultrasafeai/lib/tools";
import { zodToJsonSchema } from "zod-to-json-schema";
import { z } from "zod";

// Build a flat tool from a Zod schema
const WeatherSchema = z.object({
    city: z.string().describe("City name"),
    unit: z.enum(["celsius", "fahrenheit"]).optional(),
});

const weatherTool = functionTool(
    "get_weather",
    "Get the current weather for a city.",
    zodToJsonSchema(WeatherSchema)
);

const response = await client.chat.completions.create({
    model: "usf-mini",
    messages: [{ role: "user", content: "What's the weather in London?" }],
    tools: [weatherTool],
});

API accepts flat format (name/description/parameters at top level). If you have tools in OpenAI nested format ({ type: "function", function: {...} }), normalise them first:

import { normalizeTools } from "ultrasafeai/lib/tools";

const tools = normalizeTools([
    { type: "function", function: { name: "get_weather", description: "...", parameters: {...} } }
]);
// → [{ name: "get_weather", description: "...", parameters: {...} }]

Interfaces:

| Interface | Shape | Description | |---|---|---| | ChatFunctionTool | { name, description?, parameters?, strict? } | Flat format — what the API expects | | FunctionTool | { type: "function", function: { name, description?, parameters? } } | Nested format — for migration from other SDKs |

Functions:

| Function | Description | |---|---| | functionTool(name, description, parameters, opts?) | Build a flat ChatFunctionTool | | normalizeTool(tool) | Convert a flat or nested tool to flat | | normalizeTools(tools[]) | Normalize an array of tools to flat | | toolMessage({ tool_call_id, name, content }) | Build a tool role message for the conversation |


Structured Output

Import: import { parseChatCompletion } from "ultrasafeai/lib/parsing"

Parse a completion's JSON content into a typed value using a Zod schema (or any object with a .parse() method).

import { UltrasafeAI } from "ultrasafeai";
import { parseChatCompletion } from "ultrasafeai/lib/parsing";
import { z } from "zod";

const client = new UltrasafeAI({ apiKey: "YOUR_API_KEY" });

const SentimentSchema = z.object({
    sentiment: z.enum(["positive", "neutral", "negative"]),
    confidence: z.number(),
});

const raw = await client.chat.completions.create({
    model: "usf-mini",
    messages: [
        { role: "system", content: "Respond with JSON only." },
        { role: "user", content: "The product is excellent!" },
    ],
    response_format: { type: "json_object" },
});

const result = parseChatCompletion(raw, SentimentSchema);
console.log(result.parsed.sentiment);   // "positive"
console.log(result.parsed.confidence);  // 0.97

API: parseChatCompletion(completion, schema) — parses choices[0].message.content as JSON, calls schema.parse(data), and returns ParsedChatCompletion<T> with a .parsed field containing the typed value.


Pagination

Import: import { iterPage, collectPage } from "ultrasafeai/lib/pagination"

List endpoints return Page<T> or CursorPage<T>. These helpers make iteration ergonomic.

import { iterPage, collectPage } from "ultrasafeai/lib/pagination";

const page = await client.models.list();

// Iterate
for (const model of iterPage(page)) {
    console.log(model.id);
}

// Or collect into array
const models = collectPage(page);

Interfaces:

| Interface | Fields | Description | |---|---|---| | Page<T> | data: T[], object: string | Standard list response | | CursorPage<T> | data, object, has_more, next_cursor? | Cursor-paginated list |

Functions:

| Function | Description | |---|---| | iterPage(page) | Generator that yields each item in page.data | | collectPage(page) | Spreads page.data into a flat array |