@flatkey-ai/cli 0.1.16 → 0.1.17
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/package.json +1 -1
- package/src/api.js +62 -3
- package/src/cli.js +15 -9
- package/src/help.js +10 -2
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -44,6 +44,15 @@ export function generateVideo(options) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export function planVideoRequest(options) {
|
|
47
|
+
const model = options.model ?? "seedance-2.0-pro";
|
|
48
|
+
const imageUrls = [
|
|
49
|
+
...arrayOption(options.image_url),
|
|
50
|
+
...arrayOption(options.imageUrl),
|
|
51
|
+
...arrayOption(options.first_frame_url),
|
|
52
|
+
...arrayOption(options.firstFrameUrl),
|
|
53
|
+
...arrayOption(options.last_frame_url),
|
|
54
|
+
...arrayOption(options.lastFrameUrl),
|
|
55
|
+
];
|
|
47
56
|
const ratio = validateOptionalValue(
|
|
48
57
|
optionValue(options, "ratio", "aspect"),
|
|
49
58
|
["16:9", "9:16", "4:3", "3:4", "21:9", "1:1"],
|
|
@@ -54,8 +63,8 @@ export function planVideoRequest(options) {
|
|
|
54
63
|
["480p", "720p", "1080p"],
|
|
55
64
|
"resolution",
|
|
56
65
|
);
|
|
57
|
-
|
|
58
|
-
model
|
|
66
|
+
const basePayload = cleanObject({
|
|
67
|
+
model,
|
|
59
68
|
prompt: options.prompt,
|
|
60
69
|
duration: parseOptionalInteger(options.duration),
|
|
61
70
|
aspect: ratio,
|
|
@@ -63,7 +72,16 @@ export function planVideoRequest(options) {
|
|
|
63
72
|
resolution,
|
|
64
73
|
quality: resolution,
|
|
65
74
|
fps: parseOptionalInteger(options.fps),
|
|
66
|
-
|
|
75
|
+
images: !isSeedanceModel(model) && imageUrls.length > 0 ? imageUrls : undefined,
|
|
76
|
+
});
|
|
77
|
+
const seedanceContent = buildSeedanceContent(options);
|
|
78
|
+
if (isSeedanceModel(model) && seedanceContent.length > 0) {
|
|
79
|
+
return planJsonPost(options, "/v1/video/generations", cleanObject({
|
|
80
|
+
...basePayload,
|
|
81
|
+
content: seedanceContent,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
return planJsonPost(options, "/v1/video/generations", basePayload);
|
|
67
85
|
}
|
|
68
86
|
|
|
69
87
|
export function generateAudio(options) {
|
|
@@ -275,6 +293,47 @@ function validateOptionalValue(value, allowed, name) {
|
|
|
275
293
|
throw new Error(`Invalid ${name}: ${value}. Allowed values: ${allowed.join(", ")}`);
|
|
276
294
|
}
|
|
277
295
|
|
|
296
|
+
function isSeedanceModel(model) {
|
|
297
|
+
return /seedance/i.test(model);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function buildSeedanceContent(options) {
|
|
301
|
+
const content = [];
|
|
302
|
+
if (options.prompt !== undefined) {
|
|
303
|
+
content.push({ type: "text", text: options.prompt });
|
|
304
|
+
}
|
|
305
|
+
for (const url of arrayOption(options.image_url)) {
|
|
306
|
+
content.push({ type: "image_url", image_url: { url }, role: "reference_image" });
|
|
307
|
+
}
|
|
308
|
+
for (const url of arrayOption(options.imageUrl)) {
|
|
309
|
+
content.push({ type: "image_url", image_url: { url }, role: "reference_image" });
|
|
310
|
+
}
|
|
311
|
+
for (const url of arrayOption(options.first_frame_url)) {
|
|
312
|
+
content.push({ type: "image_url", image_url: { url }, role: "first_frame" });
|
|
313
|
+
}
|
|
314
|
+
for (const url of arrayOption(options.firstFrameUrl)) {
|
|
315
|
+
content.push({ type: "image_url", image_url: { url }, role: "first_frame" });
|
|
316
|
+
}
|
|
317
|
+
for (const url of arrayOption(options.last_frame_url)) {
|
|
318
|
+
content.push({ type: "image_url", image_url: { url }, role: "last_frame" });
|
|
319
|
+
}
|
|
320
|
+
for (const url of arrayOption(options.lastFrameUrl)) {
|
|
321
|
+
content.push({ type: "image_url", image_url: { url }, role: "last_frame" });
|
|
322
|
+
}
|
|
323
|
+
for (const url of arrayOption(options.video_url)) {
|
|
324
|
+
content.push({ type: "video_url", video_url: { url }, role: "reference_video" });
|
|
325
|
+
}
|
|
326
|
+
for (const url of arrayOption(options.videoUrl)) {
|
|
327
|
+
content.push({ type: "video_url", video_url: { url }, role: "reference_video" });
|
|
328
|
+
}
|
|
329
|
+
return content;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function arrayOption(value) {
|
|
333
|
+
if (value === undefined) return [];
|
|
334
|
+
return Array.isArray(value) ? value : [value];
|
|
335
|
+
}
|
|
336
|
+
|
|
278
337
|
function cleanObject(value) {
|
|
279
338
|
return Object.fromEntries(
|
|
280
339
|
Object.entries(value).filter(([, entry]) => entry !== undefined),
|
package/src/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ const COMMANDS = new Set([
|
|
|
16
16
|
|
|
17
17
|
const GROUP_ACTIONS = new Set(["audio", "auth", "image", "text", "video"]);
|
|
18
18
|
const GLOBAL_OPTIONS = new Set(["api_key", "base_url", "dry_run", "help", "json", "output", "out"]);
|
|
19
|
+
const REPEATABLE_OPTIONS = new Set(["image_url", "video_url"]);
|
|
19
20
|
const COMMAND_OPTIONS = {
|
|
20
21
|
"audio generate": new Set(["model", "prompt", "similarity_boost", "stability", "style", "voice_id"]),
|
|
21
22
|
"audio music": new Set(["music_length_ms", "prompt"]),
|
|
@@ -35,7 +36,7 @@ const COMMAND_OPTIONS = {
|
|
|
35
36
|
"text generate": new Set(["model", "prompt"]),
|
|
36
37
|
version: new Set([]),
|
|
37
38
|
video: new Set([]),
|
|
38
|
-
"video generate": new Set(["aspect", "duration", "fps", "model", "prompt", "ratio", "resolution"]),
|
|
39
|
+
"video generate": new Set(["aspect", "duration", "first_frame_url", "fps", "image_url", "last_frame_url", "model", "prompt", "ratio", "resolution", "video_url"]),
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
export function parseArgv(argv) {
|
|
@@ -115,12 +116,21 @@ function parseOptions(tokens) {
|
|
|
115
116
|
options[name] = true;
|
|
116
117
|
continue;
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
+
if (REPEATABLE_OPTIONS.has(name)) {
|
|
120
|
+
options[name] = [...asArray(options[name]), next];
|
|
121
|
+
} else {
|
|
122
|
+
options[name] = next;
|
|
123
|
+
}
|
|
119
124
|
index += 1;
|
|
120
125
|
}
|
|
121
126
|
return options;
|
|
122
127
|
}
|
|
123
128
|
|
|
129
|
+
function asArray(value) {
|
|
130
|
+
if (value === undefined) return [];
|
|
131
|
+
return Array.isArray(value) ? value : [value];
|
|
132
|
+
}
|
|
133
|
+
|
|
124
134
|
function validateCommandOptions(command) {
|
|
125
135
|
const key = command.action ? `${command.group} ${command.action}` : command.group;
|
|
126
136
|
const allowed = COMMAND_OPTIONS[key] ?? new Set();
|
|
@@ -215,15 +225,11 @@ export async function runCommand(command, deps = {}) {
|
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
async function handleLogin(command, deps) {
|
|
218
|
-
const { ensureDeviceId, readConfig,
|
|
219
|
-
const { createDeviceAuthorization, pollDeviceAuthorization } = await import("./api.js");
|
|
228
|
+
const { ensureDeviceId, readConfig, writeAuthConfig } = await import("./config.js");
|
|
229
|
+
const { DEFAULT_CONSOLE_URL, createDeviceAuthorization, pollDeviceAuthorization } = await import("./api.js");
|
|
220
230
|
const deviceId = await ensureDeviceId({ configDir: deps.configDir });
|
|
221
231
|
const version = await readPackageVersion();
|
|
222
|
-
const
|
|
223
|
-
consoleUrl: command.options.console_url,
|
|
224
|
-
env: deps.env ?? process.env,
|
|
225
|
-
configDir: deps.configDir,
|
|
226
|
-
});
|
|
232
|
+
const consoleOrigin = firstNonEmpty(command.options.console_url, DEFAULT_CONSOLE_URL);
|
|
227
233
|
const authorization = await createDeviceAuthorization({
|
|
228
234
|
consoleUrl: consoleOrigin,
|
|
229
235
|
deviceId,
|
package/src/help.js
CHANGED
|
@@ -208,20 +208,28 @@ Options:
|
|
|
208
208
|
video: `Usage: flatkey video generate --prompt <txt> [options]
|
|
209
209
|
|
|
210
210
|
Options:
|
|
211
|
-
--model <model> Model id, default
|
|
211
|
+
--model <model> Model id, default seedance-2.0-pro
|
|
212
212
|
--duration <seconds> Video duration
|
|
213
213
|
--ratio <value> 16:9, 9:16, 4:3, 3:4, 21:9, or 1:1
|
|
214
214
|
--resolution <value> 480p, 720p, or 1080p
|
|
215
|
+
--image-url <url> Add reference image URL, repeatable
|
|
216
|
+
--video-url <url> Add reference video URL, repeatable
|
|
217
|
+
--first-frame-url <url> Add first frame image URL
|
|
218
|
+
--last-frame-url <url> Add last frame image URL
|
|
215
219
|
--fps <fps> Frames per second
|
|
216
220
|
--output, -o <file> Write video file
|
|
217
221
|
--json Print machine-readable JSON`,
|
|
218
222
|
"video generate": `Usage: flatkey video generate --prompt <txt> [options]
|
|
219
223
|
|
|
220
224
|
Options:
|
|
221
|
-
--model <model> Model id, default
|
|
225
|
+
--model <model> Model id, default seedance-2.0-pro
|
|
222
226
|
--duration <seconds> Video duration
|
|
223
227
|
--ratio <value> 16:9, 9:16, 4:3, 3:4, 21:9, or 1:1
|
|
224
228
|
--resolution <value> 480p, 720p, or 1080p
|
|
229
|
+
--image-url <url> Add reference image URL, repeatable
|
|
230
|
+
--video-url <url> Add reference video URL, repeatable
|
|
231
|
+
--first-frame-url <url> Add first frame image URL
|
|
232
|
+
--last-frame-url <url> Add last frame image URL
|
|
225
233
|
--fps <fps> Frames per second
|
|
226
234
|
--output, -o <file> Write video file
|
|
227
235
|
--json Print machine-readable JSON`,
|