@docyrus/animaguru 0.36.0 → 0.39.0
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 +77 -14
- package/dist/animaguru.js +281 -134
- package/package.json +1 -1
- package/skills/animaguru/SKILL.md +20 -4
- package/skills/animaguru/references/avatars.md +15 -2
- package/skills/animaguru/references/cloud.md +2 -2
- package/skills/animaguru-video/SKILL.md +19 -1
- package/templates/video/src/kit/gif.ts +40 -0
package/dist/animaguru.js
CHANGED
|
@@ -19761,7 +19761,7 @@ var require_ignore2 = __commonJS({
|
|
|
19761
19761
|
// cli/package.json
|
|
19762
19762
|
var package_default = {
|
|
19763
19763
|
name: "@docyrus/animaguru",
|
|
19764
|
-
version: "0.
|
|
19764
|
+
version: "0.39.0",
|
|
19765
19765
|
description: "Agent-friendly AnimaGuru CLI built with CrustJS",
|
|
19766
19766
|
type: "module",
|
|
19767
19767
|
bin: {
|
|
@@ -45002,9 +45002,11 @@ var ALL_TOP_ACTIONS = [...new Set(Object.values(SPRITE_TOP_ACTIONS).flat())];
|
|
|
45002
45002
|
var CUSTOM_FRAMES = { min: 2, max: 12 };
|
|
45003
45003
|
|
|
45004
45004
|
// shared/sprites/models.ts
|
|
45005
|
-
var DEFAULT_SPRITE_IMAGE_MODEL = "fal/gpt-image-2.
|
|
45005
|
+
var DEFAULT_SPRITE_IMAGE_MODEL = "fal/gpt-image-2.6-medium";
|
|
45006
45006
|
var SPRITE_IMAGE_MODELS = [
|
|
45007
|
-
{ id: DEFAULT_SPRITE_IMAGE_MODEL, label: "GPT Image 2.
|
|
45007
|
+
{ id: DEFAULT_SPRITE_IMAGE_MODEL, label: "GPT Image 2.6 Flare \xB7 medium (fal)", provider: "fal", edit: true, nativeAlpha: true, maxImages: 16, relCost: 0.3, quality: "medium", endpoints: { generate: "openai/gpt-image-2.6/flare/text-to-image", edit: "openai/gpt-image-2.6/flare/edit" } },
|
|
45008
|
+
{ id: "fal/gpt-image-2.6-sunburst-high", label: "GPT Image 2.6 Sunburst \xB7 high (fal)", provider: "fal", edit: true, nativeAlpha: true, maxImages: 16, relCost: 1, quality: "high", endpoints: { generate: "openai/gpt-image-2.6/sunburst/text-to-image", edit: "openai/gpt-image-2.6/sunburst/edit" } },
|
|
45009
|
+
{ id: "fal/gpt-image-2.5-medium", label: "GPT Image 2.5 \xB7 medium (fal)", provider: "fal", edit: true, nativeAlpha: true, maxImages: 16, relCost: 0.3, quality: "medium", endpoints: { generate: "openai/gpt-image-2.5/flare/text-to-image", edit: "openai/gpt-image-2.5/flare/edit" } },
|
|
45008
45010
|
{ id: "fal/gpt-image-2-low", label: "GPT Image 2 \xB7 low (fal)", provider: "fal", edit: true, spriteBackupCutout: true, maxImages: 16, relCost: 0.2, quality: "low", endpoints: { generate: "openai/gpt-image-2", edit: "openai/gpt-image-2/edit" } },
|
|
45009
45011
|
{ id: "fal/muse-image", label: "Muse Image (fal)", provider: "fal", edit: true, maxImages: 10, relCost: 0.2, endpoints: { generate: "meta/muse-image/text-to-image", edit: "meta/muse-image/edit" } },
|
|
45010
45012
|
{ id: "fal/krea-2-turbo", label: "Krea 2 Turbo (fal)", provider: "fal", edit: false, maxImages: 0, relCost: 0.16, endpoints: { generate: "fal-ai/krea-2/turbo" } },
|
|
@@ -45267,6 +45269,7 @@ import { chmod as chmod2, mkdir as mkdir4, readFile as readFile2, rename as rena
|
|
|
45267
45269
|
import { dirname as dirname3, join as join4, resolve as resolve3 } from "node:path";
|
|
45268
45270
|
import { homedir as homedir3 } from "node:os";
|
|
45269
45271
|
import { createHash, randomUUID } from "node:crypto";
|
|
45272
|
+
var USER_AGENT = `animaguru-cli/${package_default.version}`;
|
|
45270
45273
|
function serverUrl(value) {
|
|
45271
45274
|
const url3 = new URL(value);
|
|
45272
45275
|
if (url3.username || url3.password || url3.search || url3.hash || url3.pathname !== "/") throw new Error("Use an origin URL without credentials, path, query or fragment.");
|
|
@@ -45332,18 +45335,19 @@ var Client = class {
|
|
|
45332
45335
|
origin;
|
|
45333
45336
|
async request(path, options = {}) {
|
|
45334
45337
|
const token3 = options.authenticated !== false ? await sessionToken(this.origin) : void 0;
|
|
45335
|
-
const generation = options.method === "POST" && /^\/api\/v1\/sprites\/[^/]+\/(jobs|assets|avatars|avatars\/looks|avatars\/[^/]+\/consent)$/.test(path);
|
|
45338
|
+
const generation = options.method === "POST" && /^\/api\/v1\/sprites\/[^/]+\/(jobs|assets|avatars|avatars\/looks|avatars\/videos|avatars\/[^/]+\/consent)$/.test(path);
|
|
45336
45339
|
const idempotency = generation ? { "Idempotency-Key": generationRequestId(path, options.body) } : {};
|
|
45337
45340
|
const response = await fetch(`${this.origin}${path}`, {
|
|
45338
45341
|
method: options.method ?? "GET",
|
|
45339
|
-
headers: { Origin: this.origin, ...token3 ? { Authorization: `Bearer ${token3}` } : {}, ...options.body instanceof Blob ? { "Content-Type": options.body.type || "application/octet-stream" } : options.body !== void 0 && !(options.body instanceof FormData) ? { "Content-Type": "application/json" } : {}, ...idempotency, ...options.headers },
|
|
45342
|
+
headers: { Origin: this.origin, "User-Agent": USER_AGENT, ...token3 ? { Authorization: `Bearer ${token3}` } : {}, ...options.body instanceof Blob ? { "Content-Type": options.body.type || "application/octet-stream" } : options.body !== void 0 && !(options.body instanceof FormData) ? { "Content-Type": "application/json" } : {}, ...idempotency, ...options.headers },
|
|
45340
45343
|
body: options.body instanceof FormData || options.body instanceof Blob ? options.body : options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
45341
45344
|
redirect: "error",
|
|
45342
45345
|
signal: this.signal ? AbortSignal.any([this.signal, AbortSignal.timeout(options.timeout ?? 3e4)]) : AbortSignal.timeout(options.timeout ?? 3e4)
|
|
45343
45346
|
});
|
|
45344
45347
|
if (response.ok && options.raw) return response;
|
|
45345
45348
|
const data = await response.json();
|
|
45346
|
-
|
|
45349
|
+
const code = typeof data.error === "string" ? data.error : typeof data.error?.code === "string" ? data.error.code : "request_failed";
|
|
45350
|
+
if (!response.ok) throw new ServiceError(response.status, code, data.error_description ?? (typeof data.error === "object" ? data.error.message : void 0) ?? data.message ?? `Request failed (${response.status}).`);
|
|
45347
45351
|
return data;
|
|
45348
45352
|
}
|
|
45349
45353
|
};
|
|
@@ -46973,6 +46977,130 @@ async function createAnimation(options) {
|
|
|
46973
46977
|
};
|
|
46974
46978
|
}
|
|
46975
46979
|
|
|
46980
|
+
// shared/avatars.ts
|
|
46981
|
+
var AVATAR_OWNERSHIPS = ["public", "private"];
|
|
46982
|
+
var AVATAR_LOOK_TYPES = ["studio_avatar", "digital_twin", "photo_avatar"];
|
|
46983
|
+
var AVATAR_CREATE_TYPES = ["prompt", "photo", "digital_twin"];
|
|
46984
|
+
var AVATAR_ASPECT_RATIOS = ["auto", "16:9", "9:16", "1:1", "4:5", "5:4"];
|
|
46985
|
+
var LOOK_PACK_ASPECT_RATIOS = ["16:9", "9:16"];
|
|
46986
|
+
var AVATAR_LOOK_METHODS = ["look_pack", "template"];
|
|
46987
|
+
var AVATAR_CREDIT_UNITS = { digital_twin: 2130, photo: 1320, prompt: 1320 };
|
|
46988
|
+
var AVATAR_LOOK_CREDIT_UNITS = 1320;
|
|
46989
|
+
var LOOKS_PER_METHOD = { look_pack: 5, template: 2 };
|
|
46990
|
+
var AVATAR_LOOK_TEMPLATES = [
|
|
46991
|
+
{ id: "5a8e6be843ee4321a014946bf62aa322", method: "look_pack", name: "Modern Corporate", variant: "female" },
|
|
46992
|
+
{ id: "5e659e76755d47fd9160a2d7dedce124", method: "look_pack", name: "Modern Corporate", variant: "male" },
|
|
46993
|
+
{ id: "e1650a9029d04ea1a350421c163295fd", method: "look_pack", name: "Stylish Business-Casual", variant: "female" },
|
|
46994
|
+
{ id: "a5f8e0c0cb654c1a83c695629b173af5", method: "look_pack", name: "Stylish Business-Casual", variant: "male" },
|
|
46995
|
+
{ id: "e7b000e2cb0d44f1a2d2f291a38b395a", method: "look_pack", name: "Scandinavian Minimal", variant: "female" },
|
|
46996
|
+
{ id: "9600f78f27bb49d792e1c56ce624b929", method: "look_pack", name: "Scandinavian Minimal", variant: "male" },
|
|
46997
|
+
{ id: "d7ad40ec97d4459a92b33398b57caf4e", method: "look_pack", name: "Cool Tech / Slate", variant: "female" },
|
|
46998
|
+
{ id: "fbd03fc3603a4e3caff594f5743a1733", method: "look_pack", name: "Cool Tech / Slate", variant: "male" },
|
|
46999
|
+
{ id: "14f4070bd5a04eb6b1f82ae087cd0f30", method: "look_pack", name: "Healthcare", variant: "female" },
|
|
47000
|
+
{ id: "ce706bfa8556401e8c4401765102a455", method: "look_pack", name: "Healthcare", variant: "male" },
|
|
47001
|
+
{ id: "b0cae4fbae384ab9ab9a8e73ba504be8", method: "look_pack", name: "Keynote Power Presenter", variant: "female" },
|
|
47002
|
+
{ id: "71e84769162d4f4186563ad9e0fc45b8", method: "look_pack", name: "Keynote Power Presenter", variant: "male" },
|
|
47003
|
+
{ id: "935ea0b7cdde4e6eb5a198a3d666f677", method: "look_pack", name: "Fitness", variant: "female" },
|
|
47004
|
+
{ id: "daeb8b15c92a4acf9ffb437ba5534458", method: "look_pack", name: "Fitness", variant: "male" },
|
|
47005
|
+
{ id: "6f183d726933457c9035fc0aa4e9c0c3", method: "look_pack", name: "Automotive Dealership", variant: "female" },
|
|
47006
|
+
{ id: "8595c78b466c4e51802731229c59b6e7", method: "look_pack", name: "Automotive Dealership", variant: "male" },
|
|
47007
|
+
{ id: "b30c83d99cec48e09c8f5b07ed8aa38c", method: "template", name: "Business Casual", variant: "female" },
|
|
47008
|
+
{ id: "2dc326030e2e4471babcc9eda56131b6", method: "template", name: "Business Casual", variant: "male" },
|
|
47009
|
+
{ id: "00c49daa4eb94386a0c12508043bab17", method: "template", name: "Podcast", variant: "female" },
|
|
47010
|
+
{ id: "0e52ceafe4d5456fb83c1e39899ff76a", method: "template", name: "Podcast", variant: "male" }
|
|
47011
|
+
];
|
|
47012
|
+
var avatarTemplate = (id2) => AVATAR_LOOK_TEMPLATES.find((t) => t.id === id2);
|
|
47013
|
+
var heygenId = external_exports.string().trim().regex(/^(?!\.{1,2}$)[A-Za-z0-9_.-]{1,128}$/, "Use an avatar id returned by AnimaGuru.");
|
|
47014
|
+
var sha = external_exports.string().regex(/^[a-f0-9]{64}$/);
|
|
47015
|
+
var name = external_exports.string().trim().min(1).max(80);
|
|
47016
|
+
var https = external_exports.string().trim().max(2048).url().refine((url3) => url3.startsWith("https://"), "Use an HTTPS URL.");
|
|
47017
|
+
var AVATAR_INLINE_MAX_BYTES = 8 * 1024 * 1024;
|
|
47018
|
+
var AVATAR_PHOTO_TYPES = ["image/png", "image/jpeg", "image/webp"];
|
|
47019
|
+
var AVATAR_FOOTAGE_TYPES = ["video/mp4", "video/quicktime", "video/webm"];
|
|
47020
|
+
var avatarFile = external_exports.discriminatedUnion("type", [
|
|
47021
|
+
external_exports.object({ type: external_exports.literal("file"), sha }),
|
|
47022
|
+
external_exports.object({ type: external_exports.literal("url"), url: https }),
|
|
47023
|
+
external_exports.object({
|
|
47024
|
+
type: external_exports.literal("base64"),
|
|
47025
|
+
mediaType: external_exports.enum([...AVATAR_PHOTO_TYPES, ...AVATAR_FOOTAGE_TYPES]),
|
|
47026
|
+
data: external_exports.string().max(Math.ceil(AVATAR_INLINE_MAX_BYTES / 3) * 4, "Inline files must be at most 8 MB; use a URL or a project file.").regex(/^[A-Za-z0-9+/]+={0,2}$/, "Send the file as standard base64.")
|
|
47027
|
+
})
|
|
47028
|
+
]);
|
|
47029
|
+
var subjectConsent = external_exports.literal(true, { error: "Confirm that the person shown agreed to become an avatar (subjectConsent: true)." });
|
|
47030
|
+
var avatarCreateRequest = external_exports.discriminatedUnion("type", [
|
|
47031
|
+
external_exports.object({
|
|
47032
|
+
type: external_exports.literal("prompt"),
|
|
47033
|
+
name,
|
|
47034
|
+
prompt: external_exports.string().trim().min(3).max(1e3),
|
|
47035
|
+
aspectRatio: external_exports.enum(AVATAR_ASPECT_RATIOS).default("auto"),
|
|
47036
|
+
lookId: heygenId.optional(),
|
|
47037
|
+
groupId: heygenId.optional(),
|
|
47038
|
+
referenceImages: external_exports.array(avatarFile).max(3).default([])
|
|
47039
|
+
}),
|
|
47040
|
+
external_exports.object({ type: external_exports.literal("photo"), name, file: avatarFile, groupId: heygenId.optional(), subjectConsent }),
|
|
47041
|
+
external_exports.object({ type: external_exports.literal("digital_twin"), name, file: avatarFile, groupId: heygenId.optional(), subjectConsent })
|
|
47042
|
+
]).superRefine((p, ctx) => {
|
|
47043
|
+
const files = p.type === "prompt" ? p.referenceImages : [p.file];
|
|
47044
|
+
const footage = p.type === "digital_twin";
|
|
47045
|
+
for (const [index2, file2] of files.entries()) {
|
|
47046
|
+
if (file2.type !== "base64") continue;
|
|
47047
|
+
const allowed = footage ? AVATAR_FOOTAGE_TYPES : AVATAR_PHOTO_TYPES;
|
|
47048
|
+
if (!allowed.includes(file2.mediaType)) ctx.addIssue({ code: "custom", message: footage ? "Send footage as MP4, MOV or WebM." : "Send a PNG, JPEG or WebP image.", path: p.type === "prompt" ? ["referenceImages", index2, "mediaType"] : ["file", "mediaType"] });
|
|
47049
|
+
}
|
|
47050
|
+
});
|
|
47051
|
+
var avatarLooksRequest = external_exports.discriminatedUnion("method", [
|
|
47052
|
+
external_exports.object({ method: external_exports.literal("look_pack"), lookId: heygenId, templateId: heygenId, aspectRatio: external_exports.enum(LOOK_PACK_ASPECT_RATIOS).default("16:9") }),
|
|
47053
|
+
external_exports.object({ method: external_exports.literal("template"), lookId: heygenId, templateId: heygenId })
|
|
47054
|
+
]).superRefine((p, ctx) => {
|
|
47055
|
+
const known = avatarTemplate(p.templateId);
|
|
47056
|
+
if (known && known.method !== p.method) ctx.addIssue({ code: "custom", message: `This template is applied with method ${known.method}.`, path: ["method"] });
|
|
47057
|
+
});
|
|
47058
|
+
var heygenVoiceId = external_exports.string().trim().regex(/^[A-Za-z0-9_.-]{1,128}$/, "Use a HeyGen voice ID.");
|
|
47059
|
+
var avatarGroupUpdate = external_exports.object({ defaultVoiceId: heygenVoiceId });
|
|
47060
|
+
var avatarLookUpdate = external_exports.object({ name: external_exports.string().trim().min(1).max(255) });
|
|
47061
|
+
var avatarConsentRequest = external_exports.object({ rerouteUrl: https.optional() });
|
|
47062
|
+
var limit = external_exports.coerce.number().int().min(1).max(50).default(20);
|
|
47063
|
+
var token = external_exports.string().max(2048).optional();
|
|
47064
|
+
var avatarListQuery = external_exports.object({ ownership: external_exports.enum(AVATAR_OWNERSHIPS).default("public"), limit, token });
|
|
47065
|
+
var avatarLookListQuery = external_exports.object({ groupId: heygenId.optional(), avatarType: external_exports.enum(AVATAR_LOOK_TYPES).optional(), limit, token });
|
|
47066
|
+
var avatarVoiceListQuery = external_exports.object({ ownership: external_exports.enum(AVATAR_OWNERSHIPS).default("public"), language: external_exports.string().trim().min(1).max(40).optional(), gender: external_exports.enum(["male", "female"]).optional(), limit, token });
|
|
47067
|
+
var avatarCreateEstimate = (p) => AVATAR_CREDIT_UNITS[p.type];
|
|
47068
|
+
var avatarLooksEstimate = (p) => LOOKS_PER_METHOD[p.method] * AVATAR_LOOK_CREDIT_UNITS;
|
|
47069
|
+
var AVATAR_VIDEO_MODEL_IDS = ["heygen/avatar-iv", "heygen/avatar-v", "heygen/avatar-iii"];
|
|
47070
|
+
var DEFAULT_AVATAR_VIDEO_MODEL = "heygen/avatar-iv";
|
|
47071
|
+
var AVATAR_VIDEO_RESOLUTIONS = ["720p", "1080p"];
|
|
47072
|
+
var AVATAR_EXPRESSIVENESS = ["low", "medium", "high"];
|
|
47073
|
+
var AVATAR_SCRIPT_MAX = 1500;
|
|
47074
|
+
var AVATAR_VIDEO_MAX_SECONDS = 120;
|
|
47075
|
+
var avatarVideoRequest = external_exports.object({
|
|
47076
|
+
type: external_exports.literal("video"),
|
|
47077
|
+
name,
|
|
47078
|
+
model: external_exports.enum(AVATAR_VIDEO_MODEL_IDS).default(DEFAULT_AVATAR_VIDEO_MODEL),
|
|
47079
|
+
/** A look of this workspace's avatars or of HeyGen's catalog. */
|
|
47080
|
+
lookId: heygenId,
|
|
47081
|
+
/** What the avatar says. */
|
|
47082
|
+
script: external_exports.string().trim().min(1).max(AVATAR_SCRIPT_MAX).optional(),
|
|
47083
|
+
/** Saved speech or music in this project that the avatar lip-syncs instead of a script. */
|
|
47084
|
+
soundtrack: sha.optional(),
|
|
47085
|
+
/** The voice that speaks the script; without it, the look's own voice. */
|
|
47086
|
+
voiceId: heygenVoiceId.optional(),
|
|
47087
|
+
aspectRatio: external_exports.enum(AVATAR_ASPECT_RATIOS).default("auto"),
|
|
47088
|
+
resolution: external_exports.enum(AVATAR_VIDEO_RESOLUTIONS).default("1080p"),
|
|
47089
|
+
/** How the body and hands move: photo avatars on Avatar IV, any look on Avatar V. */
|
|
47090
|
+
motionPrompt: external_exports.string().trim().min(3).max(1e3).optional(),
|
|
47091
|
+
/** How much a photo avatar moves on Avatar IV (low unless set). */
|
|
47092
|
+
expressiveness: external_exports.enum(AVATAR_EXPRESSIVENESS).optional(),
|
|
47093
|
+
/** The clip's length, which the server sets: the audio's, or the script's estimate until the clip is made. */
|
|
47094
|
+
seconds: external_exports.number().positive().max(600).optional()
|
|
47095
|
+
}).superRefine((p, ctx) => {
|
|
47096
|
+
const issue2 = (path, message) => ctx.addIssue({ code: "custom", message, path: [path] });
|
|
47097
|
+
if (p.script && p.soundtrack) issue2("soundtrack", "Give the avatar a script or a saved audio track, not both.");
|
|
47098
|
+
if (!p.script && !p.soundtrack) issue2("script", "Write what the avatar says, or choose saved speech or music for it to lip-sync.");
|
|
47099
|
+
if (p.soundtrack && p.voiceId) issue2("voiceId", "A saved audio track speaks in its own voice; leave out voiceId.");
|
|
47100
|
+
if (p.model === "heygen/avatar-iii" && p.motionPrompt) issue2("motionPrompt", "Avatar III doesn't take a motion prompt; use Avatar IV or Avatar V.");
|
|
47101
|
+
if (p.model !== "heygen/avatar-iv" && p.expressiveness) issue2("expressiveness", "Only Avatar IV takes expressiveness.");
|
|
47102
|
+
});
|
|
47103
|
+
|
|
46976
47104
|
// shared/model-assets.ts
|
|
46977
47105
|
var MODEL_GENERATORS = [
|
|
46978
47106
|
{
|
|
@@ -47042,7 +47170,7 @@ var rigCostUsd = (clips2) => 0.2 + 0.12 * clips2;
|
|
|
47042
47170
|
var modelCostUsd = (p) => generationCostUsd(p) + (p.rig ? rigCostUsd(p.animations.length) : 0);
|
|
47043
47171
|
|
|
47044
47172
|
// shared/assets.ts
|
|
47045
|
-
var ASSET_TYPES = ["image", "vector", "video", "music", "speech", "sfx", "model"];
|
|
47173
|
+
var ASSET_TYPES = ["image", "vector", "gif", "video", "music", "speech", "sfx", "model"];
|
|
47046
47174
|
var SPEECH_MODELS = [
|
|
47047
47175
|
{ id: "gemini-3.8-flash-tts", label: "Gemini 3.8 Flash TTS", provider: "google" },
|
|
47048
47176
|
{ id: "gemini-3.8-flash-lite-tts", label: "Gemini 3.8 Flash-Lite TTS", provider: "google" },
|
|
@@ -47325,6 +47453,7 @@ var videoDefaults = (p) => {
|
|
|
47325
47453
|
return { ...p, seconds: p.seconds ?? defaultSeconds(model, p.workflow), resolution: p.resolution ?? videoResolutions(model, p.workflow)[0], mode: p.mode ?? model.modes[0] };
|
|
47326
47454
|
};
|
|
47327
47455
|
var IMAGE_ASPECT_RATIOS = ["1:1", "3:2", "2:3", "16:9", "9:16"];
|
|
47456
|
+
var IMAGE_SIZES = { "1:1": [1024, 1024], "3:2": [1536, 1024], "2:3": [1024, 1536], "16:9": [1536, 864], "9:16": [864, 1536] };
|
|
47328
47457
|
var MAX_IMAGE_REFERENCES = 4;
|
|
47329
47458
|
var MAX_MASK_REGIONS = 8;
|
|
47330
47459
|
var imageReferences = external_exports.array(blob).max(MAX_IMAGE_REFERENCES).refine((shas2) => new Set(shas2).size === shas2.length, "Choose each reference image once.").default([]);
|
|
@@ -47342,10 +47471,13 @@ var imageAsset = external_exports.object({
|
|
|
47342
47471
|
var imageChecks = (p, ctx) => {
|
|
47343
47472
|
if (p.mask && !p.references.length) ctx.addIssue({ code: "custom", message: "A mask edits Image 1; add the image to edit as the first reference.", path: ["mask"] });
|
|
47344
47473
|
};
|
|
47345
|
-
var VECTOR_MODELS = [{ id: "fal/ideogram-vector", label: "Ideogram Vector (fal)" }];
|
|
47474
|
+
var VECTOR_MODELS = [{ id: "fal/ideogram-vector", label: "Ideogram Vector (fal)" }, { id: "fal/gpt-image-2.6-vector", label: "GPT Image 2.6 Vector (fal)" }];
|
|
47475
|
+
var VECTOR_MODEL_IDS = ["fal/ideogram-vector", "fal/gpt-image-2.6-vector"];
|
|
47476
|
+
var GPT_VECTOR_MODEL = "fal/gpt-image-2.6-vector";
|
|
47346
47477
|
var VECTOR_WORKFLOWS = ["text-to-vector", "image-to-vector"];
|
|
47347
47478
|
var VECTOR_QUALITIES = ["low", "medium", "high"];
|
|
47348
47479
|
var VECTOR_ASPECT_RATIOS = ["auto", "1:1", "1:4", "1:3", "1:2", "9:16", "10:16", "2:3", "3:4", "4:5", "5:4", "4:3", "3:2", "16:10", "16:9", "2:1", "3:1", "4:1"];
|
|
47480
|
+
var GPT_VECTOR_ASPECT_RATIOS = VECTOR_ASPECT_RATIOS.filter((ratio) => ratio !== "1:4" && ratio !== "4:1");
|
|
47349
47481
|
var VECTOR_SHAPES = ["detailed", "simple"];
|
|
47350
47482
|
var MAX_VECTOR_REFERENCES = 5;
|
|
47351
47483
|
var VECTOR_REFERENCE_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -47355,7 +47487,7 @@ var vectorAsset = external_exports.object({
|
|
|
47355
47487
|
/** Image-to-vector takes no prompt. */
|
|
47356
47488
|
prompt: external_exports.string().trim().max(4e3).default(""),
|
|
47357
47489
|
type: external_exports.literal("vector"),
|
|
47358
|
-
model: external_exports.
|
|
47490
|
+
model: external_exports.enum(VECTOR_MODEL_IDS).default("fal/ideogram-vector"),
|
|
47359
47491
|
workflow: external_exports.enum(VECTOR_WORKFLOWS).default("text-to-vector"),
|
|
47360
47492
|
/** Text-to-vector; defaults to medium. */
|
|
47361
47493
|
quality: external_exports.enum(VECTOR_QUALITIES).optional(),
|
|
@@ -47368,11 +47500,24 @@ var vectorAsset = external_exports.object({
|
|
|
47368
47500
|
/** Image-to-vector; defaults to detailed. */
|
|
47369
47501
|
shapes: external_exports.enum(VECTOR_SHAPES).optional(),
|
|
47370
47502
|
/** Text-to-vector. */
|
|
47371
|
-
seed: external_exports.number().int().min(0).max(2 ** 32 - 1).optional()
|
|
47503
|
+
seed: external_exports.number().int().min(0).max(2 ** 32 - 1).optional(),
|
|
47504
|
+
/** GPT Image 2.6: draw the art alone, without a background (default false). */
|
|
47505
|
+
transparent: external_exports.boolean().optional()
|
|
47372
47506
|
});
|
|
47373
47507
|
function vectorChecks(p, ctx) {
|
|
47374
47508
|
const issue2 = (path, message) => ctx.addIssue({ code: "custom", message, path: [path] });
|
|
47375
47509
|
if (new Set(p.references).size !== p.references.length) issue2("references", "Choose each reference image once.");
|
|
47510
|
+
if (p.model === GPT_VECTOR_MODEL) {
|
|
47511
|
+
if (p.workflow !== "text-to-vector") return issue2("workflow", "GPT Image 2.6 Vector draws from text; trace a saved image with Ideogram Vector (fal/ideogram-vector).");
|
|
47512
|
+
if (p.prompt.length < 3) issue2("prompt", "Describe the vector in at least 3 characters.");
|
|
47513
|
+
if (p.references.length) issue2("references", "GPT Image 2.6 Vector draws from the prompt alone; follow reference images with Ideogram Vector (fal/ideogram-vector).");
|
|
47514
|
+
if (p.source) issue2("source", "Only image-to-vector traces a saved image.");
|
|
47515
|
+
if (p.shapes) issue2("shapes", "Only image-to-vector takes shapes.");
|
|
47516
|
+
if (p.seed !== void 0) issue2("seed", "GPT Image 2.6 Vector doesn't take a seed.");
|
|
47517
|
+
if (p.aspectRatio && !GPT_VECTOR_ASPECT_RATIOS.includes(p.aspectRatio)) issue2("aspectRatio", "GPT Image 2.6 Vector draws between 1:3 and 3:1; choose another aspect ratio.");
|
|
47518
|
+
return;
|
|
47519
|
+
}
|
|
47520
|
+
if (p.transparent !== void 0) issue2("transparent", "Only GPT Image 2.6 Vector (fal/gpt-image-2.6-vector) leaves out the background.");
|
|
47376
47521
|
if (p.workflow === "text-to-vector") {
|
|
47377
47522
|
if (p.prompt.length < 3) issue2("prompt", "Describe the vector in at least 3 characters.");
|
|
47378
47523
|
if (p.source) issue2("source", "Only image-to-vector traces a saved image; use references to guide text-to-vector.");
|
|
@@ -47384,7 +47529,39 @@ function vectorChecks(p, ctx) {
|
|
|
47384
47529
|
for (const field of ["quality", "aspectRatio", "seed"]) if (p[field] !== void 0) issue2(field, `image-to-vector doesn't take ${field === "aspectRatio" ? "an aspect ratio" : field === "seed" ? "a seed" : "a quality"}; the SVG follows the image.`);
|
|
47385
47530
|
if (p.references.length) issue2("references", "image-to-vector traces its source alone and takes no references.");
|
|
47386
47531
|
}
|
|
47387
|
-
var vectorDefaults = (p) => p.workflow === "text-to-vector" ? { ...p, quality: p.quality ?? "medium", aspectRatio: p.aspectRatio ?? "auto" } : { ...p, shapes: p.shapes ?? "detailed" };
|
|
47532
|
+
var vectorDefaults = (p) => p.workflow === "text-to-vector" ? { ...p, quality: p.quality ?? "medium", aspectRatio: p.aspectRatio ?? "auto", ...p.model === GPT_VECTOR_MODEL ? { transparent: p.transparent ?? false } : {} } : { ...p, shapes: p.shapes ?? "detailed" };
|
|
47533
|
+
var GIF_MODELS = [
|
|
47534
|
+
{ id: "fal/gpt-image-2.6-gif", label: "GPT Image 2.6 Flare GIF (fal)" },
|
|
47535
|
+
{ id: "fal/gpt-image-2.6-sunburst-gif", label: "GPT Image 2.6 Sunburst GIF (fal)" }
|
|
47536
|
+
];
|
|
47537
|
+
var GIF_MODEL_IDS = ["fal/gpt-image-2.6-gif", "fal/gpt-image-2.6-sunburst-gif"];
|
|
47538
|
+
var DEFAULT_GIF_MODEL = "fal/gpt-image-2.6-gif";
|
|
47539
|
+
var GIF_QUALITIES = ["low", "medium", "high"];
|
|
47540
|
+
var GIF_FRAMES = { min: 2, max: 16, default: 9 };
|
|
47541
|
+
var GIF_FRAME_MS = { min: 20, max: 2e3, default: 200 };
|
|
47542
|
+
var MAX_GIF_REFERENCES = 4;
|
|
47543
|
+
var GIF_PIXEL_BUDGET = 3840 * 2160;
|
|
47544
|
+
function gifFrameSize(aspectRatio, frames) {
|
|
47545
|
+
const [w, h] = IMAGE_SIZES[aspectRatio];
|
|
47546
|
+
const scale = Math.min(1, Math.sqrt(GIF_PIXEL_BUDGET / Math.max(1, frames) / (w * h)));
|
|
47547
|
+
const width = Math.max(16, Math.floor(w * scale / 16) * 16);
|
|
47548
|
+
return [width, Math.max(16, Math.floor(width * h / w / 16) * 16)];
|
|
47549
|
+
}
|
|
47550
|
+
var gifAsset = external_exports.object({
|
|
47551
|
+
...base,
|
|
47552
|
+
type: external_exports.literal("gif"),
|
|
47553
|
+
model: external_exports.enum(GIF_MODEL_IDS).default(DEFAULT_GIF_MODEL),
|
|
47554
|
+
aspectRatio: external_exports.enum(IMAGE_ASPECT_RATIOS).default("1:1"),
|
|
47555
|
+
frames: external_exports.number().int().min(GIF_FRAMES.min).max(GIF_FRAMES.max).default(GIF_FRAMES.default),
|
|
47556
|
+
/** How long each frame shows, in milliseconds; rounded to 10. */
|
|
47557
|
+
frameMs: external_exports.number().min(GIF_FRAME_MS.min).max(GIF_FRAME_MS.max).default(GIF_FRAME_MS.default),
|
|
47558
|
+
quality: external_exports.enum(GIF_QUALITIES).default("medium"),
|
|
47559
|
+
/** Frames without a background, for a sprite over a scene. */
|
|
47560
|
+
transparent: external_exports.boolean().default(false),
|
|
47561
|
+
/** Saved images or sprite art to animate or follow, named Image 1, Image 2… in the prompt. */
|
|
47562
|
+
references: external_exports.array(blob).max(MAX_GIF_REFERENCES).refine((shas2) => new Set(shas2).size === shas2.length, "Choose each reference image once.").default([])
|
|
47563
|
+
});
|
|
47564
|
+
var gifDefaults = (p) => ({ ...p, frameMs: Math.round(p.frameMs / 10) * 10 });
|
|
47388
47565
|
var musicAsset = external_exports.object({
|
|
47389
47566
|
name: base.name,
|
|
47390
47567
|
/** A soundtrack may leave it out, and so may a song sung from lyrics, where it sets the style. */
|
|
@@ -47503,17 +47680,23 @@ var assetRequest = external_exports.discriminatedUnion("type", [
|
|
|
47503
47680
|
}).transform((p) => ({ ...p, voice: p.voice || defaultSpeechVoice(p.model) })),
|
|
47504
47681
|
external_exports.object({ ...base, type: external_exports.literal("sfx"), model: external_exports.literal("eleven_text_to_sound_v2").default("eleven_text_to_sound_v2"), seconds: external_exports.number().min(0.5).max(30).default(5), loop: external_exports.boolean().default(false), promptInfluence: external_exports.number().min(0).max(1).default(0.3) }),
|
|
47505
47682
|
vectorAsset.superRefine(vectorChecks).transform(vectorDefaults),
|
|
47506
|
-
modelAsset.superRefine(modelChecks).transform(modelDefaults)
|
|
47683
|
+
modelAsset.superRefine(modelChecks).transform(modelDefaults),
|
|
47684
|
+
gifAsset.transform(gifDefaults)
|
|
47507
47685
|
]);
|
|
47508
47686
|
var assetGenerationRequest = external_exports.discriminatedUnion("type", [imageAsset.omit({ model: true }).superRefine(imageChecks), ...assetRequest.options.slice(1)]);
|
|
47509
47687
|
var LIBRARY_AUDIO_MODEL = "library-audio";
|
|
47510
47688
|
var libraryAudio = external_exports.object({ name: base.name, prompt: external_exports.string().trim().max(4e3).default(""), type: external_exports.enum(["music", "sfx"]), model: external_exports.literal(LIBRARY_AUDIO_MODEL), loop: external_exports.boolean().default(false) });
|
|
47511
47689
|
var UPLOADED_MODEL = "uploaded";
|
|
47512
47690
|
var uploadedMedia = external_exports.object({ name: base.name, prompt: external_exports.string().trim().max(4e3).default(""), type: external_exports.enum(["image", "video"]), model: external_exports.literal(UPLOADED_MODEL) });
|
|
47513
|
-
var savedAssetOptions = external_exports.union([assetRequest, libraryAudio, uploadedMedia]);
|
|
47691
|
+
var savedAssetOptions = external_exports.union([assetRequest, avatarVideoRequest, libraryAudio, uploadedMedia]);
|
|
47514
47692
|
var speechCharacters = (text2) => Array.from(text2).length;
|
|
47515
47693
|
var imageEstimate = (p) => Math.ceil((130 + 40 * p.references.length) * spriteImageModel(p.model).relCost);
|
|
47516
|
-
var vectorEstimate = (p) => p.workflow === "image-to-vector" ? 100 : p.quality === "low" ? 130 : p.quality === "high" ? p.references.length ? 320 : 200 : 160;
|
|
47694
|
+
var vectorEstimate = (p) => p.model === GPT_VECTOR_MODEL ? p.quality === "low" ? 80 : p.quality === "high" ? 220 : 120 : p.workflow === "image-to-vector" ? 100 : p.quality === "low" ? 130 : p.quality === "high" ? p.references.length ? 320 : 200 : 160;
|
|
47695
|
+
var GIF_UNITS_PER_MEGAPIXEL = { low: 13, medium: 39, high: 130 };
|
|
47696
|
+
function gifEstimate(p) {
|
|
47697
|
+
const [w, h] = gifFrameSize(p.aspectRatio, p.frames);
|
|
47698
|
+
return Math.ceil(p.frames * (w * h) / (1024 * 1024) * GIF_UNITS_PER_MEGAPIXEL[p.quality] + 12 * p.references.length);
|
|
47699
|
+
}
|
|
47517
47700
|
function videoExtras(p, facts = {}) {
|
|
47518
47701
|
const w = p.workflow;
|
|
47519
47702
|
if (spriteVideoModel(p.model).provider === "heygen") {
|
|
@@ -47533,6 +47716,7 @@ var modelEstimate = (p) => Math.max(1, Math.ceil(modelCostUsd(p) / 1e-3));
|
|
|
47533
47716
|
function assetEstimate(p, now = Date.now()) {
|
|
47534
47717
|
if (p.type === "image") return imageEstimate(p);
|
|
47535
47718
|
if (p.type === "vector") return vectorEstimate(p);
|
|
47719
|
+
if (p.type === "gif") return gifEstimate(p);
|
|
47536
47720
|
if (p.type === "model") return modelEstimate(p);
|
|
47537
47721
|
if (p.type === "video") return spriteVideoEstimate(spriteVideoModel(p.model), p, videoExtras(p));
|
|
47538
47722
|
if (p.type === "music") return Math.ceil(musicCostUsd(p) / 1e-3);
|
|
@@ -48218,7 +48402,7 @@ ${entries.join(",\n")}
|
|
|
48218
48402
|
}}
|
|
48219
48403
|
`;
|
|
48220
48404
|
}
|
|
48221
|
-
async function
|
|
48405
|
+
async function token2(context, access4) {
|
|
48222
48406
|
const result = await context.client.request(`/api/v1/cloud/${context.link.projectId}/token`, { method: "POST", body: { access: access4 } });
|
|
48223
48407
|
const remote = new URL(result.remote);
|
|
48224
48408
|
if (remote.protocol !== "https:" && !(remote.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(remote.hostname))) throw new Error("The server returned an unsafe cloud remote.");
|
|
@@ -48385,7 +48569,7 @@ async function cloudStatus(options) {
|
|
|
48385
48569
|
await saveState(context);
|
|
48386
48570
|
let cloud = null;
|
|
48387
48571
|
if (!options.offline) {
|
|
48388
|
-
const latest = await fetchLatest(context, await
|
|
48572
|
+
const latest = await fetchLatest(context, await token2(context, "read"));
|
|
48389
48573
|
cloud = { latest, newer: Boolean(latest && latest !== context.state.base) };
|
|
48390
48574
|
}
|
|
48391
48575
|
return {
|
|
@@ -48403,7 +48587,7 @@ async function cloudStatus(options) {
|
|
|
48403
48587
|
async function pushCloud(options) {
|
|
48404
48588
|
const context = await openContext(options.dir, options);
|
|
48405
48589
|
return withLock(context.root, async () => {
|
|
48406
|
-
const remote = await
|
|
48590
|
+
const remote = await token2(context, "write");
|
|
48407
48591
|
const latest = await fetchLatest(context, remote);
|
|
48408
48592
|
if (latest && latest !== context.state.base) throw new Error(`The project's animations have a newer version (${short(latest)}). Run animaguru cloud pull, then push again.`);
|
|
48409
48593
|
const { files: scanned, skipped, tooLarge } = await scanFiles(context.root);
|
|
@@ -48461,7 +48645,7 @@ function defaultMessage(diff) {
|
|
|
48461
48645
|
async function pullCloud(options) {
|
|
48462
48646
|
const context = await openContext(options.dir, options);
|
|
48463
48647
|
return withLock(context.root, async () => {
|
|
48464
|
-
const latest = await fetchLatest(context, await
|
|
48648
|
+
const latest = await fetchLatest(context, await token2(context, "read"));
|
|
48465
48649
|
if (!latest || latest === context.state.base) return { updated: false, version: context.state.base, message: "Already up to date." };
|
|
48466
48650
|
const { files: scanned, tooLarge } = await scanFiles(context.root);
|
|
48467
48651
|
const local = await describeFiles(context, scanned);
|
|
@@ -48512,7 +48696,7 @@ async function restoreCloud(options) {
|
|
|
48512
48696
|
const context = await openContext(options.dir, options);
|
|
48513
48697
|
return withLock(context.root, async () => {
|
|
48514
48698
|
if (!/^[a-f0-9]{4,40}$/.test(options.version)) throw new Error("Pass a version ID from animaguru cloud versions.");
|
|
48515
|
-
await fetchLatest(context, await
|
|
48699
|
+
await fetchLatest(context, await token2(context, "read"));
|
|
48516
48700
|
let version4;
|
|
48517
48701
|
try {
|
|
48518
48702
|
version4 = await import_isomorphic_git.default.expandOid({ fs, gitdir: context.gitdir, oid: options.version });
|
|
@@ -48807,13 +48991,16 @@ var extras = {
|
|
|
48807
48991
|
speech: ["voice", "delivery"],
|
|
48808
48992
|
sfx: ["seconds", "loop", "prompt-influence"],
|
|
48809
48993
|
model: ["reference", "texture", "pbr", "faces", "rig", "animations", "height", "splats", "photo", "seed"],
|
|
48810
|
-
vector: ["workflow", "references", "source", "aspect-ratio", "quality", "shapes", "seed"]
|
|
48994
|
+
vector: ["workflow", "references", "source", "aspect-ratio", "quality", "shapes", "seed", "transparent"],
|
|
48995
|
+
gif: ["aspect-ratio", "frames", "frame-ms", "quality", "transparent", "references"]
|
|
48811
48996
|
};
|
|
48997
|
+
var typeName = (type) => type === "gif" ? "GIF" : type;
|
|
48812
48998
|
var list2 = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
|
|
48813
48999
|
function accepted(type) {
|
|
48814
49000
|
const options = extras[type];
|
|
48815
49001
|
if (!options) return "";
|
|
48816
|
-
|
|
49002
|
+
const name2 = typeName(type);
|
|
49003
|
+
return `${name2[0].toUpperCase()}${name2.slice(1)} assets accept ${list2(["--name", "--prompt", "--model", ...options.map((option) => `--${option}`)])}.`;
|
|
48817
49004
|
}
|
|
48818
49005
|
function parseAsset(input2) {
|
|
48819
49006
|
const value = input2 && typeof input2 === "object" && "type" in input2 && input2.type === "image" ? { ...input2, model: void 0 } : input2;
|
|
@@ -48843,10 +49030,10 @@ function assetFromFlags(flags) {
|
|
|
48843
49030
|
for (const name2 of Object.values(extras).flat()) {
|
|
48844
49031
|
const value = flags[name2];
|
|
48845
49032
|
const given2 = value !== void 0 && (value !== false || (name2 === "texture" || name2 === "pbr") && flags.type !== "model");
|
|
48846
|
-
if (given2 && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets. ${accepted(flags.type)}`.trim());
|
|
49033
|
+
if (given2 && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${typeName(flags.type)} assets. ${accepted(flags.type)}`.trim());
|
|
48847
49034
|
}
|
|
48848
49035
|
const promptOptional = flags.type === "video" || flags.type === "vector" || flags.type === "model" && (flags.reference || isSplatGenerator(flags.model ?? "")) || flags.type === "music" && (flags.model === "fal/mureka-9.5-soundtrack" || flags.lyrics !== void 0);
|
|
48849
|
-
if (!promptOptional && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets${flags.type === "model" ? " unless --reference names an image to build from" : flags.type === "music" ? " unless Mureka 9.5 Song sings --lyrics or Mureka 9.5 Soundtrack scores --source" : ""}.`);
|
|
49036
|
+
if (!promptOptional && flags.prompt === void 0) throw new Error(`--prompt is required for ${typeName(flags.type)} assets${flags.type === "model" ? " unless --reference names an image to build from" : flags.type === "music" ? " unless Mureka 9.5 Song sings --lyrics or Mureka 9.5 Soundtrack scores --source" : ""}.`);
|
|
48850
49037
|
const base2 = { type: flags.type, name: flags.name, prompt: flags.prompt, model: flags.model };
|
|
48851
49038
|
if (flags.type === "image") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], transparent: flags.transparent, references: shas(flags.references), mask: regions(flags.mask) });
|
|
48852
49039
|
if (flags.type === "video") {
|
|
@@ -48886,7 +49073,8 @@ function assetFromFlags(flags) {
|
|
|
48886
49073
|
if (flags.type === "sfx") return parseAsset({ ...base2, seconds: flags.seconds, loop: flags.loop, promptInfluence: flags["prompt-influence"] });
|
|
48887
49074
|
if (flags.type === "music") return parseAsset({ ...base2, lyrics: flags.lyrics, styles: shas(flags.styles), vocals: flags.vocals, seconds: flags.seconds, source: flags.source });
|
|
48888
49075
|
if (flags.type === "model") return parseAsset({ ...base2, reference: flags.reference, texture: flags.texture, pbr: flags.pbr, faces: flags.faces, rig: flags.rig, animations: clips(flags.animations), height: flags.height, splats: flags.splats, photo: flags.photo || void 0, seed: flags.seed });
|
|
48889
|
-
if (flags.type === "vector") return parseAsset({ ...base2, workflow: flags.workflow, quality: flags.quality, aspectRatio: flags["aspect-ratio"], references: shas(flags.references), source: flags.source, shapes: flags.shapes, seed: flags.seed });
|
|
49076
|
+
if (flags.type === "vector") return parseAsset({ ...base2, workflow: flags.workflow, quality: flags.quality, aspectRatio: flags["aspect-ratio"], references: shas(flags.references), source: flags.source, shapes: flags.shapes, seed: flags.seed, transparent: flags.transparent || void 0 });
|
|
49077
|
+
if (flags.type === "gif") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], frames: flags.frames, frameMs: flags["frame-ms"], quality: flags.quality, transparent: flags.transparent, references: shas(flags.references) });
|
|
48890
49078
|
return parseAsset({ ...base2, ...flags.type === "speech" ? { voice: flags.voice, delivery: flags.delivery } : {} });
|
|
48891
49079
|
}
|
|
48892
49080
|
async function assetFromFile(file2, model) {
|
|
@@ -48982,6 +49170,7 @@ var MIME_EXTENSIONS = {
|
|
|
48982
49170
|
"image/png": "png",
|
|
48983
49171
|
"image/jpeg": "jpg",
|
|
48984
49172
|
"image/webp": "webp",
|
|
49173
|
+
"image/gif": "gif",
|
|
48985
49174
|
"image/svg+xml": "svg",
|
|
48986
49175
|
"video/mp4": "mp4",
|
|
48987
49176
|
"video/webm": "webm",
|
|
@@ -49101,96 +49290,6 @@ async function submitAssetBatch(client, project, requests, options, signal) {
|
|
|
49101
49290
|
import { readFile as readFile11, stat as stat6 } from "node:fs/promises";
|
|
49102
49291
|
import { extname } from "node:path";
|
|
49103
49292
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
49104
|
-
|
|
49105
|
-
// shared/avatars.ts
|
|
49106
|
-
var AVATAR_OWNERSHIPS = ["public", "private"];
|
|
49107
|
-
var AVATAR_LOOK_TYPES = ["studio_avatar", "digital_twin", "photo_avatar"];
|
|
49108
|
-
var AVATAR_CREATE_TYPES = ["prompt", "photo", "digital_twin"];
|
|
49109
|
-
var AVATAR_ASPECT_RATIOS = ["auto", "16:9", "9:16", "1:1", "4:5", "5:4"];
|
|
49110
|
-
var LOOK_PACK_ASPECT_RATIOS = ["16:9", "9:16"];
|
|
49111
|
-
var AVATAR_LOOK_METHODS = ["look_pack", "template"];
|
|
49112
|
-
var AVATAR_CREDIT_UNITS = { digital_twin: 2130, photo: 1320, prompt: 1320 };
|
|
49113
|
-
var AVATAR_LOOK_CREDIT_UNITS = 1320;
|
|
49114
|
-
var LOOKS_PER_METHOD = { look_pack: 5, template: 2 };
|
|
49115
|
-
var AVATAR_LOOK_TEMPLATES = [
|
|
49116
|
-
{ id: "5a8e6be843ee4321a014946bf62aa322", method: "look_pack", name: "Modern Corporate", variant: "female" },
|
|
49117
|
-
{ id: "5e659e76755d47fd9160a2d7dedce124", method: "look_pack", name: "Modern Corporate", variant: "male" },
|
|
49118
|
-
{ id: "e1650a9029d04ea1a350421c163295fd", method: "look_pack", name: "Stylish Business-Casual", variant: "female" },
|
|
49119
|
-
{ id: "a5f8e0c0cb654c1a83c695629b173af5", method: "look_pack", name: "Stylish Business-Casual", variant: "male" },
|
|
49120
|
-
{ id: "e7b000e2cb0d44f1a2d2f291a38b395a", method: "look_pack", name: "Scandinavian Minimal", variant: "female" },
|
|
49121
|
-
{ id: "9600f78f27bb49d792e1c56ce624b929", method: "look_pack", name: "Scandinavian Minimal", variant: "male" },
|
|
49122
|
-
{ id: "d7ad40ec97d4459a92b33398b57caf4e", method: "look_pack", name: "Cool Tech / Slate", variant: "female" },
|
|
49123
|
-
{ id: "fbd03fc3603a4e3caff594f5743a1733", method: "look_pack", name: "Cool Tech / Slate", variant: "male" },
|
|
49124
|
-
{ id: "14f4070bd5a04eb6b1f82ae087cd0f30", method: "look_pack", name: "Healthcare", variant: "female" },
|
|
49125
|
-
{ id: "ce706bfa8556401e8c4401765102a455", method: "look_pack", name: "Healthcare", variant: "male" },
|
|
49126
|
-
{ id: "b0cae4fbae384ab9ab9a8e73ba504be8", method: "look_pack", name: "Keynote Power Presenter", variant: "female" },
|
|
49127
|
-
{ id: "71e84769162d4f4186563ad9e0fc45b8", method: "look_pack", name: "Keynote Power Presenter", variant: "male" },
|
|
49128
|
-
{ id: "935ea0b7cdde4e6eb5a198a3d666f677", method: "look_pack", name: "Fitness", variant: "female" },
|
|
49129
|
-
{ id: "daeb8b15c92a4acf9ffb437ba5534458", method: "look_pack", name: "Fitness", variant: "male" },
|
|
49130
|
-
{ id: "6f183d726933457c9035fc0aa4e9c0c3", method: "look_pack", name: "Automotive Dealership", variant: "female" },
|
|
49131
|
-
{ id: "8595c78b466c4e51802731229c59b6e7", method: "look_pack", name: "Automotive Dealership", variant: "male" },
|
|
49132
|
-
{ id: "b30c83d99cec48e09c8f5b07ed8aa38c", method: "template", name: "Business Casual", variant: "female" },
|
|
49133
|
-
{ id: "2dc326030e2e4471babcc9eda56131b6", method: "template", name: "Business Casual", variant: "male" },
|
|
49134
|
-
{ id: "00c49daa4eb94386a0c12508043bab17", method: "template", name: "Podcast", variant: "female" },
|
|
49135
|
-
{ id: "0e52ceafe4d5456fb83c1e39899ff76a", method: "template", name: "Podcast", variant: "male" }
|
|
49136
|
-
];
|
|
49137
|
-
var avatarTemplate = (id2) => AVATAR_LOOK_TEMPLATES.find((t) => t.id === id2);
|
|
49138
|
-
var heygenId = external_exports.string().trim().regex(/^(?!\.{1,2}$)[A-Za-z0-9_.-]{1,128}$/, "Use an avatar id returned by AnimaGuru.");
|
|
49139
|
-
var sha = external_exports.string().regex(/^[a-f0-9]{64}$/);
|
|
49140
|
-
var name = external_exports.string().trim().min(1).max(80);
|
|
49141
|
-
var https = external_exports.string().trim().max(2048).url().refine((url3) => url3.startsWith("https://"), "Use an HTTPS URL.");
|
|
49142
|
-
var AVATAR_INLINE_MAX_BYTES = 8 * 1024 * 1024;
|
|
49143
|
-
var AVATAR_PHOTO_TYPES = ["image/png", "image/jpeg", "image/webp"];
|
|
49144
|
-
var AVATAR_FOOTAGE_TYPES = ["video/mp4", "video/quicktime", "video/webm"];
|
|
49145
|
-
var avatarFile = external_exports.discriminatedUnion("type", [
|
|
49146
|
-
external_exports.object({ type: external_exports.literal("file"), sha }),
|
|
49147
|
-
external_exports.object({ type: external_exports.literal("url"), url: https }),
|
|
49148
|
-
external_exports.object({
|
|
49149
|
-
type: external_exports.literal("base64"),
|
|
49150
|
-
mediaType: external_exports.enum([...AVATAR_PHOTO_TYPES, ...AVATAR_FOOTAGE_TYPES]),
|
|
49151
|
-
data: external_exports.string().max(Math.ceil(AVATAR_INLINE_MAX_BYTES / 3) * 4, "Inline files must be at most 8 MB; use a URL or a project file.").regex(/^[A-Za-z0-9+/]+={0,2}$/, "Send the file as standard base64.")
|
|
49152
|
-
})
|
|
49153
|
-
]);
|
|
49154
|
-
var subjectConsent = external_exports.literal(true, { error: "Confirm that the person shown agreed to become an avatar (subjectConsent: true)." });
|
|
49155
|
-
var avatarCreateRequest = external_exports.discriminatedUnion("type", [
|
|
49156
|
-
external_exports.object({
|
|
49157
|
-
type: external_exports.literal("prompt"),
|
|
49158
|
-
name,
|
|
49159
|
-
prompt: external_exports.string().trim().min(3).max(1e3),
|
|
49160
|
-
aspectRatio: external_exports.enum(AVATAR_ASPECT_RATIOS).default("auto"),
|
|
49161
|
-
lookId: heygenId.optional(),
|
|
49162
|
-
groupId: heygenId.optional(),
|
|
49163
|
-
referenceImages: external_exports.array(avatarFile).max(3).default([])
|
|
49164
|
-
}),
|
|
49165
|
-
external_exports.object({ type: external_exports.literal("photo"), name, file: avatarFile, groupId: heygenId.optional(), subjectConsent }),
|
|
49166
|
-
external_exports.object({ type: external_exports.literal("digital_twin"), name, file: avatarFile, groupId: heygenId.optional(), subjectConsent })
|
|
49167
|
-
]).superRefine((p, ctx) => {
|
|
49168
|
-
const files = p.type === "prompt" ? p.referenceImages : [p.file];
|
|
49169
|
-
const footage = p.type === "digital_twin";
|
|
49170
|
-
for (const [index2, file2] of files.entries()) {
|
|
49171
|
-
if (file2.type !== "base64") continue;
|
|
49172
|
-
const allowed = footage ? AVATAR_FOOTAGE_TYPES : AVATAR_PHOTO_TYPES;
|
|
49173
|
-
if (!allowed.includes(file2.mediaType)) ctx.addIssue({ code: "custom", message: footage ? "Send footage as MP4, MOV or WebM." : "Send a PNG, JPEG or WebP image.", path: p.type === "prompt" ? ["referenceImages", index2, "mediaType"] : ["file", "mediaType"] });
|
|
49174
|
-
}
|
|
49175
|
-
});
|
|
49176
|
-
var avatarLooksRequest = external_exports.discriminatedUnion("method", [
|
|
49177
|
-
external_exports.object({ method: external_exports.literal("look_pack"), lookId: heygenId, templateId: heygenId, aspectRatio: external_exports.enum(LOOK_PACK_ASPECT_RATIOS).default("16:9") }),
|
|
49178
|
-
external_exports.object({ method: external_exports.literal("template"), lookId: heygenId, templateId: heygenId })
|
|
49179
|
-
]).superRefine((p, ctx) => {
|
|
49180
|
-
const known = avatarTemplate(p.templateId);
|
|
49181
|
-
if (known && known.method !== p.method) ctx.addIssue({ code: "custom", message: `This template is applied with method ${known.method}.`, path: ["method"] });
|
|
49182
|
-
});
|
|
49183
|
-
var avatarGroupUpdate = external_exports.object({ defaultVoiceId: external_exports.string().trim().min(1).max(255) });
|
|
49184
|
-
var avatarLookUpdate = external_exports.object({ name: external_exports.string().trim().min(1).max(255) });
|
|
49185
|
-
var avatarConsentRequest = external_exports.object({ rerouteUrl: https.optional() });
|
|
49186
|
-
var limit = external_exports.coerce.number().int().min(1).max(50).default(20);
|
|
49187
|
-
var token2 = external_exports.string().max(2048).optional();
|
|
49188
|
-
var avatarListQuery = external_exports.object({ ownership: external_exports.enum(AVATAR_OWNERSHIPS).default("public"), limit, token: token2 });
|
|
49189
|
-
var avatarLookListQuery = external_exports.object({ groupId: heygenId.optional(), avatarType: external_exports.enum(AVATAR_LOOK_TYPES).optional(), limit, token: token2 });
|
|
49190
|
-
var avatarCreateEstimate = (p) => AVATAR_CREDIT_UNITS[p.type];
|
|
49191
|
-
var avatarLooksEstimate = (p) => LOOKS_PER_METHOD[p.method] * AVATAR_LOOK_CREDIT_UNITS;
|
|
49192
|
-
|
|
49193
|
-
// cli/src/avatars.ts
|
|
49194
49293
|
var MEDIA_TYPES = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".mp4": "video/mp4", ".mov": "video/quicktime", ".webm": "video/webm" };
|
|
49195
49294
|
var avatarsPath = (project) => `/api/v1/sprites/${encodeURIComponent(project)}/avatars`;
|
|
49196
49295
|
function parse3(schema, input2) {
|
|
@@ -49225,6 +49324,24 @@ function looksFromFlags(flags) {
|
|
|
49225
49324
|
if (flags["aspect-ratio"] && method !== "look_pack") throw new Error("--aspect-ratio applies only to Look Packs.");
|
|
49226
49325
|
return parse3(avatarLooksRequest, { method, lookId: flags.look, templateId: flags.template, aspectRatio: flags["aspect-ratio"] });
|
|
49227
49326
|
}
|
|
49327
|
+
async function avatarVideoFromFlags(flags) {
|
|
49328
|
+
if (flags.script && flags["script-file"]) throw new Error("Pass --script or --script-file, not both.");
|
|
49329
|
+
const script = flags["script-file"] ? (await readFile11(flags["script-file"], "utf8")).trim() : flags.script;
|
|
49330
|
+
if (flags.audio && !/^[a-f0-9]{64}$/.test(flags.audio)) throw new Error("--audio takes the file SHA of saved speech or music from assets list.");
|
|
49331
|
+
return parse3(avatarVideoRequest, {
|
|
49332
|
+
type: "video",
|
|
49333
|
+
name: flags.name,
|
|
49334
|
+
lookId: flags.look,
|
|
49335
|
+
model: flags.model,
|
|
49336
|
+
script,
|
|
49337
|
+
soundtrack: flags.audio,
|
|
49338
|
+
voiceId: flags.voice,
|
|
49339
|
+
aspectRatio: flags["aspect-ratio"],
|
|
49340
|
+
resolution: flags.resolution,
|
|
49341
|
+
motionPrompt: flags["motion-prompt"],
|
|
49342
|
+
expressiveness: flags.expressiveness
|
|
49343
|
+
});
|
|
49344
|
+
}
|
|
49228
49345
|
function authorize(options) {
|
|
49229
49346
|
if (!options.yes) throw new Error("Pass --yes to authorize spending credits, or --dry-run to validate and estimate without creating anything.");
|
|
49230
49347
|
}
|
|
@@ -49238,6 +49355,11 @@ async function submitLooks(client, project, body, options) {
|
|
|
49238
49355
|
authorize(options);
|
|
49239
49356
|
return client.request(`${avatarsPath(project)}/looks`, { method: "POST", body, timeout: 18e4 });
|
|
49240
49357
|
}
|
|
49358
|
+
async function submitAvatarVideo(client, project, body, options) {
|
|
49359
|
+
if (options["dry-run"]) return client.request(`${avatarsPath(project)}/videos/estimate`, { method: "POST", body });
|
|
49360
|
+
authorize(options);
|
|
49361
|
+
return client.request(`${avatarsPath(project)}/videos`, { method: "POST", body });
|
|
49362
|
+
}
|
|
49241
49363
|
async function waitForLook(client, project, lookId, timeout, signal, interval = 1e4) {
|
|
49242
49364
|
if (!Number.isFinite(timeout) || timeout <= 0) throw new Error("Timeout must be positive.");
|
|
49243
49365
|
const deadline = Date.now() + timeout * 1e3;
|
|
@@ -50943,6 +51065,7 @@ async function curl(options, io) {
|
|
|
50943
51065
|
if (!headers.has("content-type")) headers.set("Content-Type", parsesAsJson(body) ? "application/json" : "application/x-www-form-urlencoded");
|
|
50944
51066
|
}
|
|
50945
51067
|
headers.set("Authorization", `Bearer ${await sessionToken(url3.origin)}`);
|
|
51068
|
+
if (!headers.has("user-agent")) headers.set("User-Agent", USER_AGENT);
|
|
50946
51069
|
if (!headers.has("origin")) headers.set("Origin", url3.origin);
|
|
50947
51070
|
const method = (options.request ?? (options.uploadFile !== void 0 ? "PUT" : body !== void 0 ? "POST" : "GET")).toUpperCase();
|
|
50948
51071
|
const timeout = AbortSignal.timeout(options.maxTime * 1e3);
|
|
@@ -50981,7 +51104,7 @@ async function curl(options, io) {
|
|
|
50981
51104
|
}
|
|
50982
51105
|
|
|
50983
51106
|
// cli/src/commands.ts
|
|
50984
|
-
var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id), ...VECTOR_MODELS.map((m) => m.id), ...MODEL_GENERATOR_IDS];
|
|
51107
|
+
var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id), ...VECTOR_MODELS.map((m) => m.id), ...GIF_MODELS.map((m) => m.id), ...MODEL_GENERATOR_IDS];
|
|
50985
51108
|
var assetAuthorizationFlags = [
|
|
50986
51109
|
{ name: "yes", type: "boolean", description: "Authorize spending credits" },
|
|
50987
51110
|
{ name: "dry-run", type: "boolean", description: "Validate and estimate locally without submitting a paid job" }
|
|
@@ -50994,14 +51117,23 @@ var catalogSections = {
|
|
|
50994
51117
|
sprites: ["styles", "kinds", "actions", "videoModels"],
|
|
50995
51118
|
image: ["assetTypes"],
|
|
50996
51119
|
vector: ["assetTypes", "vectorModels", "vectorOptions"],
|
|
51120
|
+
gif: ["assetTypes", "gifModels", "gifOptions"],
|
|
50997
51121
|
video: ["assetTypes", "videoModels", "videoProfiles"],
|
|
50998
51122
|
music: ["assetTypes", "musicModels", "musicOptions"],
|
|
50999
51123
|
speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices", "heygenVoices"],
|
|
51000
51124
|
sfx: ["assetTypes", "sfxModels"],
|
|
51001
51125
|
model: ["assetTypes", "modelGenerators", "modelAnimations"],
|
|
51002
|
-
avatars: ["avatarTypes", "avatarLookTypes"]
|
|
51126
|
+
avatars: ["avatarTypes", "avatarLookTypes", "avatarVideoModels"]
|
|
51127
|
+
};
|
|
51128
|
+
var gifOptions = {
|
|
51129
|
+
frames: GIF_FRAMES,
|
|
51130
|
+
frameMs: GIF_FRAME_MS,
|
|
51131
|
+
qualities: GIF_QUALITIES,
|
|
51132
|
+
aspectRatios: IMAGE_ASPECT_RATIOS,
|
|
51133
|
+
maxReferences: MAX_GIF_REFERENCES,
|
|
51134
|
+
frameSizes: Object.fromEntries(IMAGE_ASPECT_RATIOS.map((ratio) => [ratio, Object.fromEntries(Array.from({ length: GIF_FRAMES.max - GIF_FRAMES.min + 1 }, (_, i2) => GIF_FRAMES.min + i2).map((frames) => [frames, gifFrameSize(ratio, frames)]))]))
|
|
51003
51135
|
};
|
|
51004
|
-
var catalog = () => ({ styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), musicOptions: { styles: MUREKA_STYLES, vocals: MUREKA_VOCALS, songSeconds: SONG_SECONDS, maxLyrics: MAX_SONG_LYRICS }, speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), modelGenerators: MODEL_GENERATORS.map((g) => ({ id: g.id, label: g.label, output: g.output, ...g.output === "spz" ? { splats: g.splats } : { faces: g.faces } })), modelAnimations: MODEL_ANIMATIONS, vectorModels: VECTOR_MODELS.map((m) => m.id), vectorOptions: { workflows: VECTOR_WORKFLOWS, qualities: VECTOR_QUALITIES, aspectRatios: VECTOR_ASPECT_RATIOS, shapes: VECTOR_SHAPES, maxReferences: MAX_VECTOR_REFERENCES }, elevenLabsVoices: ELEVENLABS_VOICES, heygenVoices: HEYGEN_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
|
|
51136
|
+
var catalog = () => ({ styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), musicOptions: { styles: MUREKA_STYLES, vocals: MUREKA_VOCALS, songSeconds: SONG_SECONDS, maxLyrics: MAX_SONG_LYRICS }, speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), modelGenerators: MODEL_GENERATORS.map((g) => ({ id: g.id, label: g.label, output: g.output, ...g.output === "spz" ? { splats: g.splats } : { faces: g.faces } })), modelAnimations: MODEL_ANIMATIONS, vectorModels: VECTOR_MODELS.map((m) => m.id), vectorOptions: { workflows: VECTOR_WORKFLOWS, qualities: VECTOR_QUALITIES, aspectRatios: VECTOR_ASPECT_RATIOS, gptAspectRatios: GPT_VECTOR_ASPECT_RATIOS, shapes: VECTOR_SHAPES, maxReferences: MAX_VECTOR_REFERENCES }, gifModels: GIF_MODELS.map((m) => m.id), gifOptions, elevenLabsVoices: ELEVENLABS_VOICES, heygenVoices: HEYGEN_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES, avatarVideoModels: AVATAR_VIDEO_MODEL_IDS });
|
|
51005
51137
|
var modelFlags = [
|
|
51006
51138
|
{ name: "video-model", type: "string", choices: SPRITE_VIDEO_MODEL_IDS, description: "Video model override for this operation" }
|
|
51007
51139
|
];
|
|
@@ -51221,8 +51353,8 @@ Confirm code: ${device.user_code}`);
|
|
|
51221
51353
|
else if (e.code !== "authorization_pending") throw e;
|
|
51222
51354
|
}
|
|
51223
51355
|
}
|
|
51224
|
-
throw new Error(
|
|
51225
|
-
}))).add(defineCommand("status", { description: "Show the signed-in user" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request("/api/v1/me"))))).add(defineCommand("logout", { description: "Revoke the CLI session and remove its saved credentials" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
51356
|
+
throw new Error(`Device code expired. Run auth login again. If the browser said the CLI needs a plan, choose one at ${client.origin}/app/billing first: every account starts with a 7-day Individual Starter trial, and members of a team on the Team plan are covered by it.`);
|
|
51357
|
+
}))).add(defineCommand("status", { description: "Show the signed-in user, its plan or Starter trial, and whether the CLI can act for it (agents)" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request("/api/v1/me"))))).add(defineCommand("logout", { description: "Revoke the CLI session and remove its saved credentials" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
51226
51358
|
const client = new Client(flags.url, signal);
|
|
51227
51359
|
try {
|
|
51228
51360
|
await client.request("/api/auth/sign-out", { method: "POST", body: {} });
|
|
@@ -51248,7 +51380,7 @@ Confirm code: ${device.user_code}`);
|
|
|
51248
51380
|
})))).add(defineCommand("credits", { description: "Show the selected workspace's remaining credit balance" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
51249
51381
|
const client = new Client(flags.url, signal);
|
|
51250
51382
|
out(stdout, await client.request(`/api/v1/credits${await workspaceQuery(client)}`));
|
|
51251
|
-
}))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings, speech voices and avatar types" }, (command) => command.flags({ name: "type", type: "string", choices: Object.keys(catalogSections), description: "Only one part: sprites, image, vector, video, music, speech, sfx, model or avatars" }).action(({ flags, stdout }) => {
|
|
51383
|
+
}))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings, speech voices and avatar types" }, (command) => command.flags({ name: "type", type: "string", choices: Object.keys(catalogSections), description: "Only one part: sprites, image, vector, gif, video, music, speech, sfx, model or avatars" }).action(({ flags, stdout }) => {
|
|
51252
51384
|
const full = catalog();
|
|
51253
51385
|
const section = flags.type;
|
|
51254
51386
|
out(stdout, section ? Object.fromEntries(catalogSections[section].map((key) => [key, full[key]])) : full);
|
|
@@ -51319,21 +51451,21 @@ Confirm code: ${device.user_code}`);
|
|
|
51319
51451
|
).action(async ({ args, flags, stdout, signal }) => out(stdout, await moveWork(new Client(flags.url, signal), args.id, flags))))).add(defineCommand("delete", { description: "Delete a project; requires --yes" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags({ name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
51320
51452
|
if (!flags.yes) throw new Error("Pass --yes to delete this project.");
|
|
51321
51453
|
out(stdout, await new Client(flags.url, signal).request(`/api/v1/projects/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
|
|
51322
|
-
})))).command("assets", (assets) => assets.add(defineCommand("list", { description: "List saved assets, their blob hashes, and configured generation models" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/assets`))))).add(defineCommand("generate", { description: "Generate an image, vector (SVG), video, music, speech, sound-effect or 3D model asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
51454
|
+
})))).command("assets", (assets) => assets.add(defineCommand("list", { description: "List saved assets, their blob hashes, and configured generation models" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/assets`))))).add(defineCommand("generate", { description: "Generate an image, vector (SVG), animated GIF, video, music, speech, sound-effect or 3D model asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
51323
51455
|
{ name: "type", type: "string", required: true, choices: ASSET_TYPES },
|
|
51324
51456
|
{ name: "name", type: "string", required: true },
|
|
51325
51457
|
{ name: "prompt", type: "string", description: "Description to generate, or verbatim transcript for speech; video lip-sync and relight and vector image-to-vector take none, and camera-controls, insert-video, recast, 3d-to-video, a Mureka soundtrack and a song with --lyrics (where it sets the style) may leave it out" },
|
|
51326
|
-
{ name: "model", type: "string", choices: assetModelIds, description: "Model for the chosen asset type" },
|
|
51327
|
-
{ name: "aspect-ratio", type: "string", choices: [.../* @__PURE__ */ new Set([...IMAGE_ASPECT_RATIOS, "auto", ...VIDEO_ASPECT_RATIOS, ...VECTOR_ASPECT_RATIOS])], description: "Image: 1:1 (default), 3:2, 2:3, 16:9 or 9:16; a masked edit keeps Image 1's shape. Video from text or a style without --reference: 21:9\u20139:16 (default 16:9). Extension, reference-to-video, relight and keyframes-to-video: auto (default, the inputs' shape) or a ratio to crop to. Vector from text: auto (default, the model's choice) or 1:4\u20134:1" },
|
|
51328
|
-
{ name: "transparent", type: "boolean", description: "Image: transparent background" },
|
|
51329
|
-
{ name: "references", type: "string", description: "Comma-separated blob SHAs of this project's images or sprite art, named Image 1, Image 2\u2026 in the prompt. Image: up to 4 to follow, such as a character sheet. Vector from text: up to 5, the first leading. Video: subjects or looks to keep (reference-to-video and insert-video up to 9, 3d-to-video up to 8), or recast's new people, one photo each (up to 4)" },
|
|
51458
|
+
{ name: "model", type: "string", choices: assetModelIds, description: "Model for the chosen asset type. Vector: fal/ideogram-vector (default) or fal/gpt-image-2.6-vector. GIF: fal/gpt-image-2.6-gif (default, Flare, faster) or fal/gpt-image-2.6-sunburst-gif (finer, slower)" },
|
|
51459
|
+
{ name: "aspect-ratio", type: "string", choices: [.../* @__PURE__ */ new Set([...IMAGE_ASPECT_RATIOS, "auto", ...VIDEO_ASPECT_RATIOS, ...VECTOR_ASPECT_RATIOS])], description: "Image: 1:1 (default), 3:2, 2:3, 16:9 or 9:16; a masked edit keeps Image 1's shape. Video from text or a style without --reference: 21:9\u20139:16 (default 16:9). Extension, reference-to-video, relight and keyframes-to-video: auto (default, the inputs' shape) or a ratio to crop to. Vector from text: auto (default, the model's choice) or 1:4\u20134:1 (GPT Image 2.6 1:3\u20133:1). GIF: 1:1 (default), 3:2, 2:3, 16:9 or 9:16" },
|
|
51460
|
+
{ name: "transparent", type: "boolean", description: "Image or GIF: transparent background. Vector with --model fal/gpt-image-2.6-vector: leave out the background" },
|
|
51461
|
+
{ name: "references", type: "string", description: "Comma-separated blob SHAs of this project's images, GIFs (their first frame) or sprite art, named Image 1, Image 2\u2026 in the prompt. Image: up to 4 to follow, such as a character sheet. Vector from text (Ideogram): up to 5, the first leading. GIF: up to 4 to animate or follow. Video: subjects or looks to keep (reference-to-video and insert-video up to 9, 3d-to-video up to 8), or recast's new people, one photo each (up to 4)" },
|
|
51330
51462
|
{ name: "mask", type: "string", description: "Image: edit only these rectangles of Image 1 (the first --references image), as x,y,width,height fractions of its size from the top left, up to 8 separated by semicolons; the rest is kept" },
|
|
51331
51463
|
{ name: "workflow", type: "string", choices: [...VIDEO_WORKFLOWS, ...VECTOR_WORKFLOWS], description: "Video: image-to-video (default), text-to-video or extend-video; H3 Max also reference-to-video, lip-sync, camera-controls, insert-video, recast, relight, 3d-to-video and style, FLUX 3 Max keyframes-to-video, HeyGen Video 1 and Seedance reference-to-video, as the model's videoProfiles allow. Vector: text-to-vector (default) or image-to-vector, which traces --source" },
|
|
51332
|
-
{ name: "reference", type: "string", description: "Video: starting image blob SHA from this project's assets or sprites; the speaking face for lip-sync, the image the camera moves around for camera-controls. Model: the image or sprite art to build it from (image-to-3D); without one the prompt describes it" },
|
|
51464
|
+
{ name: "reference", type: "string", description: "Video: starting image blob SHA from this project's assets (a GIF's SHA gives its first frame) or sprites; the speaking face for lip-sync, the image the camera moves around for camera-controls. Model: the image or sprite art to build it from (image-to-3D); without one the prompt describes it" },
|
|
51333
51465
|
{ name: "end-reference", type: "string", description: "Video: ending image blob SHA; models with endFrameOnly accept it without --reference" },
|
|
51334
51466
|
{ name: "middle-reference", type: "string", description: "Reference-to-video: image blob SHA reached at --middle-seconds; needs --reference and --end-reference, 480p or 768p" },
|
|
51335
51467
|
{ name: "middle-seconds", type: "number", description: "Reference-to-video: when the middle image is reached, in seconds" },
|
|
51336
|
-
{ name: "source", type: "string", description: "Blob SHA of a video asset in this project: the clip to extend, insert a scene into, recast or relight, or the 3D render 3d-to-video turns into footage. Vector image-to-vector: the image or sprite art to trace. Music with --model fal/mureka-9.5-soundtrack: the video (up to 100 MB), image or sprite art to score; a video's soundtrack runs as long as the video" },
|
|
51468
|
+
{ name: "source", type: "string", description: "Blob SHA of a video asset in this project: the clip to extend, insert a scene into, recast or relight, or the 3D render 3d-to-video turns into footage. Vector image-to-vector: the image, GIF (its first frame) or sprite art to trace. Music with --model fal/mureka-9.5-soundtrack: the video (up to 100 MB), image, GIF still or sprite art to score; a video's soundtrack runs as long as the video" },
|
|
51337
51469
|
{ name: "soundtrack", type: "string", description: "Video from an image or text: blob SHA of a music, speech or SFX asset pinned as the soundtrack (2 s or longer). Lip-sync: the speech to say (5 s\u201315 min), which sets the length" },
|
|
51338
51470
|
{ name: "audio-references", type: "string", description: "Extension or reference-to-video: up to 3 comma-separated audio asset blob SHAs (on fal and Seedance 2\u201315 s each, 15 s total; Seedance 2.5 30 s) guiding the sound; refer to them as Audio 1, Audio 2\u2026 in the prompt" },
|
|
51339
51471
|
{ name: "reference-videos", type: "string", description: "Reference-to-video or insert-video: up to 3 comma-separated video asset blob SHAs (on fal 2\u201315 s each, 15 s total; HeyGen reads the first 5 s of each) guiding motion, named Video 1, Video 2\u2026 in the prompt" },
|
|
@@ -51370,7 +51502,9 @@ Confirm code: ${device.user_code}`);
|
|
|
51370
51502
|
{ name: "splats", type: "number", description: "Model with --model idol: how many Gaussian splats, 32,768\u20131,048,576 (default 262,144)" },
|
|
51371
51503
|
{ name: "photo", type: "boolean", description: "Model with --model idol: --reference is a camera photo, cropped more loosely than a render or generated image" },
|
|
51372
51504
|
{ name: "prompt-influence", type: "number", description: "SFX: prompt adherence, 0\u20131 (default 0.3)" },
|
|
51373
|
-
{ name: "quality", type: "string", choices: VECTOR_QUALITIES, description: "Vector from text: low (fastest
|
|
51505
|
+
{ name: "quality", type: "string", choices: [.../* @__PURE__ */ new Set([...VECTOR_QUALITIES, ...GIF_QUALITIES])], description: "Vector from text: low (fastest), medium (default) or high; Ideogram 13, 16 or 20 credits (32 at high with --references), GPT Image 2.6 holds 8, 12 or 22 and is charged fal's metered tokens. GIF: low, medium (default) or high detail in every frame" },
|
|
51506
|
+
{ name: "frames", type: "number", description: `GIF: how many frames, ${GIF_FRAMES.min}\u2013${GIF_FRAMES.max} (default ${GIF_FRAMES.default}); all frames share one picture's pixels, so more frames make each smaller (catalog --type gif lists the sizes)` },
|
|
51507
|
+
{ name: "frame-ms", type: "number", description: `GIF: how long each frame shows, ${GIF_FRAME_MS.min}\u2013${GIF_FRAME_MS.max} ms (default ${GIF_FRAME_MS.default}), rounded to 10 ms` },
|
|
51374
51508
|
{ name: "shapes", type: "string", choices: VECTOR_SHAPES, description: "Vector image-to-vector (10 credits): detailed (default) keeps fine detail, simple uses fewer, simpler shapes" },
|
|
51375
51509
|
...assetAuthorizationFlags,
|
|
51376
51510
|
...assetWaitFlags,
|
|
@@ -51391,7 +51525,7 @@ Confirm code: ${device.user_code}`);
|
|
|
51391
51525
|
const result = await submitAssetBatch(new Client(flags.url, signal), args.id, await assetsFromBatchFile(flags.file, flags.model), flags, signal);
|
|
51392
51526
|
out(stdout, result);
|
|
51393
51527
|
if (result.error) throw new Error(result.error);
|
|
51394
|
-
}))).add(defineCommand("download", { description: "Download a saved asset by id; refuses to overwrite" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "asset", type: "string", required: true, description: "Asset id from assets list" }).flags({ name: "output", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await downloadAsset(new Client(flags.url, signal), args.id, args.asset, flags.output)))))).command("avatars", (avatars) => avatars.add(defineCommand("list", { description: "List HeyGen avatar characters: the public catalog, or --ownership private for this
|
|
51528
|
+
}))).add(defineCommand("download", { description: "Download a saved asset by id; refuses to overwrite" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "asset", type: "string", required: true, description: "Asset id from assets list" }).flags({ name: "output", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await downloadAsset(new Client(flags.url, signal), args.id, args.asset, flags.output)))))).command("avatars", (avatars) => avatars.add(defineCommand("list", { description: "List HeyGen avatar characters: the public catalog, or --ownership private for this workspace's own, which all its projects share" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "ownership", type: "string", choices: AVATAR_OWNERSHIPS, default: "public" }, { name: "limit", type: "number", default: 20, description: "Avatars per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}?${new URLSearchParams({ ownership: flags.ownership, limit: String(flags.limit), ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("looks", { description: "List an avatar's looks with --group, or HeyGen's public looks; a look ID is what HeyGen renders with" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string", description: "Avatar group ID: one of this workspace's or a public one" }, { name: "avatar-type", type: "string", choices: AVATAR_LOOK_TYPES }, { name: "limit", type: "number", default: 20, description: "Looks per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/looks?${new URLSearchParams({ limit: String(flags.limit), ...flags.group ? { groupId: flags.group } : {}, ...flags["avatar-type"] ? { avatarType: flags["avatar-type"] } : {}, ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("get", { description: "Show one avatar group (--group) or look (--look), with status and consent" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string" }, { name: "look", type: "string" }).action(async ({ args, flags, stdout, signal }) => {
|
|
51395
51529
|
if (Boolean(flags.group) === Boolean(flags.look)) throw new Error("Pass --group or --look.");
|
|
51396
51530
|
out(stdout, await new Client(flags.url, signal).request(flags.look ? `${avatarsPath(args.id)}/looks/${encodeURIComponent(flags.look)}` : `${avatarsPath(args.id)}/${encodeURIComponent(flags.group)}`));
|
|
51397
51531
|
}))).add(defineCommand("templates", { description: "List HeyGen Look Packs and look templates with their female and male IDs" }, (command) => command.action(({ stdout }) => out(stdout, { templates: AVATAR_LOOK_TEMPLATES })))).add(defineCommand("create", { description: "Create a HeyGen avatar from a prompt, a photo or footage (digital_twin); --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
@@ -51399,19 +51533,32 @@ Confirm code: ${device.user_code}`);
|
|
|
51399
51533
|
{ name: "name", type: "string", required: true },
|
|
51400
51534
|
{ name: "prompt", type: "string", description: "Prompt: the character, wardrobe, setting and light, up to 1000 characters" },
|
|
51401
51535
|
{ name: "aspect-ratio", type: "string", choices: AVATAR_ASPECT_RATIOS, description: "Prompt: image shape (default auto)" },
|
|
51402
|
-
{ name: "look", type: "string", description: "Prompt: one of this
|
|
51536
|
+
{ name: "look", type: "string", description: "Prompt: one of this workspace's looks to put in a new outfit or setting" },
|
|
51403
51537
|
{ name: "reference-images", type: "string", description: "Prompt: up to 3 comma-separated wardrobe or style references (project image SHA, HTTPS URL or local file)" },
|
|
51404
51538
|
{ name: "file", type: "string", description: "Photo or digital_twin: project image/video SHA, HTTPS URL (up to 32 MB) or local file (up to 8 MB)" },
|
|
51405
|
-
{ name: "group", type: "string", description: "Add the result to one of this
|
|
51539
|
+
{ name: "group", type: "string", description: "Add the result to one of this workspace's avatar groups" },
|
|
51406
51540
|
{ name: "subject-consent", type: "boolean", description: "Photo or digital_twin: confirm the person shown agreed to become an avatar" },
|
|
51407
51541
|
...assetAuthorizationFlags
|
|
51408
|
-
).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitAvatar(new Client(flags.url, signal), args.id, await avatarFromFlags(flags), flags))))).add(defineCommand("add-looks", { description: "Apply a Look Pack (five looks) or look template (two) to one of this
|
|
51409
|
-
{ name: "look", type: "string", required: true, description: "Reference look ID from this
|
|
51542
|
+
).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitAvatar(new Client(flags.url, signal), args.id, await avatarFromFlags(flags), flags))))).add(defineCommand("add-looks", { description: "Apply a Look Pack (five looks) or look template (two) to one of this workspace's looks; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
51543
|
+
{ name: "look", type: "string", required: true, description: "Reference look ID from this workspace's avatars" },
|
|
51410
51544
|
{ name: "template", type: "string", required: true, description: "Template ID from avatars templates" },
|
|
51411
51545
|
{ name: "method", type: "string", choices: AVATAR_LOOK_METHODS, description: "Needed only for templates outside the gallery" },
|
|
51412
51546
|
{ name: "aspect-ratio", type: "string", choices: LOOK_PACK_ASPECT_RATIOS, description: "Look Pack: 16:9 (default) or 9:16, cropped to portrait" },
|
|
51413
51547
|
...assetAuthorizationFlags
|
|
51414
|
-
).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitLooks(new Client(flags.url, signal), args.id, looksFromFlags(flags), flags))))).add(defineCommand("wait", { description: "Wait until HeyGen finishes a new look; fail if it fails or times out" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "look", type: "string", required: true, description: "Look ID from avatars create or add-looks" }).flags({ name: "timeout", type: "number", default: 900, description: "Maximum seconds to wait" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await waitForLook(new Client(flags.url, signal), args.id, args.look, flags.timeout, signal))))).add(defineCommand("rename", { description: "Rename one of this
|
|
51548
|
+
).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitLooks(new Client(flags.url, signal), args.id, looksFromFlags(flags), flags))))).add(defineCommand("wait", { description: "Wait until HeyGen finishes a new look; fail if it fails or times out" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "look", type: "string", required: true, description: "Look ID from avatars create or add-looks" }).flags({ name: "timeout", type: "number", default: 900, description: "Maximum seconds to wait" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await waitForLook(new Client(flags.url, signal), args.id, args.look, flags.timeout, signal))))).add(defineCommand("rename", { description: "Rename one of this workspace's photo avatar or digital twin looks" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "look", type: "string", required: true }).flags({ name: "name", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/looks/${encodeURIComponent(args.look)}`, { method: "PATCH", body: { name: flags.name } }))))).add(defineCommand("voice", { description: "Set the default voice of one of this workspace's avatars: a public voice or one of its own cloned voices" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "group", type: "string", required: true }).flags({ name: "voice", type: "string", required: true, description: "Voice ID from avatars voices" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/${encodeURIComponent(args.group)}`, { method: "PATCH", body: { defaultVoiceId: flags.voice } }))))).add(defineCommand("voices", { description: "List voices an avatar can speak with: HeyGen's public library, or --ownership private for those cloned from this workspace's digital twins" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "ownership", type: "string", choices: AVATAR_OWNERSHIPS, default: "public" }, { name: "language", type: "string", description: "Public voices in one language, such as English or Turkish" }, { name: "gender", type: "string", choices: ["male", "female"] }, { name: "limit", type: "number", default: 20, description: "Voices per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/voices?${new URLSearchParams({ ownership: flags.ownership, limit: String(flags.limit), ...flags.language ? { language: flags.language } : {}, ...flags.gender ? { gender: flags.gender } : {}, ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("video", { description: "Make a video of an avatar look speaking a script or lip-syncing saved audio, saved to the project; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
51549
|
+
{ name: "look", type: "string", required: true, description: "A completed look ID: one of this workspace's avatars or a public one" },
|
|
51550
|
+
{ name: "name", type: "string", required: true, description: "Name of the saved video" },
|
|
51551
|
+
{ name: "script", type: "string", description: `What the avatar says, up to ${AVATAR_SCRIPT_MAX} characters` },
|
|
51552
|
+
{ name: "script-file", type: "string", description: "Read the script from a UTF-8 text file" },
|
|
51553
|
+
{ name: "audio", type: "string", description: `Instead of a script: the file SHA of saved speech or music to lip-sync, up to ${AVATAR_VIDEO_MAX_SECONDS} seconds` },
|
|
51554
|
+
{ name: "voice", type: "string", description: "Voice for the script (avatars voices); the look's own voice by default" },
|
|
51555
|
+
{ name: "model", type: "string", choices: AVATAR_VIDEO_MODEL_IDS, description: "Rendering engine the look supports (default heygen/avatar-iv)" },
|
|
51556
|
+
{ name: "aspect-ratio", type: "string", choices: AVATAR_ASPECT_RATIOS, description: "auto (the look's shape, default), 16:9, 9:16, 1:1, 4:5 or 5:4" },
|
|
51557
|
+
{ name: "resolution", type: "string", choices: AVATAR_VIDEO_RESOLUTIONS, description: "720p or 1080p (default)" },
|
|
51558
|
+
{ name: "motion-prompt", type: "string", description: "Body and hand movement: photo avatars on Avatar IV, any look on Avatar V" },
|
|
51559
|
+
{ name: "expressiveness", type: "string", choices: AVATAR_EXPRESSIVENESS, description: "Photo avatars on Avatar IV: how much they move" },
|
|
51560
|
+
...assetAuthorizationFlags
|
|
51561
|
+
).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitAvatarVideo(new Client(flags.url, signal), args.id, await avatarVideoFromFlags(flags), flags))))).add(defineCommand("consent", { description: "Get a 24-hour link where the person in a digital twin records consent" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "group", type: "string", required: true }).flags({ name: "reroute-url", type: "string", description: "HTTPS page to send the person to afterwards" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/${encodeURIComponent(args.group)}/consent`, { method: "POST", body: flags["reroute-url"] ? { rerouteUrl: flags["reroute-url"] } : {} }))))).add(defineCommand("delete", { description: "Permanently delete one of this workspace's avatars (--group, with every look and its cloned voice) or one look (--look); requires --yes" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string" }, { name: "look", type: "string" }, { name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
51415
51562
|
if (Boolean(flags.group) === Boolean(flags.look)) throw new Error("Pass --group or --look.");
|
|
51416
51563
|
if (!flags.yes) throw new Error("Pass --yes to delete the avatar for good.");
|
|
51417
51564
|
out(stdout, await new Client(flags.url, signal).request(flags.look ? `${avatarsPath(args.id)}/looks/${encodeURIComponent(flags.look)}` : `${avatarsPath(args.id)}/${encodeURIComponent(flags.group)}`, { method: "DELETE" }));
|