@decartai/sdk 0.0.7 → 0.0.12
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 +28 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +7 -4
- package/dist/process/client.js +3 -2
- package/dist/process/request.js +6 -2
- package/dist/process/types.d.ts +136 -3
- package/dist/realtime/client.js +2 -1
- package/dist/realtime/webrtc-connection.js +7 -2
- package/dist/realtime/webrtc-manager.js +1 -1
- package/dist/shared/model.d.ts +45 -9
- package/dist/shared/model.js +53 -38
- package/dist/utils/user-agent.js +32 -0
- package/dist/version.js +10 -0
- package/package.json +59 -60
package/README.md
CHANGED
|
@@ -82,6 +82,34 @@ const result = await client.process({
|
|
|
82
82
|
videoElement.src = URL.createObjectURL(result);
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
## Development
|
|
86
|
+
|
|
87
|
+
### Setup
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pnpm install
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Development Commands
|
|
94
|
+
|
|
95
|
+
- `pnpm build` - Build the project
|
|
96
|
+
- `pnpm dev:example` - Run Vite dev server for examples
|
|
97
|
+
- `pnpm test` - Run unit tests
|
|
98
|
+
- `pnpm test:e2e` - Run end-to-end tests
|
|
99
|
+
- `pnpm typecheck` - Type check with TypeScript
|
|
100
|
+
- `pnpm format` - Format code with Biome
|
|
101
|
+
- `pnpm lint` - Lint code with Biome
|
|
102
|
+
|
|
103
|
+
### Publishing
|
|
104
|
+
|
|
105
|
+
1. **Version bump**: Run `pnpm release` to bump the version (this uses `bumpp` to create a new version tag) and push it to GitHub
|
|
106
|
+
2. **Automated publish**: The GitHub Actions workflow will:
|
|
107
|
+
- Build the project
|
|
108
|
+
- Publish to npm
|
|
109
|
+
- Create a GitHub release with changelog
|
|
110
|
+
|
|
111
|
+
The package is published to npm as `@decartai/sdk`.
|
|
112
|
+
|
|
85
113
|
## License
|
|
86
114
|
|
|
87
115
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -10,12 +10,25 @@ import { z } from "zod";
|
|
|
10
10
|
declare const decartClientOptionsSchema: z.ZodObject<{
|
|
11
11
|
apiKey: z.ZodString;
|
|
12
12
|
baseUrl: z.ZodOptional<z.ZodURL>;
|
|
13
|
+
integration: z.ZodOptional<z.ZodString>;
|
|
13
14
|
}, z.core.$strip>;
|
|
14
15
|
type DecartClientOptions = z.infer<typeof decartClientOptionsSchema>;
|
|
15
16
|
declare const createDecartClient: (options: DecartClientOptions) => {
|
|
16
17
|
realtime: {
|
|
17
18
|
connect: (stream: MediaStream, options: RealTimeClientConnectOptions) => Promise<RealTimeClient>;
|
|
18
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Client for video and image generation.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const client = createDecartClient({ apiKey: "your-api-key" });
|
|
26
|
+
* const result = await client.process({
|
|
27
|
+
* model: models.video("lucy-pro-t2v"),
|
|
28
|
+
* prompt: "A beautiful sunset over the ocean"
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
19
32
|
process: ProcessClient;
|
|
20
33
|
};
|
|
21
34
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,8 @@ import { z } from "zod";
|
|
|
7
7
|
//#region src/index.ts
|
|
8
8
|
const decartClientOptionsSchema = z.object({
|
|
9
9
|
apiKey: z.string().min(1),
|
|
10
|
-
baseUrl: z.url().optional()
|
|
10
|
+
baseUrl: z.url().optional(),
|
|
11
|
+
integration: z.string().optional()
|
|
11
12
|
});
|
|
12
13
|
const createDecartClient = (options) => {
|
|
13
14
|
const parsedOptions = decartClientOptionsSchema.safeParse(options);
|
|
@@ -17,14 +18,16 @@ const createDecartClient = (options) => {
|
|
|
17
18
|
if (issue.path.includes("baseUrl")) throw createInvalidBaseUrlError(options.baseUrl);
|
|
18
19
|
throw parsedOptions.error;
|
|
19
20
|
}
|
|
20
|
-
const { baseUrl = "https://api.decart.ai", apiKey } = parsedOptions.data;
|
|
21
|
+
const { baseUrl = "https://api.decart.ai", apiKey, integration } = parsedOptions.data;
|
|
21
22
|
const realtime = createRealTimeClient({
|
|
22
23
|
baseUrl: "wss://api3.decart.ai",
|
|
23
|
-
apiKey
|
|
24
|
+
apiKey,
|
|
25
|
+
integration
|
|
24
26
|
});
|
|
25
27
|
const process = createProcessClient({
|
|
26
28
|
baseUrl,
|
|
27
|
-
apiKey
|
|
29
|
+
apiKey,
|
|
30
|
+
integration
|
|
28
31
|
});
|
|
29
32
|
return {
|
|
30
33
|
realtime,
|
package/dist/process/client.js
CHANGED
|
@@ -3,7 +3,7 @@ import { fileInputToBlob, sendRequest } from "./request.js";
|
|
|
3
3
|
|
|
4
4
|
//#region src/process/client.ts
|
|
5
5
|
const createProcessClient = (opts) => {
|
|
6
|
-
const { apiKey, baseUrl } = opts;
|
|
6
|
+
const { apiKey, baseUrl, integration } = opts;
|
|
7
7
|
const _process = async (options) => {
|
|
8
8
|
const { model, signal,...inputs } = options;
|
|
9
9
|
const parsedInputs = model.inputSchema.safeParse(inputs);
|
|
@@ -16,7 +16,8 @@ const createProcessClient = (opts) => {
|
|
|
16
16
|
apiKey,
|
|
17
17
|
model,
|
|
18
18
|
inputs: processedInputs,
|
|
19
|
-
signal
|
|
19
|
+
signal,
|
|
20
|
+
integration
|
|
20
21
|
});
|
|
21
22
|
};
|
|
22
23
|
return _process;
|
package/dist/process/request.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createInvalidInputError, createSDKError } from "../utils/errors.js";
|
|
2
|
+
import { buildUserAgent } from "../utils/user-agent.js";
|
|
2
3
|
|
|
3
4
|
//#region src/process/request.ts
|
|
4
5
|
async function fileInputToBlob(input) {
|
|
@@ -13,14 +14,17 @@ async function fileInputToBlob(input) {
|
|
|
13
14
|
}
|
|
14
15
|
throw createInvalidInputError("Invalid file input type");
|
|
15
16
|
}
|
|
16
|
-
async function sendRequest({ baseUrl, apiKey, model, inputs, signal }) {
|
|
17
|
+
async function sendRequest({ baseUrl, apiKey, model, inputs, signal, integration }) {
|
|
17
18
|
const formData = new FormData();
|
|
18
19
|
for (const [key, value] of Object.entries(inputs)) if (value !== void 0 && value !== null) if (value instanceof Blob) formData.append(key, value);
|
|
19
20
|
else formData.append(key, String(value));
|
|
20
21
|
const endpoint = `${baseUrl}${model.urlPath}`;
|
|
21
22
|
const response = await fetch(endpoint, {
|
|
22
23
|
method: "POST",
|
|
23
|
-
headers: {
|
|
24
|
+
headers: {
|
|
25
|
+
"X-API-KEY": apiKey,
|
|
26
|
+
"User-Agent": buildUserAgent(integration)
|
|
27
|
+
},
|
|
24
28
|
body: formData,
|
|
25
29
|
signal
|
|
26
30
|
});
|
package/dist/process/types.d.ts
CHANGED
|
@@ -1,12 +1,145 @@
|
|
|
1
|
-
import { ModelDefinition, ModelInputSchemas } from "../shared/model.js";
|
|
1
|
+
import { ImageModels, ModelDefinition, ModelInputSchemas, VideoModels } from "../shared/model.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/process/types.d.ts
|
|
5
|
+
type FileInput = File | Blob | ReadableStream | URL | string;
|
|
5
6
|
type InferModelInputs<T extends ModelDefinition> = T["name"] extends keyof ModelInputSchemas ? z.input<ModelInputSchemas[T["name"]]> : Record<string, never>;
|
|
7
|
+
/**
|
|
8
|
+
* Model-specific input documentation for image generation models.
|
|
9
|
+
*/
|
|
10
|
+
interface ImageGenerationInputs {
|
|
11
|
+
/**
|
|
12
|
+
* Text description to use for the generation.
|
|
13
|
+
*
|
|
14
|
+
* See our [Prompt Engineering](https://docs.platform.decart.ai/models/image/image-generation#prompt-engineering) guide for how to write prompt for Decart image models effectively.
|
|
15
|
+
*/
|
|
16
|
+
prompt: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Model-specific input documentation for image editing models.
|
|
20
|
+
*/
|
|
21
|
+
interface ImageEditingInputs {
|
|
22
|
+
/**
|
|
23
|
+
* Text description of the changes to apply to the image.
|
|
24
|
+
*
|
|
25
|
+
* It's highly recommended to read our [Prompt Engineering for Edits](https://docs.platform.decart.ai/models/image/image-editing#prompt-engineering-for-edits) guide for how to write effective editing prompts.
|
|
26
|
+
*/
|
|
27
|
+
prompt: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Model-specific input documentation for video models.
|
|
31
|
+
*/
|
|
32
|
+
interface VideoModelInputs {
|
|
33
|
+
/**
|
|
34
|
+
* Text description to use for the generation.
|
|
35
|
+
*
|
|
36
|
+
* See our [Prompt Engineering](https://docs.platform.decart.ai/models/video/video-generation#prompt-engineering) guide for how to write prompt for Decart video models effectively.
|
|
37
|
+
*/
|
|
38
|
+
prompt: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Default inputs for models that only require a prompt.
|
|
42
|
+
*/
|
|
43
|
+
interface PromptInput {
|
|
44
|
+
/**
|
|
45
|
+
* Text description to use for the generation.
|
|
46
|
+
*/
|
|
47
|
+
prompt: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Conditional type that selects the appropriate model-specific input documentation based on the model type.
|
|
51
|
+
* This allows different models to have field-specific documentation while maintaining type safety.
|
|
52
|
+
* Specific models are checked first, then falls back to category-based selection.
|
|
53
|
+
*/
|
|
54
|
+
type ModelSpecificInputs<T extends ModelDefinition> = T["name"] extends "lucy-pro-i2i" ? ImageEditingInputs : T["name"] extends ImageModels ? ImageGenerationInputs : T["name"] extends VideoModels ? VideoModelInputs : PromptInput;
|
|
55
|
+
interface ProcessInputs {
|
|
56
|
+
/**
|
|
57
|
+
* Random seed for reproducible results.
|
|
58
|
+
*
|
|
59
|
+
* Using the same seed with the same prompt and settings will produce the same output every time.
|
|
60
|
+
* This is useful for testing, debugging, or when you want to recreate a specific result.
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
seed?: number;
|
|
64
|
+
/**
|
|
65
|
+
* The output resolution to use for the generation.
|
|
66
|
+
*
|
|
67
|
+
* @default "720p"
|
|
68
|
+
*/
|
|
69
|
+
resolution?: "480p" | "720p";
|
|
70
|
+
/**
|
|
71
|
+
* The output orientation to use for the generation.
|
|
72
|
+
*
|
|
73
|
+
* @default "landscape"
|
|
74
|
+
*/
|
|
75
|
+
orientation?: "landscape" | "portrait";
|
|
76
|
+
/**
|
|
77
|
+
* The data to use for generation (for image-to-image and video-to-video).
|
|
78
|
+
* Can be a File, Blob, ReadableStream, URL, or string URL.
|
|
79
|
+
*/
|
|
80
|
+
data?: FileInput;
|
|
81
|
+
/**
|
|
82
|
+
* The start frame image (for first-last-frame models).
|
|
83
|
+
* Can be a File, Blob, ReadableStream, URL, or string URL.
|
|
84
|
+
*/
|
|
85
|
+
start?: FileInput;
|
|
86
|
+
/**
|
|
87
|
+
* The end frame image (for first-last-frame models).
|
|
88
|
+
* Can be a File, Blob, ReadableStream, URL, or string URL.
|
|
89
|
+
*/
|
|
90
|
+
end?: FileInput;
|
|
91
|
+
/**
|
|
92
|
+
* Whether to enhance the prompt.
|
|
93
|
+
*
|
|
94
|
+
* @remarks
|
|
95
|
+
* For best results, keep this `true` (default) to let Decart's AI enhance your prompts.
|
|
96
|
+
* Only disable it if you need exact prompt control.
|
|
97
|
+
*
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
enhance_prompt?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* The number of inference steps.
|
|
103
|
+
*
|
|
104
|
+
* @default 50
|
|
105
|
+
*/
|
|
106
|
+
num_inference_steps?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* ProcessInputs combined with model-specific inputs.
|
|
110
|
+
* This ensures fields have the correct descriptions based on the model type.
|
|
111
|
+
* Add fields to ImageGenerationInputs, ImageEditingInputs, VideoModelInputs, or PromptInput
|
|
112
|
+
* to provide model-specific documentation for any field.
|
|
113
|
+
*/
|
|
114
|
+
type ModelSpecificProcessInputs<T extends ModelDefinition> = ProcessInputs & ModelSpecificInputs<T>;
|
|
115
|
+
/**
|
|
116
|
+
* Pick only the fields from ModelSpecificProcessInputs that exist in the inferred model inputs,
|
|
117
|
+
* so JSDoc comments will be preserved, while type inference will be accurate.
|
|
118
|
+
*/
|
|
119
|
+
type PickDocumentedInputs<T extends ModelDefinition> = Pick<ModelSpecificProcessInputs<T>, keyof ModelSpecificProcessInputs<T> & keyof InferModelInputs<T>>;
|
|
120
|
+
/**
|
|
121
|
+
* Merge documented inputs with inferred inputs, ensuring zod types take precedence
|
|
122
|
+
* while preserving JSDoc comments from ModelSpecificProcessInputs.
|
|
123
|
+
*
|
|
124
|
+
* By intersecting PickDocumentedInputs with InferModelInputs, we get:
|
|
125
|
+
* - JSDoc comments from ModelSpecificProcessInputs (from PickDocumentedInputs)
|
|
126
|
+
* - Accurate types from zod schemas (from InferModelInputs, takes precedence in intersection)
|
|
127
|
+
*/
|
|
128
|
+
type MergeDocumentedInputs<T extends ModelDefinition> = PickDocumentedInputs<T> & InferModelInputs<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Options for the process client to generate video or image content.
|
|
131
|
+
*
|
|
132
|
+
* @template T - The model definition type
|
|
133
|
+
*/
|
|
6
134
|
type ProcessOptions<T extends ModelDefinition = ModelDefinition> = {
|
|
135
|
+
/**
|
|
136
|
+
* The model definition to use.
|
|
137
|
+
*/
|
|
7
138
|
model: T;
|
|
139
|
+
/**
|
|
140
|
+
* Optional `AbortSignal` for canceling the request.
|
|
141
|
+
*/
|
|
8
142
|
signal?: AbortSignal;
|
|
9
|
-
} &
|
|
10
|
-
type FileInput = File | Blob | ReadableStream | URL | string;
|
|
143
|
+
} & MergeDocumentedInputs<T>;
|
|
11
144
|
//#endregion
|
|
12
145
|
export { FileInput, ProcessOptions };
|
package/dist/realtime/client.js
CHANGED
|
@@ -17,7 +17,7 @@ const realTimeClientConnectOptionsSchema = z.object({
|
|
|
17
17
|
customizeOffer: createAsyncFunctionSchema(z.function()).optional()
|
|
18
18
|
});
|
|
19
19
|
const createRealTimeClient = (opts) => {
|
|
20
|
-
const { baseUrl, apiKey } = opts;
|
|
20
|
+
const { baseUrl, apiKey, integration } = opts;
|
|
21
21
|
const connect = async (stream, options) => {
|
|
22
22
|
const eventEmitter = mitt();
|
|
23
23
|
const parsedOptions = realTimeClientConnectOptionsSchema.safeParse(options);
|
|
@@ -31,6 +31,7 @@ const createRealTimeClient = (opts) => {
|
|
|
31
31
|
sessionId,
|
|
32
32
|
fps: options.model.fps,
|
|
33
33
|
initialState,
|
|
34
|
+
integration,
|
|
34
35
|
onRemoteStream,
|
|
35
36
|
onConnectionStateChange: (state) => {
|
|
36
37
|
eventEmitter.emit("connectionChange", state);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { buildUserAgent } from "../utils/user-agent.js";
|
|
2
|
+
|
|
1
3
|
//#region src/realtime/webrtc-connection.ts
|
|
2
4
|
const ICE_SERVERS = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
3
5
|
var WebRTCConnection = class {
|
|
@@ -9,13 +11,16 @@ var WebRTCConnection = class {
|
|
|
9
11
|
constructor(callbacks = {}) {
|
|
10
12
|
this.callbacks = callbacks;
|
|
11
13
|
}
|
|
12
|
-
async connect(url, localStream, timeout = 25e3) {
|
|
14
|
+
async connect(url, localStream, timeout = 25e3, integration) {
|
|
13
15
|
const deadline = Date.now() + timeout;
|
|
14
16
|
this.localStream = localStream;
|
|
17
|
+
const userAgent = encodeURIComponent(buildUserAgent(integration));
|
|
18
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
19
|
+
const wsUrl = `${url}${separator}user_agent=${userAgent}`;
|
|
15
20
|
await new Promise((resolve, reject) => {
|
|
16
21
|
this.connectionReject = reject;
|
|
17
22
|
const timer = setTimeout(() => reject(/* @__PURE__ */ new Error("WebSocket timeout")), timeout);
|
|
18
|
-
this.ws = new WebSocket(
|
|
23
|
+
this.ws = new WebSocket(wsUrl);
|
|
19
24
|
this.ws.onopen = () => {
|
|
20
25
|
clearTimeout(timer);
|
|
21
26
|
resolve();
|
|
@@ -24,7 +24,7 @@ var WebRTCManager = class {
|
|
|
24
24
|
}
|
|
25
25
|
async connect(localStream) {
|
|
26
26
|
return pRetry(async () => {
|
|
27
|
-
await this.connection.connect(this.config.webrtcUrl, localStream);
|
|
27
|
+
await this.connection.connect(this.config.webrtcUrl, localStream, 25e3, this.config.integration);
|
|
28
28
|
return true;
|
|
29
29
|
}, {
|
|
30
30
|
retries: 5,
|
package/dist/shared/model.d.ts
CHANGED
|
@@ -13,32 +13,44 @@ declare const modelInputSchemas: {
|
|
|
13
13
|
readonly "lucy-pro-t2v": z.ZodObject<{
|
|
14
14
|
prompt: z.ZodString;
|
|
15
15
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
16
|
-
resolution: z.ZodOptional<z.
|
|
16
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
"720p": "720p";
|
|
18
|
+
"480p": "480p";
|
|
19
|
+
}>>>;
|
|
17
20
|
orientation: z.ZodOptional<z.ZodString>;
|
|
18
21
|
}, z.core.$strip>;
|
|
19
22
|
readonly "lucy-pro-t2i": z.ZodObject<{
|
|
20
23
|
prompt: z.ZodString;
|
|
21
24
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
22
|
-
resolution: z.ZodOptional<z.
|
|
25
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
26
|
+
"720p": "720p";
|
|
27
|
+
"480p": "480p";
|
|
28
|
+
}>>>;
|
|
23
29
|
orientation: z.ZodOptional<z.ZodString>;
|
|
24
30
|
}, z.core.$strip>;
|
|
25
31
|
readonly "lucy-pro-i2v": z.ZodObject<{
|
|
26
32
|
prompt: z.ZodString;
|
|
27
33
|
data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
28
34
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
29
|
-
resolution: z.ZodOptional<z.
|
|
35
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
36
|
+
"720p": "720p";
|
|
37
|
+
"480p": "480p";
|
|
38
|
+
}>>>;
|
|
30
39
|
}, z.core.$strip>;
|
|
31
40
|
readonly "lucy-dev-i2v": z.ZodObject<{
|
|
32
41
|
prompt: z.ZodString;
|
|
33
42
|
data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
34
43
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
35
|
-
resolution: z.ZodOptional<z.
|
|
44
|
+
resolution: z.ZodOptional<z.ZodDefault<z.ZodLiteral<"720p">>>;
|
|
36
45
|
}, z.core.$strip>;
|
|
37
46
|
readonly "lucy-pro-v2v": z.ZodObject<{
|
|
38
47
|
prompt: z.ZodString;
|
|
39
48
|
data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
40
49
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
41
|
-
resolution: z.ZodOptional<z.
|
|
50
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
51
|
+
"720p": "720p";
|
|
52
|
+
"480p": "480p";
|
|
53
|
+
}>>>;
|
|
42
54
|
enhance_prompt: z.ZodOptional<z.ZodBoolean>;
|
|
43
55
|
num_inference_steps: z.ZodOptional<z.ZodNumber>;
|
|
44
56
|
}, z.core.$strip>;
|
|
@@ -46,7 +58,7 @@ declare const modelInputSchemas: {
|
|
|
46
58
|
prompt: z.ZodString;
|
|
47
59
|
data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
48
60
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
49
|
-
resolution: z.ZodOptional<z.
|
|
61
|
+
resolution: z.ZodOptional<z.ZodDefault<z.ZodLiteral<"720p">>>;
|
|
50
62
|
enhance_prompt: z.ZodOptional<z.ZodBoolean>;
|
|
51
63
|
}, z.core.$strip>;
|
|
52
64
|
readonly "lucy-pro-flf2v": z.ZodObject<{
|
|
@@ -54,13 +66,19 @@ declare const modelInputSchemas: {
|
|
|
54
66
|
start: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
55
67
|
end: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
56
68
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
57
|
-
resolution: z.ZodOptional<z.
|
|
69
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
70
|
+
"720p": "720p";
|
|
71
|
+
"480p": "480p";
|
|
72
|
+
}>>>;
|
|
58
73
|
}, z.core.$strip>;
|
|
59
74
|
readonly "lucy-pro-i2i": z.ZodObject<{
|
|
60
75
|
prompt: z.ZodString;
|
|
61
76
|
data: z.ZodUnion<readonly [z.ZodCustom<File, File>, z.ZodCustom<Blob, Blob>, z.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>, z.ZodCustom<URL, URL>, z.ZodURL]>;
|
|
62
77
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
63
|
-
resolution: z.ZodOptional<z.
|
|
78
|
+
resolution: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
79
|
+
"720p": "720p";
|
|
80
|
+
"480p": "480p";
|
|
81
|
+
}>>>;
|
|
64
82
|
enhance_prompt: z.ZodOptional<z.ZodBoolean>;
|
|
65
83
|
}, z.core.$strip>;
|
|
66
84
|
};
|
|
@@ -71,11 +89,29 @@ type ModelDefinition<T extends Model = Model> = {
|
|
|
71
89
|
fps: number;
|
|
72
90
|
width: number;
|
|
73
91
|
height: number;
|
|
74
|
-
inputSchema: T extends keyof ModelInputSchemas ? ModelInputSchemas[T] : z.
|
|
92
|
+
inputSchema: T extends keyof ModelInputSchemas ? ModelInputSchemas[T] : z.ZodTypeAny;
|
|
75
93
|
};
|
|
76
94
|
declare const models: {
|
|
77
95
|
realtime: <T extends RealTimeModels>(model: T) => ModelDefinition<T>;
|
|
96
|
+
/**
|
|
97
|
+
* Get a video model identifier.
|
|
98
|
+
*
|
|
99
|
+
* Available options:
|
|
100
|
+
* - `"lucy-pro-t2v"` - Text-to-video
|
|
101
|
+
* - `"lucy-pro-i2v"` - Image-to-video
|
|
102
|
+
* - `"lucy-pro-v2v"` - Video-to-video
|
|
103
|
+
* - `"lucy-pro-flf2v"` - First-last-frame-to-video
|
|
104
|
+
* - `"lucy-dev-i2v"` - Image-to-video (Dev quality)
|
|
105
|
+
* - `"lucy-dev-v2v"` - Video-to-video (Dev quality)
|
|
106
|
+
*/
|
|
78
107
|
video: <T extends VideoModels>(model: T) => ModelDefinition<T>;
|
|
108
|
+
/**
|
|
109
|
+
* Get an image model identifier.
|
|
110
|
+
*
|
|
111
|
+
* Available options:
|
|
112
|
+
* - `"lucy-pro-t2i"` - Text-to-image
|
|
113
|
+
* - `"lucy-pro-i2i"` - Image-to-image
|
|
114
|
+
*/
|
|
79
115
|
image: <T extends ImageModels>(model: T) => ModelDefinition<T>;
|
|
80
116
|
};
|
|
81
117
|
//#endregion
|
package/dist/shared/model.js
CHANGED
|
@@ -28,59 +28,74 @@ const fileInputSchema = z.union([
|
|
|
28
28
|
z.instanceof(URL),
|
|
29
29
|
z.url()
|
|
30
30
|
]);
|
|
31
|
+
/**
|
|
32
|
+
* Resolution schema for dev models. Supports only 720p.
|
|
33
|
+
*/
|
|
34
|
+
const devResolutionSchema = z.literal("720p").default("720p").optional().describe("The resolution to use for the generation. For dev models, only `720p` is supported.");
|
|
35
|
+
/**
|
|
36
|
+
* Resolution schema for pro models.
|
|
37
|
+
* @param defaultValue - Optional default value (e.g., "720p")
|
|
38
|
+
*/
|
|
39
|
+
const proResolutionSchema = () => {
|
|
40
|
+
return z.enum(["720p", "480p"]).optional().describe("The resolution to use for the generation").default("720p");
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Resolution schema for lucy-pro-v2v (supports 720p and 480p).
|
|
44
|
+
*/
|
|
45
|
+
const proV2vResolutionSchema = z.enum(["720p", "480p"]).optional().describe("The resolution to use for the generation").default("720p");
|
|
31
46
|
const modelInputSchemas = {
|
|
32
47
|
"lucy-pro-t2v": z.object({
|
|
33
|
-
prompt: z.string(),
|
|
34
|
-
seed: z.number().optional(),
|
|
35
|
-
resolution:
|
|
36
|
-
orientation: z.string().optional()
|
|
48
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
49
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
50
|
+
resolution: proResolutionSchema(),
|
|
51
|
+
orientation: z.string().optional().describe("The orientation to use for the generation")
|
|
37
52
|
}),
|
|
38
53
|
"lucy-pro-t2i": z.object({
|
|
39
|
-
prompt: z.string(),
|
|
40
|
-
seed: z.number().optional(),
|
|
41
|
-
resolution:
|
|
42
|
-
orientation: z.string().optional()
|
|
54
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
55
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
56
|
+
resolution: proResolutionSchema(),
|
|
57
|
+
orientation: z.string().optional().describe("The orientation to use for the generation")
|
|
43
58
|
}),
|
|
44
59
|
"lucy-pro-i2v": z.object({
|
|
45
|
-
prompt: z.string(),
|
|
46
|
-
data: fileInputSchema,
|
|
47
|
-
seed: z.number().optional(),
|
|
48
|
-
resolution:
|
|
60
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
61
|
+
data: fileInputSchema.describe("The image data to use for generation (File, Blob, ReadableStream, URL, or string URL)"),
|
|
62
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
63
|
+
resolution: proResolutionSchema()
|
|
49
64
|
}),
|
|
50
65
|
"lucy-dev-i2v": z.object({
|
|
51
|
-
prompt: z.string(),
|
|
52
|
-
data: fileInputSchema,
|
|
53
|
-
seed: z.number().optional(),
|
|
54
|
-
resolution:
|
|
66
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
67
|
+
data: fileInputSchema.describe("The image data to use for generation (File, Blob, ReadableStream, URL, or string URL)"),
|
|
68
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
69
|
+
resolution: devResolutionSchema
|
|
55
70
|
}),
|
|
56
71
|
"lucy-pro-v2v": z.object({
|
|
57
|
-
prompt: z.string(),
|
|
58
|
-
data: fileInputSchema,
|
|
59
|
-
seed: z.number().optional(),
|
|
60
|
-
resolution:
|
|
61
|
-
enhance_prompt: z.boolean().optional(),
|
|
62
|
-
num_inference_steps: z.number().optional()
|
|
72
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
73
|
+
data: fileInputSchema.describe("The video data to use for generation (File, Blob, ReadableStream, URL, or string URL)"),
|
|
74
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
75
|
+
resolution: proV2vResolutionSchema,
|
|
76
|
+
enhance_prompt: z.boolean().optional().describe("Whether to enhance the prompt"),
|
|
77
|
+
num_inference_steps: z.number().optional().describe("The number of inference steps")
|
|
63
78
|
}),
|
|
64
79
|
"lucy-dev-v2v": z.object({
|
|
65
|
-
prompt: z.string(),
|
|
66
|
-
data: fileInputSchema,
|
|
67
|
-
seed: z.number().optional(),
|
|
68
|
-
resolution:
|
|
69
|
-
enhance_prompt: z.boolean().optional()
|
|
80
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
81
|
+
data: fileInputSchema.describe("The video data to use for generation (File, Blob, ReadableStream, URL, or string URL)"),
|
|
82
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
83
|
+
resolution: devResolutionSchema,
|
|
84
|
+
enhance_prompt: z.boolean().optional().describe("Whether to enhance the prompt")
|
|
70
85
|
}),
|
|
71
86
|
"lucy-pro-flf2v": z.object({
|
|
72
|
-
prompt: z.string(),
|
|
73
|
-
start: fileInputSchema,
|
|
74
|
-
end: fileInputSchema,
|
|
75
|
-
seed: z.number().optional(),
|
|
76
|
-
resolution:
|
|
87
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
88
|
+
start: fileInputSchema.describe("The start frame image (File, Blob, ReadableStream, URL, or string URL)"),
|
|
89
|
+
end: fileInputSchema.describe("The end frame image (File, Blob, ReadableStream, URL, or string URL)"),
|
|
90
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
91
|
+
resolution: proResolutionSchema()
|
|
77
92
|
}),
|
|
78
93
|
"lucy-pro-i2i": z.object({
|
|
79
|
-
prompt: z.string(),
|
|
80
|
-
data: fileInputSchema,
|
|
81
|
-
seed: z.number().optional(),
|
|
82
|
-
resolution:
|
|
83
|
-
enhance_prompt: z.boolean().optional()
|
|
94
|
+
prompt: z.string().describe("The prompt to use for the generation"),
|
|
95
|
+
data: fileInputSchema.describe("The image data to use for generation (File, Blob, ReadableStream, URL, or string URL)"),
|
|
96
|
+
seed: z.number().optional().describe("The seed to use for the generation"),
|
|
97
|
+
resolution: proResolutionSchema(),
|
|
98
|
+
enhance_prompt: z.boolean().optional().describe("Whether to enhance the prompt")
|
|
84
99
|
})
|
|
85
100
|
};
|
|
86
101
|
const modelDefinitionSchema = z.object({
|
|
@@ -104,7 +119,7 @@ const _models = {
|
|
|
104
119
|
mirage_v2: {
|
|
105
120
|
urlPath: "/v1/stream",
|
|
106
121
|
name: "mirage_v2",
|
|
107
|
-
fps:
|
|
122
|
+
fps: 22,
|
|
108
123
|
width: 1280,
|
|
109
124
|
height: 704,
|
|
110
125
|
inputSchema: z.object({})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { VERSION } from "../version.js";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/user-agent.ts
|
|
4
|
+
function getRuntimeEnvironment(globalThisAny = globalThis) {
|
|
5
|
+
if (globalThisAny.window) return "runtime/browser";
|
|
6
|
+
if (globalThisAny.navigator?.userAgent) return `runtime/${globalThisAny.navigator.userAgent.toLowerCase()}`;
|
|
7
|
+
if (globalThisAny.process?.versions?.node) return `runtime/node.js/${globalThisAny.process.version.substring(0)}`;
|
|
8
|
+
if (globalThisAny.EdgeRuntime) return "runtime/vercel-edge";
|
|
9
|
+
return "runtime/unknown";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Builds the User-Agent string for the SDK.
|
|
13
|
+
* Format: decart-js-sdk/{version} lang/js {integration} {runtime}
|
|
14
|
+
*
|
|
15
|
+
* @param integration - Optional integration identifier (e.g., "vercel-ai-sdk/3.0.0")
|
|
16
|
+
* @param globalThisAny - The global object (defaults to globalThis). Can be mocked for testing.
|
|
17
|
+
* @returns Complete User-Agent string
|
|
18
|
+
* @example
|
|
19
|
+
* buildUserAgent() // => "decart-js-sdk/0.0.7 lang/js runtime/node.js/v18.17.0"
|
|
20
|
+
* buildUserAgent("vercel-ai-sdk/3.0.0") // => "decart-js-sdk/0.0.7 lang/js vercel-ai-sdk/3.0.0 runtime/node.js/v18.17.0"
|
|
21
|
+
*/
|
|
22
|
+
function buildUserAgent(integration, globalThisAny = globalThis) {
|
|
23
|
+
return [
|
|
24
|
+
`decart-js-sdk/${VERSION}`,
|
|
25
|
+
"lang/js",
|
|
26
|
+
...integration ? [integration] : [],
|
|
27
|
+
getRuntimeEnvironment(globalThisAny)
|
|
28
|
+
].join(" ");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { buildUserAgent };
|
package/dist/version.js
ADDED
package/package.json
CHANGED
|
@@ -1,61 +1,60 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
2
|
+
"name": "@decartai/sdk",
|
|
3
|
+
"version": "0.0.12",
|
|
4
|
+
"description": "Decart's JavaScript SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"private": false,
|
|
8
|
+
"homepage": "https://github.com/decartai/sdk#readme",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/decartai/sdk/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/DecartAI/sdk"
|
|
15
|
+
},
|
|
16
|
+
"author": "Adir Amsalem <adir@decart.ai>",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./dist/index.js",
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.15.17",
|
|
33
|
+
"biome": "^0.3.3",
|
|
34
|
+
"bumpp": "^10.1.0",
|
|
35
|
+
"msw": "^2.11.3",
|
|
36
|
+
"pkg-pr-new": "^0.0.56",
|
|
37
|
+
"tsdown": "^0.14.1",
|
|
38
|
+
"typescript": "^5.8.3",
|
|
39
|
+
"vite": "^7.1.2",
|
|
40
|
+
"vitest": "^3.1.3"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"mitt": "^3.0.1",
|
|
44
|
+
"p-retry": "^6.2.1",
|
|
45
|
+
"uuid": "^11.1.0",
|
|
46
|
+
"zod": "^4.0.17"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"dev": "tsdown --watch",
|
|
51
|
+
"dev:example": "vite dev --port 3000",
|
|
52
|
+
"test": "vitest unit",
|
|
53
|
+
"test:e2e": "vitest e2e",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"format": "biome format --write",
|
|
56
|
+
"format:check": "biome check",
|
|
57
|
+
"lint": "biome lint",
|
|
58
|
+
"release": "bumpp"
|
|
59
|
+
}
|
|
60
|
+
}
|