@docyrus/animaguru 0.20.0 → 0.23.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/NOTICE.md +25 -1
- package/README.md +32 -3
- package/dist/animaguru.js +430 -253
- package/package.json +1 -1
- package/skills/animaguru/SKILL.md +1 -1
- package/skills/animaguru-archive-light-table/SKILL.md +34 -0
- package/skills/animaguru-archive-light-table/references/recipe.md +26 -0
- package/skills/animaguru-briefing-board/SKILL.md +34 -0
- package/skills/animaguru-briefing-board/references/recipe.md +27 -0
- package/skills/animaguru-data-physicalization/SKILL.md +34 -0
- package/skills/animaguru-data-physicalization/references/recipe.md +27 -0
- package/skills/animaguru-exploded-teardown/SKILL.md +34 -0
- package/skills/animaguru-exploded-teardown/references/recipe.md +27 -0
- package/skills/animaguru-lidar-survey/SKILL.md +34 -0
- package/skills/animaguru-lidar-survey/references/recipe.md +26 -0
- package/skills/animaguru-machine-anatomy/LICENSE +21 -0
- package/skills/animaguru-machine-anatomy/SKILL.md +42 -0
- package/skills/animaguru-machine-anatomy/references/craft.md +97 -0
- package/skills/animaguru-machine-anatomy/references/recipe.md +52 -0
- package/skills/animaguru-microscope-story/SKILL.md +34 -0
- package/skills/animaguru-microscope-story/references/recipe.md +26 -0
- package/skills/animaguru-satellite-briefing/SKILL.md +34 -0
- package/skills/animaguru-satellite-briefing/references/recipe.md +27 -0
- package/skills/animaguru-white-model-projection/SKILL.md +34 -0
- package/skills/animaguru-white-model-projection/references/recipe.md +27 -0
- package/templates/video/README.md +1 -1
- package/templates/video/VIDEO-STYLE-NOTICES.txt +25 -1
- package/templates/video/shared/locales/en/style-studies.json +73 -0
- package/templates/video/src/kit/anatomy/LICENSE +21 -0
- package/templates/video/src/kit/anatomy/iso-kit.ts +842 -0
- package/templates/video/src/kit/anatomy/palette.ts +41 -0
- package/templates/video/src/kit/anatomy/pixi.ts +43 -0
- package/templates/video/src/player.ts +20 -0
- package/templates/video/src/studies/anatomy-plotter.ts +179 -0
- package/templates/video/src/studies/scenes.ts +171 -0
- package/templates/video/src/style.css +19 -3
- package/templates/video/style-source-provenance.json +7 -2
package/dist/animaguru.js
CHANGED
|
@@ -2312,8 +2312,8 @@ var require_lib = __commonJS({
|
|
|
2312
2312
|
if (typeof cb !== "function") {
|
|
2313
2313
|
opts = cb;
|
|
2314
2314
|
cb = null;
|
|
2315
|
-
deferred = new this.Promise(function(
|
|
2316
|
-
deferredResolve =
|
|
2315
|
+
deferred = new this.Promise(function(resolve18, reject) {
|
|
2316
|
+
deferredResolve = resolve18;
|
|
2317
2317
|
deferredReject = reject;
|
|
2318
2318
|
});
|
|
2319
2319
|
}
|
|
@@ -2461,17 +2461,17 @@ var require_lib = __commonJS({
|
|
|
2461
2461
|
if (typeof cb === "function") {
|
|
2462
2462
|
fnx(cb);
|
|
2463
2463
|
} else {
|
|
2464
|
-
return new this.Promise(function(
|
|
2464
|
+
return new this.Promise(function(resolve18, reject) {
|
|
2465
2465
|
if (fnx.length === 1) {
|
|
2466
2466
|
fnx(function(err2, ret) {
|
|
2467
2467
|
if (err2) {
|
|
2468
2468
|
reject(err2);
|
|
2469
2469
|
} else {
|
|
2470
|
-
|
|
2470
|
+
resolve18(ret);
|
|
2471
2471
|
}
|
|
2472
2472
|
});
|
|
2473
2473
|
} else {
|
|
2474
|
-
|
|
2474
|
+
resolve18(fnx());
|
|
2475
2475
|
}
|
|
2476
2476
|
});
|
|
2477
2477
|
}
|
|
@@ -6862,7 +6862,7 @@ var require_pify = __commonJS({
|
|
|
6862
6862
|
"use strict";
|
|
6863
6863
|
var processFn = (fn, options) => function(...args) {
|
|
6864
6864
|
const P = options.promiseModule;
|
|
6865
|
-
return new P((
|
|
6865
|
+
return new P((resolve18, reject) => {
|
|
6866
6866
|
if (options.multiArgs) {
|
|
6867
6867
|
args.push((...result) => {
|
|
6868
6868
|
if (options.errorFirst) {
|
|
@@ -6870,10 +6870,10 @@ var require_pify = __commonJS({
|
|
|
6870
6870
|
reject(result);
|
|
6871
6871
|
} else {
|
|
6872
6872
|
result.shift();
|
|
6873
|
-
|
|
6873
|
+
resolve18(result);
|
|
6874
6874
|
}
|
|
6875
6875
|
} else {
|
|
6876
|
-
|
|
6876
|
+
resolve18(result);
|
|
6877
6877
|
}
|
|
6878
6878
|
});
|
|
6879
6879
|
} else if (options.errorFirst) {
|
|
@@ -6881,11 +6881,11 @@ var require_pify = __commonJS({
|
|
|
6881
6881
|
if (error62) {
|
|
6882
6882
|
reject(error62);
|
|
6883
6883
|
} else {
|
|
6884
|
-
|
|
6884
|
+
resolve18(result);
|
|
6885
6885
|
}
|
|
6886
6886
|
});
|
|
6887
6887
|
} else {
|
|
6888
|
-
args.push(
|
|
6888
|
+
args.push(resolve18);
|
|
6889
6889
|
}
|
|
6890
6890
|
fn.apply(this, args);
|
|
6891
6891
|
});
|
|
@@ -11400,7 +11400,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11400
11400
|
} catch (err22) {
|
|
11401
11401
|
if (err22 === null || err22.code === "EEXIST") return;
|
|
11402
11402
|
if (err22.code === "ENOENT" && attempt < retries) {
|
|
11403
|
-
await new Promise((
|
|
11403
|
+
await new Promise((resolve18) => setTimeout(resolve18, 0));
|
|
11404
11404
|
continue;
|
|
11405
11405
|
}
|
|
11406
11406
|
throw err22;
|
|
@@ -14616,9 +14616,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14616
14616
|
throw Error("You cannot write to a FIFO that has already been ended!");
|
|
14617
14617
|
}
|
|
14618
14618
|
if (this._waiting) {
|
|
14619
|
-
const
|
|
14619
|
+
const resolve18 = this._waiting;
|
|
14620
14620
|
this._waiting = null;
|
|
14621
|
-
|
|
14621
|
+
resolve18({ value: chunk });
|
|
14622
14622
|
} else {
|
|
14623
14623
|
this._queue.push(chunk);
|
|
14624
14624
|
}
|
|
@@ -14626,9 +14626,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14626
14626
|
end() {
|
|
14627
14627
|
this._ended = true;
|
|
14628
14628
|
if (this._waiting) {
|
|
14629
|
-
const
|
|
14629
|
+
const resolve18 = this._waiting;
|
|
14630
14630
|
this._waiting = null;
|
|
14631
|
-
|
|
14631
|
+
resolve18({ done: true });
|
|
14632
14632
|
}
|
|
14633
14633
|
}
|
|
14634
14634
|
destroy(err2) {
|
|
@@ -14647,8 +14647,8 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14647
14647
|
"You cannot call read until the previous call to read has returned!"
|
|
14648
14648
|
);
|
|
14649
14649
|
}
|
|
14650
|
-
return new Promise((
|
|
14651
|
-
this._waiting =
|
|
14650
|
+
return new Promise((resolve18) => {
|
|
14651
|
+
this._waiting = resolve18;
|
|
14652
14652
|
});
|
|
14653
14653
|
}
|
|
14654
14654
|
};
|
|
@@ -14803,7 +14803,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14803
14803
|
const acks = [];
|
|
14804
14804
|
let nak = false;
|
|
14805
14805
|
let done = false;
|
|
14806
|
-
return new Promise((
|
|
14806
|
+
return new Promise((resolve18, reject) => {
|
|
14807
14807
|
forAwait2(packetlines, (data) => {
|
|
14808
14808
|
const line = data.toString("utf8").trim();
|
|
14809
14809
|
if (line.startsWith("shallow")) {
|
|
@@ -14830,11 +14830,11 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14830
14830
|
nak = true;
|
|
14831
14831
|
}
|
|
14832
14832
|
if (done) {
|
|
14833
|
-
stream.error ? reject(stream.error) :
|
|
14833
|
+
stream.error ? reject(stream.error) : resolve18({ shallows, unshallows, acks, nak, packfile, progress });
|
|
14834
14834
|
}
|
|
14835
14835
|
}).finally(() => {
|
|
14836
14836
|
if (!done) {
|
|
14837
|
-
stream.error ? reject(stream.error) :
|
|
14837
|
+
stream.error ? reject(stream.error) : resolve18({ shallows, unshallows, acks, nak, packfile, progress });
|
|
14838
14838
|
}
|
|
14839
14839
|
});
|
|
14840
14840
|
});
|
|
@@ -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.23.0",
|
|
19765
19765
|
description: "Agent-friendly AnimaGuru CLI built with CrustJS",
|
|
19766
19766
|
type: "module",
|
|
19767
19767
|
bin: {
|
|
@@ -24295,8 +24295,8 @@ var version = defineExtension(VERSION).factory((extension, value, options = {})
|
|
|
24295
24295
|
|
|
24296
24296
|
// cli/src/commands.ts
|
|
24297
24297
|
import { spawn as spawn3 } from "node:child_process";
|
|
24298
|
-
import { mkdir as mkdir15, readFile as
|
|
24299
|
-
import { dirname as dirname14, resolve as
|
|
24298
|
+
import { mkdir as mkdir15, readFile as readFile19, writeFile as writeFile16 } from "node:fs/promises";
|
|
24299
|
+
import { dirname as dirname14, resolve as resolve17 } from "node:path";
|
|
24300
24300
|
import { setTimeout as delay6 } from "node:timers/promises";
|
|
24301
24301
|
|
|
24302
24302
|
// node_modules/fflate/esm/index.mjs
|
|
@@ -25339,13 +25339,14 @@ var SPRITE_IMAGE_MODEL_IDS = SPRITE_IMAGE_MODELS.map((m) => m.id);
|
|
|
25339
25339
|
function spriteImageModel(id2) {
|
|
25340
25340
|
return SPRITE_IMAGE_MODELS.find((m) => m.id === id2) ?? SPRITE_IMAGE_MODELS[0];
|
|
25341
25341
|
}
|
|
25342
|
-
var VIDEO_WORKFLOWS = ["image-to-video", "text-to-video", "extend-video", "reference-to-video", "lip-sync", "camera-controls", "insert-video", "recast", "relight", "3d-to-video", "style"];
|
|
25342
|
+
var VIDEO_WORKFLOWS = ["image-to-video", "text-to-video", "extend-video", "reference-to-video", "lip-sync", "camera-controls", "insert-video", "recast", "relight", "3d-to-video", "style", "keyframes-to-video"];
|
|
25343
25343
|
var STUDIO_VIDEO_WORKFLOWS = ["image-to-video", "text-to-video", "extend-video"];
|
|
25344
25344
|
var MEDIA_LENGTH_WORKFLOWS = ["lip-sync", "recast", "relight", "3d-to-video"];
|
|
25345
25345
|
var lengthFromMedia = (workflow) => MEDIA_LENGTH_WORKFLOWS.includes(workflow);
|
|
25346
25346
|
var VIDEO_STYLES = ["vhs", "retro-toon-70s", "low-poly", "hand-drawn", "16bit-pixel"];
|
|
25347
25347
|
var VHS_DAMAGE_LEVELS = ["light", "medium", "heavy"];
|
|
25348
|
-
var VIDEO_RESOLUTIONS = ["480p", "768p", "1080p", "2k"];
|
|
25348
|
+
var VIDEO_RESOLUTIONS = ["480p", "720p", "768p", "1080p", "2k"];
|
|
25349
|
+
var H3_RESOLUTIONS = ["480p", "768p", "1080p", "2k"];
|
|
25349
25350
|
var VIDEO_ASPECT_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
25350
25351
|
var PROMPT_EXPANSION_MODES = ["disabled", "balanced", "quality"];
|
|
25351
25352
|
var EXTEND_OUTPUTS = ["extended", "continuation"];
|
|
@@ -25359,7 +25360,10 @@ var MAX_RECAST_PEOPLE = 4;
|
|
|
25359
25360
|
var MAX_3D_REFERENCES = 8;
|
|
25360
25361
|
var MAX_CAMERA_KEYFRAMES = 12;
|
|
25361
25362
|
var MAX_CAMERA_TURNS = 32;
|
|
25363
|
+
var MAX_IMAGE_KEYFRAMES = 10;
|
|
25364
|
+
var KEYFRAME_FPS = 24;
|
|
25362
25365
|
var H3_MAX = "minimax/h3-max";
|
|
25366
|
+
var FLUX_3_MAX = "blackforestlabs/flux-3-max";
|
|
25363
25367
|
var h3Endpoints = (route) => ({ "image-to-video": `${route}/image-to-video`, "text-to-video": `${route}/text-to-video`, "extend-video": `${route}/extend-video` });
|
|
25364
25368
|
var SPRITE_VIDEO_MODELS = [
|
|
25365
25369
|
{
|
|
@@ -25388,7 +25392,8 @@ var SPRITE_VIDEO_MODELS = [
|
|
|
25388
25392
|
id: "fal/minimax-h3-max",
|
|
25389
25393
|
label: "MiniMax H3 Max (fal.ai)",
|
|
25390
25394
|
provider: "fal",
|
|
25391
|
-
|
|
25395
|
+
// Every workflow but FLUX 3 Max's keyframes.
|
|
25396
|
+
workflows: VIDEO_WORKFLOWS.filter((w) => w !== "keyframes-to-video"),
|
|
25392
25397
|
endpoints: {
|
|
25393
25398
|
...h3Endpoints(H3_MAX),
|
|
25394
25399
|
"reference-to-video": `${H3_MAX}/reference-to-video`,
|
|
@@ -25402,11 +25407,11 @@ var SPRITE_VIDEO_MODELS = [
|
|
|
25402
25407
|
},
|
|
25403
25408
|
resolutions: ["480p", "768p", "1080p"],
|
|
25404
25409
|
workflowOptions: {
|
|
25405
|
-
"extend-video": { resolutions:
|
|
25406
|
-
"lip-sync": { resolutions:
|
|
25410
|
+
"extend-video": { resolutions: H3_RESOLUTIONS },
|
|
25411
|
+
"lip-sync": { resolutions: H3_RESOLUTIONS, seconds: { min: 5, max: 900, fractional: true } },
|
|
25407
25412
|
"insert-video": { resolutions: ["480p", "768p"], seconds: { min: 5, max: 13, fractional: true }, creditsPerSecond: { "480p": 5, "768p": 6 } },
|
|
25408
25413
|
recast: { resolutions: ["768p", "1080p"], seconds: { min: 5, max: 30, fractional: true }, creditsPerSecond: { "768p": 30, "1080p": 45 } },
|
|
25409
|
-
relight: { resolutions:
|
|
25414
|
+
relight: { resolutions: H3_RESOLUTIONS, seconds: { min: 2.33, max: 15, fractional: true } },
|
|
25410
25415
|
"3d-to-video": { seconds: { min: 1, max: 15, fractional: true } },
|
|
25411
25416
|
style: { resolutions: ["768p"], seconds: { min: 5, max: 15 } }
|
|
25412
25417
|
},
|
|
@@ -25426,7 +25431,7 @@ var SPRITE_VIDEO_MODELS = [
|
|
|
25426
25431
|
workflows: STUDIO_VIDEO_WORKFLOWS,
|
|
25427
25432
|
endpoints: h3Endpoints("minimax/h3-max-turbo"),
|
|
25428
25433
|
resolutions: ["480p", "768p", "1080p"],
|
|
25429
|
-
workflowOptions: { "extend-video": { resolutions:
|
|
25434
|
+
workflowOptions: { "extend-video": { resolutions: H3_RESOLUTIONS } },
|
|
25430
25435
|
modes: ["speed"],
|
|
25431
25436
|
lastFrame: true,
|
|
25432
25437
|
endFrameOnly: true,
|
|
@@ -25435,6 +25440,21 @@ var SPRITE_VIDEO_MODELS = [
|
|
|
25435
25440
|
audio: true,
|
|
25436
25441
|
estimatedCreditsPerSecond: { "480p": { speed: 2.5 }, "768p": { speed: 4 }, "1080p": { speed: 8 }, "2k": { speed: 16 } },
|
|
25437
25442
|
seconds: { min: 1, max: 15, fractional: true }
|
|
25443
|
+
},
|
|
25444
|
+
{
|
|
25445
|
+
id: "fal/flux-3-max",
|
|
25446
|
+
label: "FLUX 3 Max (fal.ai)",
|
|
25447
|
+
provider: "fal",
|
|
25448
|
+
workflows: ["image-to-video", "text-to-video", "keyframes-to-video"],
|
|
25449
|
+
endpoints: { "image-to-video": `${FLUX_3_MAX}/image-to-video`, "text-to-video": `${FLUX_3_MAX}/text-to-video`, "keyframes-to-video": `${FLUX_3_MAX}/keyframes-to-video` },
|
|
25450
|
+
falInputs: "flux",
|
|
25451
|
+
resolutions: ["720p", "1080p"],
|
|
25452
|
+
modes: ["quality"],
|
|
25453
|
+
lastFrame: true,
|
|
25454
|
+
seed: true,
|
|
25455
|
+
promptExpansion: ["balanced", "quality"],
|
|
25456
|
+
estimatedCreditsPerSecond: { "720p": { quality: 17 }, "1080p": { quality: 29 } },
|
|
25457
|
+
seconds: { min: 5, max: 20 }
|
|
25438
25458
|
}
|
|
25439
25459
|
];
|
|
25440
25460
|
var SPRITE_VIDEO_MODEL_IDS = SPRITE_VIDEO_MODELS.map((m) => m.id);
|
|
@@ -30496,7 +30516,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
30496
30516
|
var NONE = 0;
|
|
30497
30517
|
var ASSUMED = 1;
|
|
30498
30518
|
var PROVEN = 2;
|
|
30499
|
-
function isRecursive(inst, stack,
|
|
30519
|
+
function isRecursive(inst, stack, resolve18) {
|
|
30500
30520
|
const cached2 = recursive.get(inst);
|
|
30501
30521
|
if (cached2 !== void 0)
|
|
30502
30522
|
return cached2 ? PROVEN : NONE;
|
|
@@ -30506,7 +30526,7 @@ function isRecursive(inst, stack, resolve17) {
|
|
|
30506
30526
|
let result = NONE;
|
|
30507
30527
|
const check2 = (child) => {
|
|
30508
30528
|
if (result !== PROVEN && child?._zod) {
|
|
30509
|
-
const answer = isRecursive(child, stack,
|
|
30529
|
+
const answer = isRecursive(child, stack, resolve18);
|
|
30510
30530
|
if (answer > result)
|
|
30511
30531
|
result = answer;
|
|
30512
30532
|
}
|
|
@@ -30517,7 +30537,7 @@ function isRecursive(inst, stack, resolve17) {
|
|
|
30517
30537
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
30518
30538
|
if (spread && !desc.enumerable)
|
|
30519
30539
|
continue;
|
|
30520
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
30540
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve18) : NONE;
|
|
30521
30541
|
if (child > answer)
|
|
30522
30542
|
answer = child;
|
|
30523
30543
|
}
|
|
@@ -30581,7 +30601,7 @@ function isRecursive(inst, stack, resolve17) {
|
|
|
30581
30601
|
break;
|
|
30582
30602
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
30583
30603
|
case "lazy": {
|
|
30584
|
-
const inner = def._cachedInner ?? (
|
|
30604
|
+
const inner = def._cachedInner ?? (resolve18 ? inst._zod.innerType : void 0);
|
|
30585
30605
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
30586
30606
|
break;
|
|
30587
30607
|
}
|
|
@@ -45199,6 +45219,12 @@ async function saveWorkspace(origin, workspaceId) {
|
|
|
45199
45219
|
credentials[origin] = { ...saved, workspaceId };
|
|
45200
45220
|
await writeCredentials(credentials);
|
|
45201
45221
|
}
|
|
45222
|
+
async function sessionToken(origin) {
|
|
45223
|
+
const saved = (await readCredentials())[origin];
|
|
45224
|
+
const token3 = process.env.ANIMAGURU_TOKEN ?? (saved && saved.expiresAt > Date.now() ? saved.token : void 0);
|
|
45225
|
+
if (!token3) throw new Error("Sign in with animaguru auth login, or set ANIMAGURU_TOKEN.");
|
|
45226
|
+
return token3;
|
|
45227
|
+
}
|
|
45202
45228
|
var ServiceError = class extends Error {
|
|
45203
45229
|
constructor(status, code, message) {
|
|
45204
45230
|
super(message);
|
|
@@ -45216,12 +45242,7 @@ var Client = class {
|
|
|
45216
45242
|
signal;
|
|
45217
45243
|
origin;
|
|
45218
45244
|
async request(path, options = {}) {
|
|
45219
|
-
|
|
45220
|
-
if (options.authenticated !== false) {
|
|
45221
|
-
const saved = (await readCredentials())[this.origin];
|
|
45222
|
-
token3 = process.env.ANIMAGURU_TOKEN ?? (saved && saved.expiresAt > Date.now() ? saved.token : void 0);
|
|
45223
|
-
if (!token3) throw new Error("Sign in with animaguru auth login, or set ANIMAGURU_TOKEN.");
|
|
45224
|
-
}
|
|
45245
|
+
const token3 = options.authenticated !== false ? await sessionToken(this.origin) : void 0;
|
|
45225
45246
|
const generation = options.method === "POST" && /^\/api\/v1\/sprites\/[^/]+\/(jobs|assets|avatars|avatars\/looks|avatars\/[^/]+\/consent)$/.test(path);
|
|
45226
45247
|
const idempotency = generation ? { "Idempotency-Key": generationRequestId(path, options.body) } : {};
|
|
45227
45248
|
const response = await fetch(`${this.origin}${path}`, {
|
|
@@ -45347,14 +45368,7 @@ var animation_styles_default = {
|
|
|
45347
45368
|
"Masked reveals",
|
|
45348
45369
|
"Speech & beat timing"
|
|
45349
45370
|
],
|
|
45350
|
-
previewCaption: "
|
|
45351
|
-
studyCopy: [
|
|
45352
|
-
"Make",
|
|
45353
|
-
"every",
|
|
45354
|
-
"word",
|
|
45355
|
-
"move.",
|
|
45356
|
-
"TYPE / RHYTHM / EMPHASIS"
|
|
45357
|
-
],
|
|
45371
|
+
previewCaption: "Words slam, mask and split into letters on a 120 bpm beat across four color fields, then settle into a lockup. Drawn entirely in code.",
|
|
45358
45372
|
family: "graphic",
|
|
45359
45373
|
example: false
|
|
45360
45374
|
},
|
|
@@ -45371,11 +45385,7 @@ var animation_styles_default = {
|
|
|
45371
45385
|
"Connected transitions",
|
|
45372
45386
|
"Designed easing"
|
|
45373
45387
|
],
|
|
45374
|
-
previewCaption: "A
|
|
45375
|
-
studyCopy: [
|
|
45376
|
-
"A shape. An idea.",
|
|
45377
|
-
"One connected system."
|
|
45378
|
-
],
|
|
45388
|
+
previewCaption: "A bouncing ball splits and morphs into hills and a sun, a skyline rises, and a cyclist rides into dusk before an iris closes. Every shape is drawn and morphed in code.",
|
|
45379
45389
|
family: "graphic",
|
|
45380
45390
|
example: false
|
|
45381
45391
|
},
|
|
@@ -45392,13 +45402,7 @@ var animation_styles_default = {
|
|
|
45392
45402
|
"Drawn connections",
|
|
45393
45403
|
"Readable drawing holds"
|
|
45394
45404
|
],
|
|
45395
|
-
previewCaption: "
|
|
45396
|
-
studyCopy: [
|
|
45397
|
-
"Draw the connection.",
|
|
45398
|
-
"Imagine",
|
|
45399
|
-
"Connect",
|
|
45400
|
-
"Create"
|
|
45401
|
-
],
|
|
45405
|
+
previewCaption: "A generated hand draws an AnimaGuru-generated marker illustration stroke by stroke, colors it in, titles it and wipes the board clean.",
|
|
45402
45406
|
family: "graphic",
|
|
45403
45407
|
example: false
|
|
45404
45408
|
},
|
|
@@ -45415,13 +45419,7 @@ var animation_styles_default = {
|
|
|
45415
45419
|
"Travelling path markers",
|
|
45416
45420
|
"Controlled camera movement"
|
|
45417
45421
|
],
|
|
45418
|
-
previewCaption: "
|
|
45419
|
-
studyCopy: [
|
|
45420
|
-
"A world, connected.",
|
|
45421
|
-
"Collect",
|
|
45422
|
-
"Shape",
|
|
45423
|
-
"Share"
|
|
45424
|
-
],
|
|
45422
|
+
previewCaption: "An isometric town assembles tile by tile: buildings extrude, trees pop, cars and a train start running and the windows light up at dusk. Built from projected geometry in code.",
|
|
45425
45423
|
family: "technical",
|
|
45426
45424
|
example: false
|
|
45427
45425
|
},
|
|
@@ -45438,14 +45436,7 @@ var animation_styles_default = {
|
|
|
45438
45436
|
"Counted values",
|
|
45439
45437
|
"Comparison highlights"
|
|
45440
45438
|
],
|
|
45441
|
-
previewCaption: "
|
|
45442
|
-
studyCopy: [
|
|
45443
|
-
"Make the comparison clear.",
|
|
45444
|
-
"A",
|
|
45445
|
-
"B",
|
|
45446
|
-
"C",
|
|
45447
|
-
"ILLUSTRATIVE DATA / SAMPLE VALUES"
|
|
45448
|
-
],
|
|
45439
|
+
previewCaption: "A line chart is drawn, counted and annotated, then becomes ranked bars beside a platform donut. Drawn entirely in code from sample values.",
|
|
45449
45440
|
family: "technical",
|
|
45450
45441
|
example: false
|
|
45451
45442
|
},
|
|
@@ -45462,12 +45453,7 @@ var animation_styles_default = {
|
|
|
45462
45453
|
"Parameter changes",
|
|
45463
45454
|
"Semantic transformations"
|
|
45464
45455
|
],
|
|
45465
|
-
previewCaption: "A
|
|
45466
|
-
studyCopy: [
|
|
45467
|
-
"See the relationship.",
|
|
45468
|
-
"radius",
|
|
45469
|
-
"area"
|
|
45470
|
-
],
|
|
45456
|
+
previewCaption: "A unit circle traces a sine wave, then becomes the largest of 90 rotating circles that draw \u03C0. Plotted from a real Fourier series.",
|
|
45471
45457
|
family: "technical",
|
|
45472
45458
|
example: false
|
|
45473
45459
|
},
|
|
@@ -45484,19 +45470,7 @@ var animation_styles_default = {
|
|
|
45484
45470
|
"Bounded zooms",
|
|
45485
45471
|
"State transitions"
|
|
45486
45472
|
],
|
|
45487
|
-
previewCaption: "A
|
|
45488
|
-
studyCopy: [
|
|
45489
|
-
"Focus on what matters.",
|
|
45490
|
-
"CONCEPTUAL INTERFACE",
|
|
45491
|
-
"Workspace",
|
|
45492
|
-
"Overview",
|
|
45493
|
-
"Projects",
|
|
45494
|
-
"Library",
|
|
45495
|
-
"New project",
|
|
45496
|
-
"Project created",
|
|
45497
|
-
"Create your next idea.",
|
|
45498
|
-
"Ready to create"
|
|
45499
|
-
],
|
|
45473
|
+
previewCaption: "A cursor drives a dashboard: a live toggle, hover lift, drag-to-reorder, a modal with typing and loading, then a toast and a phone notification. Every element and interaction is coded.",
|
|
45500
45474
|
family: "technical",
|
|
45501
45475
|
example: false
|
|
45502
45476
|
},
|
|
@@ -45513,10 +45487,7 @@ var animation_styles_default = {
|
|
|
45513
45487
|
"Pose-to-pose timing",
|
|
45514
45488
|
"Gesture & reaction"
|
|
45515
45489
|
],
|
|
45516
|
-
previewCaption: "
|
|
45517
|
-
studyCopy: [
|
|
45518
|
-
"An idea comes to life."
|
|
45519
|
-
],
|
|
45490
|
+
previewCaption: "Pip, a cartoon character drawn and animated in AnimaGuru, walks a generated meadow and hops a log, with a following camera, squash and stretch, and dust on landing.",
|
|
45520
45491
|
family: "character",
|
|
45521
45492
|
example: false
|
|
45522
45493
|
},
|
|
@@ -45533,11 +45504,7 @@ var animation_styles_default = {
|
|
|
45533
45504
|
"Palette accents",
|
|
45534
45505
|
"Pixel transitions"
|
|
45535
45506
|
],
|
|
45536
|
-
previewCaption: "
|
|
45537
|
-
studyCopy: [
|
|
45538
|
-
"SMALL PIXELS.",
|
|
45539
|
-
"BIG POSSIBILITIES."
|
|
45540
|
-
],
|
|
45507
|
+
previewCaption: "Bit, a pixel-art sprite animated in AnimaGuru, runs a side-scrolling level built from generated parallax layers, with coins, sparkles and a score drawn in code.",
|
|
45541
45508
|
family: "character",
|
|
45542
45509
|
example: false
|
|
45543
45510
|
},
|
|
@@ -45554,10 +45521,7 @@ var animation_styles_default = {
|
|
|
45554
45521
|
"Foreground reveals",
|
|
45555
45522
|
"Selective organic motion"
|
|
45556
45523
|
],
|
|
45557
|
-
previewCaption: "
|
|
45558
|
-
studyCopy: [
|
|
45559
|
-
"Let the picture breathe."
|
|
45560
|
-
],
|
|
45524
|
+
previewCaption: "Five AnimaGuru-generated oil-painted planes on a slow dolly, with haze between them, sun rays, drifting pollen and wind in the grass.",
|
|
45561
45525
|
family: "material",
|
|
45562
45526
|
example: false
|
|
45563
45527
|
},
|
|
@@ -45574,13 +45538,8 @@ var animation_styles_default = {
|
|
|
45574
45538
|
"Matched reveals",
|
|
45575
45539
|
"Controlled depth"
|
|
45576
45540
|
],
|
|
45577
|
-
studyCopy: [
|
|
45578
|
-
"Bring the signal forward.",
|
|
45579
|
-
"Concept stage",
|
|
45580
|
-
"One clear focus"
|
|
45581
|
-
],
|
|
45582
45541
|
family: "technical",
|
|
45583
|
-
previewCaption: "
|
|
45542
|
+
previewCaption: "Glass interface panels assemble around a hero card on a reflective stage under sweeping light. Built in code with depth of field and floor reflections.",
|
|
45584
45543
|
example: true
|
|
45585
45544
|
},
|
|
45586
45545
|
"studio-product-reveal": {
|
|
@@ -45596,13 +45555,8 @@ var animation_styles_default = {
|
|
|
45596
45555
|
"Detail close-ups",
|
|
45597
45556
|
"Layered part separation"
|
|
45598
45557
|
],
|
|
45599
|
-
studyCopy: [
|
|
45600
|
-
"Form. Material. Detail.",
|
|
45601
|
-
"Illustrative product",
|
|
45602
|
-
"Light reveals the shape"
|
|
45603
|
-
],
|
|
45604
45558
|
family: "material",
|
|
45605
|
-
previewCaption: "
|
|
45559
|
+
previewCaption: "An unbranded fragrance bottle generated with AnimaGuru turns under a strip light: a macro start, a pull-back, anamorphic glints and a title lockup.",
|
|
45606
45560
|
example: true
|
|
45607
45561
|
},
|
|
45608
45562
|
"risograph-print": {
|
|
@@ -45618,13 +45572,8 @@ var animation_styles_default = {
|
|
|
45618
45572
|
"Registration shifts",
|
|
45619
45573
|
"Held-drawing cadence"
|
|
45620
45574
|
],
|
|
45621
|
-
studyCopy: [
|
|
45622
|
-
"Two inks. More possibilities.",
|
|
45623
|
-
"Separate plates",
|
|
45624
|
-
"Meet in the overprint"
|
|
45625
|
-
],
|
|
45626
45575
|
family: "print",
|
|
45627
|
-
previewCaption: "
|
|
45576
|
+
previewCaption: "An AnimaGuru-generated illustration separated in code into yellow, fluorescent pink and teal drums, then printed pass by pass with riso grain and slight misregistration.",
|
|
45628
45577
|
example: true
|
|
45629
45578
|
},
|
|
45630
45579
|
"halftone-editorial": {
|
|
@@ -45640,13 +45589,8 @@ var animation_styles_default = {
|
|
|
45640
45589
|
"Stamp impacts",
|
|
45641
45590
|
"Layered panel changes"
|
|
45642
45591
|
],
|
|
45643
|
-
studyCopy: [
|
|
45644
|
-
"Give the idea a headline.",
|
|
45645
|
-
"An original print study",
|
|
45646
|
-
"Make the point readable"
|
|
45647
|
-
],
|
|
45648
45592
|
family: "print",
|
|
45649
|
-
previewCaption: "
|
|
45593
|
+
previewCaption: "An AnimaGuru-generated stage photo screened in code into black and orange halftone dots at 45\xB0 and 15\xB0, pulling back from the dots to a magazine spread.",
|
|
45650
45594
|
example: true
|
|
45651
45595
|
},
|
|
45652
45596
|
"silkscreen-poster": {
|
|
@@ -45662,13 +45606,8 @@ var animation_styles_default = {
|
|
|
45662
45606
|
"Layer-by-layer builds",
|
|
45663
45607
|
"Graphic holds"
|
|
45664
45608
|
],
|
|
45665
|
-
studyCopy: [
|
|
45666
|
-
"One ink. One impression.",
|
|
45667
|
-
"Print the composition",
|
|
45668
|
-
"Hold the finished image"
|
|
45669
|
-
],
|
|
45670
45609
|
family: "print",
|
|
45671
|
-
previewCaption: "
|
|
45610
|
+
previewCaption: "AnimaGuru-generated poster art cut into five flat stencils in code and pulled screen by screen with a squeegee, ending on the finished print.",
|
|
45672
45611
|
example: true
|
|
45673
45612
|
},
|
|
45674
45613
|
"art-deco-motion": {
|
|
@@ -45684,13 +45623,8 @@ var animation_styles_default = {
|
|
|
45684
45623
|
"Sequenced lights",
|
|
45685
45624
|
"Mechanical settling"
|
|
45686
45625
|
],
|
|
45687
|
-
studyCopy: [
|
|
45688
|
-
"Geometry catches the light.",
|
|
45689
|
-
"Open from the center",
|
|
45690
|
-
"A measured reveal"
|
|
45691
|
-
],
|
|
45692
45626
|
family: "graphic",
|
|
45693
|
-
previewCaption: "
|
|
45627
|
+
previewCaption: "Gold keylines, stepped arches and a sunburst fan open symmetrically; chevrons and marquee lights run in sequence while a specular sweep crosses the metal. Drawn entirely in code.",
|
|
45694
45628
|
example: true
|
|
45695
45629
|
},
|
|
45696
45630
|
"blueprint-drafting": {
|
|
@@ -45706,13 +45640,25 @@ var animation_styles_default = {
|
|
|
45706
45640
|
"Exploded parts",
|
|
45707
45641
|
"Anchored dimensions"
|
|
45708
45642
|
],
|
|
45709
|
-
|
|
45710
|
-
|
|
45711
|
-
|
|
45712
|
-
|
|
45643
|
+
family: "technical",
|
|
45644
|
+
previewCaption: "A drafting point traces an AnimaGuru-generated cyanotype line by line, then dimensions, callouts and a title block are drawn in.",
|
|
45645
|
+
example: true
|
|
45646
|
+
},
|
|
45647
|
+
"machine-anatomy": {
|
|
45648
|
+
name: "Machine Anatomy",
|
|
45649
|
+
description: "Ideas built as working isometric machines: dozens of small shaded parts in a framed figure, with a live readout driven by the mechanism.",
|
|
45650
|
+
materials: [
|
|
45651
|
+
"Four-tone isometric solids",
|
|
45652
|
+
"Small, precise parts",
|
|
45653
|
+
"Figure card and live readout"
|
|
45654
|
+
],
|
|
45655
|
+
motion: [
|
|
45656
|
+
"Mechanism-driven movement",
|
|
45657
|
+
"Eased travel and springs",
|
|
45658
|
+
"Exploded assemblies"
|
|
45713
45659
|
],
|
|
45714
45660
|
family: "technical",
|
|
45715
|
-
previewCaption: "
|
|
45661
|
+
previewCaption: "One dispensing head on a gantry fills a sixteen-well tray in a serpentine pass while the readout counts wells and milliliters. Drawn in code with the bundled Anatomy kit.",
|
|
45716
45662
|
example: true
|
|
45717
45663
|
},
|
|
45718
45664
|
"holographic-scan": {
|
|
@@ -45728,13 +45674,8 @@ var animation_styles_default = {
|
|
|
45728
45674
|
"Target locking",
|
|
45729
45675
|
"Local part separation"
|
|
45730
45676
|
],
|
|
45731
|
-
studyCopy: [
|
|
45732
|
-
"Scan. Focus. Understand.",
|
|
45733
|
-
"Illustrative part model",
|
|
45734
|
-
"Follow the detail"
|
|
45735
|
-
],
|
|
45736
45677
|
family: "technical",
|
|
45737
|
-
previewCaption: "
|
|
45678
|
+
previewCaption: "A wireframe turbofan grows under a moving scan, locks onto its parts and separates them with callouts. Projected 3D geometry drawn in code.",
|
|
45738
45679
|
example: true
|
|
45739
45680
|
},
|
|
45740
45681
|
"paper-popup": {
|
|
@@ -45750,13 +45691,8 @@ var animation_styles_default = {
|
|
|
45750
45691
|
"Back-to-front arrival",
|
|
45751
45692
|
"Paper-stage transitions"
|
|
45752
45693
|
],
|
|
45753
|
-
studyCopy: [
|
|
45754
|
-
"A flat page gains a world.",
|
|
45755
|
-
"An original paper mechanism",
|
|
45756
|
-
"Fold. Open. Discover."
|
|
45757
|
-
],
|
|
45758
45694
|
family: "paper",
|
|
45759
|
-
previewCaption: "
|
|
45695
|
+
previewCaption: "A book opens and AnimaGuru-generated cardstock layers hinge up from the fold with shadows and spring, while a pull tab lifts the balloon and sun.",
|
|
45760
45696
|
example: true
|
|
45761
45697
|
},
|
|
45762
45698
|
"shadow-theatre": {
|
|
@@ -45772,13 +45708,8 @@ var animation_styles_default = {
|
|
|
45772
45708
|
"Jointed articulation",
|
|
45773
45709
|
"Lamp-distance changes"
|
|
45774
45710
|
],
|
|
45775
|
-
studyCopy: [
|
|
45776
|
-
"A silhouette tells a thousand things.",
|
|
45777
|
-
"Light and carved shape",
|
|
45778
|
-
"Move with the material"
|
|
45779
|
-
],
|
|
45780
45711
|
family: "paper",
|
|
45781
|
-
previewCaption: "
|
|
45712
|
+
previewCaption: "Shadow puppets generated with AnimaGuru perform behind a lit linen screen, finished in code with the cloth's weave, a breathing lamp and a warm glow.",
|
|
45782
45713
|
example: true
|
|
45783
45714
|
},
|
|
45784
45715
|
"engraved-relief-print": {
|
|
@@ -45794,13 +45725,8 @@ var animation_styles_default = {
|
|
|
45794
45725
|
"Progressive hatching",
|
|
45795
45726
|
"Successive impressions"
|
|
45796
45727
|
],
|
|
45797
|
-
studyCopy: [
|
|
45798
|
-
"Every mark has a direction.",
|
|
45799
|
-
"Carve the form",
|
|
45800
|
-
"Pull the impression"
|
|
45801
|
-
],
|
|
45802
45728
|
family: "print",
|
|
45803
|
-
previewCaption: "
|
|
45729
|
+
previewCaption: "A generated woodblock print pulled in order: hatching carved first, then two color impressions rolled into register.",
|
|
45804
45730
|
example: true
|
|
45805
45731
|
},
|
|
45806
45732
|
"ascii-crt": {
|
|
@@ -45816,13 +45742,8 @@ var animation_styles_default = {
|
|
|
45816
45742
|
"Grid-scale reveals",
|
|
45817
45743
|
"Analytic afterglow"
|
|
45818
45744
|
],
|
|
45819
|
-
studyCopy: [
|
|
45820
|
-
"A picture made of characters.",
|
|
45821
|
-
"Signal on the grid",
|
|
45822
|
-
"Pixels become language"
|
|
45823
|
-
],
|
|
45824
45745
|
family: "cinematic",
|
|
45825
|
-
previewCaption: "
|
|
45746
|
+
previewCaption: "An AnimaGuru-generated jellyfish clip rendered as real ASCII on a 128-column green-phosphor terminal, with curvature, glow trails and a typed command.",
|
|
45826
45747
|
example: true
|
|
45827
45748
|
},
|
|
45828
45749
|
"analog-film-tape": {
|
|
@@ -45838,13 +45759,8 @@ var animation_styles_default = {
|
|
|
45838
45759
|
"Deterministic weave",
|
|
45839
45760
|
"Tape-inspired transitions"
|
|
45840
45761
|
],
|
|
45841
|
-
studyCopy: [
|
|
45842
|
-
"A different kind of time.",
|
|
45843
|
-
"Original scene / film variant",
|
|
45844
|
-
"Texture follows the medium"
|
|
45845
|
-
],
|
|
45846
45762
|
family: "cinematic",
|
|
45847
|
-
previewCaption: "
|
|
45763
|
+
previewCaption: "Two generated summer scenes projected at 18 fps, with gate weave, grain, a slipped splice and a film burn.",
|
|
45848
45764
|
example: true
|
|
45849
45765
|
},
|
|
45850
45766
|
"glass-mosaic": {
|
|
@@ -45860,13 +45776,8 @@ var animation_styles_default = {
|
|
|
45860
45776
|
"Moving light bands",
|
|
45861
45777
|
"Identity-preserving rearrangement"
|
|
45862
45778
|
],
|
|
45863
|
-
studyCopy: [
|
|
45864
|
-
"Pieces become a picture.",
|
|
45865
|
-
"Original glass-like mosaic",
|
|
45866
|
-
"Light passes through"
|
|
45867
|
-
],
|
|
45868
45779
|
family: "material",
|
|
45869
|
-
previewCaption: "
|
|
45780
|
+
previewCaption: "An AnimaGuru-generated peacock cut in code into leaded glass pieces that slot in one by one, then lit by a low sun crossing the window.",
|
|
45870
45781
|
example: true
|
|
45871
45782
|
},
|
|
45872
45783
|
"portal-zoom": {
|
|
@@ -45882,13 +45793,8 @@ var animation_styles_default = {
|
|
|
45882
45793
|
"Layered parallax",
|
|
45883
45794
|
"Occluded scene handoffs"
|
|
45884
45795
|
],
|
|
45885
|
-
studyCopy: [
|
|
45886
|
-
"Every frame opens another.",
|
|
45887
|
-
"An original nested world",
|
|
45888
|
-
"Keep the journey continuous"
|
|
45889
|
-
],
|
|
45890
45796
|
family: "cinematic",
|
|
45891
|
-
previewCaption: "
|
|
45797
|
+
previewCaption: "A continuous zoom through four AnimaGuru-generated worlds, each framed inside the last, that ends exactly where it began.",
|
|
45892
45798
|
example: true
|
|
45893
45799
|
},
|
|
45894
45800
|
"photo-footage-editorial": {
|
|
@@ -45904,13 +45810,8 @@ var animation_styles_default = {
|
|
|
45904
45810
|
"Media-wall selection",
|
|
45905
45811
|
"Focused detail reveals"
|
|
45906
45812
|
],
|
|
45907
|
-
studyCopy: [
|
|
45908
|
-
"Give every image its place.",
|
|
45909
|
-
"Original illustrated media cards",
|
|
45910
|
-
"Frame the detail"
|
|
45911
|
-
],
|
|
45912
45813
|
family: "cinematic",
|
|
45913
|
-
previewCaption: "
|
|
45814
|
+
previewCaption: "Six generated photographs on a contact sheet. The circled frame becomes footage, then returns to its strip.",
|
|
45914
45815
|
example: true
|
|
45915
45816
|
},
|
|
45916
45817
|
"stop-motion-objects": {
|
|
@@ -45926,13 +45827,8 @@ var animation_styles_default = {
|
|
|
45926
45827
|
"Physical-looking assembly",
|
|
45927
45828
|
"Held-drawing timing"
|
|
45928
45829
|
],
|
|
45929
|
-
studyCopy: [
|
|
45930
|
-
"Build it one piece at a time.",
|
|
45931
|
-
"Illustrative tactile objects",
|
|
45932
|
-
"Deliberate held poses"
|
|
45933
|
-
],
|
|
45934
45830
|
family: "material",
|
|
45935
|
-
previewCaption: "
|
|
45831
|
+
previewCaption: "Clay footage generated with AnimaGuru, held on twos at 12 fps, with a nudge of the set and a flicker of the lamp between poses.",
|
|
45936
45832
|
example: true
|
|
45937
45833
|
},
|
|
45938
45834
|
"miniature-diorama": {
|
|
@@ -45948,13 +45844,8 @@ var animation_styles_default = {
|
|
|
45948
45844
|
"Elevated camera travel",
|
|
45949
45845
|
"Optional time-lapse activity"
|
|
45950
45846
|
],
|
|
45951
|
-
studyCopy: [
|
|
45952
|
-
"A small world, carefully built.",
|
|
45953
|
-
"An original 2.5D miniature",
|
|
45954
|
-
"Let scale guide the view"
|
|
45955
|
-
],
|
|
45956
45847
|
family: "material",
|
|
45957
|
-
previewCaption: "
|
|
45848
|
+
previewCaption: "A generated harbor model with a slow elevated drift, a focus band on the quay and small time-lapsed activity.",
|
|
45958
45849
|
example: true
|
|
45959
45850
|
},
|
|
45960
45851
|
"sand-drawing": {
|
|
@@ -45970,13 +45861,8 @@ var animation_styles_default = {
|
|
|
45970
45861
|
"Authored reshape paths",
|
|
45971
45862
|
"Material holds"
|
|
45972
45863
|
],
|
|
45973
|
-
studyCopy: [
|
|
45974
|
-
"A shape emerges from grains.",
|
|
45975
|
-
"Original procedural sand study",
|
|
45976
|
-
"Reveal the silhouette"
|
|
45977
|
-
],
|
|
45978
45864
|
family: "material",
|
|
45979
|
-
previewCaption: "
|
|
45865
|
+
previewCaption: "A whale is swept into a seabird on a lit sand table, in one take. Footage generated with AnimaGuru.",
|
|
45980
45866
|
example: true
|
|
45981
45867
|
},
|
|
45982
45868
|
"generative-light-signal": {
|
|
@@ -45992,20 +45878,150 @@ var animation_styles_default = {
|
|
|
45992
45878
|
"Measured cue response",
|
|
45993
45879
|
"Controlled pattern changes"
|
|
45994
45880
|
],
|
|
45995
|
-
studyCopy: [
|
|
45996
|
-
"Turn a signal into movement.",
|
|
45997
|
-
"Original analytic field",
|
|
45998
|
-
"Follow the rhythm"
|
|
45999
|
-
],
|
|
46000
45881
|
family: "graphic",
|
|
46001
|
-
previewCaption: "
|
|
45882
|
+
previewCaption: "Seeded light particles stream along braided ribbons, flaring as timed pulses pass. A seamless loop rendered in code.",
|
|
45883
|
+
example: true
|
|
45884
|
+
},
|
|
45885
|
+
"satellite-briefing": {
|
|
45886
|
+
name: "Satellite Briefing",
|
|
45887
|
+
description: "Satellite imagery graded to an analyst's grey, with thin measured hairlines, dated passes and one reading per screen in one continuous zoom.",
|
|
45888
|
+
materials: [
|
|
45889
|
+
"Georeferenced imagery plates",
|
|
45890
|
+
"Analyst grey grade",
|
|
45891
|
+
"Hairline measurements"
|
|
45892
|
+
],
|
|
45893
|
+
motion: [
|
|
45894
|
+
"Orbit-to-ground dive",
|
|
45895
|
+
"Dated scan passes",
|
|
45896
|
+
"Range lines that count up"
|
|
45897
|
+
],
|
|
45898
|
+
previewCaption: "From orbit down to a drying lake: four satellite passes print their shorelines and a range line measures the retreat. Procedural terrain drawn in code, not a real place.",
|
|
45899
|
+
family: "evidence",
|
|
45900
|
+
example: true
|
|
45901
|
+
},
|
|
45902
|
+
"briefing-board": {
|
|
45903
|
+
name: "Engineering Briefing Board",
|
|
45904
|
+
description: "A filmed whiteboard wall where printed cards land with weight and marker ink in fixed colours measures every option against one limit.",
|
|
45905
|
+
materials: [
|
|
45906
|
+
"Enamel board with ghosts",
|
|
45907
|
+
"Three-colour marker ink",
|
|
45908
|
+
"Printed cards & magnets"
|
|
45909
|
+
],
|
|
45910
|
+
motion: [
|
|
45911
|
+
"Riding dimension lines",
|
|
45912
|
+
"Weighted landings",
|
|
45913
|
+
"Whole-wall reveal"
|
|
45914
|
+
],
|
|
45915
|
+
previewCaption: "Three drones are measured against one reserve line, a stamp picks the winner and the camera pulls back to the whole wall. Drawn in code with illustrative values.",
|
|
45916
|
+
family: "evidence",
|
|
45917
|
+
example: true
|
|
45918
|
+
},
|
|
45919
|
+
"lidar-survey": {
|
|
45920
|
+
name: "LiDAR Survey",
|
|
45921
|
+
description: "Measured point clouds flown through in the dark, peeled by a cutting plane and condensed into a raking-lit surface with traced features.",
|
|
45922
|
+
materials: [
|
|
45923
|
+
"Point clouds coloured by height",
|
|
45924
|
+
"Raking-lit relief",
|
|
45925
|
+
"Amber traced features"
|
|
45926
|
+
],
|
|
45927
|
+
motion: [
|
|
45928
|
+
"Scan fronts",
|
|
45929
|
+
"Canopy peel",
|
|
45930
|
+
"Points condensing to ground"
|
|
45931
|
+
],
|
|
45932
|
+
previewCaption: "A scan front paints a forest in points, a cutting plane peels the canopy and the ground condenses to reveal old field walls. A procedural cloud drawn in code, not a real survey.",
|
|
45933
|
+
family: "evidence",
|
|
45934
|
+
example: true
|
|
45935
|
+
},
|
|
45936
|
+
"white-model-projection": {
|
|
45937
|
+
name: "White Model Projection",
|
|
45938
|
+
description: "A white massing model in a dark room, where projected light paints data onto the buildings one layer at a time.",
|
|
45939
|
+
materials: [
|
|
45940
|
+
"Matte white massing",
|
|
45941
|
+
"Projected data light",
|
|
45942
|
+
"Pins & single readouts"
|
|
45943
|
+
],
|
|
45944
|
+
motion: [
|
|
45945
|
+
"Lights out, lamp on",
|
|
45946
|
+
"Decade-by-decade switch-ons",
|
|
45947
|
+
"A rising level of light"
|
|
45948
|
+
],
|
|
45949
|
+
previewCaption: "The house lights cut, each decade lights the buildings it left, a level of light climbs every facade and the tallest tower is picked out. Rendered in code; an illustrative district.",
|
|
45950
|
+
family: "evidence",
|
|
45951
|
+
example: true
|
|
45952
|
+
},
|
|
45953
|
+
"data-physicalization": {
|
|
45954
|
+
name: "Data Physicalization",
|
|
45955
|
+
description: "Statistics built as countable objects on a crafted base, lit like a studio product shot and read at the edge of one unit.",
|
|
45956
|
+
materials: [
|
|
45957
|
+
"Countable unit plates",
|
|
45958
|
+
"Metal, acrylic & walnut",
|
|
45959
|
+
"Pinned paper readings"
|
|
45960
|
+
],
|
|
45961
|
+
motion: [
|
|
45962
|
+
"Pieces placed with weight",
|
|
45963
|
+
"Tracked growth",
|
|
45964
|
+
"Pull-back to the installation"
|
|
45965
|
+
],
|
|
45966
|
+
previewCaption: "Ten years of two series become aluminium and acrylic plates on a walnut slab; the stacks cross in 2020 and the camera pulls back to the whole installation. Rendered in code with illustrative values.",
|
|
45967
|
+
family: "evidence",
|
|
45968
|
+
example: true
|
|
45969
|
+
},
|
|
45970
|
+
"exploded-teardown": {
|
|
45971
|
+
name: "Exploded Teardown",
|
|
45972
|
+
description: "A product taken apart on one axis under studio light, every part named with the numbers in its own files, then closed and dimensioned.",
|
|
45973
|
+
materials: [
|
|
45974
|
+
"Studio-lit product parts",
|
|
45975
|
+
"Painted circuit boards",
|
|
45976
|
+
"Leader labels & dimensions"
|
|
45977
|
+
],
|
|
45978
|
+
motion: [
|
|
45979
|
+
"Layer-by-layer separation",
|
|
45980
|
+
"Lights on inside",
|
|
45981
|
+
"Closing and measuring"
|
|
45982
|
+
],
|
|
45983
|
+
previewCaption: "An original pad controller lifts apart in one orbit, its LEDs light the diffuser, labels land in a column and it closes to be dimensioned. Rendered in code from its own model.",
|
|
45984
|
+
family: "evidence",
|
|
45985
|
+
example: true
|
|
45986
|
+
},
|
|
45987
|
+
"microscope-story": {
|
|
45988
|
+
name: "Microscope Story",
|
|
45989
|
+
description: "One continuous dive from a slide on the bench to a single cell, with focus breaths, true scale bars and readings counted from the image.",
|
|
45990
|
+
materials: [
|
|
45991
|
+
"Stained specimen plates",
|
|
45992
|
+
"Frosted instrument panels",
|
|
45993
|
+
"Measured rings & counts"
|
|
45994
|
+
],
|
|
45995
|
+
motion: [
|
|
45996
|
+
"Log-zoom dive",
|
|
45997
|
+
"Focus breaths & sweeps",
|
|
45998
|
+
"Counting the colour"
|
|
45999
|
+
],
|
|
46000
|
+
previewCaption: "A slide on the bench dives to 10\xD7, the blue inside one circle is counted pixel by pixel, then the camera goes on to a single nucleus. A procedural specimen drawn in code, not a real slide.",
|
|
46001
|
+
family: "evidence",
|
|
46002
|
+
example: true
|
|
46003
|
+
},
|
|
46004
|
+
"archive-light-table": {
|
|
46005
|
+
name: "Archive Light Table",
|
|
46006
|
+
description: "Archive photographs and documents on a backlit table, where a loupe turns a negative positive and catalogue records sit beside the objects.",
|
|
46007
|
+
materials: [
|
|
46008
|
+
"Backlit archive objects",
|
|
46009
|
+
"Loupe optics",
|
|
46010
|
+
"Catalogue tags & index"
|
|
46011
|
+
],
|
|
46012
|
+
motion: [
|
|
46013
|
+
"Table glides",
|
|
46014
|
+
"Loupe landings & develop fronts",
|
|
46015
|
+
"Into the photograph"
|
|
46016
|
+
],
|
|
46017
|
+
previewCaption: "Three NASA Ames photographs of one airfield on a light table; under the loupe a 1933 negative turns positive and opens into the picture. Public-domain NASA scans; the negatives are simulated.",
|
|
46018
|
+
family: "evidence",
|
|
46002
46019
|
example: true
|
|
46003
46020
|
}
|
|
46004
46021
|
},
|
|
46005
46022
|
browseStyles: "Browse animation styles",
|
|
46006
46023
|
styleCount_one: "{{count}} visual style, guided by your brief",
|
|
46007
46024
|
styleCount_other: "{{count}} visual styles, guided by your brief",
|
|
46008
|
-
previewBrand: "ANIMAGURU / MOTION STUDIES",
|
|
46009
46025
|
families: {
|
|
46010
46026
|
all: "All styles",
|
|
46011
46027
|
graphic: "Graphic & type",
|
|
@@ -46014,7 +46030,8 @@ var animation_styles_default = {
|
|
|
46014
46030
|
paper: "Paper & cutout",
|
|
46015
46031
|
character: "Character & pixel",
|
|
46016
46032
|
material: "Materials & depth",
|
|
46017
|
-
cinematic: "Cinema & media"
|
|
46033
|
+
cinematic: "Cinema & media",
|
|
46034
|
+
evidence: "Evidence & data"
|
|
46018
46035
|
},
|
|
46019
46036
|
searchLabel: "Search visual styles",
|
|
46020
46037
|
searchPlaceholder: "Try paper, product, typography\u2026",
|
|
@@ -46111,6 +46128,7 @@ var VIDEO_STYLE_IDS = [
|
|
|
46111
46128
|
"silkscreen-poster",
|
|
46112
46129
|
"art-deco-motion",
|
|
46113
46130
|
"blueprint-drafting",
|
|
46131
|
+
"machine-anatomy",
|
|
46114
46132
|
"holographic-scan",
|
|
46115
46133
|
"paper-popup",
|
|
46116
46134
|
"shadow-theatre",
|
|
@@ -46123,7 +46141,15 @@ var VIDEO_STYLE_IDS = [
|
|
|
46123
46141
|
"stop-motion-objects",
|
|
46124
46142
|
"miniature-diorama",
|
|
46125
46143
|
"sand-drawing",
|
|
46126
|
-
"generative-light-signal"
|
|
46144
|
+
"generative-light-signal",
|
|
46145
|
+
"satellite-briefing",
|
|
46146
|
+
"briefing-board",
|
|
46147
|
+
"lidar-survey",
|
|
46148
|
+
"white-model-projection",
|
|
46149
|
+
"data-physicalization",
|
|
46150
|
+
"exploded-teardown",
|
|
46151
|
+
"microscope-story",
|
|
46152
|
+
"archive-light-table"
|
|
46127
46153
|
];
|
|
46128
46154
|
var VIDEO_WORKFLOW_IDS = [
|
|
46129
46155
|
"product-proof",
|
|
@@ -46452,6 +46478,7 @@ var cameraKeyframe = external_exports.object({
|
|
|
46452
46478
|
/** Distance from the subject in scene units. */
|
|
46453
46479
|
distance: external_exports.number().gt(0).max(100)
|
|
46454
46480
|
});
|
|
46481
|
+
var imageKeyframe = external_exports.object({ image: blob, seconds: external_exports.number().min(0).max(20) });
|
|
46455
46482
|
var videoAsset = external_exports.object({
|
|
46456
46483
|
name: base.name,
|
|
46457
46484
|
/** Lip-sync and relight take no prompt, and camera-controls, insert-video, recast and 3d-to-video may leave it out. */
|
|
@@ -46478,6 +46505,8 @@ var videoAsset = external_exports.object({
|
|
|
46478
46505
|
referenceVideos: external_exports.array(blob).max(MAX_REFERENCE_VIDEOS).optional(),
|
|
46479
46506
|
/** The camera's path around the reference image: 2–12 keyframes. */
|
|
46480
46507
|
camera: external_exports.array(cameraKeyframe).min(2).max(MAX_CAMERA_KEYFRAMES).optional(),
|
|
46508
|
+
/** Keyframes-to-video: 1–10 images pinned to moments of the clip, each on a frame of its own. */
|
|
46509
|
+
keyframes: external_exports.array(imageKeyframe).min(1).max(MAX_IMAGE_KEYFRAMES).optional(),
|
|
46481
46510
|
/** Seconds into the source where the inserted scene starts, and where the source resumes after it. */
|
|
46482
46511
|
insertAt: external_exports.number().min(1.625).max(60).optional(),
|
|
46483
46512
|
resumeAt: external_exports.number().gt(1.625).max(60).optional(),
|
|
@@ -46521,6 +46550,7 @@ var TAKES = {
|
|
|
46521
46550
|
references: ["reference-to-video", "insert-video", "recast", "3d-to-video"],
|
|
46522
46551
|
referenceVideos: ["reference-to-video", "insert-video"],
|
|
46523
46552
|
camera: ["camera-controls"],
|
|
46553
|
+
keyframes: ["keyframes-to-video"],
|
|
46524
46554
|
insertAt: ["insert-video"],
|
|
46525
46555
|
resumeAt: ["insert-video"],
|
|
46526
46556
|
colorMatch: ["insert-video"],
|
|
@@ -46531,8 +46561,8 @@ var TAKES = {
|
|
|
46531
46561
|
generatedReferences: ["3d-to-video"],
|
|
46532
46562
|
style: ["style"],
|
|
46533
46563
|
damage: ["style"],
|
|
46534
|
-
aspectRatio: ["text-to-video", "extend-video", "reference-to-video", "relight", "style"],
|
|
46535
|
-
promptExpansion: ["image-to-video", "text-to-video", "extend-video", "reference-to-video", "camera-controls", "insert-video"],
|
|
46564
|
+
aspectRatio: ["text-to-video", "extend-video", "reference-to-video", "relight", "style", "keyframes-to-video"],
|
|
46565
|
+
promptExpansion: ["image-to-video", "text-to-video", "extend-video", "reference-to-video", "camera-controls", "insert-video", "keyframes-to-video"],
|
|
46536
46566
|
seed: ALL.filter((w) => w !== "3d-to-video"),
|
|
46537
46567
|
extendOutput: ["extend-video"]
|
|
46538
46568
|
};
|
|
@@ -46543,7 +46573,8 @@ var NEEDS = {
|
|
|
46543
46573
|
recast: ["source", "references", "subjectConsent"],
|
|
46544
46574
|
relight: ["source", "lighting"],
|
|
46545
46575
|
"3d-to-video": ["source"],
|
|
46546
|
-
style: ["style"]
|
|
46576
|
+
style: ["style"],
|
|
46577
|
+
"keyframes-to-video": ["keyframes"]
|
|
46547
46578
|
};
|
|
46548
46579
|
var LABELS = {
|
|
46549
46580
|
reference: "a starting image",
|
|
@@ -46556,6 +46587,7 @@ var LABELS = {
|
|
|
46556
46587
|
references: "reference images",
|
|
46557
46588
|
referenceVideos: "reference videos",
|
|
46558
46589
|
camera: "camera keyframes",
|
|
46590
|
+
keyframes: "keyframe images",
|
|
46559
46591
|
insertAt: "insertAt",
|
|
46560
46592
|
resumeAt: "resumeAt",
|
|
46561
46593
|
colorMatch: "colorMatch",
|
|
@@ -46641,6 +46673,11 @@ function videoChecks(p, ctx) {
|
|
|
46641
46673
|
const travel = p.camera.slice(1).reduce((sum, k, i2) => sum + Math.abs(k.azimuth - p.camera[i2].azimuth), 0);
|
|
46642
46674
|
if (travel > 360 * MAX_CAMERA_TURNS) issue2("camera", `The camera may travel at most ${MAX_CAMERA_TURNS} full turns around the subject.`);
|
|
46643
46675
|
}
|
|
46676
|
+
if (p.keyframes) {
|
|
46677
|
+
const frames = p.keyframes.map((k) => Math.round(k.seconds * KEYFRAME_FPS));
|
|
46678
|
+
if (new Set(frames).size !== frames.length) issue2("keyframes", `Put each keyframe on a frame of its own; the video has ${KEYFRAME_FPS} frames a second.`);
|
|
46679
|
+
if (p.keyframes.some((k) => k.seconds > seconds2)) issue2("keyframes", "Put each keyframe within the video's length.");
|
|
46680
|
+
}
|
|
46644
46681
|
}
|
|
46645
46682
|
var defaultSeconds = (model, workflow) => {
|
|
46646
46683
|
const r = videoSeconds(model, workflow);
|
|
@@ -47112,7 +47149,7 @@ var CLOUD_PART_BYTES = 8 * 1024 * 1024;
|
|
|
47112
47149
|
var CLOUD_MANIFEST_PATH = ".animaguru-cloud.json";
|
|
47113
47150
|
var CLOUD_MANIFEST_MAX_BYTES = 16 * 1024 * 1024;
|
|
47114
47151
|
var CLOUD_MAX_FILES = 5e4;
|
|
47115
|
-
var CLOUD_STORAGE_BYTES = { pro: 20 * 1024 ** 3, team: 100 * 1024 ** 3 };
|
|
47152
|
+
var CLOUD_STORAGE_BYTES = { starter: 5 * 1024 ** 3, pro: 20 * 1024 ** 3, team: 100 * 1024 ** 3 };
|
|
47116
47153
|
var cloudProjectId = external_exports.string().regex(/^prj_[A-Za-z0-9]{8,40}$/, "Use a project ID such as prj_\u2026.");
|
|
47117
47154
|
var sha256Hex = external_exports.string().regex(/^[a-f0-9]{64}$/, "Use a lowercase SHA-256 hex digest.");
|
|
47118
47155
|
var gitObjectId = external_exports.string().regex(/^[a-f0-9]{40}$/, "Use a full 40-character version ID.");
|
|
@@ -47917,6 +47954,7 @@ var extras = {
|
|
|
47917
47954
|
"middle-reference",
|
|
47918
47955
|
"middle-seconds",
|
|
47919
47956
|
"camera",
|
|
47957
|
+
"keyframes",
|
|
47920
47958
|
"insert-at",
|
|
47921
47959
|
"resume-at",
|
|
47922
47960
|
"color-match",
|
|
@@ -47951,11 +47989,16 @@ var regions = (value) => value?.split(";").filter((region) => region.trim()).map
|
|
|
47951
47989
|
if (rest.length || [x2, y, width, height].some((n) => !Number.isFinite(n))) throw new Error(`--mask regions are x,y,width,height in fractions of Image 1, separated by semicolons; "${region.trim()}" is not.`);
|
|
47952
47990
|
return { x: x2, y, width, height };
|
|
47953
47991
|
});
|
|
47954
|
-
var
|
|
47992
|
+
var cameraKeyframes = (value) => value?.split(";").filter((frame) => frame.trim()).map((frame) => {
|
|
47955
47993
|
const [time3, azimuth, elevation, distance, ...rest] = frame.split(",").map((n) => n.trim() ? Number(n) : NaN);
|
|
47956
47994
|
if (rest.length || [time3, azimuth, elevation, distance].some((n) => !Number.isFinite(n))) throw new Error(`--camera keyframes are time,azimuth,elevation,distance (time 0\u20131, angles in degrees), separated by semicolons; "${frame.trim()}" is not.`);
|
|
47957
47995
|
return { time: time3, azimuth, elevation, distance };
|
|
47958
47996
|
});
|
|
47997
|
+
var imageKeyframes = (value) => value?.split(";").filter((frame) => frame.trim()).map((frame) => {
|
|
47998
|
+
const [seconds2, image, ...rest] = frame.split(",").map((part) => part.trim());
|
|
47999
|
+
if (rest.length || !image || !seconds2 || !Number.isFinite(Number(seconds2))) throw new Error(`--keyframes are seconds,image SHA pairs separated by semicolons, e.g. "0,SHA;5,SHA"; "${frame.trim()}" is not.`);
|
|
48000
|
+
return { image, seconds: Number(seconds2) };
|
|
48001
|
+
});
|
|
47959
48002
|
function assetFromFlags(flags) {
|
|
47960
48003
|
if (flags.type === "image" && flags.model) throw new Error("Image models are managed by staff. Omit --model.");
|
|
47961
48004
|
for (const name2 of Object.values(extras).flat()) {
|
|
@@ -47978,7 +48021,8 @@ function assetFromFlags(flags) {
|
|
|
47978
48021
|
referenceVideos: shas(flags["reference-videos"]),
|
|
47979
48022
|
middleReference: flags["middle-reference"],
|
|
47980
48023
|
middleSeconds: flags["middle-seconds"],
|
|
47981
|
-
camera:
|
|
48024
|
+
camera: cameraKeyframes(flags.camera),
|
|
48025
|
+
keyframes: imageKeyframes(flags.keyframes),
|
|
47982
48026
|
insertAt: flags["insert-at"],
|
|
47983
48027
|
resumeAt: flags["resume-at"],
|
|
47984
48028
|
colorMatch: flags["color-match"],
|
|
@@ -48688,8 +48732,8 @@ async function youtubeLogin(options) {
|
|
|
48688
48732
|
let receive;
|
|
48689
48733
|
let fail;
|
|
48690
48734
|
let used = false;
|
|
48691
|
-
const callback = new Promise((
|
|
48692
|
-
receive =
|
|
48735
|
+
const callback = new Promise((resolve18, reject) => {
|
|
48736
|
+
receive = resolve18;
|
|
48693
48737
|
fail = reject;
|
|
48694
48738
|
});
|
|
48695
48739
|
void callback.catch(() => {
|
|
@@ -48727,9 +48771,9 @@ async function youtubeLogin(options) {
|
|
|
48727
48771
|
response.end("Authorization received. Return to your AnimaGuru terminal.");
|
|
48728
48772
|
receive(code);
|
|
48729
48773
|
});
|
|
48730
|
-
await new Promise((
|
|
48774
|
+
await new Promise((resolve18, reject) => {
|
|
48731
48775
|
server.once("error", reject);
|
|
48732
|
-
server.listen(0, "127.0.0.1",
|
|
48776
|
+
server.listen(0, "127.0.0.1", resolve18);
|
|
48733
48777
|
});
|
|
48734
48778
|
const address = server.address();
|
|
48735
48779
|
if (!address || typeof address === "string") throw new Error("Cannot open the local YouTube authorization listener.");
|
|
@@ -48764,7 +48808,7 @@ async function youtubeLogin(options) {
|
|
|
48764
48808
|
clearTimeout(timer);
|
|
48765
48809
|
options.signal?.removeEventListener("abort", abort);
|
|
48766
48810
|
server.closeAllConnections();
|
|
48767
|
-
await new Promise((
|
|
48811
|
+
await new Promise((resolve18) => server.close(() => resolve18()));
|
|
48768
48812
|
}
|
|
48769
48813
|
});
|
|
48770
48814
|
}
|
|
@@ -49868,6 +49912,114 @@ async function referenceGet(client, id2, options) {
|
|
|
49868
49912
|
return report(options.wait ? await finished(client, analysis, options.log) : analysis, options);
|
|
49869
49913
|
}
|
|
49870
49914
|
|
|
49915
|
+
// cli/src/curl.ts
|
|
49916
|
+
import { createWriteStream as createWriteStream2, openAsBlob as openAsBlob2 } from "node:fs";
|
|
49917
|
+
import { readFile as readFile18, unlink as unlink3 } from "node:fs/promises";
|
|
49918
|
+
import { extname as extname4, resolve as resolve16 } from "node:path";
|
|
49919
|
+
import { Readable as Readable2 } from "node:stream";
|
|
49920
|
+
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
49921
|
+
function curlUrl(server, target2) {
|
|
49922
|
+
const origin = serverUrl(server);
|
|
49923
|
+
const url3 = target2.startsWith("/") && !target2.startsWith("//") ? new URL(target2, origin) : URL.canParse(target2) ? new URL(target2) : null;
|
|
49924
|
+
if (!url3 || url3.origin !== origin || url3.username || url3.password) throw new Error(`animaguru curl calls only ${origin}. Pass a path such as /api/v1/me.`);
|
|
49925
|
+
return url3;
|
|
49926
|
+
}
|
|
49927
|
+
function curlHeaders(lines = []) {
|
|
49928
|
+
const headers = new Headers();
|
|
49929
|
+
for (const line of lines) {
|
|
49930
|
+
const colon = line.indexOf(":");
|
|
49931
|
+
const name2 = colon > 0 ? line.slice(0, colon).trim() : "";
|
|
49932
|
+
if (!name2) throw new Error(`Write headers as "Name: value", not "${line}".`);
|
|
49933
|
+
if (/^(authorization|host)$/i.test(name2)) throw new Error(`Leave out the ${name2} header; animaguru curl sends the signed-in session's.`);
|
|
49934
|
+
headers.append(name2, line.slice(colon + 1).trim());
|
|
49935
|
+
}
|
|
49936
|
+
return headers;
|
|
49937
|
+
}
|
|
49938
|
+
var UPLOAD_TYPES = {
|
|
49939
|
+
".mp4": "video/mp4",
|
|
49940
|
+
".webm": "video/webm",
|
|
49941
|
+
".mov": "video/quicktime",
|
|
49942
|
+
".jpg": "image/jpeg",
|
|
49943
|
+
".jpeg": "image/jpeg",
|
|
49944
|
+
".png": "image/png",
|
|
49945
|
+
".webp": "image/webp",
|
|
49946
|
+
".gif": "image/gif",
|
|
49947
|
+
".json": "application/json",
|
|
49948
|
+
".txt": "text/plain"
|
|
49949
|
+
};
|
|
49950
|
+
var isText = (type) => /^(text\/|application\/([\w.+-]*\+)?(json|xml)\b|application\/(javascript|x-www-form-urlencoded)\b)/i.test(type);
|
|
49951
|
+
var readStdin = async () => {
|
|
49952
|
+
const chunks = [];
|
|
49953
|
+
for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
|
|
49954
|
+
return Buffer.concat(chunks);
|
|
49955
|
+
};
|
|
49956
|
+
async function bodyValue(value, io) {
|
|
49957
|
+
if (value === "@-") return (io.stdin ?? readStdin)();
|
|
49958
|
+
return value.startsWith("@") ? readFile18(resolve16(value.slice(1))) : value;
|
|
49959
|
+
}
|
|
49960
|
+
var parsesAsJson = (body) => {
|
|
49961
|
+
try {
|
|
49962
|
+
JSON.parse(body.toString());
|
|
49963
|
+
return true;
|
|
49964
|
+
} catch {
|
|
49965
|
+
return false;
|
|
49966
|
+
}
|
|
49967
|
+
};
|
|
49968
|
+
async function curl(options, io) {
|
|
49969
|
+
const url3 = curlUrl(options.server, options.target);
|
|
49970
|
+
const headers = curlHeaders(options.header);
|
|
49971
|
+
if ([options.data, options.json, options.uploadFile].filter((value) => value !== void 0).length > 1) throw new Error("Use one of --data, --json and --upload-file.");
|
|
49972
|
+
let body;
|
|
49973
|
+
if (options.uploadFile !== void 0) {
|
|
49974
|
+
const file2 = resolve16(options.uploadFile);
|
|
49975
|
+
body = await openAsBlob2(file2);
|
|
49976
|
+
if (!headers.has("content-type")) headers.set("Content-Type", UPLOAD_TYPES[extname4(file2).toLowerCase()] ?? "application/octet-stream");
|
|
49977
|
+
} else if (options.json !== void 0) {
|
|
49978
|
+
body = await bodyValue(options.json, io);
|
|
49979
|
+
if (!headers.has("content-type")) headers.set("Content-Type", "application/json");
|
|
49980
|
+
if (!headers.has("accept")) headers.set("Accept", "application/json");
|
|
49981
|
+
} else if (options.data !== void 0) {
|
|
49982
|
+
body = await bodyValue(options.data, io);
|
|
49983
|
+
if (!headers.has("content-type")) headers.set("Content-Type", parsesAsJson(body) ? "application/json" : "application/x-www-form-urlencoded");
|
|
49984
|
+
}
|
|
49985
|
+
headers.set("Authorization", `Bearer ${await sessionToken(url3.origin)}`);
|
|
49986
|
+
if (!headers.has("origin")) headers.set("Origin", url3.origin);
|
|
49987
|
+
const method = (options.request ?? (options.uploadFile !== void 0 ? "PUT" : body !== void 0 ? "POST" : "GET")).toUpperCase();
|
|
49988
|
+
const timeout = AbortSignal.timeout(options.maxTime * 1e3);
|
|
49989
|
+
const response = await fetch(url3, { method, headers, body, redirect: "manual", signal: io.signal ? AbortSignal.any([io.signal, timeout]) : timeout });
|
|
49990
|
+
if (options.include) io.stdout([`HTTP ${response.status} ${response.statusText}`.trim(), ...[...response.headers].map(([name2, value]) => `${name2}: ${value}`), ""].join("\n"));
|
|
49991
|
+
const type = response.headers.get("content-type") ?? "";
|
|
49992
|
+
const failed = options.fail && response.status >= 400;
|
|
49993
|
+
if (options.output !== void 0 && !failed) {
|
|
49994
|
+
const file2 = resolve16(options.output);
|
|
49995
|
+
let bytes = 0;
|
|
49996
|
+
try {
|
|
49997
|
+
await pipeline2(
|
|
49998
|
+
response.body ? Readable2.fromWeb(response.body) : Readable2.from([]),
|
|
49999
|
+
async function* (chunks) {
|
|
50000
|
+
for await (const chunk of chunks) {
|
|
50001
|
+
bytes += chunk.length;
|
|
50002
|
+
yield chunk;
|
|
50003
|
+
}
|
|
50004
|
+
},
|
|
50005
|
+
createWriteStream2(file2, { flags: "wx" })
|
|
50006
|
+
);
|
|
50007
|
+
} catch (error62) {
|
|
50008
|
+
if (error62.code === "EEXIST") throw new Error(`${options.output} already exists; choose another --output.`);
|
|
50009
|
+
await unlink3(file2).catch(() => void 0);
|
|
50010
|
+
throw error62;
|
|
50011
|
+
}
|
|
50012
|
+
io.stdout(JSON.stringify({ status: response.status, contentType: type || null, bytes, file: file2 }));
|
|
50013
|
+
} else if (!response.body || isText(type) || failed) {
|
|
50014
|
+
const text2 = await response.text();
|
|
50015
|
+
if (text2) io.stdout(text2.replace(/\n$/, ""));
|
|
50016
|
+
} else {
|
|
50017
|
+
await response.body.cancel();
|
|
50018
|
+
throw new Error(`The response is ${type || "binary"} (HTTP ${response.status}). Save it with -o FILE.`);
|
|
50019
|
+
}
|
|
50020
|
+
if (failed) throw new Error(`HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""} from ${method} ${url3.pathname}.`);
|
|
50021
|
+
}
|
|
50022
|
+
|
|
49871
50023
|
// cli/src/commands.ts
|
|
49872
50024
|
var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id)];
|
|
49873
50025
|
var assetAuthorizationFlags = [
|
|
@@ -49918,12 +50070,12 @@ var workspaceQuery = async (client) => {
|
|
|
49918
50070
|
async function openBrowser(url3) {
|
|
49919
50071
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32" : "xdg-open";
|
|
49920
50072
|
const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url3] : [url3];
|
|
49921
|
-
await new Promise((
|
|
50073
|
+
await new Promise((resolve18) => {
|
|
49922
50074
|
const child = spawn3(command, args, { stdio: "ignore", detached: true });
|
|
49923
|
-
child.once("error", () =>
|
|
50075
|
+
child.once("error", () => resolve18());
|
|
49924
50076
|
child.once("spawn", () => {
|
|
49925
50077
|
child.unref();
|
|
49926
|
-
|
|
50078
|
+
resolve18();
|
|
49927
50079
|
});
|
|
49928
50080
|
});
|
|
49929
50081
|
}
|
|
@@ -50024,7 +50176,7 @@ function createCli() {
|
|
|
50024
50176
|
).action(async ({ args, flags, stdout, signal }) => out(stdout, await changeVideoSubtitles(new Client(flags.url, signal), args.id, flags))))).add(defineCommand("delete", { description: "Remove a video and its hosted files" }, (command) => command.args({ name: "id", type: "string", required: true }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }, { name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
50025
50177
|
if (!flags.yes) throw new Error("Pass --yes to delete the video.");
|
|
50026
50178
|
out(stdout, await new Client(flags.url, signal).request(`/api/v1/videos/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
|
|
50027
|
-
})))).command("cloud", (cloud) => cloud.add(defineCommand("list", { description: "List projects with synced animations in the selected workspace, with plan and storage (Individual Pro and Team)" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).action(async ({ flags, stdout, signal }) => {
|
|
50179
|
+
})))).command("cloud", (cloud) => cloud.add(defineCommand("list", { description: "List projects with synced animations in the selected workspace, with plan and storage (Individual Starter, Individual Pro and Team)" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).action(async ({ flags, stdout, signal }) => {
|
|
50028
50180
|
const client = new Client(flags.url, signal);
|
|
50029
50181
|
out(stdout, await client.request(`/api/v1/cloud${await workspaceQuery(client)}`));
|
|
50030
50182
|
}))).add(defineCommand("link", { description: "Sync this video workspace with a project's animations: --project for an existing project, or a new project in the selected workspace" }, (command) => command.flags(
|
|
@@ -50042,7 +50194,31 @@ function createCli() {
|
|
|
50042
50194
|
}))).add(defineCommand("restore", { description: "Make the folder, or --path parts of it, match an earlier version; push afterwards to save it as the newest" }, (command) => command.args({ name: "version", type: "string", required: true, description: "Version ID or its first characters" }).flags({ name: "dir", type: "string", default: "." }, { name: "path", type: "string", multiple: true, description: "File or folder to restore; repeatable" }, { name: "yes", type: "boolean", description: "Replace unsaved local changes (copies are kept)" }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await restoreCloud({ dir: flags.dir, version: args.version, paths: flags.path, yes: flags.yes, log: stderr, signal }))))).add(defineCommand("clone", { description: "Download the newest version of a project's animations into a new folder" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Project ID" }, { name: "directory", type: "string", description: "New folder; defaults to the project name" }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await cloneCloud(new Client(flags.url, signal), { id: args.id, dir: args.directory, log: stderr, signal }))))).add(defineCommand("unlink", { description: "Stop syncing this folder; the project's animations and versions stay" }, (command) => command.flags({ name: "dir", type: "string", default: "." }).action(async ({ flags, stdout }) => out(stdout, await unlinkCloud({ dir: flags.dir }))))).add(defineCommand("delete", { description: "Delete a project's animations with all their versions, drafts and stored files; the project and its assets stay. Requires --yes" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Project ID" }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }, { name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
50043
50195
|
if (!flags.yes) throw new Error("Pass --yes to delete the project's animations and every saved version.");
|
|
50044
50196
|
out(stdout, await new Client(flags.url, signal).request(`/api/v1/cloud/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
|
|
50045
|
-
})))).
|
|
50197
|
+
})))).add(defineCommand("curl", { description: "Call an AnimaGuru API path as the signed-in user with curl's flags; the server and the session's token are added for you. Prints the response body, or saves it with -o" }, (command) => command.args({ name: "path", type: "string", required: true, description: "API path such as /api/v1/me (with any query string), or a full URL on the server" }).flags(
|
|
50198
|
+
{ name: "request", short: "X", type: "string", description: "HTTP method; GET by default, POST with --data or --json, PUT with --upload-file" },
|
|
50199
|
+
{ name: "header", short: "H", type: "string", multiple: true, description: '"Name: value" request header; repeatable. Authorization is added for you' },
|
|
50200
|
+
{ name: "data", short: "d", type: "string", aliases: ["data-binary"], description: "Request body: text, @FILE or @- for standard input. JSON is sent as application/json" },
|
|
50201
|
+
{ name: "json", type: "string", description: "JSON body (text, @FILE or @-) with JSON Content-Type and Accept headers" },
|
|
50202
|
+
{ name: "upload-file", short: "T", type: "string", description: "Stream a file as the body (PUT unless -X); Content-Type follows its extension unless -H sets one" },
|
|
50203
|
+
{ name: "output", short: "o", type: "string", description: "Save the response body to a new file and print a JSON summary; needed for video and images" },
|
|
50204
|
+
{ name: "include", short: "i", type: "boolean", noNegate: true, description: "Print the status line and response headers first" },
|
|
50205
|
+
{ name: "fail", short: "f", type: "boolean", default: true, description: "Exit non-zero on HTTP 4xx and 5xx after printing the body; --no-fail exits 0 like plain curl" },
|
|
50206
|
+
{ name: "silent", short: "s", type: "boolean", noNegate: true, description: "Accepted for curl compatibility; nothing else is printed anyway" },
|
|
50207
|
+
{ name: "max-time", short: "m", type: "number", default: 600, description: "Maximum seconds for the whole request" },
|
|
50208
|
+
{ name: "server", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }
|
|
50209
|
+
).action(async ({ args, flags, stdout, signal }) => curl({
|
|
50210
|
+
server: flags.server,
|
|
50211
|
+
target: args.path,
|
|
50212
|
+
request: flags.request,
|
|
50213
|
+
header: flags.header,
|
|
50214
|
+
data: flags.data,
|
|
50215
|
+
json: flags.json,
|
|
50216
|
+
uploadFile: flags["upload-file"],
|
|
50217
|
+
output: flags.output,
|
|
50218
|
+
include: flags.include,
|
|
50219
|
+
fail: flags.fail,
|
|
50220
|
+
maxTime: flags["max-time"]
|
|
50221
|
+
}, { stdout, signal })))).command("auth", (auth) => auth.add(defineCommand("login", { description: "Approve a browser sign-in and save a seven-day CLI session" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).flags({ name: "browser", type: "boolean", default: true, description: "Open the browser; --no-browser prints the URL only" }).action(async ({ flags, stdout, stderr, signal }) => {
|
|
50046
50222
|
const client = new Client(flags.url, signal);
|
|
50047
50223
|
const device = await client.request("/api/auth/device/code", { method: "POST", authenticated: false, body: { client_id: CLI_CLIENT_ID } });
|
|
50048
50224
|
stderr(`Open ${device.verification_uri_complete}
|
|
@@ -50164,11 +50340,11 @@ Confirm code: ${device.user_code}`);
|
|
|
50164
50340
|
{ name: "name", type: "string", required: true },
|
|
50165
50341
|
{ 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" },
|
|
50166
50342
|
{ name: "model", type: "string", choices: assetModelIds, description: "Model for the chosen asset type" },
|
|
50167
|
-
{ 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 and
|
|
50343
|
+
{ 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" },
|
|
50168
50344
|
{ name: "transparent", type: "boolean", description: "Image: transparent background" },
|
|
50169
50345
|
{ 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)" },
|
|
50170
50346
|
{ 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" },
|
|
50171
|
-
{ 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, as the model's videoProfiles allow" },
|
|
50347
|
+
{ 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" },
|
|
50172
50348
|
{ 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" },
|
|
50173
50349
|
{ name: "end-reference", type: "string", description: "Video: ending image blob SHA; models with endFrameOnly accept it without --reference" },
|
|
50174
50350
|
{ name: "middle-reference", type: "string", description: "Reference-to-video: image blob SHA reached at --middle-seconds; needs --reference and --end-reference, 480p or 768p" },
|
|
@@ -50178,6 +50354,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50178
50354
|
{ 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" },
|
|
50179
50355
|
{ 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" },
|
|
50180
50356
|
{ name: "camera", type: "string", description: 'Camera-controls: 2\u201312 keyframes time,azimuth,elevation,distance (time 0\u20131, angles in degrees, elevation \u221290\u201390) separated by semicolons, e.g. "0,0,0,1;1,90,15,1.2"' },
|
|
50357
|
+
{ name: "keyframes", type: "string", description: 'Keyframes-to-video (FLUX 3 Max): 1\u201310 seconds,image-SHA pairs separated by semicolons, e.g. "0,SHA;2.5,SHA;5,SHA"; each image is reached at its second, on a frame of its own of the 24 fps clip, within --seconds' },
|
|
50181
50358
|
{ name: "insert-at", type: "number", description: "Insert-video: seconds into --source where the new scene starts (1.625\u201360)" },
|
|
50182
50359
|
{ name: "resume-at", type: "number", description: "Insert-video: seconds into --source where it resumes after the scene" },
|
|
50183
50360
|
{ name: "color-match", type: "boolean", description: "Insert-video: match the scene's colors to the source (default on; --no-color-match turns it off)" },
|
|
@@ -50188,10 +50365,10 @@ Confirm code: ${device.user_code}`);
|
|
|
50188
50365
|
{ name: "generated-references", type: "number", description: "3d-to-video without --references: how many reference images it may draw, 1\u20138 (default 2)" },
|
|
50189
50366
|
{ name: "style", type: "string", choices: VIDEO_STYLES, description: "Style workflow: the preset look, at 768p for 5\u201315 whole seconds" },
|
|
50190
50367
|
{ name: "damage", type: "string", choices: VHS_DAMAGE_LEVELS, description: "VHS style: tape damage (fal's default medium)" },
|
|
50191
|
-
{ name: "seconds", type: "number", description: "Video or SFX duration in seconds (default 5); H3 takes fractions (6.5); extensions add this many seconds, insert-video's scene is 5\u201313; lip-sync, recast, relight and 3d-to-video take their input's length; SFX supports 0.5\u201330" },
|
|
50368
|
+
{ name: "seconds", type: "number", description: "Video or SFX duration in seconds (default 5); H3 takes fractions (6.5), FLUX 3 Max 5\u201320 whole seconds; extensions add this many seconds, insert-video's scene is 5\u201313; lip-sync, recast, relight and 3d-to-video take their input's length; SFX supports 0.5\u201330" },
|
|
50192
50369
|
{ name: "resolution", type: "string", choices: VIDEO_RESOLUTIONS, description: "Video resolution supported by the selected model and workflow (default its first)" },
|
|
50193
50370
|
{ name: "mode", type: "string", choices: ["cost", "speed", "quality"], description: "Video generation mode supported by the selected model (default its first)" },
|
|
50194
|
-
{ 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" },
|
|
50371
|
+
{ 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" },
|
|
50195
50372
|
{ name: "seed", type: "number", description: "Video: seed for repeatable results, where the model takes one" },
|
|
50196
50373
|
{ 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)" },
|
|
50197
50374
|
{ name: "voice", type: "string", description: "Gemini voice name or ElevenLabs voice ID (defaults: Kore / George)" },
|
|
@@ -50243,7 +50420,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50243
50420
|
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" }));
|
|
50244
50421
|
})))).command("jobs", (jobs) => jobs.add(defineCommand("list", { description: "List the latest generation jobs" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/jobs`))))).add(defineCommand("submit", { description: "Submit a typed JSON job: character, animate, custom or redraw; spends credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags(...modelFlags).flags({ name: "file", type: "string", required: true, description: "JSON job file" }, { name: "yes", type: "boolean", required: true, description: "Authorize spending credits" }).action(async ({ args, flags, stdout, signal }) => {
|
|
50245
50422
|
if (!flags.yes) throw new Error("Pass --yes to authorize spending credits.");
|
|
50246
|
-
const body = spriteJobBody.parse({ ...JSON.parse(await
|
|
50423
|
+
const body = spriteJobBody.parse({ ...JSON.parse(await readFile19(flags.file, "utf8")), ...selectedModels(flags) });
|
|
50247
50424
|
out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/jobs`, { method: "POST", body }));
|
|
50248
50425
|
}))).add(defineCommand("wait", { description: "Wait for a specific job; fail if generation fails or times out" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id, { name: "job", type: "string", required: true }).flags({ name: "timeout", type: "number", default: 600, description: "Maximum seconds to wait" }).action(async ({ args, flags, stdout, signal }) => out(stdout, { job: await waitForJob(new Client(flags.url, signal), args.id, args.job, flags.timeout, signal) }))))).add(defineCommand("models", { description: "Set the default video model for future project jobs" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags(...modelFlags).action(async ({ args, flags, stdout, signal }) => {
|
|
50249
50426
|
const body = selectedModels(flags);
|
|
@@ -50258,7 +50435,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50258
50435
|
const extension = flags.file.split(".").at(-1)?.toLowerCase();
|
|
50259
50436
|
const type = extension === "png" ? "image/png" : extension === "jpg" || extension === "jpeg" ? "image/jpeg" : extension === "webp" ? "image/webp" : void 0;
|
|
50260
50437
|
if (!type) throw new Error("Use a PNG, JPEG or WebP image.");
|
|
50261
|
-
const bytes = await
|
|
50438
|
+
const bytes = await readFile19(flags.file);
|
|
50262
50439
|
if (bytes.length > 10 * 1024 * 1024) throw new Error("Image must be at most 10 MB.");
|
|
50263
50440
|
const form = new FormData();
|
|
50264
50441
|
form.set("image", new Blob([bytes], { type }), `reference.${extension}`);
|
|
@@ -50274,7 +50451,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50274
50451
|
if (!file2) throw new Error(`No file at ${args.path} in this project. List them with animaguru files list.`);
|
|
50275
50452
|
if (!/^[a-f0-9]{64}$/.test(file2.sha)) throw new Error("Invalid blob hash in manifest.");
|
|
50276
50453
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
50277
|
-
const path =
|
|
50454
|
+
const path = resolve17(flags.output);
|
|
50278
50455
|
await mkdir15(dirname14(path), { recursive: true });
|
|
50279
50456
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
50280
50457
|
await writeFile16(path, bytes, { flag: "wx" });
|
|
@@ -50289,7 +50466,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50289
50466
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
50290
50467
|
entries[path2] = new Uint8Array(await response.arrayBuffer());
|
|
50291
50468
|
}
|
|
50292
|
-
const path =
|
|
50469
|
+
const path = resolve17(flags.output);
|
|
50293
50470
|
await writeFile16(path, zipSync(entries, { level: 0 }), { flag: "wx" });
|
|
50294
50471
|
out(stdout, { path, files: manifest.files.length });
|
|
50295
50472
|
})))).extend(version(package_default.version, { format: "plain" })).extend(help()).extend(completion());
|