@decartai/sdk 0.0.4 → 0.0.6
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 +2 -2
- package/dist/realtime/client.d.ts +5 -6
- package/dist/realtime/client.js +7 -1
- package/dist/realtime/methods.js +4 -8
- package/dist/realtime/webrtc-connection.js +68 -24
- package/dist/realtime/webrtc-manager.js +5 -2
- package/dist/shared/model.d.ts +2 -2
- package/dist/shared/model.js +13 -1
- package/dist/shared/types.d.ts +1 -1
- package/dist/shared/types.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ For complete documentation, guides, and examples, visit:
|
|
|
24
24
|
```typescript
|
|
25
25
|
import { createDecartClient, models } from "@decartai/sdk";
|
|
26
26
|
|
|
27
|
-
const model = models.realtime("
|
|
27
|
+
const model = models.realtime("mirage_v2");
|
|
28
28
|
|
|
29
29
|
// Get user's camera stream
|
|
30
30
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
@@ -50,7 +50,7 @@ const realtimeClient = await client.realtime.connect(stream, {
|
|
|
50
50
|
initialState: {
|
|
51
51
|
prompt: {
|
|
52
52
|
text: "Anime",
|
|
53
|
-
|
|
53
|
+
enhance: true
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
});
|
|
@@ -6,7 +6,7 @@ import { z } from "zod";
|
|
|
6
6
|
declare const realTimeClientInitialStateSchema: z.ZodObject<{
|
|
7
7
|
prompt: z.ZodOptional<z.ZodObject<{
|
|
8
8
|
text: z.ZodString;
|
|
9
|
-
|
|
9
|
+
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
10
10
|
}, z.core.$strip>>;
|
|
11
11
|
mirror: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
12
|
}, z.core.$strip>;
|
|
@@ -14,7 +14,7 @@ type OnRemoteStreamFn = (stream: MediaStream) => void;
|
|
|
14
14
|
type RealTimeClientInitialState = z.infer<typeof realTimeClientInitialStateSchema>;
|
|
15
15
|
declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
|
|
16
16
|
model: z.ZodObject<{
|
|
17
|
-
name: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"lucy_v2v_720p_rt">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-dev-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>]>;
|
|
17
|
+
name: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-dev-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>]>;
|
|
18
18
|
urlPath: z.ZodString;
|
|
19
19
|
fps: z.ZodNumber;
|
|
20
20
|
width: z.ZodNumber;
|
|
@@ -25,7 +25,7 @@ declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
|
|
|
25
25
|
initialState: z.ZodOptional<z.ZodObject<{
|
|
26
26
|
prompt: z.ZodOptional<z.ZodObject<{
|
|
27
27
|
text: z.ZodString;
|
|
28
|
-
|
|
28
|
+
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
29
29
|
}, z.core.$strip>>;
|
|
30
30
|
mirror: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
31
31
|
}, z.core.$strip>>;
|
|
@@ -37,11 +37,10 @@ type Events = {
|
|
|
37
37
|
error: DecartSDKError;
|
|
38
38
|
};
|
|
39
39
|
type RealTimeClient = {
|
|
40
|
-
enrichPrompt: (prompt: string) => Promise<string>;
|
|
41
40
|
setPrompt: (prompt: string, {
|
|
42
|
-
|
|
41
|
+
enhance
|
|
43
42
|
}?: {
|
|
44
|
-
|
|
43
|
+
enhance?: boolean;
|
|
45
44
|
}) => void;
|
|
46
45
|
setMirror: (enabled: boolean) => void;
|
|
47
46
|
isConnected: () => boolean;
|
package/dist/realtime/client.js
CHANGED
|
@@ -43,8 +43,14 @@ const createRealTimeClient = (opts) => {
|
|
|
43
43
|
});
|
|
44
44
|
await webrtcManager.connect(stream);
|
|
45
45
|
const methods = realtimeMethods(webrtcManager);
|
|
46
|
+
if (options.initialState) {
|
|
47
|
+
if (options.initialState.prompt) {
|
|
48
|
+
const { text, enhance } = options.initialState.prompt;
|
|
49
|
+
methods.setPrompt(text, { enhance });
|
|
50
|
+
}
|
|
51
|
+
if (options.initialState.mirror) methods.setMirror(options.initialState.mirror);
|
|
52
|
+
}
|
|
46
53
|
return {
|
|
47
|
-
enrichPrompt: methods.enrichPrompt,
|
|
48
54
|
setPrompt: methods.setPrompt,
|
|
49
55
|
setMirror: methods.setMirror,
|
|
50
56
|
isConnected: () => webrtcManager.isConnected(),
|
package/dist/realtime/methods.js
CHANGED
|
@@ -2,22 +2,19 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
//#region src/realtime/methods.ts
|
|
4
4
|
const realtimeMethods = (webrtcManager) => {
|
|
5
|
-
const
|
|
6
|
-
throw new Error("Not implemented");
|
|
7
|
-
};
|
|
8
|
-
const setPrompt = (prompt, { enrich } = {}) => {
|
|
5
|
+
const setPrompt = (prompt, { enhance } = {}) => {
|
|
9
6
|
const parsedInput = z.object({
|
|
10
7
|
prompt: z.string().min(1),
|
|
11
|
-
|
|
8
|
+
enhance: z.boolean().optional().default(true)
|
|
12
9
|
}).safeParse({
|
|
13
10
|
prompt,
|
|
14
|
-
|
|
11
|
+
enhance
|
|
15
12
|
});
|
|
16
13
|
if (!parsedInput.success) throw parsedInput.error;
|
|
17
14
|
webrtcManager.sendMessage({
|
|
18
15
|
type: "prompt",
|
|
19
16
|
prompt: parsedInput.data.prompt,
|
|
20
|
-
enhance_prompt: parsedInput.data.
|
|
17
|
+
enhance_prompt: parsedInput.data.enhance
|
|
21
18
|
});
|
|
22
19
|
};
|
|
23
20
|
const setMirror = (enabled) => {
|
|
@@ -29,7 +26,6 @@ const realtimeMethods = (webrtcManager) => {
|
|
|
29
26
|
});
|
|
30
27
|
};
|
|
31
28
|
return {
|
|
32
|
-
enrichPrompt,
|
|
33
29
|
setPrompt,
|
|
34
30
|
setMirror
|
|
35
31
|
};
|
|
@@ -3,13 +3,17 @@ const ICE_SERVERS = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
|
3
3
|
var WebRTCConnection = class {
|
|
4
4
|
pc = null;
|
|
5
5
|
ws = null;
|
|
6
|
+
localStream = null;
|
|
7
|
+
connectionReject = null;
|
|
6
8
|
state = "disconnected";
|
|
7
9
|
constructor(callbacks = {}) {
|
|
8
10
|
this.callbacks = callbacks;
|
|
9
11
|
}
|
|
10
|
-
async connect(url, localStream, timeout =
|
|
12
|
+
async connect(url, localStream, timeout = 25e3) {
|
|
11
13
|
const deadline = Date.now() + timeout;
|
|
14
|
+
this.localStream = localStream;
|
|
12
15
|
await new Promise((resolve, reject) => {
|
|
16
|
+
this.connectionReject = reject;
|
|
13
17
|
const timer = setTimeout(() => reject(/* @__PURE__ */ new Error("WebSocket timeout")), timeout);
|
|
14
18
|
this.ws = new WebSocket(url);
|
|
15
19
|
this.ws.onopen = () => {
|
|
@@ -28,34 +32,35 @@ var WebRTCConnection = class {
|
|
|
28
32
|
};
|
|
29
33
|
this.ws.onclose = () => this.setState("disconnected");
|
|
30
34
|
});
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.setState(s === "connected" ? "connected" : ["connecting", "new"].includes(s) ? "connecting" : "disconnected");
|
|
47
|
-
};
|
|
48
|
-
this.handleSignalingMessage({ type: "ready" });
|
|
49
|
-
while (Date.now() < deadline) {
|
|
50
|
-
if (this.state === "connected") return;
|
|
51
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
52
|
-
}
|
|
53
|
-
throw new Error("Connection timeout");
|
|
35
|
+
await this.setupNewPeerConnection();
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
this.connectionReject = reject;
|
|
38
|
+
const checkConnection = setInterval(() => {
|
|
39
|
+
if (this.state === "connected") {
|
|
40
|
+
clearInterval(checkConnection);
|
|
41
|
+
this.connectionReject = null;
|
|
42
|
+
resolve();
|
|
43
|
+
} else if (Date.now() >= deadline) {
|
|
44
|
+
clearInterval(checkConnection);
|
|
45
|
+
this.connectionReject = null;
|
|
46
|
+
reject(/* @__PURE__ */ new Error("Connection timeout"));
|
|
47
|
+
}
|
|
48
|
+
}, 100);
|
|
49
|
+
});
|
|
54
50
|
}
|
|
55
51
|
async handleSignalingMessage(msg) {
|
|
56
52
|
if (!this.pc) return;
|
|
57
53
|
try {
|
|
58
54
|
switch (msg.type) {
|
|
55
|
+
case "error": {
|
|
56
|
+
const error = new Error(msg.error);
|
|
57
|
+
this.callbacks.onError?.(error);
|
|
58
|
+
if (this.connectionReject) {
|
|
59
|
+
this.connectionReject(error);
|
|
60
|
+
this.connectionReject = null;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
59
64
|
case "ready": {
|
|
60
65
|
await this.applyCodecPreference("video/VP8");
|
|
61
66
|
const offer = await this.pc.createOffer();
|
|
@@ -89,6 +94,11 @@ var WebRTCConnection = class {
|
|
|
89
94
|
case "ice-candidate":
|
|
90
95
|
if (msg.candidate) await this.pc.addIceCandidate(msg.candidate);
|
|
91
96
|
break;
|
|
97
|
+
case "ice-restart": {
|
|
98
|
+
const turnConfig = msg.turn_config;
|
|
99
|
+
if (turnConfig) await this.setupNewPeerConnection(turnConfig);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
92
102
|
}
|
|
93
103
|
} catch (error) {
|
|
94
104
|
console.error("[WebRTC] Error:", error);
|
|
@@ -105,12 +115,46 @@ var WebRTCConnection = class {
|
|
|
105
115
|
this.callbacks.onStateChange?.(state);
|
|
106
116
|
}
|
|
107
117
|
}
|
|
118
|
+
async setupNewPeerConnection(turnConfig) {
|
|
119
|
+
if (!this.localStream) throw new Error("No local stream found");
|
|
120
|
+
if (this.pc) {
|
|
121
|
+
this.pc.getSenders().forEach((sender) => {
|
|
122
|
+
if (sender.track) this.pc.removeTrack(sender);
|
|
123
|
+
});
|
|
124
|
+
this.pc.close();
|
|
125
|
+
}
|
|
126
|
+
const iceServers = ICE_SERVERS;
|
|
127
|
+
if (turnConfig) iceServers.push({
|
|
128
|
+
urls: turnConfig.server_url,
|
|
129
|
+
credential: turnConfig.credential,
|
|
130
|
+
username: turnConfig.username
|
|
131
|
+
});
|
|
132
|
+
this.pc = new RTCPeerConnection({ iceServers });
|
|
133
|
+
this.localStream.getTracks().forEach((track) => this.pc.addTrack(track, this.localStream));
|
|
134
|
+
this.pc.ontrack = (e) => {
|
|
135
|
+
if (e.streams?.[0]) this.callbacks.onRemoteStream?.(e.streams[0]);
|
|
136
|
+
};
|
|
137
|
+
this.pc.onicecandidate = (e) => {
|
|
138
|
+
this.send({
|
|
139
|
+
type: "ice-candidate",
|
|
140
|
+
candidate: e.candidate
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
this.pc.onconnectionstatechange = () => {
|
|
144
|
+
if (!this.pc) return;
|
|
145
|
+
const s = this.pc.connectionState;
|
|
146
|
+
this.setState(s === "connected" ? "connected" : ["connecting", "new"].includes(s) ? "connecting" : "disconnected");
|
|
147
|
+
};
|
|
148
|
+
this.pc.oniceconnectionstatechange = () => {};
|
|
149
|
+
this.handleSignalingMessage({ type: "ready" });
|
|
150
|
+
}
|
|
108
151
|
cleanup() {
|
|
109
152
|
this.pc?.getSenders().forEach((s) => s.track?.stop());
|
|
110
153
|
this.pc?.close();
|
|
111
154
|
this.pc = null;
|
|
112
155
|
this.ws?.close();
|
|
113
156
|
this.ws = null;
|
|
157
|
+
this.localStream = null;
|
|
114
158
|
this.setState("disconnected");
|
|
115
159
|
}
|
|
116
160
|
async applyCodecPreference(preferredCodecName) {
|
|
@@ -5,7 +5,10 @@ import pRetry from "p-retry";
|
|
|
5
5
|
const PERMANENT_ERRORS = [
|
|
6
6
|
"permission denied",
|
|
7
7
|
"not allowed",
|
|
8
|
-
"invalid session"
|
|
8
|
+
"invalid session",
|
|
9
|
+
"401",
|
|
10
|
+
"invalid api key",
|
|
11
|
+
"unauthorized"
|
|
9
12
|
];
|
|
10
13
|
var WebRTCManager = class {
|
|
11
14
|
connection;
|
|
@@ -29,7 +32,7 @@ var WebRTCManager = class {
|
|
|
29
32
|
minTimeout: 1e3,
|
|
30
33
|
maxTimeout: 1e4,
|
|
31
34
|
onFailedAttempt: (error) => {
|
|
32
|
-
console.
|
|
35
|
+
console.error(`[WebRTC] Failed to connect: ${error.message}`);
|
|
33
36
|
this.connection.cleanup();
|
|
34
37
|
},
|
|
35
38
|
shouldRetry: (error) => {
|
package/dist/shared/model.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/shared/model.d.ts
|
|
4
|
-
declare const realtimeModels: z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"lucy_v2v_720p_rt">]>;
|
|
4
|
+
declare const realtimeModels: z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">]>;
|
|
5
5
|
declare const videoModels: z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-dev-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">]>;
|
|
6
6
|
declare const imageModels: z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>;
|
|
7
|
-
declare const modelSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"lucy_v2v_720p_rt">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-dev-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>]>;
|
|
7
|
+
declare const modelSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-dev-i2v">, z.ZodLiteral<"lucy-dev-v2v">, z.ZodLiteral<"lucy-pro-t2v">, z.ZodLiteral<"lucy-pro-i2v">, z.ZodLiteral<"lucy-pro-v2v">, z.ZodLiteral<"lucy-pro-flf2v">]>, z.ZodUnion<readonly [z.ZodLiteral<"lucy-pro-t2i">, z.ZodLiteral<"lucy-pro-i2i">]>]>;
|
|
8
8
|
type Model = z.infer<typeof modelSchema>;
|
|
9
9
|
type RealTimeModels = z.infer<typeof realtimeModels>;
|
|
10
10
|
type VideoModels = z.infer<typeof videoModels>;
|
package/dist/shared/model.js
CHANGED
|
@@ -2,7 +2,11 @@ import { createModelNotFoundError } from "../utils/errors.js";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/shared/model.ts
|
|
5
|
-
const realtimeModels = z.union([
|
|
5
|
+
const realtimeModels = z.union([
|
|
6
|
+
z.literal("mirage"),
|
|
7
|
+
z.literal("mirage_v2"),
|
|
8
|
+
z.literal("lucy_v2v_720p_rt")
|
|
9
|
+
]);
|
|
6
10
|
const videoModels = z.union([
|
|
7
11
|
z.literal("lucy-dev-i2v"),
|
|
8
12
|
z.literal("lucy-dev-v2v"),
|
|
@@ -97,6 +101,14 @@ const _models = {
|
|
|
97
101
|
height: 704,
|
|
98
102
|
inputSchema: z.object({})
|
|
99
103
|
},
|
|
104
|
+
mirage_v2: {
|
|
105
|
+
urlPath: "/v1/stream",
|
|
106
|
+
name: "mirage_v2",
|
|
107
|
+
fps: 12,
|
|
108
|
+
width: 1280,
|
|
109
|
+
height: 704,
|
|
110
|
+
inputSchema: z.object({})
|
|
111
|
+
},
|
|
100
112
|
lucy_v2v_720p_rt: {
|
|
101
113
|
urlPath: "/v1/stream",
|
|
102
114
|
name: "lucy_v2v_720p_rt",
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
declare const modelStateSchema: z.ZodObject<{
|
|
5
5
|
prompt: z.ZodOptional<z.ZodObject<{
|
|
6
6
|
text: z.ZodString;
|
|
7
|
-
|
|
7
|
+
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
8
8
|
}, z.core.$strip>>;
|
|
9
9
|
mirror: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
10
10
|
}, z.core.$strip>;
|
package/dist/shared/types.js
CHANGED
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
const modelStateSchema = z.object({
|
|
5
5
|
prompt: z.object({
|
|
6
6
|
text: z.string().min(1),
|
|
7
|
-
|
|
7
|
+
enhance: z.boolean().optional().default(true)
|
|
8
8
|
}).optional(),
|
|
9
9
|
mirror: z.boolean().optional().default(false)
|
|
10
10
|
});
|