jassie-ai
v1.0.4
Published
Official TypeScript SDK for the Jassie AI API — works with Node.js, React, Next.js, Vue, Angular, Svelte, React Native, and every JS/TS framework
Maintainers
Readme
Jassie AI SDK
Official TypeScript SDK for the Jassie AI API — built by Airbin.
Generate text, code, images, videos, music, speech, and real-time voice calls — all from one SDK. Works with Node.js, React, Next.js, Vue, Angular, Svelte, React Native, Deno, Bun, and every JS/TS runtime.
- Zero runtime dependencies
- Full TypeScript support with strict types
- Real-time streaming via Server-Sent Events (SSE)
- Automatic retries with exponential backoff
Table of Contents
- Installation
- Setup
- Text Generation
- Code Generation
- Image Generation
- Video Generation
- Music Generation
- Voice (TTS, STT & Voice Call)
- Streaming
- Error Handling
- React Native
- About
Installation
npm install jassie-aiSetup
import JassieAI from 'jassie-ai';
const client = new JassieAI({ apiKey: 'your-api-key' });Text Generation
| Model | Description |
|---|---|
| jassie-pulse | Lightning-fast text intelligence with million-token context |
| jassie-bolt | Flagship multimodal model — text, images, and video input |
// Non-streaming
const response = await client.text.generate({
model: 'jassie-pulse',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain how DNS works.' },
],
web: 'auto',
});
console.log(response.content);
console.log(response.web_search?.query); // search query, if web search was used
// Streaming
const stream = client.text.generate({
model: 'jassie-pulse',
messages: [{ role: 'user', content: 'Write a poem about the ocean.' }],
stream: true,
});
for await (const chunk of stream) {
if (chunk.type === 'text') process.stdout.write(chunk.content);
}Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-pulse' \| 'jassie-bolt' | Yes | — | Model to use |
| messages | Message[] | Yes | — | Array of conversation messages |
| stream | boolean | No | false | Enable real-time streaming |
| maxTokens | number | No | 5000 | Maximum tokens in the response |
| temperature | number | No | 0.7 | Randomness (0 = deterministic, 2 = creative) |
| web | 'auto' \| 'always' \| null | No | null | Web search mode |
Message format: { role: 'system' | 'user' | 'assistant', content: string, image?: string | string[], video?: string | string[] }
Note: The
imageandvideofields are only supported byjassie-bolt. Pulse is a text-only model.
Vision (Bolt only)
jassie-bolt can analyze images and videos passed in messages.
// Single image
const response = await client.text.generate({
model: 'jassie-bolt',
messages: [
{
role: 'user',
content: 'Describe this image.',
image: 'https://example.com/photo.jpg',
},
],
});
// Multiple images
const response = await client.text.generate({
model: 'jassie-bolt',
messages: [
{
role: 'user',
content: 'Compare these two images.',
image: ['https://example.com/a.jpg', 'https://example.com/b.jpg'],
},
],
});
// Video
const response = await client.text.generate({
model: 'jassie-bolt',
messages: [
{
role: 'user',
content: 'What is happening in this video?',
video: 'https://example.com/clip.mp4',
},
],
});Response (non-streaming)
| Field | Type | Description |
|---|---|---|
| type | 'text' \| 'error' | Response type |
| content | string | The generated text |
| index | number | Output index (starting at 0) |
| request_id | string | Unique identifier for the request |
| chunks | number | Total number of tokens generated |
| duration_seconds | number | Time in seconds the model took to generate the response |
| web_search | { query: string } | Present when a web search was performed |
Code Generation
| Model | Description |
|---|---|
| jassie-code | Writes, refactors, and debugs across dozens of languages |
const response = await client.code.generate({
model: 'jassie-code',
messages: [{ role: 'user', content: 'Write a function to reverse a linked list in Python.' }],
});
console.log(response.content);
// With web search for up-to-date APIs
const response = await client.code.generate({
model: 'jassie-code',
messages: [{ role: 'user', content: 'Show me how to use the latest Bun.serve() API.' }],
web: 'auto',
});Same parameters and response format as Text Generation.
Image Generation
| Model | Description |
|---|---|
| jassie-pixel | Photorealistic 2K image generation |
| jassie-pixel-x | 4K ultra-high-resolution image generation |
Two modes: v1 (synchronous) blocks until done, v2 (asynchronous) returns a taskId immediately.
// v1 — Synchronous (blocks until image is ready)
const result = await client.image.generate({
model: 'jassie-pixel',
prompt: 'A sunset over mountains, digital art style',
});
console.log(result.imageUrl);
// v2 — Asynchronous (returns immediately)
const task = await client.image.generateAsync({
model: 'jassie-pixel-x',
prompt: 'A futuristic cityscape at night',
aspectRatio: '16:9',
});
// Check status (single check)
const status = await client.image.status(task.taskId);
// Or poll until done
const final = await client.image.status(task.taskId, {
interval: 3000,
timeout: 120000,
onPoll: (res) => console.log(res.status),
});
// Or stream live updates (SSE)
const stream = client.image.statusStream(task.taskId);
for await (const event of stream) {
if (event.type === 'preview') console.log('Preview:', event.imageUrl);
if (event.type === 'completed') console.log('Done:', event.imageUrl);
if (event.type === 'failed') console.error('Failed:', event.error);
}Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-pixel' \| 'jassie-pixel-x' | Yes | — | Model (pixel = 2K, pixel-x = 4K) |
| prompt | string | Yes | — | Image description |
| image | string \| string[] | No | — | Input image URL(s) for editing or composition (up to 14) |
| aspectRatio | string | No | '1:1' | '1:1', '4:3', '3:4', '16:9', '9:16', '3:2', '2:3', '21:9' |
Response
| Field | Type | Description |
|---|---|---|
| model | string | Model used |
| taskId | string | Unique task identifier |
| status | 'pending' \| 'preview_ready' \| 'succeeded' \| 'failed' | Current status |
| imageUrl | string \| null | URL to generated image (when succeeded) |
| expiresOn | string \| null | When the image URL expires |
Stream Events
| Type | Fields | Description |
|---|---|---|
| status | model, taskId, status | Status changed (pending / preview_ready) |
| preview | model, taskId, imageUrl | Base64 preview available |
| completed | model, taskId, imageUrl, expiresOn | Final hosted URL ready |
| failed | model, taskId, error | Generation failed |
Video Generation
| Model | Description |
|---|---|
| jassie-vibe | 720p HD video generation |
| jassie-motion | 1080p Full-HD video generation |
| jassie-cinema | 1080p cinematic video generation with multimodal references |
Video generation is asynchronous — generate() returns a taskId immediately.
Vibe & Motion
const task = await client.video.generate({
model: 'jassie-vibe',
prompt: 'A calm ocean wave crashing on a sandy beach',
duration: 5,
aspectRatio: '16:9',
});
const result = await client.video.status(task.taskId);
if (result.status === 'succeeded') console.log(result.videoUrl);| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-vibe' \| 'jassie-motion' | Yes | — | Model (vibe = 720p, motion = 1080p) |
| prompt | string | Yes | — | Video description |
| duration | number | No | 5 | Duration in seconds |
| references | Reference[] | No | — | Reference(s) for style guidance. Mutually exclusive with firstFrame/lastFrame. |
| firstFrame | string | No | — | Starting frame image URL |
| lastFrame | string | No | — | Ending frame image URL |
| aspectRatio | string | No | '16:9' | '16:9', '4:3', '1:1', '3:4', '9:16', '21:9', 'adaptive' |
Cinema
jassie-cinema supports multimodal references — pass images, videos, and audio clips to guide generation. Up to 9 images, 3 videos, and 3 audio clips per request.
// Text-to-video
const task = await client.video.generate({
model: 'jassie-cinema',
prompt: 'A cinematic drone shot over a mountain range at golden hour',
duration: 10,
aspectRatio: '21:9',
});
// With multimodal references
const task = await client.video.generate({
model: 'jassie-cinema',
prompt: 'First-person POV product ad. Opening frame is Image 1, use Video 1 for camera framing, Audio 1 as background music.',
duration: 11,
aspectRatio: '16:9',
references: [
{ type: 'image', url: 'https://example.com/product-shot.jpg' },
{ type: 'image', url: 'https://example.com/brand-logo.jpg' },
{ type: 'video', url: 'https://example.com/camera-reference.mp4' },
{ type: 'audio', url: 'https://example.com/background-music.mp3' },
],
});
const result = await client.video.status(task.taskId);
if (result.status === 'succeeded') console.log(result.videoUrl);| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-cinema' | Yes | — | Cinema model (1080p) |
| prompt | string | Yes | — | Video description |
| duration | number | No | 5 | Duration in seconds (up to 15) |
| references | Reference[] | No | — | Multimodal references (see below) |
| aspectRatio | string | No | '16:9' | '21:9', '16:9', '4:3', '1:1', '3:4', '9:16' |
Reference: { type: 'image' | 'video' | 'audio', url: string }
Response
| Field | Type | Description |
|---|---|---|
| model | string | Model used |
| taskId | string | Unique task identifier |
| status | 'pending' \| 'running' \| 'succeeded' \| 'failed' | Current status |
| videoUrl | string \| null | URL to generated video (when succeeded) |
| expiresOn | string \| null | When the video URL expires |
Polling Options
Pass to status() to auto-poll until terminal state:
| Parameter | Type | Default | Description |
|---|---|---|---|
| interval | number | 5000 | Milliseconds between checks |
| timeout | number | 600000 | Max wait time in ms |
| onPoll | (response) => void | — | Callback on each poll |
Polling options work the same for
image.status(),video.status(), andmusic.status().
Music Generation
| Model | Description |
|---|---|
| jassie-beat | AI music generation — vocal or instrumental |
Music generation is asynchronous — same pattern as video.
const task = await client.music.generate({
model: 'jassie-beat',
tags: 'pop, upbeat, female vocals',
lyrics: 'Calm and peaceful, floating through the night\nStars above are shining bright',
duration: 30,
seed: 42,
});
const result = await client.music.status(task.taskId);
if (result.status === 'completed') console.log(result.musicUrl);Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-beat' | Yes | — | Model to use |
| tags | string | Yes | — | Comma-separated genre/style tags (e.g. 'lo-fi, chill, piano') |
| duration | number | Yes | — | Duration in seconds (5–240) |
| lyrics | string | No | — | Song lyrics. Omit for instrumental. |
| seed | number | No | Random | Seed for reproducible results |
Response
| Field | Type | Description |
|---|---|---|
| model | string | Model used |
| taskId | string | Unique task identifier |
| status | 'pending' \| 'processing' \| 'completed' \| 'failed' | Current status |
| musicUrl | string \| null | URL to generated audio (when completed) |
| expiresOn | string \| null | When the audio URL expires |
Voice (TTS, STT & Voice Call)
| Model | Description |
|---|---|
| jassie-voice | Text-to-speech, speech-to-text, and real-time voice call. Uses VoiceDesign — describe any voice via the instruct parameter. |
Text to Speech
Returns Promise<ArrayBuffer> — raw audio bytes (MP3).
The voice is controlled entirely through the instruct parameter. Describe the voice you want — gender, tone, accent, pacing, emotion — and the model generates it.
const audio = await client.voice.tts({
model: 'jassie-voice',
text: 'Hello, how are you?',
instruct: 'A warm male voice with an American accent, speaking in a friendly tone',
seed: 42,
});
// Save to file (Node.js)
import fs from 'fs';
fs.writeFileSync('hello.mp3', Buffer.from(audio));| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| model | 'jassie-voice' | Yes | — | Model to use |
| text | string | Yes | — | Text to speak (max 5000 chars) |
| instruct | string | No | — | Voice and style description (e.g. "A calm female voice with a British accent") |
| seed | number | No | 42 | Random seed for voice consistency. Same seed + same instruct = consistent voice. |
Speech to Text
Returns Promise<string> — transcribed text. Language is auto-detected.
const text = await client.voice.stt({
model: 'jassie-voice',
file: audioBlob, // webm, mp3, wav, ogg, etc. (max 25MB)
});| Parameter | Type | Required | Description |
|---|---|---|---|
| model | 'jassie-voice' | Yes | Model to use |
| file | Blob \| File | Yes | Audio file to transcribe |
Voice Call (Real-time Chat)
Send audio and get a streamed response with both text and audio. Under the hood, this combines three models in a single pipeline: Jassie STT transcribes the user's audio, Jassie Pulse (with web search set to auto) generates the response, and Jassie TTS synthesizes the reply into streamed speech. Returns a VoiceChatStream — an async iterable of events.
Audio is streamed as raw PCM int16 chunks for low-latency playback. Each sentence produces an audio_start event, followed by one or more audio_chunk events containing base64-encoded PCM data, and finally an audio_end event. The legacy audio event (complete base64 MP3 per sentence) may appear as a fallback.
const stream = client.voice.chat({
audio: audioBlob, // recorded audio (webm, mp3, wav, etc.)
messages: [ // optional: conversation history
{ role: 'user', content: 'Hello, how are you?' },
],
instruct: 'A calm, reassuring male voice', // optional: voice description
seed: 42, // optional: consistent voice across calls
});
// Option 1: iterate events
for await (const event of stream) {
if (event.type === 'text_chunk') process.stdout.write(event.text_chunk);
if (event.type === 'audio_start') console.log('Playing:', event.sentence);
if (event.type === 'audio_chunk') playPCMChunk(event.audio_chunk); // base64 PCM int16
if (event.type === 'audio_end') console.log('Sentence done');
if (event.type === 'done') console.log('\nFull response:', event.text);
}
// Option 2: callback
await stream.eachEvent((event) => {
if (event.type === 'text_chunk') process.stdout.write(event.text_chunk);
});
// Option 3: collect final result
const result = await stream.finalResult();
console.log(result.text); // full response text
console.log(result.user_text); // transcribed user audio
// Abort anytime
stream.abort();| Parameter | Type | Required | Description |
|---|---|---|---|
| audio | Blob \| File | Yes | Recorded audio to send |
| messages | { role: string, content: string }[] | No | Conversation history for context |
| instruct | string | No | Voice and style description (e.g. "A warm female voice with a British accent") |
| seed | number | No | Random seed for voice consistency (default: 42) |
Voice Chat Event Types
| Type | Fields | Description |
|---|---|---|
| searching | — | Server is performing a web search |
| text_chunk | text_chunk | Partial text being generated |
| audio_start | sentence, sample_rate | Marks the beginning of a sentence's streamed audio (PCM int16, typically 24000 Hz) |
| audio_chunk | audio_chunk | Base64-encoded PCM int16 audio data |
| audio_end | sentence | Marks the end of a sentence's streamed audio |
| audio | audio, sentence | Fallback: complete base64-encoded MP3 audio for a sentence |
| done | text, user_text | Stream complete — full response text and transcribed user audio |
| error | error | Error message |
Voice Chat Stream Methods
| Method | Returns | Description |
|---|---|---|
| eachEvent(cb) | Promise<void> | Calls cb(event) for each event |
| finalResult() | Promise<VoiceChatEvent \| null> | Returns the done event |
| abort() | void | Cancels the stream |
Error Handling
All errors extend JassieError. The SDK auto-retries on 5xx, 429, network errors, and timeouts with exponential backoff.
import JassieAI, {
JassieAuthenticationError, // 401
JassieRateLimitError, // 429 — has retryAfter field
JassieAPIError, // 4xx / 5xx
JassieTimeoutError, // timeout exceeded
JassieConnectionError, // network failure
} from 'jassie-ai';
try {
const response = await client.text.generate({ ... });
} catch (error) {
if (error instanceof JassieRateLimitError) {
console.error('Retry after:', error.retryAfter, 'seconds');
} else if (error instanceof JassieAPIError) {
console.error(`API error ${error.status}: ${error.message}`);
}
}React Native
The SDK auto-detects React Native and uses XMLHttpRequest for streaming. Hermes does not support for await...of — use eachText() instead:
import JassieAI from 'jassie-ai';
const client = new JassieAI({ apiKey: 'your-api-key' });
// Text streaming
const stream = client.text.generate({
model: 'jassie-pulse',
messages: [{ role: 'user', content: 'Hello from React Native!' }],
stream: true,
});
await stream.eachText((text) => {
setResponse((prev) => prev + text);
});
// Image streaming
const task = await client.image.generateAsync({
model: 'jassie-pixel',
prompt: 'A sunset over mountains',
});
const imgStream = client.image.statusStream(task.taskId);
await imgStream.eachEvent((event) => {
if (event.type === 'preview') setPreview(event.imageUrl);
if (event.type === 'completed') setFinalUrl(event.imageUrl);
});
// Voice call streaming
const voiceStream = client.voice.chat({
audio: audioBlob,
instruct: 'A friendly, natural male voice',
});
await voiceStream.eachEvent((event) => {
if (event.type === 'text_chunk') setText((prev) => prev + event.text_chunk);
if (event.type === 'audio_start') console.log('Playing:', event.sentence);
if (event.type === 'audio_chunk') playPCMChunk(event.audio_chunk);
if (event.type === 'done') console.log('Done:', event.text);
});Aborting
const streamRef = useRef<{ abort: () => void } | null>(null);
const send = async (prompt: string) => {
const stream = client.text.generate({
model: 'jassie-pulse',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
streamRef.current = stream;
await stream.eachText((text) => setResponse((prev) => prev + text));
streamRef.current = null;
};
const stop = () => streamRef.current?.abort();About
Jassie AI is developed and maintained by Airbin.
- Harmandeep Mand — [email protected]
- Muhammad Hanzla — [email protected]
Website: airbin.app | API Docs: jassie.ai
License
MIT
