@decartai/sdk 0.1.13 → 0.1.15
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 +109 -10
- package/dist/create-client.d.ts +46 -0
- package/dist/create-client.js +208 -0
- package/dist/files/types.js +4 -1
- package/dist/index.d.ts +8 -150
- package/dist/index.js +6 -116
- package/dist/index.react-native.d.ts +36 -0
- package/dist/index.react-native.js +9 -0
- package/dist/package.js +4 -0
- package/dist/process/types.d.ts +2 -2
- package/dist/realtime/browser/frame-metadata-diagnostics.js +90 -0
- package/dist/realtime/browser/frame-metadata-worker.js +2 -0
- package/dist/realtime/browser/index.js +32 -0
- package/dist/realtime/{mirror-stream.js → browser/mirror-stream.js} +2 -2
- package/dist/realtime/{preflight.js → browser/preflight.js} +20 -115
- package/dist/realtime/browser/prepare-connection.js +57 -0
- package/dist/realtime/client.d.ts +11 -4
- package/dist/realtime/client.js +42 -37
- package/dist/realtime/config-realtime.js +51 -0
- package/dist/realtime/livekit.js +26 -0
- package/dist/realtime/media-channel.js +40 -11
- package/dist/realtime/methods.d.ts +1 -1
- package/dist/realtime/methods.js +7 -2
- package/dist/realtime/observability/connection-quality.d.ts +3 -3
- package/dist/realtime/observability/connection-quality.js +3 -1
- package/dist/realtime/observability/g2g.d.ts +14 -0
- package/dist/realtime/observability/realtime-observability.js +8 -32
- package/dist/realtime/observability/webrtc-stats.d.ts +4 -4
- package/dist/realtime/preflight-connectivity.js +102 -0
- package/dist/realtime/preflight-types.d.ts +30 -0
- package/dist/realtime/react-native/index.js +36 -0
- package/dist/realtime/react-native/preflight.js +10 -0
- package/dist/realtime/react-native/prepare-connection.js +26 -0
- package/dist/realtime/signaling-channel.js +3 -1
- package/dist/realtime/stream-session.js +5 -4
- package/dist/realtime/subscribe-client.js +11 -10
- package/dist/shared/model.d.ts +56 -37
- package/dist/shared/model.js +61 -18
- package/dist/shared/request.js +5 -4
- package/dist/shared/types.d.ts +2 -2
- package/dist/shared/types.js +9 -2
- package/dist/utils/errors.d.ts +3 -0
- package/dist/utils/errors.js +16 -1
- package/dist/utils/media.js +1 -1
- package/dist/utils/platform.js +17 -1
- package/dist/utils/runtime.js +13 -0
- package/dist/utils/user-agent.js +1 -1
- package/dist/version.js +9 -4
- package/package.json +10 -3
- package/dist/realtime/observability/glass-to-glass.d.ts +0 -41
- package/dist/realtime/observability/glass-to-glass.js +0 -229
- package/dist/realtime/observability/pixel-marker.js +0 -144
- package/dist/realtime/preflight.d.ts +0 -59
package/README.md
CHANGED
|
@@ -164,23 +164,38 @@ realtimeClient.on("connectionQuality", (report) => { /* ... */ });
|
|
|
164
164
|
realtimeClient.getConnectionQuality(); // latest report, or null before the first sample
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
> `onConnectionQuality` and the `connectionQuality` event are **debounced** — they only re-fire
|
|
168
|
+
> when the verdict (`quality`/`limitingFactor`) changes, so they're not a live metrics feed. For a
|
|
169
|
+
> continuous read of the raw numbers, updated every stats tick (~1/s), use the `stats` event or
|
|
170
|
+
> poll `getConnectionQuality()?.metrics`:
|
|
171
|
+
>
|
|
172
|
+
> ```typescript
|
|
173
|
+
> realtimeClient.on("stats", (s) => updateLatencyHud(s.glassToGlass?.medianMs, s.video?.framesPerSecond));
|
|
174
|
+
> // or, on your own interval:
|
|
175
|
+
> setInterval(() => console.log(realtimeClient.getConnectionQuality()?.metrics.g2gMs), 1000);
|
|
176
|
+
> ```
|
|
177
|
+
|
|
167
178
|
**Glass-to-glass latency (opt-in, diagnostic).** Network RTT hides the dominant cost in
|
|
168
179
|
real-time video — model inference — so a session can read "good" while actually feeling laggy.
|
|
169
|
-
Set `debugQuality: true` to measure the *real* camera→display latency
|
|
170
|
-
|
|
171
|
-
(`ttffMs`) and **steady-state**
|
|
172
|
-
When present, glass-to-glass drives the latency verdict instead of RTT.
|
|
180
|
+
Set `debugQuality: true` to measure the *real* camera→display latency. The SDK attaches a capture
|
|
181
|
+
timestamp using LiveKit frame metadata; the server propagates it through inference and the SDK
|
|
182
|
+
matches it to output playout. This surfaces **startup** (`ttffMs`) and **steady-state**
|
|
183
|
+
(`g2gMs`) latency. When present, glass-to-glass drives the latency verdict instead of RTT.
|
|
173
184
|
|
|
174
|
-
>
|
|
175
|
-
>
|
|
185
|
+
> Frame metadata is currently experimental in LiveKit and requires encoded-transform support.
|
|
186
|
+
> It does not alter visible pixels. `g2gDropRatio` remains `null` until frame IDs are propagated
|
|
187
|
+
> through the server pipeline as well as timestamps.
|
|
176
188
|
|
|
177
189
|
```typescript
|
|
178
190
|
const realtimeClient = await client.realtime.connect(stream, {
|
|
179
191
|
model,
|
|
180
192
|
debugQuality: true,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// g2g updates every stats tick — read it from the `stats` event (the
|
|
196
|
+
// `connectionQuality` verdict is debounced and would go stale between changes):
|
|
197
|
+
realtimeClient.on("stats", ({ glassToGlass }) => {
|
|
198
|
+
console.log(glassToGlass?.ttffMs, glassToGlass?.medianMs);
|
|
184
199
|
});
|
|
185
200
|
```
|
|
186
201
|
|
|
@@ -243,6 +258,90 @@ if (status.status === "completed") {
|
|
|
243
258
|
}
|
|
244
259
|
```
|
|
245
260
|
|
|
261
|
+
### React Native / Expo
|
|
262
|
+
|
|
263
|
+
React Native realtime requires [LiveKit's React Native packages](https://github.com/livekit/client-sdk-react-native)
|
|
264
|
+
and an early `registerGlobals()` call. Plain `react-native-webrtc` is not
|
|
265
|
+
supported. SDK imports and `createDecartClient(...)` usage stay the same.
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
npm install @decartai/sdk livekit-client@2.20.1 \
|
|
269
|
+
@livekit/react-native@2.11.1 \
|
|
270
|
+
@livekit/react-native-webrtc@144.1.1
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Call LiveKit setup from a side-effect module that runs before your router or app
|
|
274
|
+
entrypoint:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
// livekit-bootstrap.ts
|
|
278
|
+
import { registerGlobals } from "@livekit/react-native";
|
|
279
|
+
|
|
280
|
+
registerGlobals();
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
// index.ts
|
|
285
|
+
import "./livekit-bootstrap";
|
|
286
|
+
import "expo-router/entry"; // or import your root App component
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
With the globals registered, realtime usage is the same as on the web. Use the
|
|
290
|
+
model's numeric FPS when configuring native camera capture, then pass that
|
|
291
|
+
`MediaStream` to the SDK:
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
import { createDecartClient, models, resolveFpsNumber } from "@decartai/sdk";
|
|
295
|
+
import { mediaDevices } from "@livekit/react-native-webrtc";
|
|
296
|
+
|
|
297
|
+
const client = createDecartClient({ apiKey: "your-api-key-here" });
|
|
298
|
+
const model = models.realtime("lucy-2.5");
|
|
299
|
+
const captureFps = resolveFpsNumber(model.fps);
|
|
300
|
+
|
|
301
|
+
const cameraStream = await mediaDevices.getUserMedia({
|
|
302
|
+
audio: false,
|
|
303
|
+
video: {
|
|
304
|
+
facingMode: "user",
|
|
305
|
+
frameRate: captureFps,
|
|
306
|
+
width: model.width,
|
|
307
|
+
height: model.height,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const realtimeClient = await client.realtime.connect(cameraStream, {
|
|
312
|
+
model,
|
|
313
|
+
preferredVideoCodec: "vp8",
|
|
314
|
+
onRemoteStream,
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
For Expo, install the config plugins:
|
|
319
|
+
|
|
320
|
+
```sh
|
|
321
|
+
npm install @livekit/react-native-expo-plugin@1.0.2 \
|
|
322
|
+
@config-plugins/react-native-webrtc
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Add them to `app.json`:
|
|
326
|
+
|
|
327
|
+
```json
|
|
328
|
+
{
|
|
329
|
+
"expo": {
|
|
330
|
+
"plugins": [
|
|
331
|
+
"@livekit/react-native-expo-plugin",
|
|
332
|
+
"@config-plugins/react-native-webrtc"
|
|
333
|
+
]
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Run `npx expo prebuild` and rebuild the native app. LiveKit does not run in Expo
|
|
339
|
+
Go. Bare React Native apps must follow LiveKit's native setup instructions.
|
|
340
|
+
|
|
341
|
+
Outgoing `mirror`, `debugQuality`, and deep connectivity preflight are browser-only
|
|
342
|
+
and fail with `UNSUPPORTED_PLATFORM_FEATURE` on React Native. Mirror the local
|
|
343
|
+
preview with your native video view instead.
|
|
344
|
+
|
|
246
345
|
## Development
|
|
247
346
|
|
|
248
347
|
### Setup
|
|
@@ -273,4 +372,4 @@ The package is published to npm as `@decartai/sdk`.
|
|
|
273
372
|
|
|
274
373
|
## License
|
|
275
374
|
|
|
276
|
-
MIT
|
|
375
|
+
MIT
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Logger } from "./utils/logger.js";
|
|
2
|
+
|
|
3
|
+
//#region src/create-client.d.ts
|
|
4
|
+
type DecartClientOptions = {
|
|
5
|
+
proxy: string;
|
|
6
|
+
apiKey?: never;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
realtimeBaseUrl?: string;
|
|
9
|
+
integration?: string;
|
|
10
|
+
logger?: Logger;
|
|
11
|
+
telemetry?: boolean;
|
|
12
|
+
} | {
|
|
13
|
+
proxy?: never;
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
realtimeBaseUrl?: string;
|
|
17
|
+
integration?: string;
|
|
18
|
+
logger?: Logger;
|
|
19
|
+
telemetry?: boolean;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Create a Decart API client.
|
|
23
|
+
*
|
|
24
|
+
* @param options - Configuration options
|
|
25
|
+
* @param options.proxy - URL of the proxy server. When set, the client will use the proxy instead of direct API access and apiKey is not required.
|
|
26
|
+
* @param options.apiKey - API key for authentication.
|
|
27
|
+
* @param options.baseUrl - Override the default API base URL.
|
|
28
|
+
* @param options.realtimeBaseUrl - Override the default WebSocket base URL for realtime connections.
|
|
29
|
+
* @param options.integration - Optional integration identifier.
|
|
30
|
+
*
|
|
31
|
+
* Realtime media uses LiveKit only (inference must enable it in `TRANSPORTS_ENABLED`).
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* // Option 1: Explicit API key (direct API access)
|
|
36
|
+
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
37
|
+
*
|
|
38
|
+
* // Option 2: Using DECART_API_KEY environment variable
|
|
39
|
+
* const client = createDecartClient();
|
|
40
|
+
*
|
|
41
|
+
* // Option 3: Using proxy (client-side, no API key needed)
|
|
42
|
+
* const client = createDecartClient({ proxy: "https://your-server.com/api/decart" });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
//#endregion
|
|
46
|
+
export { DecartClientOptions };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { createInvalidApiKeyError, createInvalidBaseUrlError } from "./utils/errors.js";
|
|
2
|
+
import { createFilesClient } from "./files/client.js";
|
|
3
|
+
import { createProcessClient } from "./process/client.js";
|
|
4
|
+
import { createQueueClient } from "./queue/client.js";
|
|
5
|
+
import { createTokensClient } from "./tokens/client.js";
|
|
6
|
+
import { readEnv } from "./utils/env.js";
|
|
7
|
+
import { createConsoleLogger } from "./utils/logger.js";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
//#region src/create-client.ts
|
|
10
|
+
const proxySchema = z.union([z.string().url(), z.string().startsWith("/")]);
|
|
11
|
+
const decartClientOptionsSchema = z.object({
|
|
12
|
+
apiKey: z.string().min(1).optional(),
|
|
13
|
+
baseUrl: z.url().optional(),
|
|
14
|
+
proxy: proxySchema.optional(),
|
|
15
|
+
integration: z.string().optional(),
|
|
16
|
+
realtimeBaseUrl: z.url().optional()
|
|
17
|
+
}).refine((data) => {
|
|
18
|
+
const hasProxy = !!data.proxy;
|
|
19
|
+
const hasApiKey = !!data.apiKey;
|
|
20
|
+
return !(hasProxy && hasApiKey);
|
|
21
|
+
}, { message: "Cannot provide both 'proxy' and 'apiKey'. Use 'proxy' for proxy mode or 'apiKey' for direct API access." });
|
|
22
|
+
/**
|
|
23
|
+
* Create a Decart API client.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Configuration options
|
|
26
|
+
* @param options.proxy - URL of the proxy server. When set, the client will use the proxy instead of direct API access and apiKey is not required.
|
|
27
|
+
* @param options.apiKey - API key for authentication.
|
|
28
|
+
* @param options.baseUrl - Override the default API base URL.
|
|
29
|
+
* @param options.realtimeBaseUrl - Override the default WebSocket base URL for realtime connections.
|
|
30
|
+
* @param options.integration - Optional integration identifier.
|
|
31
|
+
*
|
|
32
|
+
* Realtime media uses LiveKit only (inference must enable it in `TRANSPORTS_ENABLED`).
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* // Option 1: Explicit API key (direct API access)
|
|
37
|
+
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
38
|
+
*
|
|
39
|
+
* // Option 2: Using DECART_API_KEY environment variable
|
|
40
|
+
* const client = createDecartClient();
|
|
41
|
+
*
|
|
42
|
+
* // Option 3: Using proxy (client-side, no API key needed)
|
|
43
|
+
* const client = createDecartClient({ proxy: "https://your-server.com/api/decart" });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
const createDecartClientForPlatform = (createRealtime, options = {}) => {
|
|
47
|
+
const parsedOptions = decartClientOptionsSchema.safeParse(options);
|
|
48
|
+
if (!parsedOptions.success) {
|
|
49
|
+
const issue = parsedOptions.error.issues[0];
|
|
50
|
+
if (issue.path.includes("apiKey")) throw createInvalidApiKeyError();
|
|
51
|
+
if (issue.path.includes("baseUrl") || issue.path.includes("realtimeBaseUrl")) throw createInvalidBaseUrlError(options[issue.path.includes("realtimeBaseUrl") ? "realtimeBaseUrl" : "baseUrl"]);
|
|
52
|
+
if (issue.path.includes("proxy")) throw createInvalidBaseUrlError(issue.path.includes("proxy") ? options.proxy : void 0);
|
|
53
|
+
throw parsedOptions.error;
|
|
54
|
+
}
|
|
55
|
+
const isProxyMode = "proxy" in parsedOptions.data && !!parsedOptions.data.proxy;
|
|
56
|
+
const apiKey = isProxyMode ? void 0 : ("apiKey" in parsedOptions.data ? parsedOptions.data.apiKey : void 0) ?? readEnv("DECART_API_KEY");
|
|
57
|
+
if (!isProxyMode && !apiKey) throw createInvalidApiKeyError();
|
|
58
|
+
let baseUrl;
|
|
59
|
+
if (isProxyMode && "proxy" in parsedOptions.data && parsedOptions.data.proxy) baseUrl = parsedOptions.data.proxy;
|
|
60
|
+
else baseUrl = parsedOptions.data.baseUrl || "https://api.decart.ai";
|
|
61
|
+
const { integration } = parsedOptions.data;
|
|
62
|
+
const logger = "logger" in options && options.logger ? options.logger : createConsoleLogger("info");
|
|
63
|
+
const telemetryEnabled = !("telemetry" in options && options.telemetry === false);
|
|
64
|
+
const wsBaseUrl = parsedOptions.data.realtimeBaseUrl || "wss://api3.decart.ai";
|
|
65
|
+
const realtime = createRealtime({
|
|
66
|
+
publishBaseUrl: wsBaseUrl,
|
|
67
|
+
subscribeBaseUrl: isProxyMode || parsedOptions.data.baseUrl !== void 0 ? baseUrl : wsBaseUrl.replace(/^wss?:\/\//i, "https://"),
|
|
68
|
+
apiKey: apiKey || "",
|
|
69
|
+
integration,
|
|
70
|
+
logger,
|
|
71
|
+
telemetryEnabled
|
|
72
|
+
});
|
|
73
|
+
const process = createProcessClient({
|
|
74
|
+
baseUrl,
|
|
75
|
+
apiKey: apiKey || "",
|
|
76
|
+
integration
|
|
77
|
+
});
|
|
78
|
+
const queue = createQueueClient({
|
|
79
|
+
baseUrl,
|
|
80
|
+
apiKey: apiKey || "",
|
|
81
|
+
integration
|
|
82
|
+
});
|
|
83
|
+
const tokens = createTokensClient({
|
|
84
|
+
baseUrl,
|
|
85
|
+
apiKey: apiKey || "",
|
|
86
|
+
integration
|
|
87
|
+
});
|
|
88
|
+
const files = createFilesClient({
|
|
89
|
+
baseUrl,
|
|
90
|
+
apiKey: apiKey || "",
|
|
91
|
+
integration
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
realtime: {
|
|
95
|
+
connect: realtime.connect,
|
|
96
|
+
subscribe: realtime.subscribe,
|
|
97
|
+
/**
|
|
98
|
+
* Check whether the user's network can support a real-time session
|
|
99
|
+
* *before* connecting — so you can gate showing the integration.
|
|
100
|
+
*
|
|
101
|
+
* Default (STUN-only): validates WebRTC reachability (UDP egress / TURN
|
|
102
|
+
* need) and approximate latency via a throwaway peer connection — no
|
|
103
|
+
* session, instant. Opt-in deep probe (`{ deep: true, model }`): briefly
|
|
104
|
+
* opens a real session with a synthetic source and measures *true*
|
|
105
|
+
* glass-to-glass latency (plus upstream loss/jitter),
|
|
106
|
+
* then tears it down — accurate, but costs a short GPU session.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* // Fast, pre-session reachability check
|
|
111
|
+
* const { quality, reasons } = await client.realtime.checkConnectivity();
|
|
112
|
+
* if (quality === "critical") showFallbackUI(reasons);
|
|
113
|
+
*
|
|
114
|
+
* // Accurate, measured glass-to-glass verdict
|
|
115
|
+
* const probe = await client.realtime.checkConnectivity({ deep: true, model: models.realtime("lucy-restyle-2") });
|
|
116
|
+
* console.log(probe.metrics.g2gMs);
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
checkConnectivity: realtime.checkConnectivity
|
|
120
|
+
},
|
|
121
|
+
/**
|
|
122
|
+
* Client for synchronous image generation.
|
|
123
|
+
* Only image models support the sync/process API.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
128
|
+
* const result = await client.process({
|
|
129
|
+
* model: models.image("lucy-pro-i2i"),
|
|
130
|
+
* prompt: "Transform into anime style",
|
|
131
|
+
* data: imageBlob
|
|
132
|
+
* });
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
process,
|
|
136
|
+
/**
|
|
137
|
+
* Client for queue-based async video generation.
|
|
138
|
+
* Only video models support the queue API.
|
|
139
|
+
* Jobs are submitted and processed asynchronously.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
144
|
+
*
|
|
145
|
+
* // Option 1: Submit and poll automatically
|
|
146
|
+
* const result = await client.queue.submitAndPoll({
|
|
147
|
+
* model: models.video("lucy-pro-v2v"),
|
|
148
|
+
* prompt: "Transform into anime style",
|
|
149
|
+
* data: videoBlob,
|
|
150
|
+
* onStatusChange: (job) => console.log(`Job ${job.job_id}: ${job.status}`)
|
|
151
|
+
* });
|
|
152
|
+
*
|
|
153
|
+
* // Option 2: Submit and poll manually
|
|
154
|
+
* const job = await client.queue.submit({
|
|
155
|
+
* model: models.video("lucy-pro-v2v"),
|
|
156
|
+
* prompt: "Transform into anime style",
|
|
157
|
+
* data: videoBlob
|
|
158
|
+
* });
|
|
159
|
+
*
|
|
160
|
+
* // Poll until completion
|
|
161
|
+
* while (true) {
|
|
162
|
+
* const status = await client.queue.status(job.job_id);
|
|
163
|
+
* console.log(`Job ${status.job_id}: ${status.status}`);
|
|
164
|
+
*
|
|
165
|
+
* if (status.status === "completed") {
|
|
166
|
+
* const blob = await client.queue.result(job.job_id);
|
|
167
|
+
* break;
|
|
168
|
+
* }
|
|
169
|
+
* if (status.status === "failed") {
|
|
170
|
+
* throw new Error("Job failed");
|
|
171
|
+
* }
|
|
172
|
+
* await new Promise(resolve => setTimeout(resolve, 1500));
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
queue,
|
|
177
|
+
/**
|
|
178
|
+
* Client for creating client tokens.
|
|
179
|
+
* Client tokens are short-lived API keys safe for client-side use.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* // Server-side: Create a client token
|
|
184
|
+
* const serverClient = createDecartClient({ apiKey: process.env.DECART_API_KEY });
|
|
185
|
+
* const token = await serverClient.tokens.create();
|
|
186
|
+
* // Returns: { apiKey: "ek_...", expiresAt: "2024-12-15T12:10:00Z" }
|
|
187
|
+
*
|
|
188
|
+
* // Client-side: Use the client token
|
|
189
|
+
* const client = createDecartClient({ apiKey: token.apiKey });
|
|
190
|
+
* const realtimeClient = await client.realtime.connect(stream, options);
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
tokens,
|
|
194
|
+
/**
|
|
195
|
+
* Upload files once and reuse them across generations.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* const ref = await client.files.upload(blob);
|
|
200
|
+
* await rt.set({ image: ref.id, prompt: "make it cinematic" });
|
|
201
|
+
* await rt.set({ image: ref.id, prompt: "now in noir" });
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
files
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
//#endregion
|
|
208
|
+
export { createDecartClientForPlatform };
|
package/dist/files/types.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
//#region src/files/types.ts
|
|
2
|
+
/** Prefix on every uploaded-file id; disambiguates a ref string from base64. */
|
|
3
|
+
const FILE_REF_PREFIX = "file_";
|
|
1
4
|
/** True if `value` is a `"file_..."` reference id from `client.files.upload(...)`. */
|
|
2
5
|
const isFileRefId = (value) => typeof value === "string" && value.startsWith("file_");
|
|
3
6
|
//#endregion
|
|
4
|
-
export { isFileRefId };
|
|
7
|
+
export { FILE_REF_PREFIX, isFileRefId };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CanonicalModel, CustomModelDefinition, ImageModelDefinition, ImageModels, ListedModelDefinition, Model, ModelDefinition, ModelKind, RealTimeModels, VideoModelDefinition, VideoModels, isCanonicalModel, isImageModel, isModel, isRealtimeModel, isVideoModel, listModels, modelAliases, models, resolveCanonicalModelAlias, resolveModelAlias } from "./shared/model.js";
|
|
1
|
+
import { CanonicalModel, CustomModelDefinition, ImageModelDefinition, ImageModels, ListedModelDefinition, Model, ModelDefinition, ModelFps, ModelKind, RealTimeModels, VideoModelDefinition, VideoModels, isCanonicalModel, isImageModel, isModel, isRealtimeModel, isVideoModel, listModels, modelAliases, models, resolveCanonicalModelAlias, resolveFpsNumber, resolveModelAlias } from "./shared/model.js";
|
|
3
2
|
import { FileInput, ProcessOptions, ReactNativeFile } from "./process/types.js";
|
|
4
3
|
import { FileReference, FileUploadInput } from "./files/types.js";
|
|
5
4
|
import { FilesClient, UploadFileOptions } from "./files/client.js";
|
|
@@ -7,172 +6,31 @@ import { ProcessClient } from "./process/client.js";
|
|
|
7
6
|
import { JobStatus, JobStatusResponse, JobSubmitResponse, QueueJobResult, QueueSubmitAndPollOptions, QueueSubmitOptions } from "./queue/types.js";
|
|
8
7
|
import { QueueClient } from "./queue/client.js";
|
|
9
8
|
import { DecartSDKError, ERROR_CODES } from "./utils/errors.js";
|
|
10
|
-
import {
|
|
9
|
+
import { LogLevel, Logger, createConsoleLogger, noopLogger } from "./utils/logger.js";
|
|
10
|
+
import { G2GMetrics } from "./realtime/observability/g2g.js";
|
|
11
11
|
import { WebRTCStats } from "./realtime/observability/webrtc-stats.js";
|
|
12
12
|
import { ConnectionQuality, ConnectionQualityLimitingFactor, ConnectionQualityMetrics, ConnectionQualityReport } from "./realtime/observability/connection-quality.js";
|
|
13
13
|
import { ClientSessionConnectionBreakdownEvent, ClientSessionConnectionBreakdownPhase, DiagnosticEvent, DiagnosticEventName, DiagnosticEvents, ReconnectEvent, VideoStallEvent } from "./realtime/observability/diagnostics.js";
|
|
14
14
|
import { ConnectionState, GenerationEndedMessage, QueuePosition, QueuePositionMessage } from "./realtime/types.js";
|
|
15
15
|
import { SetInput } from "./realtime/methods.js";
|
|
16
|
-
import { Events, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState } from "./realtime/client.js";
|
|
17
|
-
import { CheckConnectivityOptions, ConnectivityMetrics, ConnectivityReport, ConnectivityTransport } from "./realtime/preflight.js";
|
|
16
|
+
import { Events, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState, RealtimeMediaStream } from "./realtime/client.js";
|
|
17
|
+
import { CheckConnectivityOptions, ConnectivityMetrics, ConnectivityReport, ConnectivityTransport } from "./realtime/preflight-types.js";
|
|
18
18
|
import { RealTimeSubscribeClient, SubscribeEvents, SubscribeOptions } from "./realtime/subscribe-client.js";
|
|
19
19
|
import { ModelState } from "./shared/types.js";
|
|
20
20
|
import { CreateTokenOptions, CreateTokenResponse, TokensClient } from "./tokens/client.js";
|
|
21
|
+
import { DecartClientOptions } from "./create-client.js";
|
|
21
22
|
|
|
22
23
|
//#region src/index.d.ts
|
|
23
|
-
type DecartClientOptions = {
|
|
24
|
-
proxy: string;
|
|
25
|
-
apiKey?: never;
|
|
26
|
-
baseUrl?: string;
|
|
27
|
-
realtimeBaseUrl?: string;
|
|
28
|
-
integration?: string;
|
|
29
|
-
logger?: Logger;
|
|
30
|
-
telemetry?: boolean;
|
|
31
|
-
} | {
|
|
32
|
-
proxy?: never;
|
|
33
|
-
apiKey?: string;
|
|
34
|
-
baseUrl?: string;
|
|
35
|
-
realtimeBaseUrl?: string;
|
|
36
|
-
integration?: string;
|
|
37
|
-
logger?: Logger;
|
|
38
|
-
telemetry?: boolean;
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Create a Decart API client.
|
|
42
|
-
*
|
|
43
|
-
* @param options - Configuration options
|
|
44
|
-
* @param options.proxy - URL of the proxy server. When set, the client will use the proxy instead of direct API access and apiKey is not required.
|
|
45
|
-
* @param options.apiKey - API key for authentication.
|
|
46
|
-
* @param options.baseUrl - Override the default API base URL.
|
|
47
|
-
* @param options.realtimeBaseUrl - Override the default WebSocket base URL for realtime connections.
|
|
48
|
-
* @param options.integration - Optional integration identifier.
|
|
49
|
-
*
|
|
50
|
-
* Realtime media uses LiveKit only (inference must enable it in `TRANSPORTS_ENABLED`).
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* ```ts
|
|
54
|
-
* // (direct API access)Option 1: Explicit API key
|
|
55
|
-
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
56
|
-
*
|
|
57
|
-
* // Option 2: Using DECART_API_KEY environment variable
|
|
58
|
-
* const client = createDecartClient();
|
|
59
|
-
*
|
|
60
|
-
* // Option 3: Using proxy (client-side, no API key needed)
|
|
61
|
-
* const client = createDecartClient({ proxy: "https://your-server.com/api/decart" });
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
24
|
declare const createDecartClient: (options?: DecartClientOptions) => {
|
|
65
25
|
realtime: {
|
|
66
|
-
connect: (stream:
|
|
26
|
+
connect: <TStream extends RealtimeMediaStream = MediaStream>(stream: TStream | null, options: RealTimeClientConnectOptions<TStream>) => Promise<RealTimeClient>;
|
|
67
27
|
subscribe: (options: SubscribeOptions) => Promise<RealTimeSubscribeClient>;
|
|
68
|
-
/**
|
|
69
|
-
* Check whether the user's network can support a real-time session
|
|
70
|
-
* *before* connecting — so you can gate showing the integration.
|
|
71
|
-
*
|
|
72
|
-
* Default (STUN-only): validates WebRTC reachability (UDP egress / TURN
|
|
73
|
-
* need) and approximate latency via a throwaway peer connection — no
|
|
74
|
-
* session, instant. Opt-in deep probe (`{ deep: true, model }`): briefly
|
|
75
|
-
* opens a real session with a synthetic source and measures *true*
|
|
76
|
-
* glass-to-glass latency (and end-to-end drops / upstream loss+jitter),
|
|
77
|
-
* then tears it down — accurate, but costs a short GPU session.
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```ts
|
|
81
|
-
* // Fast, pre-session reachability check
|
|
82
|
-
* const { quality, reasons } = await client.realtime.checkConnectivity();
|
|
83
|
-
* if (quality === "critical") showFallbackUI(reasons);
|
|
84
|
-
*
|
|
85
|
-
* // Accurate, measured glass-to-glass verdict
|
|
86
|
-
* const probe = await client.realtime.checkConnectivity({ deep: true, model: models.realtime("mirage") });
|
|
87
|
-
* console.log(probe.metrics.g2gMs);
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
28
|
checkConnectivity: (options?: CheckConnectivityOptions) => Promise<ConnectivityReport>;
|
|
91
29
|
};
|
|
92
|
-
/**
|
|
93
|
-
* Client for synchronous image generation.
|
|
94
|
-
* Only image models support the sync/process API.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```ts
|
|
98
|
-
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
99
|
-
* const result = await client.process({
|
|
100
|
-
* model: models.image("lucy-pro-i2i"),
|
|
101
|
-
* prompt: "Transform into anime style",
|
|
102
|
-
* data: imageBlob
|
|
103
|
-
* });
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
30
|
process: ProcessClient;
|
|
107
|
-
/**
|
|
108
|
-
* Client for queue-based async video generation.
|
|
109
|
-
* Only video models support the queue API.
|
|
110
|
-
* Jobs are submitted and processed asynchronously.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```ts
|
|
114
|
-
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
115
|
-
*
|
|
116
|
-
* // Option 1: Submit and poll automatically
|
|
117
|
-
* const result = await client.queue.submitAndPoll({
|
|
118
|
-
* model: models.video("lucy-pro-v2v"),
|
|
119
|
-
* prompt: "Transform into anime style",
|
|
120
|
-
* data: videoBlob,
|
|
121
|
-
* onStatusChange: (job) => console.log(`Job ${job.job_id}: ${job.status}`)
|
|
122
|
-
* });
|
|
123
|
-
*
|
|
124
|
-
* // Option 2: Submit and poll manually
|
|
125
|
-
* const job = await client.queue.submit({
|
|
126
|
-
* model: models.video("lucy-pro-v2v"),
|
|
127
|
-
* prompt: "Transform into anime style",
|
|
128
|
-
* data: videoBlob
|
|
129
|
-
* });
|
|
130
|
-
*
|
|
131
|
-
* // Poll until completion
|
|
132
|
-
* while (true) {
|
|
133
|
-
* const status = await client.queue.status(job.job_id);
|
|
134
|
-
* console.log(`Job ${status.job_id}: ${status.status}`);
|
|
135
|
-
*
|
|
136
|
-
* if (status.status === "completed") {
|
|
137
|
-
* const blob = await client.queue.result(job.job_id);
|
|
138
|
-
* break;
|
|
139
|
-
* }
|
|
140
|
-
* if (status.status === "failed") {
|
|
141
|
-
* throw new Error("Job failed");
|
|
142
|
-
* }
|
|
143
|
-
* await new Promise(resolve => setTimeout(resolve, 1500));
|
|
144
|
-
* }
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
31
|
queue: QueueClient;
|
|
148
|
-
/**
|
|
149
|
-
* Client for creating client tokens.
|
|
150
|
-
* Client tokens are short-lived API keys safe for client-side use.
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```ts
|
|
154
|
-
* // Server-side: Create a client token
|
|
155
|
-
* const serverClient = createDecartClient({ apiKey: process.env.DECART_API_KEY });
|
|
156
|
-
* const token = await serverClient.tokens.create();
|
|
157
|
-
* // Returns: { apiKey: "ek_...", expiresAt: "2024-12-15T12:10:00Z" }
|
|
158
|
-
*
|
|
159
|
-
* // Client-side: Use the client token
|
|
160
|
-
* const client = createDecartClient({ apiKey: token.apiKey });
|
|
161
|
-
* const realtimeClient = await client.realtime.connect(stream, options);
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
32
|
tokens: TokensClient;
|
|
165
|
-
/**
|
|
166
|
-
* Upload files once and reuse them across generations.
|
|
167
|
-
*
|
|
168
|
-
* @example
|
|
169
|
-
* ```ts
|
|
170
|
-
* const ref = await client.files.upload(blob);
|
|
171
|
-
* await rt.set({ image: ref.id, prompt: "make it cinematic" });
|
|
172
|
-
* await rt.set({ image: ref.id, prompt: "now in noir" });
|
|
173
|
-
* ```
|
|
174
|
-
*/
|
|
175
33
|
files: FilesClient;
|
|
176
34
|
};
|
|
177
35
|
//#endregion
|
|
178
|
-
export {
|
|
36
|
+
export { CanonicalModel, CheckConnectivityOptions, ClientSessionConnectionBreakdownEvent, ClientSessionConnectionBreakdownPhase, ConnectionQuality, ConnectionQualityLimitingFactor, ConnectionQualityMetrics, ConnectionQualityReport, ConnectionState, ConnectivityMetrics, ConnectivityReport, ConnectivityTransport, CreateTokenOptions, CreateTokenResponse, CustomModelDefinition, type DecartClientOptions, DecartSDKError, DiagnosticEvent, DiagnosticEventName, DiagnosticEvents, ERROR_CODES, FileInput, FileReference, FileUploadInput, FilesClient, G2GMetrics, GenerationEndedMessage, ImageModelDefinition, ImageModels, JobStatus, JobStatusResponse, JobSubmitResponse, ListedModelDefinition, LogLevel, Logger, Model, ModelDefinition, ModelFps, ModelKind, ModelState, ProcessClient, ProcessOptions, QueueClient, QueueJobResult, QueuePosition, QueuePositionMessage, QueueSubmitAndPollOptions, QueueSubmitOptions, ReactNativeFile, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState, Events as RealTimeEvents, RealTimeModels, RealTimeSubscribeClient, RealtimeMediaStream, ReconnectEvent, SetInput, SubscribeEvents, SubscribeOptions, TokensClient, UploadFileOptions, VideoModelDefinition, VideoModels, VideoStallEvent, WebRTCStats, createConsoleLogger, createDecartClient, isCanonicalModel, isImageModel, isModel, isRealtimeModel, isVideoModel, listModels, modelAliases, models, noopLogger, resolveCanonicalModelAlias, resolveFpsNumber, resolveModelAlias };
|