@decartai/sdk 0.0.27 → 0.0.29

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 CHANGED
@@ -4,7 +4,7 @@ import { ProcessClient } from "./process/client.js";
4
4
  import { JobStatus, JobStatusResponse, JobSubmitResponse, QueueJobResult, QueueSubmitAndPollOptions, QueueSubmitOptions } from "./queue/types.js";
5
5
  import { QueueClient } from "./queue/client.js";
6
6
  import { DecartSDKError, ERROR_CODES } from "./utils/errors.js";
7
- import { RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState } from "./realtime/client.js";
7
+ import { AvatarOptions, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState } from "./realtime/client.js";
8
8
  import { ModelState } from "./shared/types.js";
9
9
  import { CreateTokenResponse, TokensClient } from "./tokens/client.js";
10
10
  import { z } from "zod";
@@ -35,7 +35,7 @@ type DecartClientOptions = z.infer<typeof decartClientOptionsSchema>;
35
35
  */
36
36
  declare const createDecartClient: (options?: DecartClientOptions) => {
37
37
  realtime: {
38
- connect: (stream: MediaStream, options: RealTimeClientConnectOptions) => Promise<RealTimeClient>;
38
+ connect: (stream: MediaStream | null, options: RealTimeClientConnectOptions) => Promise<RealTimeClient>;
39
39
  };
40
40
  /**
41
41
  * Client for synchronous image generation.
@@ -109,4 +109,4 @@ declare const createDecartClient: (options?: DecartClientOptions) => {
109
109
  tokens: TokensClient;
110
110
  };
111
111
  //#endregion
112
- export { 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 RealTimeClient, type RealTimeClientConnectOptions, type RealTimeClientInitialState, type RealTimeModels, type TokensClient, type VideoModelDefinition, type VideoModels, createDecartClient, isImageModel, isRealtimeModel, isVideoModel, models };
112
+ export { type AvatarOptions, 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 RealTimeClient, type RealTimeClientConnectOptions, type RealTimeClientInitialState, type RealTimeModels, type TokensClient, type VideoModelDefinition, type VideoModels, createDecartClient, isImageModel, isRealtimeModel, isVideoModel, models };
@@ -49,6 +49,28 @@ interface VideoModelInputs {
49
49
  */
50
50
  data?: FileInput;
51
51
  }
52
+ /**
53
+ * Model-specific input documentation for lucy-restyle-v2v.
54
+ * Allows either prompt or reference_image (mutually exclusive).
55
+ */
56
+ interface VideoRestyleInputs {
57
+ /**
58
+ * Text description to use for the video editing.
59
+ * Mutually exclusive with reference_image.
60
+ */
61
+ prompt?: string;
62
+ /**
63
+ * Reference image to transform into a prompt.
64
+ * Mutually exclusive with prompt.
65
+ * Can be a File, Blob, ReadableStream, URL, or string URL.
66
+ */
67
+ reference_image?: FileInput;
68
+ /**
69
+ * Video file to process.
70
+ * Can be a File, Blob, ReadableStream, URL, or string URL.
71
+ */
72
+ data: FileInput;
73
+ }
52
74
  /**
53
75
  * Default inputs for models that only require a prompt.
54
76
  */
@@ -63,7 +85,7 @@ interface PromptInput {
63
85
  * This allows different models to have field-specific documentation while maintaining type safety.
64
86
  * Specific models are checked first, then falls back to category-based selection.
65
87
  */
66
- type ModelSpecificInputs<T extends ModelDefinition> = T["name"] extends "lucy-pro-i2i" ? ImageEditingInputs : T["name"] extends ImageModels ? ImageGenerationInputs : T["name"] extends VideoModels ? VideoModelInputs : PromptInput;
88
+ type ModelSpecificInputs<T extends ModelDefinition> = T["name"] extends "lucy-pro-i2i" ? ImageEditingInputs : T["name"] extends "lucy-restyle-v2v" ? VideoRestyleInputs : T["name"] extends ImageModels ? ImageGenerationInputs : T["name"] extends VideoModels ? VideoModelInputs : PromptInput;
67
89
  interface ProcessInputs {
68
90
  /**
69
91
  * Random seed for reproducible results.
@@ -11,7 +11,7 @@ const createQueueClient = (opts) => {
11
11
  const parsedInputs = model.inputSchema.safeParse(inputs);
12
12
  if (!parsedInputs.success) throw createInvalidInputError(`Invalid inputs for ${model.name}: ${parsedInputs.error.message}`);
13
13
  const processedInputs = {};
14
- for (const [key, value] of Object.entries(parsedInputs.data)) if (key === "data" || key === "start" || key === "end") processedInputs[key] = await fileInputToBlob(value);
14
+ for (const [key, value] of Object.entries(parsedInputs.data)) if (key === "data" || key === "start" || key === "end" || key === "reference_image") processedInputs[key] = await fileInputToBlob(value);
15
15
  else processedInputs[key] = value;
16
16
  return submitJob({
17
17
  baseUrl,
@@ -0,0 +1,90 @@
1
+ //#region src/realtime/audio-stream-manager.ts
2
+ /**
3
+ * Manages an audio stream for avatar-live mode.
4
+ * Creates a continuous audio stream that outputs silence by default,
5
+ * and allows playing audio files through the stream.
6
+ */
7
+ var AudioStreamManager = class {
8
+ audioContext;
9
+ destination;
10
+ silenceOscillator;
11
+ silenceGain;
12
+ currentSource = null;
13
+ _isPlaying = false;
14
+ constructor() {
15
+ this.audioContext = new AudioContext();
16
+ this.destination = this.audioContext.createMediaStreamDestination();
17
+ this.silenceOscillator = this.audioContext.createOscillator();
18
+ this.silenceGain = this.audioContext.createGain();
19
+ this.silenceGain.gain.value = 0;
20
+ this.silenceOscillator.connect(this.silenceGain);
21
+ this.silenceGain.connect(this.destination);
22
+ this.silenceOscillator.start();
23
+ }
24
+ /**
25
+ * Get the MediaStream to pass to WebRTC.
26
+ * This stream outputs silence when no audio is playing.
27
+ */
28
+ getStream() {
29
+ return this.destination.stream;
30
+ }
31
+ /**
32
+ * Check if audio is currently playing.
33
+ */
34
+ isPlaying() {
35
+ return this._isPlaying;
36
+ }
37
+ /**
38
+ * Play audio through the stream.
39
+ * When the audio ends, the stream automatically reverts to silence.
40
+ * @param audio - Audio data as Blob, File, or ArrayBuffer
41
+ * @returns Promise that resolves when audio finishes playing
42
+ */
43
+ async playAudio(audio) {
44
+ if (this.audioContext.state === "suspended") await this.audioContext.resume();
45
+ if (this._isPlaying) this.stopAudio();
46
+ let arrayBuffer;
47
+ if (audio instanceof ArrayBuffer) arrayBuffer = audio;
48
+ else arrayBuffer = await audio.arrayBuffer();
49
+ const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
50
+ const source = this.audioContext.createBufferSource();
51
+ source.buffer = audioBuffer;
52
+ source.connect(this.destination);
53
+ this.currentSource = source;
54
+ this._isPlaying = true;
55
+ return new Promise((resolve) => {
56
+ source.onended = () => {
57
+ this._isPlaying = false;
58
+ this.currentSource = null;
59
+ resolve();
60
+ };
61
+ source.start();
62
+ });
63
+ }
64
+ /**
65
+ * Stop currently playing audio immediately.
66
+ * The stream will revert to silence.
67
+ */
68
+ stopAudio() {
69
+ if (this.currentSource) {
70
+ try {
71
+ this.currentSource.stop();
72
+ } catch {}
73
+ this.currentSource = null;
74
+ }
75
+ this._isPlaying = false;
76
+ }
77
+ /**
78
+ * Clean up resources.
79
+ */
80
+ cleanup() {
81
+ this.stopAudio();
82
+ try {
83
+ this.silenceOscillator.stop();
84
+ } catch {}
85
+ this.audioContext.close();
86
+ }
87
+ };
88
+
89
+ //#endregion
90
+ export { AudioStreamManager };
@@ -11,9 +11,13 @@ declare const realTimeClientInitialStateSchema: z.ZodObject<{
11
11
  }, z.core.$strip>;
12
12
  type OnRemoteStreamFn = (stream: MediaStream) => void;
13
13
  type RealTimeClientInitialState = z.infer<typeof realTimeClientInitialStateSchema>;
14
+ declare const avatarOptionsSchema: z.ZodObject<{
15
+ avatarImage: z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>;
16
+ }, z.core.$strip>;
17
+ type AvatarOptions = z.infer<typeof avatarOptionsSchema>;
14
18
  declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
15
19
  model: z.ZodObject<{
16
- 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-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">]>]>;
20
+ name: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">, z.ZodLiteral<"avatar-live">]>, 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">]>]>;
17
21
  urlPath: z.ZodString;
18
22
  queueUrlPath: z.ZodOptional<z.ZodString>;
19
23
  fps: z.ZodNumber;
@@ -29,6 +33,9 @@ declare const realTimeClientConnectOptionsSchema: z.ZodObject<{
29
33
  }, z.core.$strip>>;
30
34
  }, z.core.$strip>>;
31
35
  customizeOffer: z.ZodOptional<z.ZodCustom<z.core.$InferInnerFunctionTypeAsync<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>, z.core.$InferInnerFunctionTypeAsync<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>>;
36
+ avatar: z.ZodOptional<z.ZodObject<{
37
+ avatarImage: z.ZodUnion<readonly [z.ZodCustom<Blob, Blob>, z.ZodCustom<File, File>, z.ZodString]>;
38
+ }, z.core.$strip>>;
32
39
  }, z.core.$strip>;
33
40
  type RealTimeClientConnectOptions = z.infer<typeof realTimeClientConnectOptionsSchema>;
34
41
  type Events = {
@@ -47,6 +54,8 @@ type RealTimeClient = {
47
54
  on: <K extends keyof Events>(event: K, listener: (data: Events[K]) => void) => void;
48
55
  off: <K extends keyof Events>(event: K, listener: (data: Events[K]) => void) => void;
49
56
  sessionId: string;
57
+ setImage: (image: Blob | File | string) => Promise<void>;
58
+ playAudio?: (audio: Blob | File | ArrayBuffer) => Promise<void>;
50
59
  };
51
60
  //#endregion
52
- export { RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState };
61
+ export { AvatarOptions, RealTimeClient, RealTimeClientConnectOptions, RealTimeClientInitialState };
@@ -1,6 +1,7 @@
1
1
  import { createWebrtcError } from "../utils/errors.js";
2
2
  import { modelDefinitionSchema } from "../shared/model.js";
3
3
  import { modelStateSchema } from "../shared/types.js";
4
+ import { AudioStreamManager } from "./audio-stream-manager.js";
4
5
  import { realtimeMethods } from "./methods.js";
5
6
  import { WebRTCManager } from "./webrtc-manager.js";
6
7
  import { z } from "zod";
@@ -8,13 +9,30 @@ import mitt from "mitt";
8
9
  import { v4 } from "uuid";
9
10
 
10
11
  //#region src/realtime/client.ts
12
+ async function blobToBase64(blob) {
13
+ return new Promise((resolve, reject) => {
14
+ const reader = new FileReader();
15
+ reader.onloadend = () => {
16
+ const base64 = reader.result.split(",")[1];
17
+ resolve(base64);
18
+ };
19
+ reader.onerror = reject;
20
+ reader.readAsDataURL(blob);
21
+ });
22
+ }
11
23
  const realTimeClientInitialStateSchema = modelStateSchema;
12
24
  const createAsyncFunctionSchema = (schema) => z.custom((fn) => schema.implementAsync(fn));
25
+ const avatarOptionsSchema = z.object({ avatarImage: z.union([
26
+ z.instanceof(Blob),
27
+ z.instanceof(File),
28
+ z.string()
29
+ ]) });
13
30
  const realTimeClientConnectOptionsSchema = z.object({
14
31
  model: modelDefinitionSchema,
15
32
  onRemoteStream: z.custom((val) => typeof val === "function", { message: "onRemoteStream must be a function" }),
16
33
  initialState: realTimeClientInitialStateSchema.optional(),
17
- customizeOffer: createAsyncFunctionSchema(z.function()).optional()
34
+ customizeOffer: createAsyncFunctionSchema(z.function()).optional(),
35
+ avatar: avatarOptionsSchema.optional()
18
36
  });
19
37
  const createRealTimeClient = (opts) => {
20
38
  const { baseUrl, apiKey, integration } = opts;
@@ -23,7 +41,21 @@ const createRealTimeClient = (opts) => {
23
41
  const parsedOptions = realTimeClientConnectOptionsSchema.safeParse(options);
24
42
  if (!parsedOptions.success) throw parsedOptions.error;
25
43
  const sessionId = v4();
26
- const { onRemoteStream, initialState } = parsedOptions.data;
44
+ const isAvatarLive = options.model.name === "avatar-live";
45
+ const { onRemoteStream, initialState, avatar } = parsedOptions.data;
46
+ let audioStreamManager;
47
+ let inputStream;
48
+ if (isAvatarLive && !stream) {
49
+ audioStreamManager = new AudioStreamManager();
50
+ inputStream = audioStreamManager.getStream();
51
+ } else inputStream = stream ?? new MediaStream();
52
+ let avatarImageBase64;
53
+ if (isAvatarLive && avatar?.avatarImage) {
54
+ let imageBlob;
55
+ if (typeof avatar.avatarImage === "string") imageBlob = await (await fetch(avatar.avatarImage)).blob();
56
+ else imageBlob = avatar.avatarImage;
57
+ avatarImageBase64 = await blobToBase64(imageBlob);
58
+ }
27
59
  const webrtcManager = new WebRTCManager({
28
60
  webrtcUrl: `${`${baseUrl}${options.model.urlPath}`}?api_key=${apiKey}&model=${options.model.name}`,
29
61
  apiKey,
@@ -41,9 +73,11 @@ const createRealTimeClient = (opts) => {
41
73
  },
42
74
  customizeOffer: options.customizeOffer,
43
75
  vp8MinBitrate: 300,
44
- vp8StartBitrate: 600
76
+ vp8StartBitrate: 600,
77
+ isAvatarLive,
78
+ avatarImageBase64
45
79
  });
46
- await webrtcManager.connect(stream);
80
+ await webrtcManager.connect(inputStream);
47
81
  const methods = realtimeMethods(webrtcManager);
48
82
  if (options.initialState) {
49
83
  if (options.initialState.prompt) {
@@ -51,15 +85,36 @@ const createRealTimeClient = (opts) => {
51
85
  methods.setPrompt(text, { enhance });
52
86
  }
53
87
  }
54
- return {
88
+ const client = {
55
89
  setPrompt: methods.setPrompt,
56
90
  isConnected: () => webrtcManager.isConnected(),
57
91
  getConnectionState: () => webrtcManager.getConnectionState(),
58
- disconnect: () => webrtcManager.cleanup(),
92
+ disconnect: () => {
93
+ webrtcManager.cleanup();
94
+ audioStreamManager?.cleanup();
95
+ },
59
96
  on: eventEmitter.on,
60
97
  off: eventEmitter.off,
61
- sessionId
98
+ sessionId,
99
+ setImage: async (image) => {
100
+ let imageBase64;
101
+ if (typeof image === "string") {
102
+ let url = null;
103
+ try {
104
+ url = new URL(image);
105
+ } catch {}
106
+ if (url?.protocol === "data:") imageBase64 = image.split(",")[1];
107
+ else if (url?.protocol === "http:" || url?.protocol === "https:") imageBase64 = await blobToBase64(await (await fetch(image)).blob());
108
+ else imageBase64 = image;
109
+ } else imageBase64 = await blobToBase64(image);
110
+ return webrtcManager.setImage(imageBase64);
111
+ }
62
112
  };
113
+ if (isAvatarLive && audioStreamManager) {
114
+ const manager = audioStreamManager;
115
+ client.playAudio = (audio) => manager.playAudio(audio);
116
+ }
117
+ return client;
63
118
  };
64
119
  return { connect };
65
120
  };
@@ -3,6 +3,7 @@ import mitt from "mitt";
3
3
 
4
4
  //#region src/realtime/webrtc-connection.ts
5
5
  const ICE_SERVERS = [{ urls: "stun:stun.l.google.com:19302" }];
6
+ const AVATAR_SETUP_TIMEOUT_MS = 15e3;
6
7
  var WebRTCConnection = class {
7
8
  pc = null;
8
9
  ws = null;
@@ -38,6 +39,7 @@ var WebRTCConnection = class {
38
39
  };
39
40
  this.ws.onclose = () => this.setState("disconnected");
40
41
  });
42
+ if (this.callbacks.avatarImageBase64) await this.sendAvatarImage(this.callbacks.avatarImageBase64);
41
43
  await this.setupNewPeerConnection();
42
44
  return new Promise((resolve, reject) => {
43
45
  this.connectionReject = reject;
@@ -55,18 +57,22 @@ var WebRTCConnection = class {
55
57
  });
56
58
  }
57
59
  async handleSignalingMessage(msg) {
58
- if (!this.pc) return;
59
60
  try {
60
- switch (msg.type) {
61
- case "error": {
62
- const error = new Error(msg.error);
63
- this.callbacks.onError?.(error);
64
- if (this.connectionReject) {
65
- this.connectionReject(error);
66
- this.connectionReject = null;
67
- }
68
- break;
61
+ if (msg.type === "error") {
62
+ const error = new Error(msg.error);
63
+ this.callbacks.onError?.(error);
64
+ if (this.connectionReject) {
65
+ this.connectionReject(error);
66
+ this.connectionReject = null;
69
67
  }
68
+ return;
69
+ }
70
+ if (msg.type === "image_set") {
71
+ this.websocketMessagesEmitter.emit("imageSet", msg);
72
+ return;
73
+ }
74
+ if (!this.pc) return;
75
+ switch (msg.type) {
70
76
  case "ready": {
71
77
  await this.applyCodecPreference("video/VP8");
72
78
  const offer = await this.pc.createOffer();
@@ -118,10 +124,35 @@ var WebRTCConnection = class {
118
124
  send(message) {
119
125
  if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(message));
120
126
  }
127
+ async sendAvatarImage(imageBase64) {
128
+ return this.setImageBase64(imageBase64);
129
+ }
130
+ /**
131
+ * Send an image to the server (e.g., as a reference for inference).
132
+ * Can be called after connection is established.
133
+ */
134
+ async setImageBase64(imageBase64) {
135
+ return new Promise((resolve, reject) => {
136
+ const timeoutId = setTimeout(() => {
137
+ this.websocketMessagesEmitter.off("imageSet", listener);
138
+ reject(/* @__PURE__ */ new Error("Image send timed out"));
139
+ }, AVATAR_SETUP_TIMEOUT_MS);
140
+ const listener = (msg) => {
141
+ clearTimeout(timeoutId);
142
+ this.websocketMessagesEmitter.off("imageSet", listener);
143
+ if (msg.status === "success") resolve();
144
+ else reject(/* @__PURE__ */ new Error(`Failed to send image: ${msg.status}`));
145
+ };
146
+ this.websocketMessagesEmitter.on("imageSet", listener);
147
+ this.send({
148
+ type: "set_image",
149
+ image_data: imageBase64
150
+ });
151
+ });
152
+ }
121
153
  setState(state) {
122
154
  if (this.state !== state) {
123
155
  this.state = state;
124
- console.log(`[WebRTC] State: ${state}`);
125
156
  this.callbacks.onStateChange?.(state);
126
157
  }
127
158
  }
@@ -140,6 +171,7 @@ var WebRTCConnection = class {
140
171
  username: turnConfig.username
141
172
  });
142
173
  this.pc = new RTCPeerConnection({ iceServers });
174
+ if (this.callbacks.isAvatarLive) this.pc.addTransceiver("video", { direction: "recvonly" });
143
175
  this.localStream.getTracks().forEach((track) => {
144
176
  if (this.pc && this.localStream) this.pc.addTrack(track, this.localStream);
145
177
  });
@@ -173,7 +205,7 @@ var WebRTCConnection = class {
173
205
  }
174
206
  async applyCodecPreference(preferredCodecName) {
175
207
  if (!this.pc) return;
176
- const videoTransceiver = this.pc.getTransceivers().find((r) => r.sender.track?.kind === "video");
208
+ const videoTransceiver = this.pc.getTransceivers().find((r) => r.sender.track?.kind === "video" || r.receiver.track?.kind === "video");
177
209
  if (!videoTransceiver) {
178
210
  console.error("Could not find video transceiver. Ensure track is added to peer connection.");
179
211
  return;
@@ -21,7 +21,9 @@ var WebRTCManager = class {
21
21
  onError: config.onError,
22
22
  customizeOffer: config.customizeOffer,
23
23
  vp8MinBitrate: config.vp8MinBitrate,
24
- vp8StartBitrate: config.vp8StartBitrate
24
+ vp8StartBitrate: config.vp8StartBitrate,
25
+ isAvatarLive: config.isAvatarLive,
26
+ avatarImageBase64: config.avatarImageBase64
25
27
  });
26
28
  }
27
29
  async connect(localStream) {
@@ -58,6 +60,9 @@ var WebRTCManager = class {
58
60
  getWebsocketMessageEmitter() {
59
61
  return this.connection.websocketMessagesEmitter;
60
62
  }
63
+ setImage(imageBase64) {
64
+ return this.connection.setImageBase64(imageBase64);
65
+ }
61
66
  };
62
67
 
63
68
  //#endregion
@@ -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<"mirage_v2">, 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">, z.ZodLiteral<"avatar-live">]>;
5
5
  declare const videoModels: 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">]>;
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<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">]>, 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">]>]>;
7
+ declare const modelSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"mirage">, z.ZodLiteral<"mirage_v2">, z.ZodLiteral<"lucy_v2v_720p_rt">, z.ZodLiteral<"avatar-live">]>, 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">]>]>;
8
8
  type Model = z.infer<typeof modelSchema>;
9
9
  type RealTimeModels = z.infer<typeof realtimeModels>;
10
10
  type VideoModels = z.infer<typeof videoModels>;
@@ -92,11 +92,12 @@ declare const modelInputSchemas: {
92
92
  resolution: z.ZodOptional<z.ZodDefault<z.ZodLiteral<"720p">>>;
93
93
  }, z.core.$strip>;
94
94
  readonly "lucy-restyle-v2v": z.ZodObject<{
95
- prompt: z.ZodString;
95
+ prompt: z.ZodOptional<z.ZodString>;
96
+ reference_image: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>>;
96
97
  data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
97
98
  seed: z.ZodOptional<z.ZodNumber>;
98
99
  resolution: z.ZodDefault<z.ZodOptional<z.ZodLiteral<"720p">>>;
99
- enhance_prompt: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
100
+ enhance_prompt: z.ZodOptional<z.ZodBoolean>;
100
101
  }, z.core.$strip>;
101
102
  };
102
103
  type ModelInputSchemas = typeof modelInputSchemas;
@@ -5,7 +5,8 @@ import { z } from "zod";
5
5
  const realtimeModels = z.union([
6
6
  z.literal("mirage"),
7
7
  z.literal("mirage_v2"),
8
- z.literal("lucy_v2v_720p_rt")
8
+ z.literal("lucy_v2v_720p_rt"),
9
+ z.literal("avatar-live")
9
10
  ]);
10
11
  const videoModels = z.union([
11
12
  z.literal("lucy-dev-i2v"),
@@ -123,12 +124,13 @@ const modelInputSchemas = {
123
124
  resolution: motionResolutionSchema
124
125
  }),
125
126
  "lucy-restyle-v2v": z.object({
126
- prompt: z.string().min(1).max(1e3).describe("Text prompt for the video editing"),
127
+ prompt: z.string().min(1).max(1e3).optional().describe("Text prompt for the video editing"),
128
+ reference_image: fileInputSchema.optional().describe("Reference image to transform into a prompt (File, Blob, ReadableStream, URL, or string URL)"),
127
129
  data: fileInputSchema.describe("Video file to process (File, Blob, ReadableStream, URL, or string URL)"),
128
130
  seed: z.number().optional().describe("Seed for the video generation"),
129
131
  resolution: proV2vResolutionSchema,
130
- enhance_prompt: z.boolean().default(true).optional().describe("Whether to enhance the prompt")
131
- })
132
+ enhance_prompt: z.boolean().optional().describe("Whether to enhance the prompt (only valid with text prompt, defaults to true on backend)")
133
+ }).refine((data) => data.prompt !== void 0 !== (data.reference_image !== void 0), { message: "Must provide either 'prompt' or 'reference_image', but not both" }).refine((data) => !(data.reference_image !== void 0 && data.enhance_prompt !== void 0), { message: "'enhance_prompt' is only valid when using 'prompt', not 'reference_image'" })
132
134
  };
133
135
  const modelDefinitionSchema = z.object({
134
136
  name: modelSchema,
@@ -164,6 +166,14 @@ const _models = {
164
166
  width: 1280,
165
167
  height: 704,
166
168
  inputSchema: z.object({})
169
+ },
170
+ "avatar-live": {
171
+ urlPath: "/v1/avatar-live/stream",
172
+ name: "avatar-live",
173
+ fps: 25,
174
+ width: 1280,
175
+ height: 720,
176
+ inputSchema: z.object({})
167
177
  }
168
178
  },
169
179
  image: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decartai/sdk",
3
- "version": "0.0.27",
3
+ "version": "0.0.29",
4
4
  "description": "Decart's JavaScript SDK",
5
5
  "type": "module",
6
6
  "license": "MIT",