@visgate_ai/client 0.2.17
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/LICENSE +21 -0
- package/README.md +254 -0
- package/dist/index.cjs +801 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +511 -0
- package/dist/index.d.ts +511 -0
- package/dist/index.js +765 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Visgate AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# @visgate_ai/client
|
|
2
|
+
|
|
3
|
+
JavaScript/TypeScript SDK for the [Visgate API](https://visgateai.com) — one client for image and video generation across Fal, Replicate, and Runway.
|
|
4
|
+
|
|
5
|
+
Works in Node.js (18+), browsers, and with React, Vite, Next.js, and vanilla JS.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @visgate_ai/client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { Client } from "@visgate_ai/client";
|
|
17
|
+
|
|
18
|
+
const client = new Client(); // reads VISGATE_API_KEY from env (Node)
|
|
19
|
+
|
|
20
|
+
const result = await client.generate("a sunset over Istanbul");
|
|
21
|
+
console.log(result.imageUrl, result.cost, result.provider);
|
|
22
|
+
|
|
23
|
+
client.close();
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
With explicit API key:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
const client = new Client({ apiKey: "vg-..." });
|
|
30
|
+
const result = await client.generate("a sunset", { model: "fal-ai/flux/schnell" });
|
|
31
|
+
console.log(result.imageUrl);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **One client, three providers.** Fal, Replicate, and Runway behind a single API.
|
|
37
|
+
- **Managed and BYOK modes.** Use Visgate-managed keys or bring your own.
|
|
38
|
+
- **Promise-based API.** All methods return Promises; use `async/await` or `.then()`.
|
|
39
|
+
- **Automatic retries.** Transient errors (429, 5xx) are retried with exponential backoff.
|
|
40
|
+
- **Typed exceptions.** Catch `AuthenticationError`, `RateLimitError`, `ProviderError`, etc.
|
|
41
|
+
- **TypeScript.** Full type definitions included.
|
|
42
|
+
- **Framework-agnostic.** Use in vanilla JS, React, Vite, Next.js.
|
|
43
|
+
- **Async generation.** Video/image async mode with `client.requests.get()` for status polling; usage and billing resources.
|
|
44
|
+
|
|
45
|
+
## Authentication
|
|
46
|
+
|
|
47
|
+
**Node.js:** Set `VISGATE_API_KEY` in the environment or pass `apiKey` in options.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export VISGATE_API_KEY="vg-..."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Browser / Vite:** Pass `apiKey` in options (or use `import.meta.env.VITE_VISGATE_API_KEY` in Vite and pass it to the client).
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
const client = new Client({ apiKey: "vg-..." });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Production / proxy (recommended for browser apps)
|
|
60
|
+
|
|
61
|
+
Do not put your Visgate API key in the client. Use a server-side proxy that adds the key:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
const client = new Client({ proxyUrl: "/api/visgate" });
|
|
65
|
+
// No apiKey needed — the proxy adds Authorization on the server
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Set `VISGATE_API_KEY` on the server. This repo includes a ready-made proxy package: **`server-proxy/`** (published as `@visgate_ai/server-proxy` on npm). See [server-proxy/README.md](server-proxy/README.md) for setup; or implement your own forward that injects the key.
|
|
69
|
+
|
|
70
|
+
## BYOK (Bring Your Own Key)
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
const client = new Client({
|
|
74
|
+
apiKey: "vg-...",
|
|
75
|
+
falKey: "fal_...",
|
|
76
|
+
replicateKey: "r8_...",
|
|
77
|
+
runwayKey: "rw_...",
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
### Image Generation
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Quick generation (unified POST /generate)
|
|
87
|
+
const result = await client.generate("a cat in space", { model: "fal-ai/flux/schnell" });
|
|
88
|
+
console.log(result.status, result.imageUrl, result.cost);
|
|
89
|
+
|
|
90
|
+
// Full control (POST /images/generate) — matches API ImageGenerateRequest
|
|
91
|
+
const result = await client.images.generate("fal-ai/flux/schnell", "a cat in space", {
|
|
92
|
+
width: 1024,
|
|
93
|
+
height: 1024,
|
|
94
|
+
numImages: 1,
|
|
95
|
+
negativePrompt: null,
|
|
96
|
+
seed: null,
|
|
97
|
+
imageUrl: null, // optional: input image for img2img
|
|
98
|
+
preferCache: true, // use cache (exact or semantic match)
|
|
99
|
+
maxLatencyMs: null, // optional: max acceptable latency (ms)
|
|
100
|
+
webhookUrl: null, // optional: callback URL when done
|
|
101
|
+
callbackId: null, // optional: id in callback payload
|
|
102
|
+
});
|
|
103
|
+
// result: id, status, images, model, provider, cost, cacheHit, cacheSource?, latencyMs, savedAmount?, marginPercent?, createdAt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Video Generation
|
|
107
|
+
|
|
108
|
+
Video generation can take several minutes. To **avoid 502** when the request takes longer than proxy/Cloudflare timeout, use **async mode** (`preferAsync: true`): the API returns 202 immediately, then poll `client.requests.get(requestId)` until completed.
|
|
109
|
+
|
|
110
|
+
Use `VIDEO_MODEL_PRESETS` for provider model IDs (Fal, Replicate, Runway), or pass a model string (e.g. `fal-ai/veo3`, `replicate/lucataco/cogvideox-5b`, `runway/gen4_turbo`). For **image-to-video**, set `imageUrl` or `imageFile` in options.
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
import { Client, VIDEO_MODEL_PRESETS } from "@visgate_ai/client";
|
|
114
|
+
|
|
115
|
+
const client = new Client({ proxyUrl: "/api/visgate", timeout: 300_000 });
|
|
116
|
+
|
|
117
|
+
// Sync (wait for result; may hit proxy timeout on long videos)
|
|
118
|
+
const syncResult = await client.videos.generate(VIDEO_MODEL_PRESETS.fal, "waves on a beach", {
|
|
119
|
+
durationSeconds: 6,
|
|
120
|
+
skipGcsUpload: true,
|
|
121
|
+
});
|
|
122
|
+
console.log(syncResult.videoUrl, syncResult.cacheHit, syncResult.cost);
|
|
123
|
+
|
|
124
|
+
// Async (recommended): returns 202, poll client.requests.get(requestId)
|
|
125
|
+
const result = await client.videos.generate("fal-ai/veo3", "waves on a beach", {
|
|
126
|
+
durationSeconds: 6,
|
|
127
|
+
skipGcsUpload: true, // faster; return provider URL directly
|
|
128
|
+
preferAsync: true, // avoids 502 — returns 202, poll client.requests.get(requestId)
|
|
129
|
+
imageUrl: null, // optional: input image for img2vid (or use imageFile)
|
|
130
|
+
webhookUrl: null, // optional: callback URL when done
|
|
131
|
+
callbackId: null, // optional: id in callback payload
|
|
132
|
+
params: {}, // optional: extra provider params
|
|
133
|
+
});
|
|
134
|
+
if (result.status === "accepted") {
|
|
135
|
+
let status = await client.requests.get(result.requestId);
|
|
136
|
+
while (status.status === "pending" || status.status === "processing") {
|
|
137
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
138
|
+
status = await client.requests.get(result.requestId);
|
|
139
|
+
}
|
|
140
|
+
console.log(status.status, status.outputUrl);
|
|
141
|
+
} else {
|
|
142
|
+
console.log(result.videoUrl, result.cacheHit, result.status);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
On the server, set the proxy route’s `maxDuration` (e.g. 300 seconds) so the request is not cut off — see [server-proxy/README.md](server-proxy/README.md).
|
|
147
|
+
|
|
148
|
+
### Async request status (Requests)
|
|
149
|
+
|
|
150
|
+
After starting an async generation (video or image with `preferAsync: true`), poll the request status until completion:
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
const status = await client.requests.get(result.requestId);
|
|
154
|
+
// status: requestId, status ("pending" | "processing" | "completed" | "failed"),
|
|
155
|
+
// mediaType, provider, model, outputUrl, errorMessage, createdAt, completedAt
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Model Discovery
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
const resp = await client.models.list({ provider: "fal", mediaType: "image", limit: 20 });
|
|
162
|
+
for (const m of resp.models) console.log(m.id, m.name);
|
|
163
|
+
|
|
164
|
+
const model = await client.models.get("fal-ai/flux/schnell");
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Usage and Billing
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
const usage = await client.usage.get("month");
|
|
171
|
+
console.log(usage.totalRequests, usage.totalBilledCost, usage.cacheHitRate, usage.avgLatency, usage.history);
|
|
172
|
+
|
|
173
|
+
const logs = await client.usage.logs({ limit: 50 });
|
|
174
|
+
const dashboard = await client.usage.dashboard("week");
|
|
175
|
+
|
|
176
|
+
// Track download event (POST /usage/downloads)
|
|
177
|
+
await client.usage.trackDownload("request-id", "https://...", { mediaType: "image" });
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Billing
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
const stats = await client.billing.getStats(); // public stats
|
|
184
|
+
const info = await client.billing.getInfo(); // org billing info (tier, balance, etc.)
|
|
185
|
+
const pricing = await client.billing.getPricing(); // model pricing list
|
|
186
|
+
await client.billing.checkout(10, "https://...", { customerEmail: "..." });
|
|
187
|
+
await client.billing.updateSubscription("starter");
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Provider Management
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const keys = await client.providers.listKeys();
|
|
194
|
+
const balances = await client.providers.balances();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Health Check
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
const health = await client.health();
|
|
201
|
+
console.log(health.status);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Error Handling
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
import { Client, AuthenticationError, RateLimitError, ProviderError, ValidationError, VisgateError } from "@visgate_ai/client";
|
|
208
|
+
|
|
209
|
+
const client = new Client({ apiKey: "vg-..." });
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const result = await client.generate("a sunset");
|
|
213
|
+
} catch (err) {
|
|
214
|
+
if (err instanceof AuthenticationError) console.error("Invalid API key");
|
|
215
|
+
else if (err instanceof RateLimitError) console.error("Rate limit", err.retryAfter);
|
|
216
|
+
else if (err instanceof ProviderError) console.error("Provider error", err.provider);
|
|
217
|
+
else if (err instanceof ValidationError) console.error("Validation", err.field);
|
|
218
|
+
else if (err instanceof VisgateError) console.error(err.message, err.errorCode);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Configuration
|
|
223
|
+
|
|
224
|
+
| Option | Default | Description |
|
|
225
|
+
| ------------ | --------------------------- | ------------------------------ |
|
|
226
|
+
| `apiKey` | `process.env.VISGATE_API_KEY` | Visgate API key (optional when using `proxyUrl`) |
|
|
227
|
+
| `proxyUrl` | — | Server proxy URL; when set, no key or BYOK is sent |
|
|
228
|
+
| `baseUrl` | `https://visgateai.com/api/v1` | API base URL |
|
|
229
|
+
| `timeout` | `120000` (ms) | Request timeout |
|
|
230
|
+
| `maxRetries` | `2` | Retries for 429 and 5xx |
|
|
231
|
+
| `falKey` | — | Fal BYOK key |
|
|
232
|
+
| `replicateKey` | — | Replicate BYOK key |
|
|
233
|
+
| `runwayKey` | — | Runway BYOK key |
|
|
234
|
+
|
|
235
|
+
## AsyncClient
|
|
236
|
+
|
|
237
|
+
For API parity with the Python SDK, `AsyncClient` is also exported; it has the same interface as `Client` (all methods return Promises).
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
import { AsyncClient } from "@visgate_ai/client";
|
|
241
|
+
|
|
242
|
+
const client = new AsyncClient();
|
|
243
|
+
const result = await client.generate("a sunset");
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Repository structure
|
|
247
|
+
|
|
248
|
+
- **`src/`** — @visgate_ai/client (client library): `generate`, `images`, `videos`, `models`, `requests` (async status), `usage`, `providers`, `billing`
|
|
249
|
+
- **`server-proxy/`** — `@visgate_ai/server-proxy`: server-side proxy for Next.js and other Node runtimes. Install with `npm install @visgate_ai/server-proxy` or use locally from this repo.
|
|
250
|
+
- **`examples/`** — Next.js, vanilla, and Vite examples
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT — see [LICENSE](LICENSE).
|