@docyrus/animaguru 0.26.0 → 0.27.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 CHANGED
@@ -29,7 +29,7 @@ The npm package requires Node.js 24+. Its default registry is https://registry.n
29
29
 
30
30
  From this repository, `npm ci && npm run cli:build` builds the CLI and `npm run cli -- --help` runs it. `npm run cli:release` prepares the npm tarball and public Mac downloads. `npm run cli:publish` publishes that reviewed release under the Docyrus organization; publishing requires a logged-in npm account with organization access and any required 2FA. Each release needs a new version in `cli/package.json`; the CLI version is read from that file. `npm run deploy` builds release downloads before uploading the site.
31
31
 
32
- The command `animaguru schema` returns the Crust command schema, and `animaguru catalog` lists supported art styles, actions, asset types, models, video profiles and speech voices; `catalog --type music` (or `sprites`, `image`, `video`, `speech`, `sfx`, `avatars`) returns only that part. Shell completions: `animaguru completion zsh` (also bash and fish).
32
+ The command `animaguru schema` returns the Crust command schema, and `animaguru catalog` lists supported art styles, actions, asset types, models, video profiles and speech voices; `catalog --type music` (or `sprites`, `image`, `vector`, `video`, `speech`, `sfx`, `avatars`) returns only that part. Shell completions: `animaguru completion zsh` (also bash and fish).
33
33
 
34
34
  ## Required updates
35
35
 
@@ -49,6 +49,8 @@ CLI 0.25.0 adds seven contemporary motion-design styles: Aurora & Glass, Liquid
49
49
 
50
50
  CLI 0.26.0 adds `npm run export:mp4 -- --watermark`: beside the clean MP4, the export saves `SLUG-LANGUAGE-watermarked.mp4` with AnimaGuru's "Made with AnimaGuru" badge, drawn with the font, logo and layout of the web app's watermark. AnimaGuru's lead pipeline uploads it as the film's preview, so a film no longer waits for a reviewer's browser to watermark it.
51
51
 
52
+ CLI 0.27.0 adds vector assets: `--type vector` draws an editable SVG with Ideogram on fal, from a prompt (optionally following up to five saved images) or by tracing a saved image. `assets download` saves it as `.svg`. See [Vectors](#vectors).
53
+
52
54
  CLI 0.16.2 also installs `animaguru-art-motion` for Codex and Claude Code: one skill with 36 English art-treatment references and nine explainer motion grammars, plus AnimaGuru generation, timing, camera and review guidance. Request it explicitly for a custom film treatment; its references are separate from the gallery presets. Source coverage and the upstream MIT notice are included in the skill.
53
55
 
54
56
  CLI 0.5.2 includes a complete local PixiJS video workspace, now with 55 visual styles:
@@ -290,6 +292,23 @@ animaguru assets generate PROJECT_ID --type video --model fal/flux-3-max \
290
292
 
291
293
  `--keyframes` takes 1–10 `seconds,SHA` pairs, separated by semicolons, of this project's images or sprite art. Each is reached at its second, within `--seconds`; the clip has 24 frames a second and each keyframe needs a frame of its own. `--aspect-ratio auto` (default) follows the first keyframe, or give a ratio. FLUX 3 Max always works through the prompt before filming: `--prompt-expansion quality` asks for its thorough, slower level, any other value its light one. It takes `--seed`. Its dry runs are local estimates.
292
294
 
295
+ ### Vectors
296
+
297
+ CLI 0.27.0 adds vectors: editable SVG files drawn by Ideogram on fal.ai (`fal/ideogram-vector`), for logos, icons, mascots and flat illustrations that stay sharp at any size and can be animated shape by shape.
298
+
299
+ ```sh
300
+ # Draw from a prompt; --references guide the look, the first one leading.
301
+ animaguru assets generate PROJECT_ID --type vector --name "Fox mascot" \
302
+ --prompt "A friendly fox mascot waving, flat colors, bold clean outlines" \
303
+ --quality medium --aspect-ratio 1:1 --references CHARACTER_SHEET_SHA --dry-run
304
+
305
+ # Trace a saved image or sprite into shapes; it takes no prompt.
306
+ animaguru assets generate PROJECT_ID --type vector --name "Logo" \
307
+ --workflow image-to-vector --source IMAGE_SHA --shapes simple --dry-run
308
+ ```
309
+
310
+ `--workflow` is `text-to-vector` (default) or `image-to-vector`. From text, `--quality` is `low` (13 credits), `medium` (default, 16) or `high` (20, or 32 with references); `--aspect-ratio` is `auto` (default, the model's choice) or a ratio from 1:4 to 4:1 (`catalog --type vector` lists them); `--references` takes up to five of this project's images or sprite art of up to 10 MB each, named Image 1, Image 2… in the prompt; `--seed` repeats a result. `image-to-vector` traces `--source`, one of this project's images or sprite art of up to 50 MB, for 10 credits: `--shapes detailed` (default) keeps fine detail and `simple` uses fewer, simpler shapes. The result is saved as `image/svg+xml` and downloads as `NAME.svg`. Vectors can't be used as image or video references; trace or draw one from an image instead.
311
+
293
312
  Images have a full background by default; `--transparent` requests a cutout. CLI 0.17.0 adds `--references`, `--mask` and the 16:9 and 9:16 shapes. `--aspect-ratio` is 1:1 (default, 1024×1024), 3:2 (1536×1024), 2:3 (1024×1536), 16:9 (1536×864) or 9:16 (864×1536). `--references` takes up to four comma-separated blob SHAs of this project's images (including attached uploads) or sprite art, and the new image follows them: generate a character sheet once, then reference it in every scene to keep the character consistent. Refer to them in the prompt as Image 1, Image 2 and so on, and say what to take from each. Each reference adds a little to the estimate. `--mask` edits only part of Image 1, the first reference: give up to eight rectangles as `x,y,width,height` fractions of its size from the top left, separated by semicolons (`0,0,1,0.4` is the top 40%). The rest of the image is kept, and the result keeps Image 1's shape, which must be one of the five above. Gemini speech's `--prompt` is the verbatim transcript, and `--delivery` controls how it sounds without being spoken. Gemini speech supports both `gemini-3.8-flash-tts` and `gemini-3.8-flash-lite-tts`. Music uses Lyria. Google audio requires the server's `AI_PROVIDER_KEY_GOOGLE` secret; no provider keys are stored in the CLI.
294
313
 
295
314
  Preview a validated request and its estimated credits with `--dry-run`, without spending credits; most dry runs work offline without signing in:
@@ -312,7 +331,7 @@ animaguru assets submit PROJECT_ID --file speech.json --model gemini-3.8-flash-t
312
331
 
313
332
  `--model` overrides the file's model. Unrelated type-specific flags are rejected rather than ignored, and the error lists the flags that type accepts.
314
333
 
315
- `assets generate` and `assets submit` accept `--wait` to block until the job finishes (failing if generation fails) and `--download PATH` to wait and then save the result; `--timeout` sets the wait in seconds (default 600). A `PATH` that is an existing folder or ends in `/` receives `NAME.EXT`, named after the asset and its type (`.wav`, `.mp3`, `.png`…). The JSON output adds `job`, `asset` (`id`, `name`, `type`, `mimeType`) and `download` (`path`, `size`) to the submission receipt.
334
+ `assets generate` and `assets submit` accept `--wait` to block until the job finishes (failing if generation fails) and `--download PATH` to wait and then save the result; `--timeout` sets the wait in seconds (default 600). A `PATH` that is an existing folder or ends in `/` receives `NAME.EXT`, named after the asset and its type (`.wav`, `.mp3`, `.png`, `.svg`…). The JSON output adds `job`, `asset` (`id`, `name`, `type`, `mimeType`) and `download` (`path`, `size`) to the submission receipt.
316
335
 
317
336
  ```sh
318
337
  animaguru assets generate PROJECT_ID --type speech --name vo-01-hook \
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.26.0",
19764
+ version: "0.27.0",
19765
19765
  description: "Agent-friendly AnimaGuru CLI built with CrustJS",
19766
19766
  type: "module",
19767
19767
  bin: {
@@ -46726,7 +46726,7 @@ async function createAnimation(options) {
46726
46726
  }
46727
46727
 
46728
46728
  // shared/assets.ts
46729
- var ASSET_TYPES = ["image", "video", "music", "speech", "sfx"];
46729
+ var ASSET_TYPES = ["image", "vector", "video", "music", "speech", "sfx"];
46730
46730
  var SPEECH_MODELS = [
46731
46731
  { id: "gemini-3.8-flash-tts", label: "Gemini 3.8 Flash TTS" },
46732
46732
  { id: "gemini-3.8-flash-lite-tts", label: "Gemini 3.8 Flash-Lite TTS" },
@@ -46979,6 +46979,49 @@ var imageAsset = external_exports.object({
46979
46979
  var imageChecks = (p, ctx) => {
46980
46980
  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"] });
46981
46981
  };
46982
+ var VECTOR_MODELS = [{ id: "fal/ideogram-vector", label: "Ideogram Vector (fal)" }];
46983
+ var VECTOR_WORKFLOWS = ["text-to-vector", "image-to-vector"];
46984
+ var VECTOR_QUALITIES = ["low", "medium", "high"];
46985
+ 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"];
46986
+ var VECTOR_SHAPES = ["detailed", "simple"];
46987
+ var MAX_VECTOR_REFERENCES = 5;
46988
+ var VECTOR_REFERENCE_MAX_BYTES = 10 * 1024 * 1024;
46989
+ var VECTOR_SOURCE_MAX_BYTES = 50 * 1024 * 1024;
46990
+ var vectorAsset = external_exports.object({
46991
+ name: base.name,
46992
+ /** Image-to-vector takes no prompt. */
46993
+ prompt: external_exports.string().trim().max(4e3).default(""),
46994
+ type: external_exports.literal("vector"),
46995
+ model: external_exports.literal("fal/ideogram-vector").default("fal/ideogram-vector"),
46996
+ workflow: external_exports.enum(VECTOR_WORKFLOWS).default("text-to-vector"),
46997
+ /** Text-to-vector; defaults to medium. */
46998
+ quality: external_exports.enum(VECTOR_QUALITIES).optional(),
46999
+ /** Text-to-vector; defaults to auto. */
47000
+ aspectRatio: external_exports.enum(VECTOR_ASPECT_RATIOS).optional(),
47001
+ /** Text-to-vector: saved images or sprite art to follow, the first being the main one. */
47002
+ references: external_exports.array(blob).max(MAX_VECTOR_REFERENCES).default([]),
47003
+ /** Image-to-vector: the saved image or sprite art to trace. */
47004
+ source: blob.optional(),
47005
+ /** Image-to-vector; defaults to detailed. */
47006
+ shapes: external_exports.enum(VECTOR_SHAPES).optional(),
47007
+ /** Text-to-vector. */
47008
+ seed: external_exports.number().int().min(0).max(2 ** 32 - 1).optional()
47009
+ });
47010
+ function vectorChecks(p, ctx) {
47011
+ const issue2 = (path, message) => ctx.addIssue({ code: "custom", message, path: [path] });
47012
+ if (new Set(p.references).size !== p.references.length) issue2("references", "Choose each reference image once.");
47013
+ if (p.workflow === "text-to-vector") {
47014
+ if (p.prompt.length < 3) issue2("prompt", "Describe the vector in at least 3 characters.");
47015
+ if (p.source) issue2("source", "Only image-to-vector traces a saved image; use references to guide text-to-vector.");
47016
+ if (p.shapes) issue2("shapes", "Only image-to-vector takes shapes.");
47017
+ return;
47018
+ }
47019
+ if (p.prompt) issue2("prompt", "image-to-vector takes no prompt; leave it out.");
47020
+ if (!p.source) issue2("source", "Choose a saved image or sprite to trace.");
47021
+ 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.`);
47022
+ if (p.references.length) issue2("references", "image-to-vector traces its source alone and takes no references.");
47023
+ }
47024
+ var vectorDefaults = (p) => p.workflow === "text-to-vector" ? { ...p, quality: p.quality ?? "medium", aspectRatio: p.aspectRatio ?? "auto" } : { ...p, shapes: p.shapes ?? "detailed" };
46982
47025
  var assetRequest = external_exports.discriminatedUnion("type", [
46983
47026
  imageAsset.superRefine(imageChecks),
46984
47027
  videoAsset.superRefine(videoChecks).transform(videoDefaults),
@@ -46987,7 +47030,8 @@ var assetRequest = external_exports.discriminatedUnion("type", [
46987
47030
  if (p.voice && (isElevenLabsSpeech(p.model) ? !/^[a-zA-Z0-9]{20}$/.test(p.voice) : !SPEECH_VOICES.includes(p.voice))) ctx.addIssue({ code: "custom", message: "Choose a voice supported by the speech provider.", path: ["voice"] });
46988
47031
  if (isElevenLabsSpeech(p.model) && p.delivery) ctx.addIssue({ code: "custom", message: "ElevenLabs uses audio tags in the transcript; separate delivery instructions are only supported by Gemini.", path: ["delivery"] });
46989
47032
  }).transform((p) => ({ ...p, voice: p.voice || (isElevenLabsSpeech(p.model) ? DEFAULT_ELEVENLABS_VOICE : "Kore") })),
46990
- 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) })
47033
+ 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) }),
47034
+ vectorAsset.superRefine(vectorChecks).transform(vectorDefaults)
46991
47035
  ]);
46992
47036
  var assetGenerationRequest = external_exports.discriminatedUnion("type", [imageAsset.omit({ model: true }).superRefine(imageChecks), ...assetRequest.options.slice(1)]);
46993
47037
  var LIBRARY_AUDIO_MODEL = "library-audio";
@@ -46997,6 +47041,7 @@ var uploadedMedia = external_exports.object({ name: base.name, prompt: external_
46997
47041
  var savedAssetOptions = external_exports.union([assetRequest, libraryAudio, uploadedMedia]);
46998
47042
  var speechCharacters = (text2) => Array.from(text2).length;
46999
47043
  var imageEstimate = (p) => Math.ceil((130 + 40 * p.references.length) * spriteImageModel(p.model).relCost);
47044
+ var vectorEstimate = (p) => p.workflow === "image-to-vector" ? 100 : p.quality === "low" ? 130 : p.quality === "high" ? p.references.length ? 320 : 200 : 160;
47000
47045
  function videoExtras(p, facts = {}) {
47001
47046
  const w = p.workflow;
47002
47047
  if (w !== "reference-to-video" && w !== "insert-video" && w !== "3d-to-video") return {};
@@ -47008,6 +47053,7 @@ function videoExtras(p, facts = {}) {
47008
47053
  }
47009
47054
  function assetEstimate(p, now = Date.now()) {
47010
47055
  if (p.type === "image") return imageEstimate(p);
47056
+ if (p.type === "vector") return vectorEstimate(p);
47011
47057
  if (p.type === "video") return spriteVideoEstimate(spriteVideoModel(p.model), p, videoExtras(p));
47012
47058
  if (p.type === "music") return 80;
47013
47059
  const units = (credits) => Math.max(1, Math.ceil(credits * UNITS_PER_CREDIT));
@@ -48242,7 +48288,8 @@ var extras = {
48242
48288
  ],
48243
48289
  music: [],
48244
48290
  speech: ["voice", "delivery"],
48245
- sfx: ["seconds", "loop", "prompt-influence"]
48291
+ sfx: ["seconds", "loop", "prompt-influence"],
48292
+ vector: ["workflow", "references", "source", "aspect-ratio", "quality", "shapes", "seed"]
48246
48293
  };
48247
48294
  var list2 = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
48248
48295
  function accepted(type) {
@@ -48279,7 +48326,7 @@ function assetFromFlags(flags) {
48279
48326
  const value = flags[name2];
48280
48327
  if (value !== void 0 && value !== false && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets. ${accepted(flags.type)}`.trim());
48281
48328
  }
48282
- if (flags.type !== "video" && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets.`);
48329
+ if (flags.type !== "video" && flags.type !== "vector" && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets.`);
48283
48330
  const base2 = { type: flags.type, name: flags.name, prompt: flags.prompt, model: flags.model };
48284
48331
  if (flags.type === "image") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], transparent: flags.transparent, references: shas(flags.references), mask: regions(flags.mask) });
48285
48332
  if (flags.type === "video") {
@@ -48317,6 +48364,7 @@ function assetFromFlags(flags) {
48317
48364
  });
48318
48365
  }
48319
48366
  if (flags.type === "sfx") return parseAsset({ ...base2, seconds: flags.seconds, loop: flags.loop, promptInfluence: flags["prompt-influence"] });
48367
+ 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 });
48320
48368
  return parseAsset({ ...base2, ...flags.type === "speech" ? { voice: flags.voice, delivery: flags.delivery } : {} });
48321
48369
  }
48322
48370
  async function assetFromFile(file2, model) {
@@ -48412,6 +48460,7 @@ var MIME_EXTENSIONS = {
48412
48460
  "image/png": "png",
48413
48461
  "image/jpeg": "jpg",
48414
48462
  "image/webp": "webp",
48463
+ "image/svg+xml": "svg",
48415
48464
  "video/mp4": "mp4",
48416
48465
  "video/webm": "webm"
48417
48466
  };
@@ -50295,7 +50344,7 @@ async function curl(options, io) {
50295
50344
  }
50296
50345
 
50297
50346
  // cli/src/commands.ts
50298
- var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id)];
50347
+ 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)];
50299
50348
  var assetAuthorizationFlags = [
50300
50349
  { name: "yes", type: "boolean", description: "Authorize spending credits" },
50301
50350
  { name: "dry-run", type: "boolean", description: "Validate and estimate locally without submitting a paid job" }
@@ -50307,13 +50356,14 @@ var assetWaitFlags = [
50307
50356
  var catalogSections = {
50308
50357
  sprites: ["styles", "kinds", "actions", "videoModels"],
50309
50358
  image: ["assetTypes"],
50359
+ vector: ["assetTypes", "vectorModels", "vectorOptions"],
50310
50360
  video: ["assetTypes", "videoModels", "videoProfiles"],
50311
50361
  music: ["assetTypes", "musicModels"],
50312
50362
  speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices"],
50313
50363
  sfx: ["assetTypes", "sfxModels"],
50314
50364
  avatars: ["avatarTypes", "avatarLookTypes"]
50315
50365
  };
50316
- 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), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
50366
+ 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), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), 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, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
50317
50367
  var modelFlags = [
50318
50368
  { name: "video-model", type: "string", choices: SPRITE_VIDEO_MODEL_IDS, description: "Video model override for this operation" }
50319
50369
  ];
@@ -50542,7 +50592,7 @@ Confirm code: ${device.user_code}`);
50542
50592
  })))).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 }) => {
50543
50593
  const client = new Client(flags.url, signal);
50544
50594
  out(stdout, await client.request(`/api/v1/credits${await workspaceQuery(client)}`));
50545
- }))).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, video, music, speech, sfx or avatars" }).action(({ flags, stdout }) => {
50595
+ }))).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 or avatars" }).action(({ flags, stdout }) => {
50546
50596
  const full = catalog();
50547
50597
  const section = flags.type;
50548
50598
  out(stdout, section ? Object.fromEntries(catalogSections[section].map((key) => [key, full[key]])) : full);
@@ -50609,21 +50659,21 @@ Confirm code: ${device.user_code}`);
50609
50659
  ).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 }) => {
50610
50660
  if (!flags.yes) throw new Error("Pass --yes to delete this project.");
50611
50661
  out(stdout, await new Client(flags.url, signal).request(`/api/v1/projects/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
50612
- })))).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, video, music, speech or sound-effect asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
50662
+ })))).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 or sound-effect asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
50613
50663
  { name: "type", type: "string", required: true, choices: ASSET_TYPES },
50614
50664
  { name: "name", type: "string", required: true },
50615
- { name: "prompt", type: "string", description: "Description to generate, or verbatim transcript for speech; video lip-sync and relight take none, and camera-controls, insert-video, recast and 3d-to-video may leave it out" },
50665
+ { 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 and 3d-to-video may leave it out" },
50616
50666
  { name: "model", type: "string", choices: assetModelIds, description: "Model for the chosen asset type" },
50617
- { name: "aspect-ratio", type: "string", choices: [.../* @__PURE__ */ new Set([...IMAGE_ASPECT_RATIOS, "auto", ...VIDEO_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" },
50667
+ { 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" },
50618
50668
  { name: "transparent", type: "boolean", description: "Image: transparent background" },
50619
- { 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. 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)" },
50669
+ { 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)" },
50620
50670
  { 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" },
50621
- { name: "workflow", type: "string", choices: VIDEO_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, as the model's videoProfiles allow" },
50671
+ { 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, as the model's videoProfiles allow. Vector: text-to-vector (default) or image-to-vector, which traces --source" },
50622
50672
  { 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" },
50623
50673
  { name: "end-reference", type: "string", description: "Video: ending image blob SHA; models with endFrameOnly accept it without --reference" },
50624
50674
  { name: "middle-reference", type: "string", description: "Reference-to-video: image blob SHA reached at --middle-seconds; needs --reference and --end-reference, 480p or 768p" },
50625
50675
  { name: "middle-seconds", type: "number", description: "Reference-to-video: when the middle image is reached, in seconds" },
50626
- { 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" },
50676
+ { 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" },
50627
50677
  { 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" },
50628
50678
  { name: "audio-references", type: "string", description: "Extension or reference-to-video: up to 3 comma-separated audio asset blob SHAs (2\u201315 s each, 15 s total) guiding the sound; refer to them as Audio 1, Audio 2\u2026 in the prompt" },
50629
50679
  { name: "reference-videos", type: "string", description: "Reference-to-video or insert-video: up to 3 comma-separated video asset blob SHAs (2\u201315 s each, 15 s total) guiding motion, named Video 1, Video 2\u2026 in the prompt" },
@@ -50643,12 +50693,14 @@ Confirm code: ${device.user_code}`);
50643
50693
  { name: "resolution", type: "string", choices: VIDEO_RESOLUTIONS, description: "Video resolution supported by the selected model and workflow (default its first)" },
50644
50694
  { name: "mode", type: "string", choices: ["cost", "speed", "quality"], description: "Video generation mode supported by the selected model (default its first)" },
50645
50695
  { name: "prompt-expansion", type: "string", choices: PROMPT_EXPANSION_MODES, description: "Video: how much the model may rewrite the prompt (default disabled); extensions treat any other value as on. FLUX 3 Max always reasons about the prompt: quality thoroughly, any other value lightly" },
50646
- { name: "seed", type: "number", description: "Video: seed for repeatable results, where the model takes one" },
50696
+ { name: "seed", type: "number", description: "Video or vector from text: seed for repeatable results, where the model takes one" },
50647
50697
  { name: "extend-output", type: "string", choices: EXTEND_OUTPUTS, description: "Extension: extended (default, source plus new footage) or continuation (a 1.625 s overlap, then the new footage)" },
50648
50698
  { name: "voice", type: "string", description: "Gemini voice name or ElevenLabs voice ID (defaults: Kore / George)" },
50649
50699
  { name: "delivery", type: "string", description: "Gemini speech delivery instructions; ElevenLabs uses audio tags in the transcript" },
50650
50700
  { name: "loop", type: "boolean", description: "SFX: create a seamless loop" },
50651
50701
  { name: "prompt-influence", type: "number", description: "SFX: prompt adherence, 0\u20131 (default 0.3)" },
50702
+ { name: "quality", type: "string", choices: VECTOR_QUALITIES, description: "Vector from text: low (fastest, 13 credits), medium (default, 16) or high (20, or 32 with --references)" },
50703
+ { name: "shapes", type: "string", choices: VECTOR_SHAPES, description: "Vector image-to-vector (10 credits): detailed (default) keeps fine detail, simple uses fewer, simpler shapes" },
50652
50704
  ...assetAuthorizationFlags,
50653
50705
  ...assetWaitFlags,
50654
50706
  { name: "download", type: "string", description: "Wait, then save the result to this file, or into this folder (existing, or ending in /) as NAME.EXT; never overwrites" }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docyrus/animaguru",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Agent-friendly AnimaGuru CLI built with CrustJS",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@ Before creative work in a multi-animation workspace, select or create the intend
17
17
 
18
18
  Share the [animation-style gallery](https://animaguru.com/animation-styles), or open that URL in the internal browser when available, while asking the user to choose a style. Read the installed `animaguru.templates.json` for available styles and their skill names; `animaguru templates` lists the current CLI catalog. Offer the local catalog's choices so users select a skill actually installed in their workspace. Templates define appearance and motion; derive audience, message and story from the brief. Local scaffolding is separate from `projects create`, which creates a remote asset project. Never run `create` over an existing workspace.
19
19
 
20
- - Run `animaguru schema` for the installed command structure and flags, and `animaguru catalog` for styles, subject kinds, actions, asset types, models, video settings, and speech voices; `catalog --type music|speech|sfx|image|video|sprites|avatars` prints one section. Use `--help` on a leaf command for details.
20
+ - Run `animaguru schema` for the installed command structure and flags, and `animaguru catalog` for styles, subject kinds, actions, asset types, models, video settings, and speech voices; `catalog --type music|speech|sfx|image|vector|video|sprites|avatars` prints one section. Use `--help` on a leaf command for details.
21
21
  - Check `animaguru auth status`, `animaguru workspaces list`, and `animaguru credits` before generation. If sign-in is needed, run `animaguru auth login --no-browser` and let the user approve the printed browser URL. Select the user's requested Personal or team workspace with `animaguru workspaces use personal|TEAM_ID` before listing or creating projects. Do not read or print stored credentials. Agent runners may inject `ANIMAGURU_TOKEN` and `ANIMAGURU_WORKSPACE` as secrets or configuration.
22
22
  - The default service is `https://animaguru.com`. Respect an existing `ANIMAGURU_URL` or pass `--url` to the leaf command when the user chooses another service. HTTP is supported only for loopback development.
23
23
 
@@ -65,6 +65,15 @@ Images use the staff-managed route automatically. Use `--model` to select a mode
65
65
 
66
66
  For ElevenLabs speech, choose `eleven_v4` or `eleven_v4_turbo`, pass an ElevenLabs voice ID with `--voice` (George is the default), and put audio tags in `--prompt` rather than using `--delivery`. For sound effects, use `--type sfx`; the only model is `eleven_text_to_sound_v2`. SFX supports `--seconds` from 0.5 to 30 (default 5), `--loop`, and `--prompt-influence` from 0 to 1 (default 0.3). These additions require CLI 0.5.0 or newer; check `catalog` before using them with an installed CLI.
67
67
 
68
+ CLI 0.27.0 adds vectors: `--type vector` draws an editable SVG with Ideogram on fal (`fal/ideogram-vector`), for logos, icons, mascots and flat illustrations that must stay sharp at any size or move shape by shape. `--workflow text-to-vector` (default) draws `--prompt` at `--quality low|medium|high` (13, 16 or 20 credits; 32 at high with references), with `--aspect-ratio auto` (default) or 1:4–4:1, `--seed`, and up to five `--references` (this project's images or sprite art, the first leading, named Image 1… in the prompt). `--workflow image-to-vector --source IMAGE_SHA` traces a saved image or sprite for 10 credits, with `--shapes detailed|simple` and no `--prompt`; to vectorize a brand logo or a generated picture, save it as an image asset first. `--download` saves `NAME.svg`. Vectors can't be used as image or video references. Check `catalog --type vector` before using them with an installed CLI.
69
+
70
+ ```sh
71
+ animaguru assets generate PROJECT_ID --type vector --name "Fox mascot" \
72
+ --prompt "A friendly fox mascot waving, flat colors, bold clean outlines" --quality medium --dry-run
73
+ animaguru assets generate PROJECT_ID --type vector --name "Logo" \
74
+ --workflow image-to-vector --source IMAGE_SHA --shapes simple --dry-run
75
+ ```
76
+
68
77
  Use `--dry-run` for local request validation and estimated credits without sign-in or paid work. The estimate does not prove the server has the provider, the credits, or the reference image. Use `--yes` only within the user's existing spending authorization. For file-based requests, write the API asset request as JSON and use `assets submit PROJECT_ID --file asset.json --yes`; `--model` overrides the file's selection for non-image assets. Image model fields in old files are ignored.
69
78
 
70
79
  Add `--download PATH` to `assets generate` or `assets submit` to wait for the job and save the result in one call; a folder PATH (existing or ending in `/`) receives `NAME.EXT`, and existing files are never overwritten. `--wait` waits without downloading; `--timeout` sets the limit (default 600 s). For several assets, such as one speech file per voiceover line, write `{"defaults": {"type": "speech", "model": "…", "voice": "…", "delivery": "…"}, "assets": [{"name": "vo-01-hook", "prompt": "…"}]}` and run `assets batch PROJECT_ID --file lines.json --dry-run`, then `--yes --download production/audio/vo/`. Every item is validated before anything is submitted. If a submission fails, the batch stops and prints the receipts already submitted; check those (and `jobs list`) instead of resubmitting. Older CLIs lack these flags: check `--help`, and otherwise use `jobs wait PROJECT_ID JOB_ID`, read the asset id from `assets list` and download with `assets download PROJECT_ID ASSET_ID --output welcome.wav`, or export the complete project ZIP.
@@ -93,6 +93,10 @@ Before choreographing a scene from scratch, search the AnimaGuru motion library
93
93
 
94
94
  Pro and Team accounts can take ready-made music, sound effects, voice-overs, clips, images and sprites from the AnimaGuru asset library instead of generating them: `animaguru library search DESCRIPTION --type music|sfx|speech|video|image|sprite` (natural language and keywords). `animaguru library download ID --output public/assets/` saves a file into the film (sprites save their sheets with `animation.json` frame rectangles and timing); `animaguru library import ID --project PROJECT_ID` adds it to an AnimaGuru project's assets instead. Prefer a library whoosh or background track over generating one; it spends no credits.
95
95
 
96
+ ## Vectors
97
+
98
+ Logos, icons and flat mascots can be generated as SVG (`animaguru assets generate PROJECT_ID --type vector …`, see the `animaguru` skill) or traced from a saved image (`--workflow image-to-vector`), then saved into the film with `--download public/assets/`. Draw one with the kit's `rasterSvg(url, width)` at the width it appears on screen, so it stays sharp; for shapes that scale or move separately, load it as geometry with `Assets.load({ src, data: { parseAsGraphicsContext: true } })` and `new Graphics(context)` (see `pixijs-assets`). Ask for `--shapes simple` or `--quality low` when the art will be small or animated part by part.
99
+
96
100
  ## Voiceover, music and captions
97
101
 
98
102
  1. Generate the lines in one call: a batch file with shared speech defaults and one `{ name, prompt }` per segment, `animaguru assets batch PROJECT_ID --file production/generation/vo-lines.json --dry-run`, then `--yes --download production/audio/vo/`. Generate music with `assets generate … --type music --yes --download production/audio/music/`. See the `animaguru` skill for authorization.