2dai-cloud-sdk 1.5.3 → 1.7.0
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 +83 -1198
- package/dist/client.d.ts +107 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +387 -0
- package/dist/client.js.map +1 -1
- package/dist/constants.d.ts +30 -11
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +42 -23
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +191 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -12,138 +12,22 @@ Generate images, videos, and text using state-of-the-art AI models through a sim
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## Table of Contents
|
|
16
|
-
|
|
17
|
-
- [Features](#features)
|
|
18
|
-
- [What's New](#whats-new)
|
|
19
|
-
- [Installation](#installation)
|
|
20
|
-
- [Getting an API Key](#getting-an-api-key)
|
|
21
|
-
- [Quick Start](#quick-start)
|
|
22
|
-
- [Documentation](#documentation)
|
|
23
|
-
- [Initialization](#initialization)
|
|
24
|
-
- [Image Generation](#image-generation)
|
|
25
|
-
- [Image Editing](#image-editing)
|
|
26
|
-
- [Image Upscaling](#image-upscaling)
|
|
27
|
-
- [Video Generation](#video-generation)
|
|
28
|
-
- [Text Generation (LLM)](#text-generation-llm)
|
|
29
|
-
- [CDN Operations](#cdn-operations)
|
|
30
|
-
- [Watermarking](#watermarking)
|
|
31
|
-
- [Settings & Usage Tracking](#settings--usage-tracking)
|
|
32
|
-
- [Advanced Usage](#advanced-usage)
|
|
33
|
-
- [Complete Examples](#complete-examples)
|
|
34
|
-
- [API Reference](#api-reference)
|
|
35
|
-
- [Best Practices](#best-practices)
|
|
36
|
-
- [Troubleshooting](#troubleshooting)
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
15
|
## Features
|
|
41
16
|
|
|
42
|
-
- **Text-to-Image
|
|
43
|
-
- **Image-to-Image
|
|
44
|
-
- **AI Image Upscale
|
|
45
|
-
- **Image-to-Video
|
|
46
|
-
- **LLM Text Generation
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **Comprehensive Tests**: Full test coverage for all API endpoints and WebSocket operations
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## What's New
|
|
61
|
-
|
|
62
|
-
### v1.5.3 (Latest)
|
|
63
|
-
|
|
64
|
-
- **Comic Book Style** - New `comicbook` style preset for Gen6 Comic book illustration
|
|
65
|
-
|
|
66
|
-
### v1.5.2
|
|
67
|
-
|
|
68
|
-
- **Watercolor Style** - New `watercolor` style preset for Gen6 Watercolor Anime generation
|
|
69
|
-
- **Manga Style Update** - Improved parameters for better results
|
|
70
|
-
|
|
71
|
-
### v1.5.1
|
|
72
|
-
|
|
73
|
-
- **Rate Limit Documentation** - Clarified that Image/Video/LLM use concurrent operation limits while CDN uses rate-based limits
|
|
74
|
-
|
|
75
|
-
### v1.5.0
|
|
76
|
-
|
|
77
|
-
- **CDN Download Method** - New `downloadFromCDN()` method for downloading images and videos with automatic authentication
|
|
78
|
-
- **CDN Auth Documentation** - Updated documentation to clarify that CDN URLs require Bearer token authentication
|
|
79
|
-
|
|
80
|
-
### v1.4.2
|
|
81
|
-
|
|
82
|
-
- **npm Publishing** - Set up GitHub Actions for automated npm publishing with provenance
|
|
83
|
-
- **Documentation** - Updated package links and badges
|
|
84
|
-
|
|
85
|
-
### v1.4.0
|
|
86
|
-
|
|
87
|
-
- **AI Image Upscale** - New upscale methods for AI-powered image upscaling
|
|
88
|
-
- `upscaleImage()` - REST API upscaling with factor 2-4x
|
|
89
|
-
- `wsUpscaleImage()` - WebSocket upscaling for real-time operations
|
|
90
|
-
- **Image Description (Vision)** - Analyze images with LLM
|
|
91
|
-
- Pass `imageId` to `generateText()` or `wsGenerateLlm()` for image analysis
|
|
92
|
-
- Extract structured JSON data from images
|
|
93
|
-
- **New Types** - `UpscaleOptions`, `UpscaleResult`, `WsUpscaleRequest`, `WsUpscaleResponse`
|
|
94
|
-
- **New Constants** - `UPSCALE_FACTOR` (MIN: 2, MAX: 4, DEFAULT: 2)
|
|
95
|
-
|
|
96
|
-
### v1.3.0
|
|
97
|
-
|
|
98
|
-
- **Full WebSocket Client** - Complete WebSocket implementation
|
|
99
|
-
- `wsConnect()`, `wsGenerateImage()`, `wsGenerateVideo()`, `wsGenerateLlm()`
|
|
100
|
-
- Auto-reconnect with exponential backoff
|
|
101
|
-
- Ping/pong keepalive to prevent timeouts
|
|
102
|
-
- Request tracking with `requestId`
|
|
103
|
-
- **Image Resize for img2img** - New `width` and `height` parameters for `editImage()`
|
|
104
|
-
- Resize output to custom dimensions (320-1344) during image editing
|
|
105
|
-
- **JSON Output Enhancement** - `TextGenerationResult.json` field for parsed JSON output
|
|
106
|
-
- **WebSocket Types** - New exported types for WebSocket requests/responses
|
|
107
|
-
|
|
108
|
-
### v1.2.0
|
|
109
|
-
|
|
110
|
-
- **Video Frame Extraction** - Extract frames from videos with `?seek=<ms>` CDN parameter
|
|
111
|
-
- **Video Metadata** - `duration` and `fps` in video generation responses
|
|
112
|
-
- **WatermarkPosition Constants** - Type-safe watermark positioning
|
|
113
|
-
|
|
114
|
-
### v1.1.0
|
|
115
|
-
|
|
116
|
-
- **Style Update** - Replaced `legacy` style with new `text` style
|
|
117
|
-
- Updated style presets to match Gen6 improvements
|
|
118
|
-
|
|
119
|
-
### v1.0.3
|
|
120
|
-
|
|
121
|
-
- **Markdown Formatting** - New `useMarkdown` option for LLM text generation
|
|
122
|
-
- When enabled, responses include markdown formatting (headers, bullet points, code blocks)
|
|
123
|
-
- Works with both REST API and WebSocket connections
|
|
124
|
-
|
|
125
|
-
### v1.0.2
|
|
126
|
-
|
|
127
|
-
- **JSON Format Fix** - Fixed `jsonFormat: true` responses returning empty strings
|
|
128
|
-
- LLM text generation now correctly returns JSON responses when using `jsonFormat` and `jsonTemplate` options
|
|
129
|
-
|
|
130
|
-
### v1.0.1
|
|
131
|
-
|
|
132
|
-
- **GIF File Format Support** - Full GIF upload, download, and processing via CDN
|
|
133
|
-
- **Format Conversion** - Convert between image formats (PNG, JPG, GIF) and extract video frames as GIF
|
|
134
|
-
- **GIF Watermarking** - Apply watermarks to GIF files with position control
|
|
135
|
-
- **Enhanced Debug Logging** - Improved watermark operation debugging
|
|
136
|
-
|
|
137
|
-
### v1.0.0
|
|
138
|
-
|
|
139
|
-
- Initial public release
|
|
140
|
-
- Text-to-image generation with 12 style presets
|
|
141
|
-
- Image-to-image editing with strength control
|
|
142
|
-
- Image-to-video generation
|
|
143
|
-
- LLM text generation with memory and JSON format support
|
|
144
|
-
- 7 format presets for different aspect ratios
|
|
145
|
-
- WebSocket and REST API support
|
|
146
|
-
- Built-in rate limiting and watermarking support
|
|
17
|
+
- **Text-to-Image** - Generate stunning images from text prompts
|
|
18
|
+
- **Image-to-Image** - Edit and transform existing images
|
|
19
|
+
- **AI Image Upscale** - Upscale images 2-4x using AI
|
|
20
|
+
- **Image-to-Video** - Create videos from static images
|
|
21
|
+
- **LLM Text Generation** - Generate text with context, memory, and JSON support
|
|
22
|
+
- **LLM Streaming** - Real-time token-by-token streaming with SSE and WebSocket
|
|
23
|
+
- **OpenAI-Compatible API** - Drop-in `/v1/chat/completions` endpoint
|
|
24
|
+
- **Image Vision** - Analyze images with LLM for structured data extraction
|
|
25
|
+
- **14 Style Presets** - Realistic, anime, manga, watercolor, cinematic, and more
|
|
26
|
+
- **7 Format Presets** - Portrait, landscape, profile, story, post, smartphone, banner
|
|
27
|
+
- **Built-in Watermarking** - Apply custom watermarks to generated content
|
|
28
|
+
- **WebSocket Support** - Real-time generation with progress updates
|
|
29
|
+
- **CDN Operations** - Format conversion, resizing, frame extraction
|
|
30
|
+
- **Full TypeScript Support** - Comprehensive type definitions
|
|
147
31
|
|
|
148
32
|
---
|
|
149
33
|
|
|
@@ -153,27 +37,6 @@ Generate images, videos, and text using state-of-the-art AI models through a sim
|
|
|
153
37
|
npm install 2dai-cloud-sdk
|
|
154
38
|
```
|
|
155
39
|
|
|
156
|
-
or
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
yarn add 2dai-cloud-sdk
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Getting an API Key
|
|
165
|
-
|
|
166
|
-
To use this SDK, you need an API key.
|
|
167
|
-
|
|
168
|
-
**Request Access:**
|
|
169
|
-
1. Fill out the [API Access Request Form](https://forms.gle/TdQ8Wu3zpegvAwVg9)
|
|
170
|
-
2. We'll review your request within 24-48 hours
|
|
171
|
-
3. Once approved, you'll receive your API key via email
|
|
172
|
-
|
|
173
|
-
**Contact:**
|
|
174
|
-
- Twitter/X: [@2DAICommunity](https://x.com/2DAICommunity)
|
|
175
|
-
- Telegram: [Token2dAI](https://t.me/Token2dAI)
|
|
176
|
-
|
|
177
40
|
---
|
|
178
41
|
|
|
179
42
|
## Quick Start
|
|
@@ -181,1106 +44,128 @@ To use this SDK, you need an API key.
|
|
|
181
44
|
```typescript
|
|
182
45
|
import { createClient, STYLES, FORMATS } from '2dai-cloud-sdk';
|
|
183
46
|
|
|
184
|
-
// Initialize
|
|
47
|
+
// Initialize client
|
|
185
48
|
const client = createClient('2dai_pk_your_api_key_here');
|
|
186
49
|
|
|
187
|
-
// Generate an image
|
|
50
|
+
// Generate an image
|
|
188
51
|
const image = await client.generateImage({
|
|
189
|
-
prompt: 'a
|
|
52
|
+
prompt: 'a futuristic city at sunset with flying cars',
|
|
190
53
|
style: STYLES.cine.id,
|
|
191
54
|
format: FORMATS.landscape.id
|
|
192
55
|
});
|
|
56
|
+
console.log('Image ID:', image.imageId);
|
|
193
57
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const wsImage = await client.wsGenerateImage({
|
|
199
|
-
prompt: 'a futuristic city at night',
|
|
200
|
-
style: STYLES.cine.id,
|
|
201
|
-
format: FORMATS.landscape.id
|
|
58
|
+
// Generate text
|
|
59
|
+
const text = await client.generateText({
|
|
60
|
+
prompt: 'Explain quantum computing in simple terms',
|
|
61
|
+
system: 'You are a helpful science teacher'
|
|
202
62
|
});
|
|
203
|
-
console.log(
|
|
204
|
-
await client.close();
|
|
205
|
-
```
|
|
63
|
+
console.log(text.response);
|
|
206
64
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
import { createClient } from '2dai-cloud-sdk';
|
|
215
|
-
|
|
216
|
-
const client = createClient('2dai_pk_your_api_key_here', {
|
|
217
|
-
timeout: 300000, // Optional, 5 minutes default
|
|
218
|
-
debug: false // Optional, enable debug logging
|
|
219
|
-
});
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Image Generation
|
|
223
|
-
|
|
224
|
-
#### Generate from Text Prompt
|
|
225
|
-
|
|
226
|
-
```typescript
|
|
227
|
-
import { STYLES, FORMATS } from '2dai-cloud-sdk';
|
|
228
|
-
|
|
229
|
-
const result = await client.generateImage({
|
|
230
|
-
prompt: 'a cyberpunk cityscape at night with neon lights',
|
|
231
|
-
negativePrompt: 'blurry, low quality, distorted',
|
|
232
|
-
style: STYLES.cine.id,
|
|
233
|
-
format: FORMATS.landscape.id,
|
|
234
|
-
seed: 12345 // Optional, for reproducibility
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
console.log(result);
|
|
238
|
-
// {
|
|
239
|
-
// success: true,
|
|
240
|
-
// imageId: '550e8400-e29b-41d4-a716-446655440000',
|
|
241
|
-
// width: 1344,
|
|
242
|
-
// height: 768,
|
|
243
|
-
// seed: 12345
|
|
244
|
-
// }
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
#### Available Styles
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
import { STYLES } from '2dai-cloud-sdk';
|
|
251
|
-
|
|
252
|
-
STYLES.raw // Raw Gen6 defaults
|
|
253
|
-
STYLES.realistic // Realistic 2DAI generation
|
|
254
|
-
STYLES.text // Text & Clarity
|
|
255
|
-
STYLES.ciniji // Niji anime style with vibrant colors
|
|
256
|
-
STYLES.portrait // Gen6 Portrait
|
|
257
|
-
STYLES.cine // Gen6 Cinematic
|
|
258
|
-
STYLES.sport // Gen6 Sport
|
|
259
|
-
STYLES.fashion // Gen6 Fashion
|
|
260
|
-
STYLES.niji // Gen6 Anime Niji
|
|
261
|
-
STYLES.anime // Gen6 Anime
|
|
262
|
-
STYLES.manga // Gen6 Manga
|
|
263
|
-
STYLES.watercolor // Gen6 Watercolor Anime
|
|
264
|
-
STYLES.comicbook // Gen6 Comic book illustration
|
|
265
|
-
STYLES.paint // Gen6 Paint
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
#### Available Formats
|
|
269
|
-
|
|
270
|
-
```typescript
|
|
271
|
-
import { FORMATS } from '2dai-cloud-sdk';
|
|
272
|
-
|
|
273
|
-
FORMATS.portrait // 9:16 vertical (768x1344)
|
|
274
|
-
FORMATS.landscape // 16:9 horizontal (1344x768)
|
|
275
|
-
FORMATS.profile // 1:1 profile picture (1024x1024)
|
|
276
|
-
FORMATS.story // 9:16 story format (720x1280)
|
|
277
|
-
FORMATS.post // 9:7 wide square (1152x896)
|
|
278
|
-
FORMATS.smartphone // Phone screen (640x1344)
|
|
279
|
-
FORMATS.banner // 3:1 wide screen (1472x448)
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Image Editing
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// Edit using image ID
|
|
286
|
-
const edited = await client.editImage('550e8400-e29b-41d4-a716-446655440000', {
|
|
287
|
-
prompt: 'make the sky more dramatic with storm clouds'
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
// Edit with resize - output to custom dimensions
|
|
291
|
-
const resized = await client.editImage('550e8400-e29b-41d4-a716-446655440000', {
|
|
292
|
-
prompt: 'Seamlessly extend the image, remove the black background',
|
|
293
|
-
width: 768, // Custom output width (320-1344)
|
|
294
|
-
height: 1344 // Custom output height (320-1344)
|
|
65
|
+
// Stream text in real-time
|
|
66
|
+
const controller = client.generateTextStream({
|
|
67
|
+
prompt: 'Write a short story about AI',
|
|
68
|
+
onChunk: (chunk) => process.stdout.write(chunk),
|
|
69
|
+
onComplete: (result) => console.log(`\nTokens: ${result.totalTokens}`)
|
|
295
70
|
});
|
|
296
|
-
|
|
297
|
-
console.log(resized);
|
|
298
|
-
// {
|
|
299
|
-
// success: true,
|
|
300
|
-
// imageId: 'new-image-id',
|
|
301
|
-
// width: 768,
|
|
302
|
-
// height: 1344,
|
|
303
|
-
// seed: 12345
|
|
304
|
-
// }
|
|
305
|
-
|
|
306
|
-
// Edit with resizePad - fit original in frame with black padding
|
|
307
|
-
const padded = await client.editImage('550e8400-e29b-41d4-a716-446655440000', {
|
|
308
|
-
prompt: 'Seamlessly extend the image',
|
|
309
|
-
width: 768,
|
|
310
|
-
height: 1344,
|
|
311
|
-
resizePad: true // Fits original image in resized frame, fills extra space with black
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
// Edit via WebSocket
|
|
315
|
-
await client.wsConnect();
|
|
316
|
-
const wsEdited = await client.wsGenerateImage({
|
|
317
|
-
imageId: '550e8400-e29b-41d4-a716-446655440000',
|
|
318
|
-
prompt: 'make the image black and white',
|
|
319
|
-
width: 1344,
|
|
320
|
-
height: 768
|
|
321
|
-
});
|
|
322
|
-
console.log(wsEdited.result.imageId);
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
#### Resize Padding (`resizePad`)
|
|
326
|
-
|
|
327
|
-
When resizing images to different dimensions, the `resizePad` option controls how the original image is fitted:
|
|
328
|
-
|
|
329
|
-
| resizePad | Behavior |
|
|
330
|
-
|-----------|----------|
|
|
331
|
-
| `false` (default) | Image is cropped/stretched to fill the target dimensions |
|
|
332
|
-
| `true` | Original image fits entirely within the frame, extra space is filled with black |
|
|
333
|
-
|
|
334
|
-
### Image Upscaling
|
|
335
|
-
|
|
336
|
-
AI-powered image upscaling. No user prompt needed.
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
import { UPSCALE_FACTOR } from '2dai-cloud-sdk';
|
|
340
|
-
|
|
341
|
-
// Upscale an image (REST API)
|
|
342
|
-
const upscaled = await client.upscaleImage('550e8400-e29b-41d4-a716-446655440000', {
|
|
343
|
-
factor: 2 // 2x, 3x, or 4x (default: 2)
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
console.log(upscaled);
|
|
347
|
-
// {
|
|
348
|
-
// success: true,
|
|
349
|
-
// imageId: 'upscaled-image-id',
|
|
350
|
-
// width: 2048,
|
|
351
|
-
// height: 2048,
|
|
352
|
-
// seed: 12345
|
|
353
|
-
// }
|
|
354
|
-
|
|
355
|
-
// Upscale via WebSocket
|
|
356
|
-
await client.wsConnect();
|
|
357
|
-
const wsUpscaled = await client.wsUpscaleImage({
|
|
358
|
-
imageId: '550e8400-e29b-41d4-a716-446655440000',
|
|
359
|
-
factor: 2
|
|
360
|
-
});
|
|
361
|
-
console.log(wsUpscaled.result.imageId);
|
|
362
|
-
await client.close();
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
#### Upscale Factor Limits
|
|
366
|
-
|
|
367
|
-
```typescript
|
|
368
|
-
import { UPSCALE_FACTOR } from '2dai-cloud-sdk';
|
|
369
|
-
|
|
370
|
-
UPSCALE_FACTOR.MIN // 2
|
|
371
|
-
UPSCALE_FACTOR.MAX // 4
|
|
372
|
-
UPSCALE_FACTOR.DEFAULT // 2
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### Video Generation
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
// Generate video from image ID
|
|
379
|
-
const video = await client.generateVideo({
|
|
380
|
-
imageId: '550e8400-e29b-41d4-a716-446655440000',
|
|
381
|
-
duration: 5, // 1-10 seconds
|
|
382
|
-
fps: 16 // 8-32 fps
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// Generate video from buffer
|
|
386
|
-
const video = await client.generateVideo({
|
|
387
|
-
imageBuffer,
|
|
388
|
-
duration: 5
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
console.log(video);
|
|
392
|
-
// {
|
|
393
|
-
// success: true,
|
|
394
|
-
// videoId: '660e8400-e29b-41d4-a716-446655440000',
|
|
395
|
-
// duration: 5,
|
|
396
|
-
// fps: 16
|
|
397
|
-
// }
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
### Text Generation (LLM)
|
|
401
|
-
|
|
402
|
-
```typescript
|
|
403
|
-
// Simple text generation
|
|
404
|
-
const result = await client.generateText({
|
|
405
|
-
prompt: 'Write a short poem about AI and creativity'
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
console.log(result.response);
|
|
409
|
-
|
|
410
|
-
// With markdown formatting
|
|
411
|
-
const formatted = await client.generateText({
|
|
412
|
-
prompt: 'Explain what TypeScript is. Use headers and code examples.',
|
|
413
|
-
useMarkdown: true // Response includes markdown formatting
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
console.log(formatted.response); // Contains # headers, ```code blocks```, bullet points, etc.
|
|
417
|
-
|
|
418
|
-
// With system message and memory
|
|
419
|
-
const result = await client.generateText({
|
|
420
|
-
prompt: 'What were we discussing?',
|
|
421
|
-
system: 'You are a helpful assistant',
|
|
422
|
-
memory: [
|
|
423
|
-
'User asked about AI capabilities',
|
|
424
|
-
'Discussed image generation features'
|
|
425
|
-
]
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
// JSON format response
|
|
429
|
-
const result = await client.generateText({
|
|
430
|
-
prompt: 'Analyze this product review',
|
|
431
|
-
jsonFormat: true,
|
|
432
|
-
jsonTemplate: {
|
|
433
|
-
sentiment: 'positive/negative/neutral',
|
|
434
|
-
score: '1-10',
|
|
435
|
-
summary: 'brief summary'
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
console.log(result.response); // Returns structured JSON
|
|
440
|
-
|
|
441
|
-
// With knowledge base
|
|
442
|
-
const result = await client.generateText({
|
|
443
|
-
prompt: 'What is our refund policy?',
|
|
444
|
-
askKnowledge: {
|
|
445
|
-
sources: ['docs', 'policies'],
|
|
446
|
-
query: 'refund policy'
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
// Image description (Vision)
|
|
451
|
-
const imageResult = await client.generateImage({
|
|
452
|
-
prompt: 'a futuristic city at night'
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
const description = await client.generateText({
|
|
456
|
-
prompt: 'Analyze this image and extract structured data',
|
|
457
|
-
system: 'Extract information from images into structured JSON format.',
|
|
458
|
-
imageId: imageResult.imageId, // Pass image for analysis
|
|
459
|
-
jsonFormat: true,
|
|
460
|
-
jsonTemplate: {
|
|
461
|
-
main_subject: 'string - primary subject of the image',
|
|
462
|
-
objects: 'array of strings - objects visible in the image',
|
|
463
|
-
colors: 'array of strings - dominant colors',
|
|
464
|
-
mood: 'string - overall mood/atmosphere'
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
console.log(description.json);
|
|
469
|
-
// Output: { main_subject: "futuristic cityscape", objects: ["buildings", "lights", ...], ... }
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### CDN Operations
|
|
473
|
-
|
|
474
|
-
The CDN supports multiple file formats and operations including format conversion, resizing, and watermarking.
|
|
475
|
-
|
|
476
|
-
#### Supported File Formats
|
|
477
|
-
|
|
478
|
-
| Format | Extension | Description |
|
|
479
|
-
|--------|-----------|-------------|
|
|
480
|
-
| JPEG | `.jpg`, `.jpeg` | Standard image format |
|
|
481
|
-
| PNG | `.png` | Lossless image format with transparency |
|
|
482
|
-
| GIF | `.gif` | Static or animated image format |
|
|
483
|
-
| MP4 | `.mp4` | Video format |
|
|
484
|
-
|
|
485
|
-
#### CDN URL Pattern
|
|
486
|
-
|
|
487
|
-
For advanced use cases, the CDN URL pattern is:
|
|
488
|
-
```
|
|
489
|
-
GET /api/v1/cdn/{id}.{format}?{queryParams}
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
> **Authentication Required**: CDN URLs require Bearer token authentication.
|
|
493
|
-
> You cannot use these URLs directly in browsers or `<img>` tags.
|
|
494
|
-
> Use `client.downloadFromCDN()` (recommended) or include the `Authorization: Bearer {apiKey}` header.
|
|
495
|
-
|
|
496
|
-
#### Format Conversion Matrix
|
|
497
|
-
|
|
498
|
-
| From \ To | PNG | JPG | JPEG | GIF |
|
|
499
|
-
|-----------|-----|-----|------|-----|
|
|
500
|
-
| PNG | - | Yes | Yes | Yes |
|
|
501
|
-
| JPG | Yes | - | Yes | Yes |
|
|
502
|
-
| JPEG | Yes | Yes | - | Yes |
|
|
503
|
-
| GIF | Yes | Yes | Yes | - |
|
|
504
|
-
| MP4 | Yes | Yes | Yes | Yes |
|
|
505
|
-
|
|
506
|
-
**Notes:**
|
|
507
|
-
- Converting animated GIF to other formats extracts the first frame
|
|
508
|
-
- MP4 to image formats extracts a single frame as still image
|
|
509
|
-
- Watermarking supported on all image formats including GIF
|
|
510
|
-
|
|
511
|
-
#### CDN Query Parameters
|
|
512
|
-
|
|
513
|
-
| Parameter | Description | Example |
|
|
514
|
-
|-----------|-------------|---------|
|
|
515
|
-
| `w` | Target width in pixels | `?w=1024` |
|
|
516
|
-
| `h` | Target height in pixels | `?h=768` |
|
|
517
|
-
| `watermark` | Watermark file ID | `?watermark=abc123` |
|
|
518
|
-
| `position` | Watermark position | `?position=southeast` |
|
|
519
|
-
|
|
520
|
-
**Watermark Positions:**
|
|
521
|
-
- Sharp gravity: `northwest`, `north`, `northeast`, `west`, `center`, `east`, `southwest`, `south`, `southeast`
|
|
522
|
-
- Human-readable: `top-left`, `top-center`, `top-right`, `middle-left`, `middle-center`, `middle-right`, `bottom-left`, `bottom-center`, `bottom-right`
|
|
523
|
-
|
|
524
|
-
#### Downloading Content
|
|
525
|
-
|
|
526
|
-
Use `downloadFromCDN()` to download images or videos with automatic authentication:
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
529
|
-
import fs from 'fs';
|
|
530
|
-
|
|
531
|
-
// Download image as buffer
|
|
532
|
-
const { buffer, mimeType, size } = await client.downloadFromCDN(imageId);
|
|
533
|
-
fs.writeFileSync('image.jpg', buffer);
|
|
534
|
-
console.log(`Downloaded ${size} bytes (${mimeType})`);
|
|
535
|
-
|
|
536
|
-
// Download with format conversion (PNG)
|
|
537
|
-
const { buffer: pngBuffer } = await client.downloadFromCDN(imageId, { format: 'png' });
|
|
538
|
-
fs.writeFileSync('image.png', pngBuffer);
|
|
539
|
-
|
|
540
|
-
// Download with resize
|
|
541
|
-
const { buffer: thumbBuffer } = await client.downloadFromCDN(imageId, {
|
|
542
|
-
format: 'jpg',
|
|
543
|
-
width: 256,
|
|
544
|
-
height: 256
|
|
545
|
-
});
|
|
546
|
-
fs.writeFileSync('thumbnail.jpg', thumbBuffer);
|
|
547
|
-
|
|
548
|
-
// Download video
|
|
549
|
-
const { buffer: videoBuffer } = await client.downloadFromCDN(videoId, { format: 'mp4' });
|
|
550
|
-
fs.writeFileSync('video.mp4', videoBuffer);
|
|
551
|
-
|
|
552
|
-
// Extract frame from video at 5 seconds
|
|
553
|
-
const { buffer: frameBuffer } = await client.downloadFromCDN(videoId, {
|
|
554
|
-
format: 'jpg',
|
|
555
|
-
seek: 5000 // milliseconds
|
|
556
|
-
});
|
|
557
|
-
fs.writeFileSync('frame-5s.jpg', frameBuffer);
|
|
558
|
-
|
|
559
|
-
// Download with watermark
|
|
560
|
-
const { buffer: wmBuffer } = await client.downloadFromCDN(imageId, {
|
|
561
|
-
format: 'jpg',
|
|
562
|
-
watermark: 'watermark-cdn-id',
|
|
563
|
-
watermarkPosition: 'southeast'
|
|
564
|
-
});
|
|
565
|
-
fs.writeFileSync('watermarked.jpg', wmBuffer);
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
#### Manual Download with Axios
|
|
569
|
-
|
|
570
|
-
For advanced use cases, you can download directly using axios with the Authorization header:
|
|
571
|
-
|
|
572
|
-
```typescript
|
|
573
|
-
import axios from 'axios';
|
|
574
|
-
import fs from 'fs';
|
|
575
|
-
|
|
576
|
-
// Build CDN URL: baseUrl + /api/v1/cdn/{id}.{format}
|
|
577
|
-
const baseUrl = 'your-api-base-url'; // Use client's baseUrl or default
|
|
578
|
-
|
|
579
|
-
// Download image
|
|
580
|
-
const imageResponse = await axios.get(
|
|
581
|
-
`${baseUrl}/api/v1/cdn/${imageId}.jpg`,
|
|
582
|
-
{
|
|
583
|
-
responseType: 'arraybuffer',
|
|
584
|
-
headers: { 'Authorization': `Bearer ${apiKey}` }
|
|
585
|
-
}
|
|
586
|
-
);
|
|
587
|
-
fs.writeFileSync('output.jpg', imageResponse.data);
|
|
588
|
-
|
|
589
|
-
// Download video
|
|
590
|
-
const videoResponse = await axios.get(
|
|
591
|
-
`${baseUrl}/api/v1/cdn/${videoId}.mp4`,
|
|
592
|
-
{
|
|
593
|
-
responseType: 'arraybuffer',
|
|
594
|
-
headers: { 'Authorization': `Bearer ${apiKey}` }
|
|
595
|
-
}
|
|
596
|
-
);
|
|
597
|
-
fs.writeFileSync('output.mp4', videoResponse.data);
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
### Watermarking
|
|
601
|
-
|
|
602
|
-
```typescript
|
|
603
|
-
// Upload watermark and set as default
|
|
604
|
-
const settings = await client.getSettings();
|
|
605
|
-
await client.updateWatermark('watermark-cdn-id');
|
|
606
|
-
|
|
607
|
-
// Apply watermark to generation
|
|
608
|
-
const image = await client.generateImage({
|
|
609
|
-
prompt: 'a beautiful landscape',
|
|
610
|
-
watermark: 'watermark-cdn-id',
|
|
611
|
-
watermarkPosition: 'southeast', // bottom-right
|
|
612
|
-
copyright: '2024 My Company'
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
// Tiled watermark (images only)
|
|
616
|
-
const image = await client.generateImage({
|
|
617
|
-
prompt: 'product photography',
|
|
618
|
-
watermark: 'watermark-cdn-id',
|
|
619
|
-
watermarkAsTiles: true
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
// Apply watermark via CDN download
|
|
623
|
-
const { buffer } = await client.downloadFromCDN(imageId, {
|
|
624
|
-
watermark: watermarkId,
|
|
625
|
-
watermarkPosition: 'center'
|
|
626
|
-
});
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
### Settings & Usage Tracking
|
|
630
|
-
|
|
631
|
-
#### Understanding Rate Limits
|
|
632
|
-
|
|
633
|
-
Rate limits work differently depending on the operation type:
|
|
634
|
-
|
|
635
|
-
| Operation | Limit Type | What `requestsPer15Min` Means |
|
|
636
|
-
|-----------|------------|-------------------------------|
|
|
637
|
-
| Image | Concurrent | Max simultaneous image generations |
|
|
638
|
-
| Video | Concurrent | Max simultaneous video generations |
|
|
639
|
-
| LLM | Concurrent | Max simultaneous text generations |
|
|
640
|
-
| CDN | Rate-based | Requests per 15-minute window |
|
|
641
|
-
|
|
642
|
-
**For Image/Video/LLM:** You can have up to N operations running at once. When one completes, you can start another immediately.
|
|
643
|
-
|
|
644
|
-
**For CDN:** Traditional rate limiting - counter resets every 15 minutes.
|
|
645
|
-
|
|
646
|
-
```typescript
|
|
647
|
-
// Get API key settings with current usage
|
|
648
|
-
const settings = await client.getSettings();
|
|
649
|
-
|
|
650
|
-
console.log('API Key:', settings.name);
|
|
651
|
-
console.log('Status:', settings.status);
|
|
652
|
-
console.log('\nRate Limits:');
|
|
653
|
-
console.log('Image:', settings.rateLimits.image);
|
|
654
|
-
console.log('Video:', settings.rateLimits.video);
|
|
655
|
-
console.log('LLM:', settings.rateLimits.llm);
|
|
656
|
-
console.log('CDN:', settings.rateLimits.cdn);
|
|
657
|
-
|
|
658
|
-
// Current usage - note: image/video/llm show concurrent operations, cdn shows rate
|
|
659
|
-
console.log('\nCurrent Usage:');
|
|
660
|
-
console.log('Image (concurrent):', {
|
|
661
|
-
active: settings.currentUsage.image.current.requestsPer15Min, // Currently running
|
|
662
|
-
limit: settings.rateLimits.image.requestsPer15Min, // Max concurrent
|
|
663
|
-
available: settings.currentUsage.image.remaining.requestsPer15Min // Capacity left
|
|
664
|
-
});
|
|
665
|
-
|
|
666
|
-
// LLM usage includes token tracking
|
|
667
|
-
console.log('LLM (concurrent):', {
|
|
668
|
-
active: settings.currentUsage.llm.current.requestsPer15Min,
|
|
669
|
-
limit: settings.rateLimits.llm.requestsPer15Min,
|
|
670
|
-
tokensToday: settings.currentUsage.llm.current.tokensPerDay,
|
|
671
|
-
tokenLimit: settings.rateLimits.llm.tokensPerDay
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
// CDN uses traditional rate limiting
|
|
675
|
-
console.log('CDN (rate-based):', {
|
|
676
|
-
used15min: settings.currentUsage.cdn.current.requestsPer15Min,
|
|
677
|
-
limit15min: settings.rateLimits.cdn.requestsPer15Min,
|
|
678
|
-
resetAt: settings.currentUsage.cdn.resetAt.window15Min
|
|
679
|
-
});
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
### Rate Limit Checking
|
|
683
|
-
|
|
684
|
-
```typescript
|
|
685
|
-
// Check current rate limits for all operations
|
|
686
|
-
const limits = await client.checkLimits();
|
|
687
|
-
|
|
688
|
-
limits.forEach(limit => {
|
|
689
|
-
console.log(`${limit.operation}:`);
|
|
690
|
-
|
|
691
|
-
// For image/video/llm: shows concurrent operations (active/max)
|
|
692
|
-
// For cdn: shows rate limit usage (used/limit per window)
|
|
693
|
-
console.log(` Active: ${limit.current.requestsPer15Min}/${limit.limit.requestsPer15Min}`);
|
|
694
|
-
|
|
695
|
-
if (limit.operation === 'cdn') {
|
|
696
|
-
console.log(` Daily: ${limit.current.requestsPerDay}/${limit.limit.requestsPerDay}`);
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
if (limit.operation === 'llm') {
|
|
700
|
-
console.log(` Tokens today: ${limit.current.tokensPerDay}/${limit.limit.tokensPerDay}`);
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
### Health Check
|
|
706
|
-
|
|
707
|
-
```typescript
|
|
708
|
-
const health = await client.health();
|
|
709
|
-
console.log(health);
|
|
710
|
-
// {
|
|
711
|
-
// status: 'ok',
|
|
712
|
-
// timestamp: '2024-01-15T10:30:00.000Z'
|
|
713
|
-
// }
|
|
71
|
+
await controller.done;
|
|
714
72
|
```
|
|
715
73
|
|
|
716
74
|
---
|
|
717
75
|
|
|
718
|
-
##
|
|
719
|
-
|
|
720
|
-
### Custom Dimensions
|
|
721
|
-
|
|
722
|
-
```typescript
|
|
723
|
-
const image = await client.generateImage({
|
|
724
|
-
prompt: 'a mountain landscape',
|
|
725
|
-
width: 1280,
|
|
726
|
-
height: 720
|
|
727
|
-
// Note: width/height must be between 320-1344
|
|
728
|
-
});
|
|
729
|
-
```
|
|
76
|
+
## Documentation
|
|
730
77
|
|
|
731
|
-
|
|
78
|
+
Full documentation is available in the **[Wiki](../../wiki)**.
|
|
732
79
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
80
|
+
| Guide | Description |
|
|
81
|
+
|-------|-------------|
|
|
82
|
+
| [Getting Started](../../wiki/Getting-Started) | Installation, API key, initialization |
|
|
83
|
+
| [Image Generation](../../wiki/Image-Generation) | Text-to-image, editing, upscaling, styles & formats |
|
|
84
|
+
| [Video Generation](../../wiki/Video-Generation) | Image-to-video creation |
|
|
85
|
+
| [LLM & Streaming](../../wiki/LLM-Text-Generation) | Text generation, streaming, OpenAI-compatible API |
|
|
86
|
+
| [CDN Operations](../../wiki/CDN-Operations) | Downloads, watermarks, format conversion |
|
|
87
|
+
| [WebSocket API](../../wiki/WebSocket-API) | Real-time generation with progress updates |
|
|
88
|
+
| [API Reference](../../wiki/API-Reference) | Complete endpoint documentation |
|
|
89
|
+
| [Examples](../../wiki/Examples) | Full code examples |
|
|
90
|
+
| [Troubleshooting](../../wiki/Troubleshooting) | Common issues, debug mode, best practices |
|
|
738
91
|
|
|
739
92
|
---
|
|
740
93
|
|
|
741
|
-
##
|
|
742
|
-
|
|
743
|
-
### Example 1: Generate Image with Watermark and Download
|
|
744
|
-
|
|
745
|
-
```typescript
|
|
746
|
-
import { createClient, STYLES, FORMATS } from '2dai-cloud-sdk';
|
|
747
|
-
import fs from 'fs';
|
|
748
|
-
|
|
749
|
-
const client = createClient('2dai_pk_your_api_key_here');
|
|
750
|
-
|
|
751
|
-
async function generateAndDownload() {
|
|
752
|
-
try {
|
|
753
|
-
// Generate image
|
|
754
|
-
const result = await client.generateImage({
|
|
755
|
-
prompt: 'a futuristic city at sunset with flying cars',
|
|
756
|
-
style: STYLES.cine.id,
|
|
757
|
-
format: FORMATS.landscape.id,
|
|
758
|
-
watermark: 'your-watermark-id',
|
|
759
|
-
watermarkPosition: 'southeast'
|
|
760
|
-
});
|
|
761
|
-
|
|
762
|
-
console.log('Image generated:', result.imageId);
|
|
763
|
-
|
|
764
|
-
// Download the image
|
|
765
|
-
const { buffer } = await client.downloadFromCDN(result.imageId);
|
|
766
|
-
fs.writeFileSync('generated-image.jpg', buffer);
|
|
767
|
-
console.log('Image saved to generated-image.jpg');
|
|
768
|
-
|
|
769
|
-
} catch (error) {
|
|
770
|
-
console.error('Error:', error.message);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
generateAndDownload();
|
|
775
|
-
```
|
|
776
|
-
|
|
777
|
-
### Example 2: Generate Video and Extract GIF Frame
|
|
778
|
-
|
|
779
|
-
```typescript
|
|
780
|
-
import { createClient, STYLES, FORMATS } from '2dai-cloud-sdk';
|
|
781
|
-
import fs from 'fs';
|
|
782
|
-
|
|
783
|
-
const client = createClient('2dai_pk_your_api_key_here');
|
|
784
|
-
|
|
785
|
-
async function generateVideoAndExtractFrame() {
|
|
786
|
-
try {
|
|
787
|
-
// First generate an image
|
|
788
|
-
const image = await client.generateImage({
|
|
789
|
-
prompt: 'a dancing robot in a disco',
|
|
790
|
-
style: STYLES.anime.id,
|
|
791
|
-
format: FORMATS.profile.id
|
|
792
|
-
});
|
|
793
|
-
console.log('Image generated:', image.imageId);
|
|
794
|
-
|
|
795
|
-
// Generate video from image
|
|
796
|
-
const video = await client.generateVideo({
|
|
797
|
-
imageId: image.imageId,
|
|
798
|
-
duration: 3,
|
|
799
|
-
fps: 16
|
|
800
|
-
});
|
|
801
|
-
console.log('Video generated:', video.videoId);
|
|
802
|
-
|
|
803
|
-
// Download video as MP4
|
|
804
|
-
const { buffer: mp4Buffer } = await client.downloadFromCDN(video.videoId, { format: 'mp4' });
|
|
805
|
-
fs.writeFileSync('video.mp4', mp4Buffer);
|
|
806
|
-
console.log('Video saved to video.mp4');
|
|
807
|
-
|
|
808
|
-
// Extract first frame as GIF
|
|
809
|
-
const { buffer: gifBuffer } = await client.downloadFromCDN(video.videoId, { format: 'gif' });
|
|
810
|
-
fs.writeFileSync('thumbnail.gif', gifBuffer);
|
|
811
|
-
console.log('GIF thumbnail saved to thumbnail.gif');
|
|
812
|
-
|
|
813
|
-
} catch (error) {
|
|
814
|
-
console.error('Error:', error.message);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
generateVideoAndExtractFrame();
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
### Example 3: LLM with Memory and JSON Output
|
|
822
|
-
|
|
823
|
-
```typescript
|
|
824
|
-
import { createClient } from '2dai-cloud-sdk';
|
|
825
|
-
|
|
826
|
-
const client = createClient('2dai_pk_your_api_key_here');
|
|
827
|
-
|
|
828
|
-
async function chatWithMemory() {
|
|
829
|
-
const memory: string[] = [];
|
|
830
|
-
|
|
831
|
-
// First message
|
|
832
|
-
const response1 = await client.generateText({
|
|
833
|
-
prompt: 'My name is Alice and I love painting',
|
|
834
|
-
system: 'You are a friendly art assistant'
|
|
835
|
-
});
|
|
836
|
-
console.log('Response 1:', response1.response);
|
|
837
|
-
memory.push('User: My name is Alice and I love painting');
|
|
838
|
-
memory.push(`Assistant: ${response1.response}`);
|
|
94
|
+
## OpenAI Compatibility
|
|
839
95
|
|
|
840
|
-
|
|
841
|
-
const response2 = await client.generateText({
|
|
842
|
-
prompt: 'What art supplies would you recommend for me?',
|
|
843
|
-
system: 'You are a friendly art assistant',
|
|
844
|
-
memory
|
|
845
|
-
});
|
|
846
|
-
console.log('Response 2:', response2.response);
|
|
847
|
-
|
|
848
|
-
// Get structured JSON output
|
|
849
|
-
const analysis = await client.generateText({
|
|
850
|
-
prompt: 'Analyze the conversation we just had',
|
|
851
|
-
system: 'Analyze conversations and return structured data',
|
|
852
|
-
memory,
|
|
853
|
-
jsonFormat: true,
|
|
854
|
-
jsonTemplate: {
|
|
855
|
-
userName: 'the user name mentioned',
|
|
856
|
-
interests: 'array of user interests',
|
|
857
|
-
recommendationsGiven: 'number of recommendations',
|
|
858
|
-
sentiment: 'positive/neutral/negative'
|
|
859
|
-
}
|
|
860
|
-
});
|
|
861
|
-
console.log('Analysis:', JSON.parse(analysis.response));
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
chatWithMemory();
|
|
865
|
-
```
|
|
866
|
-
|
|
867
|
-
### Example 4: Batch Image Generation with Rate Limit Checking
|
|
96
|
+
Use with OpenAI client libraries:
|
|
868
97
|
|
|
869
98
|
```typescript
|
|
870
|
-
import
|
|
871
|
-
|
|
872
|
-
const client = createClient('2dai_pk_your_api_key_here');
|
|
873
|
-
|
|
874
|
-
async function batchGenerate(prompts: string[]) {
|
|
875
|
-
const results = [];
|
|
876
|
-
|
|
877
|
-
for (const prompt of prompts) {
|
|
878
|
-
// Check rate limits before each request
|
|
879
|
-
const limits = await client.checkLimits();
|
|
880
|
-
const imageLimit = limits.find(l => l.operation === 'image');
|
|
99
|
+
import OpenAI from 'openai';
|
|
881
100
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
const waitMs = resetTime.getTime() - Date.now();
|
|
886
|
-
await new Promise(resolve => setTimeout(resolve, waitMs + 1000));
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
try {
|
|
890
|
-
const result = await client.generateImage({
|
|
891
|
-
prompt,
|
|
892
|
-
style: STYLES.realistic.id
|
|
893
|
-
});
|
|
894
|
-
results.push({ prompt, imageId: result.imageId, success: true });
|
|
895
|
-
console.log(`Generated: ${prompt.substring(0, 30)}... -> ${result.imageId}`);
|
|
896
|
-
} catch (error: any) {
|
|
897
|
-
results.push({ prompt, error: error.message, success: false });
|
|
898
|
-
console.error(`Failed: ${prompt.substring(0, 30)}... -> ${error.message}`);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
return results;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
// Usage
|
|
906
|
-
const prompts = [
|
|
907
|
-
'a red apple on a wooden table',
|
|
908
|
-
'a blue ocean with waves',
|
|
909
|
-
'a green forest with sunlight'
|
|
910
|
-
];
|
|
911
|
-
|
|
912
|
-
batchGenerate(prompts).then(results => {
|
|
913
|
-
console.log('Batch complete:', results);
|
|
101
|
+
const client = new OpenAI({
|
|
102
|
+
apiKey: '2dai_pk_your_api_key_here',
|
|
103
|
+
baseURL: 'https://api.2dai.io/v1'
|
|
914
104
|
});
|
|
915
|
-
```
|
|
916
|
-
|
|
917
|
-
---
|
|
918
|
-
|
|
919
|
-
## API Reference
|
|
920
|
-
|
|
921
|
-
### Types
|
|
922
|
-
|
|
923
|
-
```typescript
|
|
924
|
-
interface ImageGenerationOptions {
|
|
925
|
-
prompt: string;
|
|
926
|
-
style?: StylePreset | string;
|
|
927
|
-
format?: FormatPreset | string;
|
|
928
|
-
negativePrompt?: string;
|
|
929
|
-
seed?: number;
|
|
930
|
-
width?: number;
|
|
931
|
-
height?: number;
|
|
932
|
-
watermark?: string;
|
|
933
|
-
watermarkPosition?: WatermarkPosition;
|
|
934
|
-
watermarkAsTiles?: boolean;
|
|
935
|
-
copyright?: string;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
interface VideoGenerationOptions {
|
|
939
|
-
imageId?: string;
|
|
940
|
-
imageBuffer?: Buffer;
|
|
941
|
-
duration?: number; // 1-10 seconds
|
|
942
|
-
fps?: number; // 8-32 fps
|
|
943
|
-
watermark?: string;
|
|
944
|
-
watermarkPosition?: WatermarkPosition;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
interface TextGenerationOptions {
|
|
948
|
-
prompt: string;
|
|
949
|
-
system?: string;
|
|
950
|
-
memory?: string[];
|
|
951
|
-
jsonFormat?: boolean;
|
|
952
|
-
jsonTemplate?: { [key: string]: string };
|
|
953
|
-
useRandomSeed?: boolean;
|
|
954
|
-
askKnowledge?: {
|
|
955
|
-
sources?: string[];
|
|
956
|
-
query?: string;
|
|
957
|
-
};
|
|
958
|
-
useMarkdown?: boolean; // Enable markdown formatting in response (default: false)
|
|
959
|
-
imageId?: string; // Image ID from CDN for vision/image analysis
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
interface UpscaleOptions {
|
|
963
|
-
factor?: number; // 2, 3, or 4 (default: 2)
|
|
964
|
-
seed?: number; // Optional seed for reproducibility
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
interface UpscaleResult {
|
|
968
|
-
success: boolean;
|
|
969
|
-
imageId: string;
|
|
970
|
-
width: number;
|
|
971
|
-
height: number;
|
|
972
|
-
seed?: number;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
interface OperationUsage {
|
|
976
|
-
current: {
|
|
977
|
-
requestsPer15Min: number;
|
|
978
|
-
requestsPerDay: number;
|
|
979
|
-
tokensPer15Min?: number; // Only for LLM operations
|
|
980
|
-
tokensPerDay?: number; // Only for LLM operations
|
|
981
|
-
};
|
|
982
|
-
remaining: {
|
|
983
|
-
requestsPer15Min: number;
|
|
984
|
-
requestsPerDay: number;
|
|
985
|
-
};
|
|
986
|
-
resetAt: {
|
|
987
|
-
window15Min: string; // ISO timestamp
|
|
988
|
-
daily: string; // ISO timestamp
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
interface APIKeySettings {
|
|
993
|
-
key: string;
|
|
994
|
-
name: string;
|
|
995
|
-
status: 'active' | 'suspended';
|
|
996
|
-
rateLimits: {
|
|
997
|
-
image: RateLimitConfig;
|
|
998
|
-
video: RateLimitConfig;
|
|
999
|
-
llm: LLMRateLimitConfig;
|
|
1000
|
-
cdn: RateLimitConfig;
|
|
1001
|
-
};
|
|
1002
|
-
currentUsage?: {
|
|
1003
|
-
image: OperationUsage;
|
|
1004
|
-
video: OperationUsage;
|
|
1005
|
-
llm: OperationUsage;
|
|
1006
|
-
cdn: OperationUsage;
|
|
1007
|
-
};
|
|
1008
|
-
llmSettings?: any;
|
|
1009
|
-
createdAt?: string;
|
|
1010
|
-
lastUsedAt?: string;
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
type WatermarkPosition =
|
|
1014
|
-
// Sharp gravity constants (recommended)
|
|
1015
|
-
| 'center'
|
|
1016
|
-
| 'northwest' | 'north' | 'northeast'
|
|
1017
|
-
| 'west' | 'east'
|
|
1018
|
-
| 'southwest' | 'south' | 'southeast'
|
|
1019
|
-
// Human-readable alternatives
|
|
1020
|
-
| 'top-left' | 'top-center' | 'top-right'
|
|
1021
|
-
| 'middle-left' | 'middle-center' | 'middle-right'
|
|
1022
|
-
| 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
1023
|
-
```
|
|
1024
|
-
|
|
1025
|
-
---
|
|
1026
|
-
|
|
1027
|
-
## Best Practices
|
|
1028
|
-
|
|
1029
|
-
### 1. Check Rate Limits Before Batch Operations
|
|
1030
|
-
|
|
1031
|
-
```typescript
|
|
1032
|
-
const limits = await client.checkLimits();
|
|
1033
|
-
const remaining = limits.find(l => l.operation === 'image')?.remaining.requestsPer15Min;
|
|
1034
|
-
|
|
1035
|
-
if (remaining && remaining < batchSize) {
|
|
1036
|
-
console.log(`Only ${remaining} requests available, reducing batch size`);
|
|
1037
|
-
}
|
|
1038
|
-
```
|
|
1039
|
-
|
|
1040
|
-
### 2. Use Appropriate Styles for Your Use Case
|
|
1041
105
|
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
STYLES.realistic.id
|
|
1047
|
-
|
|
1048
|
-
// For artistic/creative content
|
|
1049
|
-
STYLES.paint.id
|
|
1050
|
-
|
|
1051
|
-
// For anime/manga content
|
|
1052
|
-
STYLES.anime.id
|
|
1053
|
-
STYLES.manga.id
|
|
1054
|
-
|
|
1055
|
-
// For cinematic shots
|
|
1056
|
-
STYLES.cine.id
|
|
1057
|
-
```
|
|
1058
|
-
|
|
1059
|
-
### 3. Handle Errors Gracefully
|
|
1060
|
-
|
|
1061
|
-
```typescript
|
|
1062
|
-
try {
|
|
1063
|
-
const result = await client.generateImage({ prompt: 'test' });
|
|
1064
|
-
} catch (error: any) {
|
|
1065
|
-
if (error.message.includes('RATE_LIMIT_EXCEEDED')) {
|
|
1066
|
-
// Wait and retry
|
|
1067
|
-
await new Promise(r => setTimeout(r, 60000));
|
|
1068
|
-
} else if (error.message.includes('INVALID_API_KEY')) {
|
|
1069
|
-
// Check API key configuration
|
|
1070
|
-
} else {
|
|
1071
|
-
// Log and handle other errors
|
|
1072
|
-
console.error('Generation failed:', error.message);
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
```
|
|
1076
|
-
|
|
1077
|
-
### 4. Use Negative Prompts for Better Results (not fully supported yet)
|
|
1078
|
-
|
|
1079
|
-
```typescript
|
|
1080
|
-
const result = await client.generateImage({
|
|
1081
|
-
prompt: 'a beautiful portrait of a woman',
|
|
1082
|
-
negativePrompt: 'blurry, distorted, low quality, bad anatomy, extra limbs'
|
|
106
|
+
const completion = await client.chat.completions.create({
|
|
107
|
+
model: 'default',
|
|
108
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
109
|
+
stream: true
|
|
1083
110
|
});
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
### 5. Cache Generated Content
|
|
1087
|
-
|
|
1088
|
-
```typescript
|
|
1089
|
-
// Store image IDs for reuse
|
|
1090
|
-
const cache = new Map<string, string>();
|
|
1091
111
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
return cache.get(prompt)!;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
const result = await client.generateImage({ prompt });
|
|
1098
|
-
cache.set(prompt, result.imageId);
|
|
1099
|
-
return result.imageId;
|
|
112
|
+
for await (const chunk of completion) {
|
|
113
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || '');
|
|
1100
114
|
}
|
|
1101
115
|
```
|
|
1102
116
|
|
|
1103
|
-
### 6. Use Seeds for Reproducibility
|
|
1104
|
-
|
|
1105
|
-
```typescript
|
|
1106
|
-
// Same seed = same result (with same prompt and settings)
|
|
1107
|
-
const result1 = await client.generateImage({
|
|
1108
|
-
prompt: 'a red car',
|
|
1109
|
-
seed: 12345
|
|
1110
|
-
});
|
|
1111
|
-
|
|
1112
|
-
const result2 = await client.generateImage({
|
|
1113
|
-
prompt: 'a red car',
|
|
1114
|
-
seed: 12345
|
|
1115
|
-
});
|
|
1116
|
-
|
|
1117
|
-
// result1.imageId content will be identical to result2.imageId
|
|
1118
|
-
```
|
|
1119
|
-
|
|
1120
117
|
---
|
|
1121
118
|
|
|
1122
|
-
##
|
|
1123
|
-
|
|
1124
|
-
### Common Issues
|
|
1125
|
-
|
|
1126
|
-
#### "RATE_LIMIT_EXCEEDED" Error
|
|
1127
|
-
|
|
1128
|
-
**Problem:** You've exceeded your rate limit for the current time window.
|
|
1129
|
-
|
|
1130
|
-
**Solution:**
|
|
1131
|
-
```typescript
|
|
1132
|
-
const settings = await client.getSettings();
|
|
1133
|
-
const resetTime = settings.currentUsage?.image.resetAt.window15Min;
|
|
1134
|
-
console.log(`Rate limit resets at: ${resetTime}`);
|
|
1135
|
-
|
|
1136
|
-
// Wait for reset
|
|
1137
|
-
const waitMs = new Date(resetTime).getTime() - Date.now();
|
|
1138
|
-
await new Promise(r => setTimeout(r, waitMs + 1000));
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
#### "INVALID_API_KEY" Error
|
|
1142
|
-
|
|
1143
|
-
**Problem:** Your API key is invalid or expired.
|
|
1144
|
-
|
|
1145
|
-
**Solution:**
|
|
1146
|
-
- Verify your API key starts with `2dai_pk_`
|
|
1147
|
-
- Check that the key hasn't been revoked
|
|
1148
|
-
- Ensure you're using the correct environment (production vs staging)
|
|
1149
|
-
|
|
1150
|
-
#### Timeout Errors
|
|
1151
|
-
|
|
1152
|
-
**Problem:** Requests are timing out.
|
|
1153
|
-
|
|
1154
|
-
**Solution:**
|
|
1155
|
-
```typescript
|
|
1156
|
-
const client = createClient('2dai_pk_...', {
|
|
1157
|
-
timeout: 600000 // Increase to 10 minutes for long operations
|
|
1158
|
-
});
|
|
1159
|
-
```
|
|
1160
|
-
|
|
1161
|
-
#### Image Quality Issues
|
|
1162
|
-
|
|
1163
|
-
**Problem:** Generated images don't match expectations.
|
|
1164
|
-
|
|
1165
|
-
**Solution:**
|
|
1166
|
-
- Use more detailed, descriptive prompts (include lighting, style, mood, composition)
|
|
1167
|
-
- Add negative prompts to exclude unwanted elements (requires style support)
|
|
1168
|
-
- Try different styles for your use case (see [Available Styles](#available-styles))
|
|
1169
|
-
- Use specific dimensions with the `format` parameter
|
|
1170
|
-
- Experiment with different seeds for variations
|
|
119
|
+
## Available Styles
|
|
1171
120
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
121
|
+
| Style | Description |
|
|
122
|
+
|-------|-------------|
|
|
123
|
+
| `raw` | Unprocessed, natural look |
|
|
124
|
+
| `realistic` | Photo-realistic |
|
|
125
|
+
| `cine` | Cinematic, film-like |
|
|
126
|
+
| `portrait` | Optimized for portraits |
|
|
127
|
+
| `anime` | Japanese anime style |
|
|
128
|
+
| `manga` | Japanese manga style |
|
|
129
|
+
| `watercolor` | Watercolor painting |
|
|
130
|
+
| `paint` | Oil/acrylic painting |
|
|
131
|
+
| `comicbook` | Western comic style |
|
|
1176
132
|
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
**Problem:** Cannot download files from CDN.
|
|
1180
|
-
|
|
1181
|
-
**Solution:**
|
|
1182
|
-
```typescript
|
|
1183
|
-
// Ensure Authorization header is included
|
|
1184
|
-
const response = await axios.get(cdnUrl, {
|
|
1185
|
-
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
1186
|
-
responseType: 'arraybuffer',
|
|
1187
|
-
timeout: 30000
|
|
1188
|
-
});
|
|
1189
|
-
```
|
|
1190
|
-
|
|
1191
|
-
### Debug Mode
|
|
1192
|
-
|
|
1193
|
-
Enable debug mode to see detailed request/response logs:
|
|
1194
|
-
|
|
1195
|
-
```typescript
|
|
1196
|
-
const client = createClient('2dai_pk_...', {
|
|
1197
|
-
debug: true
|
|
1198
|
-
});
|
|
1199
|
-
```
|
|
133
|
+
See [Image Generation](../../wiki/Image-Generation#styles-reference) for all 14 styles.
|
|
1200
134
|
|
|
1201
135
|
---
|
|
1202
136
|
|
|
1203
137
|
## Testing
|
|
1204
138
|
|
|
1205
|
-
|
|
139
|
+
The SDK includes comprehensive test suites covering REST, WebSocket, and OpenAI-compatible endpoints.
|
|
1206
140
|
|
|
1207
141
|
```bash
|
|
1208
|
-
# Run all tests
|
|
142
|
+
# Run all tests
|
|
1209
143
|
npm test
|
|
1210
144
|
|
|
1211
|
-
# Run
|
|
1212
|
-
npm run test:rest
|
|
1213
|
-
|
|
1214
|
-
#
|
|
1215
|
-
npm run test:ws
|
|
1216
|
-
|
|
1217
|
-
# Run tests with coverage report
|
|
1218
|
-
npm run test:coverage
|
|
145
|
+
# Run specific test suites
|
|
146
|
+
npm run test:rest # REST API tests (25 tests)
|
|
147
|
+
npm run test:ws # WebSocket tests (38 tests)
|
|
148
|
+
npm run test:openai # OpenAI-compatible tests (15 tests)
|
|
1219
149
|
```
|
|
1220
150
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
| Test Suite | Tests | Expected Time | Notes |
|
|
1224
|
-
|------------|-------|---------------|-------|
|
|
1225
|
-
| REST API (`test:rest`) | 20 | ~6-7 min | Image/video generation dominates |
|
|
1226
|
-
| WebSocket (`test:ws`) | 26 | ~6 min | Similar generation overhead |
|
|
1227
|
-
| Full Suite (`test`) | 46 | ~12-13 min | Both suites combined |
|
|
1228
|
-
|
|
1229
|
-
**Time breakdown by operation type:**
|
|
1230
|
-
- Image Generation: ~28-37s per test (AI processing)
|
|
1231
|
-
- Image Editing: ~45-50s per test (includes resize)
|
|
1232
|
-
- Video Generation: ~100s per test (longest operation)
|
|
1233
|
-
- Image Upscale: ~80-85s per test
|
|
1234
|
-
- LLM Text Generation: ~2-11s per test (fast)
|
|
1235
|
-
- CDN/GIF Operations: <1s per test (instant)
|
|
1236
|
-
- Error Handling: <1s per test (validation only)
|
|
1237
|
-
|
|
1238
|
-
### Test Coverage
|
|
1239
|
-
|
|
1240
|
-
**REST API Tests (20 tests):**
|
|
1241
|
-
- Image Generation (2): Default settings, style + format
|
|
1242
|
-
- Image Editing (2): Basic edit, resize with dimensions
|
|
1243
|
-
- Image Upscale (1): AI upscale 2x
|
|
1244
|
-
- Video + CDN (4): Generation, MP4-to-GIF, resize
|
|
1245
|
-
- LLM Text (5): Simple prompt, system + memory, JSON, vision, markdown
|
|
1246
|
-
- Error Handling (3): Invalid API key, params, IDs
|
|
1247
|
-
- Settings (1): API key settings with usage
|
|
1248
|
-
- Frame Extraction (2): Multiple formats, resize + watermark
|
|
1249
|
-
- Watermarks (1): Position constants
|
|
1250
|
-
|
|
1251
|
-
**WebSocket Tests (26 tests):**
|
|
1252
|
-
- Connection & Auth (4): Connect, authenticate, reject invalid, ping/pong
|
|
1253
|
-
- Image Generation (2): Default, style + format
|
|
1254
|
-
- Image Editing (2): Basic edit, resize
|
|
1255
|
-
- Image Upscale (1): AI upscale via WS
|
|
1256
|
-
- Video Generation (1): 5-second video
|
|
1257
|
-
- GIF/CDN (3): MP4-to-GIF, resize, position
|
|
1258
|
-
- LLM Generation (4): Simple, system + memory + JSON, vision, markdown
|
|
1259
|
-
- Error Handling (3): Missing prompt, invalid ID, invalid dimensions
|
|
1260
|
-
- Connection Resilience (2): Graceful close, reconnection
|
|
1261
|
-
- Client SDK Options (4): Connection state, WS options, timeout, REST integration
|
|
151
|
+
See [tests/README.md](./tests/README.md) for detailed test documentation.
|
|
1262
152
|
|
|
1263
|
-
|
|
153
|
+
---
|
|
1264
154
|
|
|
1265
|
-
|
|
1266
|
-
```
|
|
1267
|
-
================================================================================
|
|
1268
|
-
🧪 TEST: Generate Image - Default Settings
|
|
1269
|
-
⏱️ [20:23:05] Total: 0.0s | Since last: 0.0s
|
|
1270
|
-
================================================================================
|
|
1271
|
-
```
|
|
155
|
+
## Changelog
|
|
1272
156
|
|
|
1273
|
-
|
|
157
|
+
See [CHANGELOG.md](./CHANGELOG.md) for version history and release notes.
|
|
1274
158
|
|
|
1275
159
|
---
|
|
1276
160
|
|
|
1277
|
-
##
|
|
161
|
+
## License
|
|
1278
162
|
|
|
1279
|
-
-
|
|
1280
|
-
- TypeScript 5.0+ (for TypeScript projects)
|
|
163
|
+
MIT License - see [LICENSE](./LICENSE) for details.
|
|
1281
164
|
|
|
1282
165
|
---
|
|
1283
166
|
|
|
1284
|
-
##
|
|
167
|
+
## Support
|
|
1285
168
|
|
|
1286
|
-
|
|
169
|
+
- **Documentation**: [Wiki](../../wiki)
|
|
170
|
+
- **Issues**: [GitHub Issues](https://github.com/2DAICommunity/2dai-cloud-sdk/issues)
|
|
171
|
+
- **Email**: [support@2dai.io](mailto:support@2dai.io)
|