skytells 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +332 -121
- package/dist/chat.cjs +33 -0
- package/dist/chat.d.ts +82 -0
- package/dist/chat.js +33 -0
- package/dist/client.cjs +1151 -35
- package/dist/client.d.ts +776 -27
- package/dist/client.js +1151 -35
- package/dist/embeddings.cjs +40 -0
- package/dist/embeddings.d.ts +38 -0
- package/dist/embeddings.js +40 -0
- package/dist/endpoints.cjs +25 -7
- package/dist/endpoints.d.ts +18 -0
- package/dist/endpoints.js +25 -7
- package/dist/http.cjs +638 -53
- package/dist/http.d.ts +136 -2
- package/dist/http.js +638 -53
- package/dist/index.cjs +52 -6
- package/dist/index.d.ts +46 -7
- package/dist/index.js +52 -6
- package/dist/orchestrator.cjs +202 -0
- package/dist/orchestrator.d.ts +142 -0
- package/dist/orchestrator.js +202 -0
- package/dist/prediction-urls.cjs +38 -0
- package/dist/prediction-urls.d.ts +18 -0
- package/dist/prediction-urls.js +38 -0
- package/dist/responses.cjs +23 -0
- package/dist/responses.d.ts +60 -0
- package/dist/responses.js +23 -0
- package/dist/safety.cjs +323 -0
- package/dist/safety.d.ts +91 -0
- package/dist/safety.js +323 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/inference.types.d.ts +583 -0
- package/dist/types/inference.types.js +65 -0
- package/dist/types/model.types.d.ts +58 -4
- package/dist/types/model.types.js +13 -0
- package/dist/types/orchestrator.types.d.ts +61 -0
- package/dist/types/orchestrator.types.js +7 -0
- package/dist/types/predict.types.d.ts +258 -16
- package/dist/types/predict.types.js +22 -0
- package/dist/types/shared.types.d.ts +156 -3
- package/dist/types/shared.types.js +73 -2
- package/dist/webhooks.cjs +310 -0
- package/dist/webhooks.d.ts +171 -0
- package/dist/webhooks.js +310 -0
- package/package.json +26 -2
package/README.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Skytells JavaScript/TypeScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/skytells)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://docs.skytells.ai/sdks/ts/)
|
|
7
|
+
[](https://learn.skytells.ai/sdks/ts/)
|
|
8
|
+
[](docs/Architecture.md)
|
|
9
|
+
|
|
10
|
+
The official JavaScript/TypeScript SDK for interacting with the [Skytells](https://skytells.ai) API. Edge-compatible with Cloudflare Workers, Vercel Edge Functions, Netlify Edge Functions, and more.
|
|
11
|
+
|
|
12
|
+
Generate text, photos, videos, avatars, audio, music, and more using Skytells' own models and partner models — all through a single API. [Explore models →](https://skytells.ai/explore/models)
|
|
4
13
|
|
|
5
14
|
## Installation
|
|
6
15
|
|
|
@@ -12,192 +21,377 @@ yarn add skytells
|
|
|
12
21
|
pnpm add skytells
|
|
13
22
|
```
|
|
14
23
|
|
|
15
|
-
##
|
|
24
|
+
## Import
|
|
16
25
|
|
|
26
|
+
```ts
|
|
27
|
+
// Recommended: factory (default export)
|
|
28
|
+
import Skytells from 'skytells';
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
// Direct class import
|
|
31
|
+
import { SkytellsClient } from 'skytells';
|
|
32
|
+
|
|
33
|
+
// Both in one import
|
|
34
|
+
import Skytells, { SkytellsClient } from 'skytells';
|
|
35
|
+
```
|
|
19
36
|
|
|
20
|
-
|
|
37
|
+
Optionally, you may use the named factory:
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
```ts
|
|
40
|
+
import { createClient } from 'skytells';
|
|
41
|
+
|
|
42
|
+
const client = createClient('sk-your-api-key');
|
|
43
|
+
// equivalent to: Skytells('sk-your-api-key') and new SkytellsClient('sk-your-api-key')
|
|
44
|
+
```
|
|
27
45
|
|
|
28
|
-
##
|
|
46
|
+
## Quick Start
|
|
29
47
|
|
|
30
48
|
```typescript
|
|
31
|
-
import
|
|
49
|
+
import Skytells from 'skytells';
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
const skytells = createClient('your-api-key-here');
|
|
35
|
-
|
|
36
|
-
// Make a prediction
|
|
37
|
-
async function makePrediction() {
|
|
38
|
-
try {
|
|
39
|
-
const prediction = await skytells.predict({
|
|
40
|
-
model: 'model-name',
|
|
41
|
-
input: {
|
|
42
|
-
prompt: 'Your prompt here'
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
console.log('Prediction ID:', prediction.id);
|
|
47
|
-
console.log('Status:', prediction.status);
|
|
48
|
-
console.log('Output:', prediction.output);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error('Error making prediction:', error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
51
|
+
const skytells = Skytells('your-api-key');
|
|
53
52
|
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
console.log('Available models:', models);
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error('Error listing models:', error);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
53
|
+
// Run a model and get the result
|
|
54
|
+
const prediction = await skytells.run('truefusion', {
|
|
55
|
+
input: { prompt: 'A cat wearing sunglasses' },
|
|
56
|
+
});
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
async function getPrediction(id) {
|
|
66
|
-
try {
|
|
67
|
-
const prediction = await skytells.getPrediction(id);
|
|
68
|
-
console.log('Prediction:', prediction);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('Error getting prediction:', error);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
58
|
+
console.log(prediction.outputs()); // "https://delivery.skytells.cloud/..."
|
|
73
59
|
```
|
|
74
60
|
|
|
75
|
-
|
|
61
|
+
**Orchestrator** (workflows / webhook triggers) uses a separate `wfb_…` key. Optional **`orchestratorApiKey`** on the same client keeps both products in one place — the SDK applies the right auth per API ([Orchestrator.md](docs/Orchestrator.md)):
|
|
76
62
|
|
|
77
|
-
|
|
63
|
+
```typescript
|
|
64
|
+
const client = Skytells('sk-…', { orchestratorApiKey: 'wfb_…' });
|
|
65
|
+
await client.orchestrator.webhooks.execute(workflowId, { /* JSON body */ });
|
|
66
|
+
```
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
- Vercel Edge Functions
|
|
81
|
-
- Netlify Edge Functions
|
|
82
|
-
- Deno Deploy
|
|
83
|
-
- Any environment with Fetch API support
|
|
68
|
+
### Obtaining an API Key
|
|
84
69
|
|
|
85
|
-
|
|
70
|
+
1. Log in at [Skytells Portal](https://www.skytells.ai/auth/signin) or [Create an Account](https://www.skytells.ai/auth/signup)
|
|
71
|
+
2. Go to [Dashboard → API Keys](https://www.skytells.ai/dashboard/api-keys)
|
|
72
|
+
3. Click **Generate New API Key** and copy it immediately
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Running a Prediction
|
|
77
|
+
|
|
78
|
+
`skytells.run()` sends a prediction, waits for completion, and returns a `Prediction` object:
|
|
86
79
|
|
|
87
80
|
```typescript
|
|
88
|
-
import
|
|
81
|
+
import Skytells from 'skytells';
|
|
82
|
+
|
|
83
|
+
const skytells = Skytells('your-api-key');
|
|
89
84
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
baseUrl: 'https://your-proxy.example.com/v1'
|
|
85
|
+
const prediction = await skytells.run('truefusion', {
|
|
86
|
+
input: { prompt: 'A sunset over mountains' },
|
|
93
87
|
});
|
|
88
|
+
|
|
89
|
+
// Access output
|
|
90
|
+
console.log(prediction.id); // "pred_abc123"
|
|
91
|
+
console.log(prediction.status); // "succeeded"
|
|
92
|
+
console.log(prediction.output); // Raw: ["https://..."] or "https://..."
|
|
93
|
+
console.log(prediction.outputs()); // Normalized: "https://..." (unwraps single-element arrays)
|
|
94
|
+
|
|
95
|
+
// Full raw response
|
|
96
|
+
const raw = prediction.raw();
|
|
97
|
+
console.log(raw.metrics); // { predict_time: 3.86, total_time: 3.86, ... }
|
|
98
|
+
console.log(raw.metadata); // { billing: { credits_used: 0 }, storage: { ... } }
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
### Progress Tracking
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
Pass an `onProgress` callback to track prediction status during polling:
|
|
99
104
|
|
|
100
105
|
```typescript
|
|
101
|
-
|
|
106
|
+
const prediction = await skytells.run('beatfusion-2.0', {
|
|
107
|
+
input: { prompt: 'rap, romantic', lyrics: 'Let me introduce the voice you hear, Beatfusion by Skytells making it clear..' },
|
|
108
|
+
}, (p) => {
|
|
109
|
+
console.log(`Status: ${p.status}, Progress: ${p.metrics?.progress ?? 'n/a'}`);
|
|
110
|
+
});
|
|
111
|
+
// [... song url ]
|
|
112
|
+
```
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
const client = createClient('your-api-key');
|
|
114
|
+
### Background Predictions
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
const unauthenticatedClient = createClient();
|
|
116
|
+
Create a prediction without waiting for it to finish:
|
|
108
117
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
```typescript
|
|
119
|
+
// Create in background (returns immediately)
|
|
120
|
+
const response = await skytells.predictions.create({
|
|
121
|
+
model: 'truefusion',
|
|
122
|
+
input: { prompt: 'A cat' },
|
|
113
123
|
});
|
|
124
|
+
console.log(response.id, response.status); // "pred_..." "pending"
|
|
125
|
+
|
|
126
|
+
// Poll until complete
|
|
127
|
+
const result = await skytells.wait(response);
|
|
128
|
+
console.log(result.output);
|
|
129
|
+
|
|
130
|
+
// Or with a timeout and progress (first GET is immediate; then every interval)
|
|
131
|
+
const result = await skytells.wait(response, {
|
|
132
|
+
interval: 2000, // delay between polls after the first refresh
|
|
133
|
+
maxWait: 120000, // wall-clock limit → WAIT_TIMEOUT
|
|
134
|
+
// signal: ac.signal, // optional AbortSignal → ABORTED
|
|
135
|
+
}, (p) => console.log(p.status));
|
|
114
136
|
```
|
|
115
137
|
|
|
116
|
-
###
|
|
138
|
+
### Queue & Dispatch
|
|
117
139
|
|
|
118
|
-
|
|
140
|
+
Batch multiple predictions and dispatch them concurrently:
|
|
119
141
|
|
|
120
142
|
```typescript
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
143
|
+
skytells.queue({ model: 'truefusion-pro', input: { prompt: 'Cat' } });
|
|
144
|
+
skytells.queue({ model: 'truefusion-x', input: { prompt: 'Dog' } });
|
|
145
|
+
skytells.queue({ model: 'FLUX-2.0', input: { prompt: 'Bird' } });
|
|
146
|
+
skytells.queue({ model: 'sora-2', input: { prompt: 'A stunning video....' } });
|
|
147
|
+
skytells.queue({ model: 'beatfusion-2.0', input: { lyrics:' Wherever you are I go In every beat every sound Your love is all around....', prompt: 'Romantic, Love' } });
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
const results = await skytells.dispatch();
|
|
151
|
+
// results: PredictionResponse[] — one per queued item
|
|
152
|
+
|
|
153
|
+
// Wait for all to complete
|
|
154
|
+
const completed = await Promise.all(results.map(r => skytells.wait(r)));
|
|
129
155
|
```
|
|
130
156
|
|
|
131
|
-
|
|
157
|
+
### Prediction Lifecycle
|
|
132
158
|
|
|
133
159
|
```typescript
|
|
134
|
-
|
|
160
|
+
// Cancel a running prediction (works while status is pending/starting/processing)
|
|
161
|
+
await prediction.cancel();
|
|
162
|
+
|
|
163
|
+
// Delete a prediction and all its output assets from storage
|
|
164
|
+
await prediction.delete();
|
|
165
|
+
|
|
166
|
+
// Fetch stream metadata for a prediction
|
|
167
|
+
const stream = await prediction.stream();
|
|
168
|
+
console.log(stream.urls?.stream);
|
|
135
169
|
```
|
|
136
170
|
|
|
137
|
-
|
|
171
|
+
### Models
|
|
138
172
|
|
|
139
173
|
```typescript
|
|
140
|
-
|
|
174
|
+
// List all models
|
|
175
|
+
const models = await skytells.models.list();
|
|
176
|
+
for (const m of models) {
|
|
177
|
+
console.log(m.name, m.type, m.pricing?.amount);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Get a specific model
|
|
181
|
+
const model = await skytells.models.get('truefusion');
|
|
182
|
+
|
|
183
|
+
// Include schemas
|
|
184
|
+
const detailed = await skytells.models.get('truefusion', {
|
|
185
|
+
fields: ['input_schema', 'output_schema'],
|
|
186
|
+
});
|
|
141
187
|
```
|
|
142
188
|
|
|
143
|
-
|
|
189
|
+
### Predictions API
|
|
144
190
|
|
|
145
191
|
```typescript
|
|
146
|
-
|
|
192
|
+
// List predictions with filters
|
|
193
|
+
const { data, pagination } = await skytells.predictions.list({
|
|
194
|
+
model: 'truefusion',
|
|
195
|
+
since: '2026-01-01',
|
|
196
|
+
until: '2026-03-15',
|
|
197
|
+
page: 2,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Get a prediction by ID
|
|
201
|
+
const prediction = await skytells.predictions.get('pred_abc123');
|
|
147
202
|
```
|
|
148
203
|
|
|
149
|
-
|
|
204
|
+
## Client Options
|
|
150
205
|
|
|
151
206
|
```typescript
|
|
152
|
-
|
|
207
|
+
import Skytells from 'skytells';
|
|
208
|
+
|
|
209
|
+
const skytells = Skytells('your-api-key', {
|
|
210
|
+
baseUrl: 'https://your-proxy.example.com/v1', // Custom API URL
|
|
211
|
+
timeout: 30000, // Omit for defaults: 60000 normally, 25000 when runtime: 'edge'
|
|
212
|
+
headers: { 'X-Custom-Header': 'value' }, // Extra headers on every request
|
|
213
|
+
retry: {
|
|
214
|
+
retries: 3, // Retry failed requests (default: 0)
|
|
215
|
+
retryDelay: 1000, // Base delay; actual wait is retryDelay * (attempt + 1) per retry
|
|
216
|
+
retryOn: [429, 500, 502, 503, 504],
|
|
217
|
+
},
|
|
218
|
+
fetch: (url, opts) => fetch(url, { ...opts, cache: 'no-store' }),
|
|
219
|
+
// runtime: 'edge', // Vercel Edge / Workers: shorter default timeout, smaller compat cache, one-time hints
|
|
220
|
+
});
|
|
153
221
|
```
|
|
154
222
|
|
|
155
|
-
|
|
223
|
+
Inspect resolved settings: **`skytells.config`** (`requestTimeoutMs`, `prefetchMaxSlugs`, `runtime`) and **`skytells.runtime`**.
|
|
156
224
|
|
|
157
|
-
|
|
225
|
+
## The Prediction Object
|
|
158
226
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
227
|
+
When you call `skytells.run()`, you get a `Prediction` object:
|
|
228
|
+
|
|
229
|
+
| Property / Method | Returns | Description |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| `.id` | `string` | Unique prediction ID |
|
|
232
|
+
| `.status` | `PredictionStatus` | `pending`, `starting`, `started`, `processing`, `succeeded`, `failed`, `cancelled` |
|
|
233
|
+
| `.output` | `string \| string[] \| undefined` | Raw output from the API |
|
|
234
|
+
| `.response` | `PredictionResponse` | Full response object |
|
|
235
|
+
| `.outputs()` | `string \| string[] \| undefined` | Normalized output — unwraps single-element arrays |
|
|
236
|
+
| `.raw()` | `PredictionResponse` | Full raw response |
|
|
237
|
+
| `.cancel()` | `Promise<PredictionResponse>` | Cancel the prediction |
|
|
238
|
+
| `.delete()` | `Promise<PredictionResponse>` | Delete the prediction and its assets |
|
|
162
239
|
|
|
163
|
-
|
|
240
|
+
### `outputs()` Behavior
|
|
241
|
+
|
|
242
|
+
| API returns | `outputs()` returns |
|
|
243
|
+
|---|---|
|
|
244
|
+
| `undefined` | `undefined` |
|
|
245
|
+
| `"https://..."` | `"https://..."` |
|
|
246
|
+
| `["https://..."]` | `"https://..."` (unwrapped) |
|
|
247
|
+
| `["a", "b"]` | `["a", "b"]` (kept as array) |
|
|
248
|
+
|
|
249
|
+
## Edge Compatibility
|
|
164
250
|
|
|
165
|
-
This SDK
|
|
251
|
+
This SDK works in any environment with **Fetch** and (for **webhook HMAC verification**) **`crypto.subtle`** (Web Crypto):
|
|
252
|
+
|
|
253
|
+
- **Cloudflare Workers & Pages**
|
|
254
|
+
- **Vercel Edge Functions**
|
|
255
|
+
- **Netlify Edge Functions**
|
|
256
|
+
- **Deno Deploy**
|
|
257
|
+
- **Node.js** — use **19+** for global `crypto.subtle`, or verify webhooks in an environment that provides it
|
|
258
|
+
- **Browsers**
|
|
259
|
+
|
|
260
|
+
Pass **`{ runtime: 'edge' }`** when constructing the client on edge/serverless so the SDK uses a **25s default request timeout** (if you don’t set `timeout`) and a **smaller** inference-compat model cache; see **`EDGE_DEFAULT_REQUEST_TIMEOUT_MS`** / **`EDGE_PREFETCH_MAX_SLUGS`** in the package exports.
|
|
166
261
|
|
|
167
262
|
## Error Handling
|
|
168
263
|
|
|
169
|
-
All
|
|
264
|
+
All methods throw `SkytellsError` on failure:
|
|
170
265
|
|
|
171
266
|
```typescript
|
|
172
|
-
import {
|
|
267
|
+
import Skytells, { SkytellsError } from 'skytells';
|
|
173
268
|
|
|
174
269
|
try {
|
|
175
|
-
const prediction = await
|
|
176
|
-
|
|
177
|
-
input: { prompt: 'Your prompt' }
|
|
270
|
+
const prediction = await skytells.run('truefusion', {
|
|
271
|
+
input: { prompt: 'A cat' },
|
|
178
272
|
});
|
|
179
273
|
} catch (error) {
|
|
180
274
|
if (error instanceof SkytellsError) {
|
|
181
|
-
console.error(
|
|
182
|
-
console.error(
|
|
183
|
-
console.error(
|
|
184
|
-
console.error(
|
|
185
|
-
} else {
|
|
186
|
-
console.error('Unknown error:', error);
|
|
275
|
+
console.error(error.message); // Human-readable message
|
|
276
|
+
console.error(error.errorId); // e.g. "VALIDATION_ERROR"
|
|
277
|
+
console.error(error.details); // Detailed info
|
|
278
|
+
console.error(error.httpStatus); // e.g. 422
|
|
187
279
|
}
|
|
188
280
|
}
|
|
189
281
|
```
|
|
190
282
|
|
|
191
|
-
###
|
|
283
|
+
### Error IDs
|
|
284
|
+
|
|
285
|
+
| Error ID | Description |
|
|
286
|
+
|---|---|
|
|
287
|
+
| `UNAUTHORIZED` | Invalid or missing API key |
|
|
288
|
+
| `VALIDATION_ERROR` | Request parameters failed validation |
|
|
289
|
+
| `MODEL_NOT_FOUND` | Model slug not found |
|
|
290
|
+
| `INSUFFICIENT_CREDITS` | Not enough credits |
|
|
291
|
+
| `RATE_LIMIT_EXCEEDED` | Too many requests |
|
|
292
|
+
| `PREDICTION_FAILED` | Prediction completed with failure |
|
|
293
|
+
| `WAIT_TIMEOUT` | Polling exceeded `maxWait` |
|
|
294
|
+
| `ABORTED` | `wait()` / `run` polling stopped via `AbortSignal` |
|
|
295
|
+
| `SDK_ERROR` | Client guard (OpenAI-compat model + `compatibilityCheck`, missing `prediction.id`, webhook crypto unavailable, …) |
|
|
296
|
+
| `REQUEST_TIMEOUT` | HTTP request timed out |
|
|
297
|
+
| `NETWORK_ERROR` | Connection issue |
|
|
298
|
+
| `SERVER_ERROR` | Non-JSON response from server |
|
|
299
|
+
| `INVALID_JSON` | Declared JSON but body failed `JSON.parse` |
|
|
192
300
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
301
|
+
## TypeScript
|
|
302
|
+
|
|
303
|
+
Full type definitions are included. Key types:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import type {
|
|
307
|
+
PredictionRequest,
|
|
308
|
+
PredictionSdkOptions,
|
|
309
|
+
PredictionResponse,
|
|
310
|
+
PredictionStatus,
|
|
311
|
+
RunOptions,
|
|
312
|
+
WaitOptions,
|
|
313
|
+
Model,
|
|
314
|
+
ClientOptions,
|
|
315
|
+
SkytellsRuntime,
|
|
316
|
+
PaginatedResponse,
|
|
317
|
+
} from 'skytells';
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Inference guard: pass **`{ compatibilityCheck: true }`** as the **second** argument to **`predict`** / **`predictions.create`**, **fourth** to **`run`** (use `undefined` for `onProgress` if unused), or **second** to **`queue`** — never inside the JSON body.
|
|
321
|
+
|
|
322
|
+
## Safety
|
|
323
|
+
|
|
324
|
+
Proactive content moderation and response parsing via `client.safety`:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
import Skytells, { SafetyTemplates } from 'skytells';
|
|
328
|
+
|
|
329
|
+
const client = Skytells(process.env.SKYTELLS_API_KEY);
|
|
330
|
+
|
|
331
|
+
// Check user input before sending to a model
|
|
332
|
+
const check = await client.safety.checkText(userInput, {
|
|
333
|
+
template: SafetyTemplates.MODERATE,
|
|
334
|
+
});
|
|
335
|
+
if (!check.passed) {
|
|
336
|
+
throw new Error(`Blocked: ${check.failedCategories.join(', ')}`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Evaluate generated prediction output (image URLs are auto-detected)
|
|
340
|
+
const prediction = await client.run('flux-pro', { input: { prompt: userInput } });
|
|
341
|
+
const eval = await client.safety.evaluate(prediction.output, SafetyTemplates.STRICT);
|
|
342
|
+
if (!eval.passed) {
|
|
343
|
+
await prediction.delete();
|
|
344
|
+
throw new Error(`Output blocked: ${eval.failedCategories.join(', ')}`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Parse content_filter_results from an existing chat completion (no extra API call)
|
|
348
|
+
const completion = await client.chat.completions.create({ ... });
|
|
349
|
+
if (client.safety.wasFiltered(completion)) {
|
|
350
|
+
const categories = client.safety.getFilteredCategories(completion);
|
|
351
|
+
console.warn('Filtered:', categories);
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
See [Safety.md](docs/Safety.md) for templates, all input types, and integration patterns.
|
|
356
|
+
|
|
357
|
+
## Migration from v1.0.2
|
|
358
|
+
|
|
359
|
+
```diff
|
|
360
|
+
- import { createClient } from 'skytells';
|
|
361
|
+
- const client = createClient('key');
|
|
362
|
+
+ import Skytells from 'skytells';
|
|
363
|
+
+ const skytells = Skytells('key');
|
|
364
|
+
|
|
365
|
+
- const models = await client.listModels();
|
|
366
|
+
+ const models = await skytells.models.list();
|
|
367
|
+
|
|
368
|
+
- const model = await client.getModel('truefusion');
|
|
369
|
+
+ const model = await skytells.models.get('truefusion');
|
|
370
|
+
|
|
371
|
+
- const pred = await client.getPrediction(id);
|
|
372
|
+
+ const pred = await skytells.predictions.get(id);
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
`createClient` is still exported for compatibility; the first call logs a console hint to prefer `import Skytells from 'skytells'`.
|
|
376
|
+
|
|
377
|
+
> The old method names still work but log deprecation warnings and will be removed in a future version.
|
|
378
|
+
|
|
379
|
+
## Documentation
|
|
380
|
+
|
|
381
|
+
- See [Official Docs](https://docs.skytells.ai/sdks/ts/) for hosted documentation.
|
|
382
|
+
- **[Client.md](docs/Client.md)** — `SkytellsClient` in full: options, every method, sub-APIs
|
|
383
|
+
- **[SDKReference.md](docs/SDKReference.md)** — Low-level reference: every class, method, type, constant
|
|
384
|
+
- [Guide.md](docs/Guide.md) — Getting started walkthroughs
|
|
385
|
+
- [Architecture.md](docs/Architecture.md) — Request pipeline, retries, streams, model cache
|
|
386
|
+
- [Reliability.md](docs/Reliability.md) — Timeouts, retries, AbortSignal, edge/serverless patterns
|
|
387
|
+
- [Errors.md](docs/Errors.md) — `SkytellsError` catalog
|
|
388
|
+
- [Prediction.md](docs/Prediction.md) — Predictions: run, wait, queue, cancel, delete
|
|
389
|
+
- [Chat.md](docs/Chat.md) — Chat completions (streaming + tools)
|
|
390
|
+
- [Responses.md](docs/Responses.md) — Responses API (SSE events, multi-turn)
|
|
391
|
+
- [Embeddings.md](docs/Embeddings.md) — Embeddings, semantic search, RAG
|
|
392
|
+
- [Safety.md](docs/Safety.md) — Content moderation, templates, prediction evaluation
|
|
393
|
+
- [Webhooks.md](docs/Webhooks.md) — Inbound webhooks, framework integrations, HMAC
|
|
394
|
+
- [Orchestrator.md](docs/Orchestrator.md) — Orchestrator workflows (`wfb_…` key)
|
|
201
395
|
|
|
202
396
|
### Non-JSON Response Handling
|
|
203
397
|
|
|
@@ -205,7 +399,7 @@ The SDK automatically handles cases when the server doesn't respond with valid J
|
|
|
205
399
|
|
|
206
400
|
```typescript
|
|
207
401
|
try {
|
|
208
|
-
const models = await
|
|
402
|
+
const models = await skytells.models.list();
|
|
209
403
|
} catch (error) {
|
|
210
404
|
if (error instanceof SkytellsError) {
|
|
211
405
|
if (error.errorId === 'SERVER_ERROR') {
|
|
@@ -241,9 +435,26 @@ npm run lint
|
|
|
241
435
|
|
|
242
436
|
See [CHANGELOG.md](CHANGELOG.md) for the latest changes.
|
|
243
437
|
|
|
244
|
-
##
|
|
245
|
-
|
|
246
|
-
|
|
438
|
+
## Documentation in this repo
|
|
439
|
+
|
|
440
|
+
| File | Description |
|
|
441
|
+
|------|-------------|
|
|
442
|
+
| [docs/Client.md](docs/Client.md) | `SkytellsClient`: options, methods, sub-APIs, best practices |
|
|
443
|
+
| [docs/SDKReference.md](docs/SDKReference.md) | Low-level reference: every export, class, type, and constant |
|
|
444
|
+
| [docs/Guide.md](docs/Guide.md) | Getting started — first prediction, chat, embeddings |
|
|
445
|
+
| [docs/Architecture.md](docs/Architecture.md) | Request pipeline, retries, streaming, model cache |
|
|
446
|
+
| [docs/Reliability.md](docs/Reliability.md) | Timeouts, retries, AbortSignal, edge/serverless |
|
|
447
|
+
| [docs/Errors.md](docs/Errors.md) | `SkytellsError` fields and all `errorId` values |
|
|
448
|
+
| [docs/Prediction.md](docs/Prediction.md) | Predictions: run, wait, queue, dispatch, cancel, webhooks |
|
|
449
|
+
| [docs/Chat.md](docs/Chat.md) | Chat completions, streaming, tools, vision |
|
|
450
|
+
| [docs/Responses.md](docs/Responses.md) | Responses API, SSE events, multi-turn |
|
|
451
|
+
| [docs/Embeddings.md](docs/Embeddings.md) | Embeddings, semantic search, RAG |
|
|
452
|
+
| [docs/Safety.md](docs/Safety.md) | Safety checks, templates, prediction output evaluation |
|
|
453
|
+
| [docs/Webhooks.md](docs/Webhooks.md) | Inbound webhooks, HMAC verification, framework integrations |
|
|
454
|
+
| [docs/Orchestrator.md](docs/Orchestrator.md) | Orchestrator: workflows, executions, integrations |
|
|
455
|
+
| [docs/.env.example](docs/.env.example) | All environment variables for local dev and CI |
|
|
456
|
+
|
|
457
|
+
Hosted: [Skytells TS SDK docs](https://docs.skytells.ai/sdks/ts/).
|
|
247
458
|
|
|
248
459
|
## License
|
|
249
460
|
|
package/dist/chat.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat API — OpenAI-compatible chat completions.
|
|
3
|
+
* Same API surface as OpenAI: client.chat.completions.create()
|
|
4
|
+
*
|
|
5
|
+
* @module chat
|
|
6
|
+
*/
|
|
7
|
+
const { ENDPOINTS } = require("./endpoints.js");
|
|
8
|
+
const { Responses } = require("./responses.js");
|
|
9
|
+
/**
|
|
10
|
+
* Completions sub-resource. Exposes create() for chat completions.
|
|
11
|
+
* Mirrors OpenAI's client.chat.completions API.
|
|
12
|
+
*/
|
|
13
|
+
export class Completions {
|
|
14
|
+
constructor(http) {
|
|
15
|
+
this.http = http;
|
|
16
|
+
}
|
|
17
|
+
create(params) {
|
|
18
|
+
if (params.stream === true) {
|
|
19
|
+
return this.http.requestStream(ENDPOINTS.CHAT_COMPLETIONS, params);
|
|
20
|
+
}
|
|
21
|
+
return this.http.request('POST', ENDPOINTS.CHAT_COMPLETIONS, params);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Chat resource. Exposes completions and responses sub-APIs.
|
|
26
|
+
* Mirrors OpenAI's client.chat structure.
|
|
27
|
+
*/
|
|
28
|
+
export class Chat {
|
|
29
|
+
constructor(http) {
|
|
30
|
+
this.completions = new Completions(http);
|
|
31
|
+
this.responses = new Responses(http);
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/chat.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat API — OpenAI-compatible chat completions.
|
|
3
|
+
* Same API surface as OpenAI: client.chat.completions.create()
|
|
4
|
+
*
|
|
5
|
+
* @module chat
|
|
6
|
+
*/
|
|
7
|
+
import type { HTTP } from './http.js';
|
|
8
|
+
import { Responses } from './responses.js';
|
|
9
|
+
import type { ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming } from './types/inference.types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Completions sub-resource. Exposes create() for chat completions.
|
|
12
|
+
* Mirrors OpenAI's client.chat.completions API.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Completions {
|
|
15
|
+
private readonly http;
|
|
16
|
+
constructor(http: HTTP);
|
|
17
|
+
/**
|
|
18
|
+
* Creates a chat completion. Same as OpenAI's `client.chat.completions.create()`.
|
|
19
|
+
*
|
|
20
|
+
* When `stream` is `false` or omitted: returns `Promise<ChatCompletion>`.
|
|
21
|
+
* When `stream` is `true`: returns an `AsyncIterable<ChatCompletionChunk>` directly;
|
|
22
|
+
* consume with `for await…of` — no extra `await` needed.
|
|
23
|
+
*
|
|
24
|
+
* @param params - model, messages, and optional stream, tools, max_tokens, temperature, etc.
|
|
25
|
+
* @returns `Promise<ChatCompletion>` or `AsyncIterable<ChatCompletionChunk>`.
|
|
26
|
+
*
|
|
27
|
+
* @example Non-streaming:
|
|
28
|
+
* ```ts
|
|
29
|
+
* const completion = await client.chat.completions.create({
|
|
30
|
+
* model: 'deepbrain-router',
|
|
31
|
+
* messages: [{ role: 'user', content: 'Hello' }],
|
|
32
|
+
* });
|
|
33
|
+
* console.log(completion.choices[0].message.content);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example Streaming:
|
|
37
|
+
* ```ts
|
|
38
|
+
* for await (const chunk of client.chat.completions.create({
|
|
39
|
+
* model: 'deepbrain-router',
|
|
40
|
+
* messages: [{ role: 'user', content: 'Hello' }],
|
|
41
|
+
* stream: true,
|
|
42
|
+
* })) {
|
|
43
|
+
* process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example Tool calling:
|
|
48
|
+
* ```ts
|
|
49
|
+
* const result = await client.chat.completions.create({
|
|
50
|
+
* model: 'deepbrain-router',
|
|
51
|
+
* messages: [{ role: 'user', content: 'What is the weather in London?' }],
|
|
52
|
+
* tools: [{
|
|
53
|
+
* type: 'function',
|
|
54
|
+
* function: {
|
|
55
|
+
* name: 'get_weather',
|
|
56
|
+
* description: 'Get current weather for a location.',
|
|
57
|
+
* parameters: {
|
|
58
|
+
* type: 'object',
|
|
59
|
+
* properties: { location: { type: 'string' } },
|
|
60
|
+
* required: ['location'],
|
|
61
|
+
* },
|
|
62
|
+
* },
|
|
63
|
+
* }],
|
|
64
|
+
* tool_choice: 'auto',
|
|
65
|
+
* });
|
|
66
|
+
* const toolCall = result.choices[0].message.tool_calls?.[0];
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
create(params: ChatCompletionCreateParamsStreaming): AsyncIterable<ChatCompletionChunk>;
|
|
70
|
+
create(params: ChatCompletionCreateParamsNonStreaming): Promise<ChatCompletion>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Chat resource. Exposes completions and responses sub-APIs.
|
|
74
|
+
* Mirrors OpenAI's client.chat structure.
|
|
75
|
+
*/
|
|
76
|
+
export declare class Chat {
|
|
77
|
+
/** Chat completions. Same as OpenAI's `client.chat.completions` */
|
|
78
|
+
readonly completions: Completions;
|
|
79
|
+
/** Responses API (`POST /v1/responses`). Same surface as OpenAI-style `client.responses`. */
|
|
80
|
+
readonly responses: Responses;
|
|
81
|
+
constructor(http: HTTP);
|
|
82
|
+
}
|