@decartai/sdk 0.0.46 → 0.0.48
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/dist/index.d.ts +2 -2
- package/dist/queue/polling.js +9 -4
- package/dist/queue/types.d.ts +2 -0
- package/dist/realtime/client.d.ts +6 -8
- package/dist/realtime/client.js +10 -21
- package/dist/realtime/webrtc-connection.js +11 -12
- package/dist/realtime/webrtc-manager.js +2 -2
- package/dist/shared/types.d.ts +1 -0
- package/dist/shared/types.js +11 -4
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { DecartSDKError, ERROR_CODES } from "./utils/errors.js";
|
|
|
7
7
|
import { ConnectionState } from "./realtime/types.js";
|
|
8
8
|
import { SetInput } from "./realtime/methods.js";
|
|
9
9
|
import { RealTimeSubscribeClient, SubscribeEvents, SubscribeOptions } from "./realtime/subscribe-client.js";
|
|
10
|
-
import {
|
|
10
|
+
import { Events, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState } from "./realtime/client.js";
|
|
11
11
|
import { ModelState } from "./shared/types.js";
|
|
12
12
|
import { CreateTokenResponse, TokensClient } from "./tokens/client.js";
|
|
13
13
|
|
|
@@ -121,4 +121,4 @@ declare const createDecartClient: (options?: DecartClientOptions) => {
|
|
|
121
121
|
tokens: TokensClient;
|
|
122
122
|
};
|
|
123
123
|
//#endregion
|
|
124
|
-
export { type
|
|
124
|
+
export { type ConnectionState, type CreateTokenResponse, DecartClientOptions, type DecartSDKError, ERROR_CODES, type FileInput, type ImageModelDefinition, type ImageModels, type JobStatus, type JobStatusResponse, type JobSubmitResponse, type Model, type ModelDefinition, type ModelState, type ProcessClient, type ProcessOptions, type QueueClient, type QueueJobResult, type QueueSubmitAndPollOptions, type QueueSubmitOptions, type ReactNativeFile, type RealTimeClient, type RealTimeClientConnectOptions, type RealTimeClientInitialState, type Events as RealTimeEvents, type RealTimeModels, type RealTimeSubscribeClient, type SetInput, type SubscribeEvents, type SubscribeOptions, type TokensClient, type VideoModelDefinition, type VideoModels, createDecartClient, isImageModel, isRealtimeModel, isVideoModel, models };
|
package/dist/queue/polling.js
CHANGED
|
@@ -19,12 +19,17 @@ async function pollUntilComplete({ checkStatus, getContent, onStatusChange, sign
|
|
|
19
19
|
if (signal?.aborted) throw new Error("Polling aborted");
|
|
20
20
|
const status = await checkStatus();
|
|
21
21
|
if (onStatusChange) onStatusChange(status);
|
|
22
|
-
if (status.status === "completed")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
if (status.status === "completed") {
|
|
23
|
+
const data = await getContent();
|
|
24
|
+
return {
|
|
25
|
+
status: "completed",
|
|
26
|
+
job_id: status.job_id,
|
|
27
|
+
data
|
|
28
|
+
};
|
|
29
|
+
}
|
|
26
30
|
if (status.status === "failed") return {
|
|
27
31
|
status: "failed",
|
|
32
|
+
job_id: status.job_id,
|
|
28
33
|
error: "Job failed"
|
|
29
34
|
};
|
|
30
35
|
await sleep(POLLING_DEFAULTS.interval);
|
package/dist/queue/types.d.ts
CHANGED
|
@@ -10,13 +10,10 @@ declare const realTimeClientInitialStateSchema: z.ZodObject<{
|
|
|
10
10
|
text: z.ZodString;
|
|
11
11
|
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
12
|
}, z.core.$strip>>;
|
|
13
|
+
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>>;
|
|
13
14
|
}, z.core.$strip>;
|
|
14
15
|
type OnRemoteStreamFn = (stream: MediaStream) => void;
|
|
15
16
|
type RealTimeClientInitialState = z.infer<typeof realTimeClientInitialStateSchema>;
|
|
16
|
-
declare const avatarOptionsSchema: z.ZodObject<{
|
|
17
|
-
avatarImage: z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>;
|
|
18
|
-
}, z.core.$strip>;
|
|
19
|
-
type AvatarOptions = z.infer<typeof avatarOptionsSchema>;
|
|
20
17
|
declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
|
|
21
18
|
model: z.ZodObject<{
|
|
22
19
|
name: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">, z.ZodLiteral<"lucy_2_rt">, z.ZodLiteral<"live_avatar">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-fast-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">, z.ZodLiteral<"lucy-motion">, z.ZodLiteral<"lucy-restyle-v2v">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>]>;
|
|
@@ -33,16 +30,17 @@ declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
|
|
|
33
30
|
text: z.ZodString;
|
|
34
31
|
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
35
32
|
}, z.core.$strip>>;
|
|
33
|
+
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>>;
|
|
36
34
|
}, z.core.$strip>>;
|
|
37
35
|
customizeOffer: z.ZodOptional<z.ZodCustom<z.core.$InferInnerFunctionTypeAsync<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>, z.core.$InferInnerFunctionTypeAsync<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>>;
|
|
38
|
-
avatar: z.ZodOptional<z.ZodObject<{
|
|
39
|
-
avatarImage: z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>;
|
|
40
|
-
}, z.core.$strip>>;
|
|
41
36
|
}, z.core.$strip>;
|
|
42
37
|
type RealTimeClientConnectOptions = z.infer<typeof realTimeClientConnectOptionsSchema>;
|
|
43
38
|
type Events = {
|
|
44
39
|
connectionChange: ConnectionState;
|
|
45
40
|
error: DecartSDKError;
|
|
41
|
+
generationTick: {
|
|
42
|
+
seconds: number;
|
|
43
|
+
};
|
|
46
44
|
};
|
|
47
45
|
type RealTimeClient = {
|
|
48
46
|
set: (input: SetInput) => Promise<void>;
|
|
@@ -66,4 +64,4 @@ type RealTimeClient = {
|
|
|
66
64
|
playAudio?: (audio: Blob | File | ArrayBuffer) => Promise<void>;
|
|
67
65
|
};
|
|
68
66
|
//#endregion
|
|
69
|
-
export {
|
|
67
|
+
export { Events, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState };
|
package/dist/realtime/client.js
CHANGED
|
@@ -51,17 +51,11 @@ async function imageToBase64(image) {
|
|
|
51
51
|
}
|
|
52
52
|
const realTimeClientInitialStateSchema = modelStateSchema;
|
|
53
53
|
const createAsyncFunctionSchema = (schema) => z.custom((fn) => schema.implementAsync(fn));
|
|
54
|
-
const avatarOptionsSchema = z.object({ avatarImage: z.union([
|
|
55
|
-
z.instanceof(Blob),
|
|
56
|
-
z.instanceof(File),
|
|
57
|
-
z.string()
|
|
58
|
-
]) });
|
|
59
54
|
const realTimeClientConnectOptionsSchema = z.object({
|
|
60
55
|
model: modelDefinitionSchema,
|
|
61
56
|
onRemoteStream: z.custom((val) => typeof val === "function", { message: "onRemoteStream must be a function" }),
|
|
62
57
|
initialState: realTimeClientInitialStateSchema.optional(),
|
|
63
|
-
customizeOffer: createAsyncFunctionSchema(z.function()).optional()
|
|
64
|
-
avatar: avatarOptionsSchema.optional()
|
|
58
|
+
customizeOffer: createAsyncFunctionSchema(z.function()).optional()
|
|
65
59
|
});
|
|
66
60
|
const createRealTimeClient = (opts) => {
|
|
67
61
|
const { baseUrl, apiKey, integration } = opts;
|
|
@@ -69,7 +63,7 @@ const createRealTimeClient = (opts) => {
|
|
|
69
63
|
const parsedOptions = realTimeClientConnectOptionsSchema.safeParse(options);
|
|
70
64
|
if (!parsedOptions.success) throw parsedOptions.error;
|
|
71
65
|
const isAvatarLive = options.model.name === "live_avatar";
|
|
72
|
-
const { onRemoteStream, initialState
|
|
66
|
+
const { onRemoteStream, initialState } = parsedOptions.data;
|
|
73
67
|
let audioStreamManager;
|
|
74
68
|
let inputStream;
|
|
75
69
|
if (isAvatarLive && !stream) {
|
|
@@ -78,13 +72,8 @@ const createRealTimeClient = (opts) => {
|
|
|
78
72
|
} else inputStream = stream ?? new MediaStream();
|
|
79
73
|
let webrtcManager;
|
|
80
74
|
try {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const response = await fetch(avatar.avatarImage);
|
|
84
|
-
if (!response.ok) throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
|
|
85
|
-
avatarImageBase64 = await blobToBase64(await response.blob());
|
|
86
|
-
} else avatarImageBase64 = await blobToBase64(avatar.avatarImage);
|
|
87
|
-
const initialPrompt = isAvatarLive && initialState?.prompt ? {
|
|
75
|
+
const initialImage = initialState?.image ? await imageToBase64(initialState.image) : void 0;
|
|
76
|
+
const initialPrompt = initialState?.prompt ? {
|
|
88
77
|
text: initialState.prompt.text,
|
|
89
78
|
enhance: initialState.prompt.enhance
|
|
90
79
|
} : void 0;
|
|
@@ -104,8 +93,8 @@ const createRealTimeClient = (opts) => {
|
|
|
104
93
|
customizeOffer: options.customizeOffer,
|
|
105
94
|
vp8MinBitrate: 300,
|
|
106
95
|
vp8StartBitrate: 600,
|
|
107
|
-
|
|
108
|
-
|
|
96
|
+
modelName: options.model.name,
|
|
97
|
+
initialImage,
|
|
109
98
|
initialPrompt
|
|
110
99
|
});
|
|
111
100
|
const manager = webrtcManager;
|
|
@@ -116,12 +105,12 @@ const createRealTimeClient = (opts) => {
|
|
|
116
105
|
sessionId = msg.session_id;
|
|
117
106
|
};
|
|
118
107
|
manager.getWebsocketMessageEmitter().on("sessionId", sessionIdListener);
|
|
108
|
+
const tickListener = (msg) => {
|
|
109
|
+
emitOrBuffer("generationTick", { seconds: msg.seconds });
|
|
110
|
+
};
|
|
111
|
+
manager.getWebsocketMessageEmitter().on("generationTick", tickListener);
|
|
119
112
|
await manager.connect(inputStream);
|
|
120
113
|
const methods = realtimeMethods(manager, imageToBase64);
|
|
121
|
-
if (!isAvatarLive && initialState?.prompt) {
|
|
122
|
-
const { text, enhance } = initialState.prompt;
|
|
123
|
-
await methods.setPrompt(text, { enhance });
|
|
124
|
-
}
|
|
125
114
|
const client = {
|
|
126
115
|
set: methods.set,
|
|
127
116
|
setPrompt: methods.setPrompt,
|
|
@@ -53,8 +53,11 @@ var WebRTCConnection = class {
|
|
|
53
53
|
rejectConnect(/* @__PURE__ */ new Error("WebSocket closed"));
|
|
54
54
|
};
|
|
55
55
|
}), connectAbort]);
|
|
56
|
-
if (this.callbacks.
|
|
57
|
-
|
|
56
|
+
if (this.callbacks.initialImage) await Promise.race([this.setImageBase64(this.callbacks.initialImage, {
|
|
57
|
+
prompt: this.callbacks.initialPrompt?.text,
|
|
58
|
+
enhance: this.callbacks.initialPrompt?.enhance
|
|
59
|
+
}), connectAbort]);
|
|
60
|
+
else if (this.callbacks.initialPrompt) await Promise.race([this.sendInitialPrompt(this.callbacks.initialPrompt), connectAbort]);
|
|
58
61
|
await this.setupNewPeerConnection();
|
|
59
62
|
await Promise.race([new Promise((resolve, reject) => {
|
|
60
63
|
const checkConnection = setInterval(() => {
|
|
@@ -98,6 +101,11 @@ var WebRTCConnection = class {
|
|
|
98
101
|
this.setState("generating");
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
104
|
+
if (msg.type === "generation_tick") {
|
|
105
|
+
this.websocketMessagesEmitter.emit("generationTick", msg);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (msg.type === "generation_ended") return;
|
|
101
109
|
if (msg.type === "session_id") {
|
|
102
110
|
this.websocketMessagesEmitter.emit("sessionId", msg);
|
|
103
111
|
return;
|
|
@@ -158,15 +166,6 @@ var WebRTCConnection = class {
|
|
|
158
166
|
console.warn("[WebRTC] Message dropped: WebSocket is not open");
|
|
159
167
|
return false;
|
|
160
168
|
}
|
|
161
|
-
async sendAvatarImage(imageBase64) {
|
|
162
|
-
return this.setImageBase64(imageBase64);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Send an image to the server (e.g., as a reference for inference).
|
|
166
|
-
* Can be called after connection is established.
|
|
167
|
-
* Pass null to clear the reference image or use a placeholder.
|
|
168
|
-
* Optionally include a prompt to send with the image.
|
|
169
|
-
*/
|
|
170
169
|
async setImageBase64(imageBase64, options) {
|
|
171
170
|
return new Promise((resolve, reject) => {
|
|
172
171
|
const timeoutId = setTimeout(() => {
|
|
@@ -244,7 +243,7 @@ var WebRTCConnection = class {
|
|
|
244
243
|
this.pc = new RTCPeerConnection({ iceServers });
|
|
245
244
|
this.setState("connecting");
|
|
246
245
|
if (this.localStream) {
|
|
247
|
-
if (this.callbacks.
|
|
246
|
+
if (this.callbacks.modelName === "live_avatar") this.pc.addTransceiver("video", { direction: "recvonly" });
|
|
248
247
|
this.localStream.getTracks().forEach((track) => {
|
|
249
248
|
if (this.pc && this.localStream) this.pc.addTrack(track, this.localStream);
|
|
250
249
|
});
|
|
@@ -36,8 +36,8 @@ var WebRTCManager = class {
|
|
|
36
36
|
customizeOffer: config.customizeOffer,
|
|
37
37
|
vp8MinBitrate: config.vp8MinBitrate,
|
|
38
38
|
vp8StartBitrate: config.vp8StartBitrate,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
modelName: config.modelName,
|
|
40
|
+
initialImage: config.initialImage,
|
|
41
41
|
initialPrompt: config.initialPrompt
|
|
42
42
|
});
|
|
43
43
|
}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ declare const modelStateSchema: z.ZodObject<{
|
|
|
6
6
|
text: z.ZodString;
|
|
7
7
|
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
8
8
|
}, z.core.$strip>>;
|
|
9
|
+
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>>;
|
|
9
10
|
}, z.core.$strip>;
|
|
10
11
|
type ModelState = z.infer<typeof modelStateSchema>;
|
|
11
12
|
//#endregion
|
package/dist/shared/types.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/shared/types.ts
|
|
4
|
-
const modelStateSchema = z.object({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const modelStateSchema = z.object({
|
|
5
|
+
prompt: z.object({
|
|
6
|
+
text: z.string().min(1),
|
|
7
|
+
enhance: z.boolean().optional().default(true)
|
|
8
|
+
}).optional(),
|
|
9
|
+
image: z.union([
|
|
10
|
+
z.instanceof(Blob),
|
|
11
|
+
z.instanceof(File),
|
|
12
|
+
z.string()
|
|
13
|
+
]).optional()
|
|
14
|
+
});
|
|
8
15
|
|
|
9
16
|
//#endregion
|
|
10
17
|
export { modelStateSchema };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decartai/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.48",
|
|
4
4
|
"description": "Decart's JavaScript SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,13 +32,15 @@
|
|
|
32
32
|
"@biomejs/biome": "2.3.8",
|
|
33
33
|
"@types/bun": "^1.3.3",
|
|
34
34
|
"@types/node": "^22.15.17",
|
|
35
|
+
"@vitest/browser-playwright": "^4",
|
|
35
36
|
"bumpp": "^10.1.0",
|
|
36
37
|
"msw": "^2.11.3",
|
|
37
38
|
"pkg-pr-new": "^0.0.56",
|
|
39
|
+
"playwright": "^1.58.2",
|
|
38
40
|
"tsdown": "^0.14.1",
|
|
39
41
|
"typescript": "^5.8.3",
|
|
40
42
|
"vite": "^7.1.2",
|
|
41
|
-
"vitest": "^
|
|
43
|
+
"vitest": "^4.0.18"
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
46
|
"mitt": "^3.0.1",
|
|
@@ -51,6 +53,7 @@
|
|
|
51
53
|
"dev:example": "vite dev --port 3000",
|
|
52
54
|
"test": "vitest unit",
|
|
53
55
|
"test:e2e": "vitest e2e",
|
|
56
|
+
"test:e2e:realtime": "vitest --config vitest.config.e2e-realtime.ts",
|
|
54
57
|
"typecheck": "tsc --noEmit",
|
|
55
58
|
"format": "biome format --write",
|
|
56
59
|
"format:check": "biome check",
|