@docyrus/animaguru 0.27.0 → 0.29.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 +28 -2
- package/dist/animaguru.js +933 -664
- package/package.json +1 -1
- package/skills/animaguru/SKILL.md +4 -1
- package/skills/animaguru-3d-models/SKILL.md +86 -0
- package/skills/animaguru-character-stage-3d/SKILL.md +35 -0
- package/skills/animaguru-character-stage-3d/references/recipe.md +26 -0
- package/skills/animaguru-exploded-teardown-3d/SKILL.md +38 -0
- package/skills/animaguru-exploded-teardown-3d/references/recipe.md +20 -0
- package/skills/animaguru-product-turntable-3d/SKILL.md +38 -0
- package/skills/animaguru-product-turntable-3d/references/recipe.md +27 -0
- package/skills/animaguru-quiz/SKILL.md +1 -1
- package/skills/animaguru-toy-diorama-3d/SKILL.md +33 -0
- package/skills/animaguru-toy-diorama-3d/references/recipe.md +26 -0
- package/skills/animaguru-video/SKILL.md +2 -2
- package/templates/video/AGENTS.md +1 -1
- package/templates/video/README.md +5 -1
- package/templates/video/package.json +3 -1
- package/templates/video/scripts/export-mp4.mjs +2 -2
- package/templates/video/scripts/install-example.mjs +10 -6
- package/templates/video/shared/locales/en/style-studies.json +35 -0
- package/templates/video/shared/locales/en/timeline.json +1 -0
- package/templates/video/src/kit/index.ts +1 -0
- package/templates/video/src/kit/three-stage.ts +262 -0
- package/templates/video/src/resource-timeline.ts +1 -0
- package/templates/video/src/studies/three/character-stage-3d.ts +172 -0
- package/templates/video/src/studies/three/exploded-teardown-3d.ts +214 -0
- package/templates/video/src/studies/three/index.ts +16 -0
- package/templates/video/src/studies/three/product-turntable-3d.ts +160 -0
- package/templates/video/src/studies/three/toy-diorama-3d.ts +245 -0
- package/templates/video/src/studies/three-film.ts +42 -0
- package/templates/video/src/style.css +2 -1
- package/templates/video/src/timeline-model.ts +1 -1
package/dist/animaguru.js
CHANGED
|
@@ -369,19 +369,19 @@ function jsonInstabilityIssues(document2) {
|
|
|
369
369
|
return issues;
|
|
370
370
|
}
|
|
371
371
|
function createStore(options) {
|
|
372
|
-
const { dirPath, name: name2, fields, pruneUnknown, access:
|
|
372
|
+
const { dirPath, name: name2, fields, pruneUnknown, access: access4 } = options;
|
|
373
373
|
const validators = /* @__PURE__ */ new Map();
|
|
374
374
|
for (const [key, def] of Object.entries(fields)) if (def.schema !== void 0) {
|
|
375
375
|
for (const option of ["default", "validate"]) if (def[option] !== void 0) throw new CrustStoreError("DEFINITION", `field "${key}" mixes "schema" with "${option}" \u2014 the schema exclusively owns validation, transformation, defaults, and optionality`);
|
|
376
376
|
validators.set(key, makeSchemaValidator(def.schema));
|
|
377
377
|
} else if (def.validate !== void 0) validators.set(key, def.validate);
|
|
378
378
|
const filePath = resolveStorePath(dirPath, name2);
|
|
379
|
-
const writeOptions =
|
|
379
|
+
const writeOptions = access4 === "private" ? {
|
|
380
380
|
fileMode: 384,
|
|
381
381
|
directoryMode: 448
|
|
382
|
-
} :
|
|
383
|
-
fileMode:
|
|
384
|
-
directoryMode:
|
|
382
|
+
} : access4 === void 0 || access4 === "default" ? {} : {
|
|
383
|
+
fileMode: access4.file,
|
|
384
|
+
directoryMode: access4.directory
|
|
385
385
|
};
|
|
386
386
|
function normalizeStateTypes(state) {
|
|
387
387
|
const normalized = { ...state };
|
|
@@ -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(resolve19, reject) {
|
|
2316
|
+
deferredResolve = resolve19;
|
|
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(resolve19, 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
|
+
resolve19(ret);
|
|
2471
2471
|
}
|
|
2472
2472
|
});
|
|
2473
2473
|
} else {
|
|
2474
|
-
|
|
2474
|
+
resolve19(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((resolve19, 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
|
+
resolve19(result);
|
|
6874
6874
|
}
|
|
6875
6875
|
} else {
|
|
6876
|
-
|
|
6876
|
+
resolve19(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
|
+
resolve19(result);
|
|
6885
6885
|
}
|
|
6886
6886
|
});
|
|
6887
6887
|
} else {
|
|
6888
|
-
args.push(
|
|
6888
|
+
args.push(resolve19);
|
|
6889
6889
|
}
|
|
6890
6890
|
fn.apply(this, args);
|
|
6891
6891
|
});
|
|
@@ -8083,17 +8083,17 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8083
8083
|
const length = Math.ceil((62 + bpath.length + 1) / 8) * 8;
|
|
8084
8084
|
const written = Buffer.alloc(length);
|
|
8085
8085
|
const writer = new BufferCursor(written);
|
|
8086
|
-
const
|
|
8087
|
-
writer.writeUInt32BE(
|
|
8088
|
-
writer.writeUInt32BE(
|
|
8089
|
-
writer.writeUInt32BE(
|
|
8090
|
-
writer.writeUInt32BE(
|
|
8091
|
-
writer.writeUInt32BE(
|
|
8092
|
-
writer.writeUInt32BE(
|
|
8093
|
-
writer.writeUInt32BE(
|
|
8094
|
-
writer.writeUInt32BE(
|
|
8095
|
-
writer.writeUInt32BE(
|
|
8096
|
-
writer.writeUInt32BE(
|
|
8086
|
+
const stat12 = normalizeStats(entry);
|
|
8087
|
+
writer.writeUInt32BE(stat12.ctimeSeconds);
|
|
8088
|
+
writer.writeUInt32BE(stat12.ctimeNanoseconds);
|
|
8089
|
+
writer.writeUInt32BE(stat12.mtimeSeconds);
|
|
8090
|
+
writer.writeUInt32BE(stat12.mtimeNanoseconds);
|
|
8091
|
+
writer.writeUInt32BE(stat12.dev);
|
|
8092
|
+
writer.writeUInt32BE(stat12.ino);
|
|
8093
|
+
writer.writeUInt32BE(stat12.mode);
|
|
8094
|
+
writer.writeUInt32BE(stat12.uid);
|
|
8095
|
+
writer.writeUInt32BE(stat12.gid);
|
|
8096
|
+
writer.writeUInt32BE(stat12.size);
|
|
8097
8097
|
writer.write(entry.oid, 20, "hex");
|
|
8098
8098
|
writer.writeUInt16BE(renderCacheEntryFlags(entry));
|
|
8099
8099
|
writer.write(entry.path, bpath.length, "utf8");
|
|
@@ -8145,13 +8145,13 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8145
8145
|
};
|
|
8146
8146
|
}
|
|
8147
8147
|
async function updateCachedIndexFile(fs2, filepath, cache) {
|
|
8148
|
-
const [
|
|
8148
|
+
const [stat12, rawIndexFile] = await Promise.all([
|
|
8149
8149
|
fs2.lstat(filepath),
|
|
8150
8150
|
fs2.read(filepath)
|
|
8151
8151
|
]);
|
|
8152
8152
|
const index3 = await GitIndex.from(rawIndexFile);
|
|
8153
8153
|
cache.map.set(filepath, index3);
|
|
8154
|
-
cache.stats.set(filepath,
|
|
8154
|
+
cache.stats.set(filepath, stat12);
|
|
8155
8155
|
}
|
|
8156
8156
|
async function isIndexStale(fs2, filepath, cache) {
|
|
8157
8157
|
const savedStats = cache.stats.get(filepath);
|
|
@@ -8208,7 +8208,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8208
8208
|
}
|
|
8209
8209
|
return path;
|
|
8210
8210
|
}
|
|
8211
|
-
function
|
|
8211
|
+
function dirname16(path) {
|
|
8212
8212
|
const last = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
8213
8213
|
if (last === -1) return ".";
|
|
8214
8214
|
if (last === 0) return "/";
|
|
@@ -8216,7 +8216,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8216
8216
|
}
|
|
8217
8217
|
function flatFileListToDirectoryStructure(files) {
|
|
8218
8218
|
const inodes = /* @__PURE__ */ new Map();
|
|
8219
|
-
const
|
|
8219
|
+
const mkdir17 = function(name2) {
|
|
8220
8220
|
if (!inodes.has(name2)) {
|
|
8221
8221
|
const dir = {
|
|
8222
8222
|
type: "tree",
|
|
@@ -8226,7 +8226,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8226
8226
|
children: []
|
|
8227
8227
|
};
|
|
8228
8228
|
inodes.set(name2, dir);
|
|
8229
|
-
dir.parent =
|
|
8229
|
+
dir.parent = mkdir17(dirname16(name2));
|
|
8230
8230
|
if (dir.parent && dir.parent !== dir) dir.parent.children.push(dir);
|
|
8231
8231
|
}
|
|
8232
8232
|
return inodes.get(name2);
|
|
@@ -8239,7 +8239,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8239
8239
|
basename: basename8(name2),
|
|
8240
8240
|
metadata,
|
|
8241
8241
|
// This recursively generates any missing parent folders.
|
|
8242
|
-
parent:
|
|
8242
|
+
parent: mkdir17(dirname16(name2)),
|
|
8243
8243
|
children: []
|
|
8244
8244
|
};
|
|
8245
8245
|
if (file2.parent) file2.parent.children.push(file2);
|
|
@@ -8247,7 +8247,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8247
8247
|
}
|
|
8248
8248
|
return inodes.get(name2);
|
|
8249
8249
|
};
|
|
8250
|
-
|
|
8250
|
+
mkdir17(".");
|
|
8251
8251
|
for (const file2 of files) {
|
|
8252
8252
|
mkfile(file2.path, file2);
|
|
8253
8253
|
}
|
|
@@ -8650,7 +8650,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8650
8650
|
}
|
|
8651
8651
|
return isAbsolute2 ? `/${normalized}` : normalized;
|
|
8652
8652
|
}
|
|
8653
|
-
function
|
|
8653
|
+
function join20(...args) {
|
|
8654
8654
|
if (args.length === 0) return ".";
|
|
8655
8655
|
let joined;
|
|
8656
8656
|
for (let i2 = 0; i2 < args.length; ++i2) {
|
|
@@ -9052,7 +9052,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
9052
9052
|
for (const [key, value] of actualRefsToWrite) {
|
|
9053
9053
|
await acquireLock(
|
|
9054
9054
|
key,
|
|
9055
|
-
async () => fs2.write(
|
|
9055
|
+
async () => fs2.write(join20(gitdir, key), `${value.trim()}
|
|
9056
9056
|
`, "utf8")
|
|
9057
9057
|
);
|
|
9058
9058
|
}
|
|
@@ -9076,7 +9076,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
9076
9076
|
}
|
|
9077
9077
|
await acquireLock(
|
|
9078
9078
|
ref,
|
|
9079
|
-
async () => fs2.write(
|
|
9079
|
+
async () => fs2.write(join20(gitdir, ref), `${value.trim()}
|
|
9080
9080
|
`, "utf8")
|
|
9081
9081
|
);
|
|
9082
9082
|
}
|
|
@@ -9094,7 +9094,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
9094
9094
|
assertWritableRef(ref);
|
|
9095
9095
|
await acquireLock(
|
|
9096
9096
|
ref,
|
|
9097
|
-
async () => fs2.write(
|
|
9097
|
+
async () => fs2.write(join20(gitdir, ref), `ref: ${value.trim()}
|
|
9098
9098
|
`, "utf8")
|
|
9099
9099
|
);
|
|
9100
9100
|
}
|
|
@@ -9121,7 +9121,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
9121
9121
|
*/
|
|
9122
9122
|
static async deleteRefs({ fs: fs2, gitdir, refs }) {
|
|
9123
9123
|
refs.forEach(assertWritableRef);
|
|
9124
|
-
await Promise.all(refs.map((ref) => fs2.rm(
|
|
9124
|
+
await Promise.all(refs.map((ref) => fs2.rm(join20(gitdir, ref))));
|
|
9125
9125
|
let text2 = await acquireLock(
|
|
9126
9126
|
"packed-refs",
|
|
9127
9127
|
async () => fs2.read(`${gitdir}/packed-refs`, { encoding: "utf8" })
|
|
@@ -10208,7 +10208,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
10208
10208
|
format = "content",
|
|
10209
10209
|
getExternalRefDelta
|
|
10210
10210
|
}) {
|
|
10211
|
-
let list3 = await fs2.readdir(
|
|
10211
|
+
let list3 = await fs2.readdir(join20(gitdir, "objects/pack"));
|
|
10212
10212
|
list3 = list3.filter((x2) => x2.endsWith(".idx"));
|
|
10213
10213
|
for (const filename of list3) {
|
|
10214
10214
|
const indexFile = `${gitdir}/objects/pack/${filename}`;
|
|
@@ -11065,9 +11065,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11065
11065
|
}
|
|
11066
11066
|
const tree = GitTree.from(object2);
|
|
11067
11067
|
for (const entry2 of tree) {
|
|
11068
|
-
map2.set(
|
|
11068
|
+
map2.set(join20(filepath, entry2.path), entry2);
|
|
11069
11069
|
}
|
|
11070
|
-
return tree.entries().map((entry2) =>
|
|
11070
|
+
return tree.entries().map((entry2) => join20(filepath, entry2.path));
|
|
11071
11071
|
}
|
|
11072
11072
|
async type(entry) {
|
|
11073
11073
|
if (entry._type === false) {
|
|
@@ -11160,9 +11160,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11160
11160
|
if (await entry.type() !== "tree") return null;
|
|
11161
11161
|
const filepath = entry._fullpath;
|
|
11162
11162
|
const { fs: fs2, dir } = this;
|
|
11163
|
-
const names = await fs2.readdir(
|
|
11163
|
+
const names = await fs2.readdir(join20(dir, filepath));
|
|
11164
11164
|
if (names === null) return null;
|
|
11165
|
-
return names.map((name2) =>
|
|
11165
|
+
return names.map((name2) => join20(filepath, name2));
|
|
11166
11166
|
}
|
|
11167
11167
|
async type(entry) {
|
|
11168
11168
|
if (entry._type === false) {
|
|
@@ -11179,23 +11179,23 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11179
11179
|
async stat(entry) {
|
|
11180
11180
|
if (entry._stat === false) {
|
|
11181
11181
|
const { fs: fs2, dir } = this;
|
|
11182
|
-
let
|
|
11183
|
-
if (!
|
|
11182
|
+
let stat12 = await fs2.lstat(`${dir}/${entry._fullpath}`);
|
|
11183
|
+
if (!stat12) {
|
|
11184
11184
|
throw new Error(
|
|
11185
11185
|
`ENOENT: no such file or directory, lstat '${entry._fullpath}'`
|
|
11186
11186
|
);
|
|
11187
11187
|
}
|
|
11188
|
-
let type =
|
|
11189
|
-
if (type === "blob" && !
|
|
11188
|
+
let type = stat12.isDirectory() ? "tree" : "blob";
|
|
11189
|
+
if (type === "blob" && !stat12.isFile() && !stat12.isSymbolicLink()) {
|
|
11190
11190
|
type = "special";
|
|
11191
11191
|
}
|
|
11192
11192
|
entry._type = type;
|
|
11193
|
-
|
|
11194
|
-
entry._mode =
|
|
11195
|
-
if (
|
|
11196
|
-
|
|
11193
|
+
stat12 = normalizeStats(stat12);
|
|
11194
|
+
entry._mode = stat12.mode;
|
|
11195
|
+
if (stat12.size === -1 && entry._actualSize) {
|
|
11196
|
+
stat12.size = entry._actualSize;
|
|
11197
11197
|
}
|
|
11198
|
-
entry._stat =
|
|
11198
|
+
entry._stat = stat12;
|
|
11199
11199
|
}
|
|
11200
11200
|
return entry._stat;
|
|
11201
11201
|
}
|
|
@@ -11383,24 +11383,24 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11383
11383
|
};
|
|
11384
11384
|
return walk2(root);
|
|
11385
11385
|
}
|
|
11386
|
-
async function mkdirp(
|
|
11386
|
+
async function mkdirp(mkdir17, filepath, retries = 10) {
|
|
11387
11387
|
try {
|
|
11388
|
-
await
|
|
11388
|
+
await mkdir17(filepath);
|
|
11389
11389
|
} catch (err2) {
|
|
11390
11390
|
if (err2 === null) return;
|
|
11391
11391
|
if (err2.code === "EEXIST") return;
|
|
11392
11392
|
if (err2.code !== "ENOENT") throw err2;
|
|
11393
|
-
const parent =
|
|
11393
|
+
const parent = dirname16(filepath);
|
|
11394
11394
|
if (parent === "." || parent === "/" || parent === filepath) throw err2;
|
|
11395
|
-
await mkdirp(
|
|
11395
|
+
await mkdirp(mkdir17, parent, retries);
|
|
11396
11396
|
for (let attempt = 0; ; attempt++) {
|
|
11397
11397
|
try {
|
|
11398
|
-
await
|
|
11398
|
+
await mkdir17(filepath);
|
|
11399
11399
|
return;
|
|
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((resolve19) => setTimeout(resolve19, 0));
|
|
11404
11404
|
continue;
|
|
11405
11405
|
}
|
|
11406
11406
|
throw err22;
|
|
@@ -11415,10 +11415,10 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11415
11415
|
} else if (entries.length) {
|
|
11416
11416
|
await Promise.all(
|
|
11417
11417
|
entries.map((entry) => {
|
|
11418
|
-
const subpath =
|
|
11419
|
-
return fs2.lstat(subpath).then((
|
|
11420
|
-
if (!
|
|
11421
|
-
return
|
|
11418
|
+
const subpath = join20(filepath, entry);
|
|
11419
|
+
return fs2.lstat(subpath).then((stat12) => {
|
|
11420
|
+
if (!stat12) return;
|
|
11421
|
+
return stat12.isDirectory() ? rmRecursive(fs2, subpath) : fs2.rm(subpath);
|
|
11422
11422
|
});
|
|
11423
11423
|
})
|
|
11424
11424
|
).then(() => fs2.rmdir(filepath));
|
|
@@ -11554,7 +11554,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11554
11554
|
try {
|
|
11555
11555
|
await this._writeFile(filepath, contents, options);
|
|
11556
11556
|
} catch (err2) {
|
|
11557
|
-
await this.mkdir(
|
|
11557
|
+
await this.mkdir(dirname16(filepath));
|
|
11558
11558
|
await this._writeFile(filepath, contents, options);
|
|
11559
11559
|
}
|
|
11560
11560
|
}
|
|
@@ -11700,7 +11700,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11700
11700
|
if (isAbsolute(submoduleGitdir)) {
|
|
11701
11701
|
return submoduleGitdir;
|
|
11702
11702
|
}
|
|
11703
|
-
const gitdir =
|
|
11703
|
+
const gitdir = join20(dirname16(dotgit), submoduleGitdir);
|
|
11704
11704
|
return gitdir;
|
|
11705
11705
|
});
|
|
11706
11706
|
} else {
|
|
@@ -11722,7 +11722,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11722
11722
|
async function abortMerge({
|
|
11723
11723
|
fs: _fs,
|
|
11724
11724
|
dir,
|
|
11725
|
-
gitdir =
|
|
11725
|
+
gitdir = join20(dir, ".git"),
|
|
11726
11726
|
commit: commit2 = "HEAD",
|
|
11727
11727
|
cache = {}
|
|
11728
11728
|
}) {
|
|
@@ -11803,17 +11803,17 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11803
11803
|
* @param {string} args.filepath - The path of the file to check.
|
|
11804
11804
|
* @returns {Promise<boolean>} - `true` if the file is ignored, `false` otherwise.
|
|
11805
11805
|
*/
|
|
11806
|
-
static async isIgnored({ fs: fs2, dir, gitdir =
|
|
11806
|
+
static async isIgnored({ fs: fs2, dir, gitdir = join20(dir, ".git"), filepath }) {
|
|
11807
11807
|
if (basename8(filepath) === ".git") return true;
|
|
11808
11808
|
if (filepath === ".") return false;
|
|
11809
11809
|
let excludes = "";
|
|
11810
|
-
const excludesFile =
|
|
11810
|
+
const excludesFile = join20(gitdir, "info", "exclude");
|
|
11811
11811
|
if (await fs2.exists(excludesFile)) {
|
|
11812
11812
|
excludes = await fs2.read(excludesFile, "utf8");
|
|
11813
11813
|
}
|
|
11814
11814
|
const pairs = [
|
|
11815
11815
|
{
|
|
11816
|
-
gitignore:
|
|
11816
|
+
gitignore: join20(dir, ".gitignore"),
|
|
11817
11817
|
filepath
|
|
11818
11818
|
}
|
|
11819
11819
|
];
|
|
@@ -11822,7 +11822,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11822
11822
|
const folder = pieces.slice(0, i2).join("/");
|
|
11823
11823
|
const file2 = pieces.slice(i2).join("/");
|
|
11824
11824
|
pairs.push({
|
|
11825
|
-
gitignore:
|
|
11825
|
+
gitignore: join20(dir, folder, ".gitignore"),
|
|
11826
11826
|
filepath: file2
|
|
11827
11827
|
});
|
|
11828
11828
|
}
|
|
@@ -11836,7 +11836,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11836
11836
|
}
|
|
11837
11837
|
const ign = ignore2().add(excludes);
|
|
11838
11838
|
ign.add(file2);
|
|
11839
|
-
const parentdir =
|
|
11839
|
+
const parentdir = dirname16(p.filepath);
|
|
11840
11840
|
if (parentdir !== "." && ign.ignores(parentdir)) return true;
|
|
11841
11841
|
if (ignoredStatus) {
|
|
11842
11842
|
ignoredStatus = !ign.test(p.filepath).unignored;
|
|
@@ -11909,7 +11909,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11909
11909
|
async function add({
|
|
11910
11910
|
fs: _fs,
|
|
11911
11911
|
dir,
|
|
11912
|
-
gitdir =
|
|
11912
|
+
gitdir = join20(dir, ".git"),
|
|
11913
11913
|
filepath,
|
|
11914
11914
|
cache = {},
|
|
11915
11915
|
force = false,
|
|
@@ -11973,17 +11973,17 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11973
11973
|
});
|
|
11974
11974
|
if (ignored) return;
|
|
11975
11975
|
}
|
|
11976
|
-
const stats = await fs2.lstat(
|
|
11976
|
+
const stats = await fs2.lstat(join20(dir, currentFilepath));
|
|
11977
11977
|
if (!stats) throw new NotFoundError(currentFilepath);
|
|
11978
11978
|
if (stats.isDirectory()) {
|
|
11979
|
-
const children = await fs2.readdir(
|
|
11979
|
+
const children = await fs2.readdir(join20(dir, currentFilepath));
|
|
11980
11980
|
if (parallel) {
|
|
11981
11981
|
const promises3 = children.map(
|
|
11982
11982
|
(child) => addToIndex({
|
|
11983
11983
|
dir,
|
|
11984
11984
|
gitdir,
|
|
11985
11985
|
fs: fs2,
|
|
11986
|
-
filepath: [
|
|
11986
|
+
filepath: [join20(currentFilepath, child)],
|
|
11987
11987
|
index: index3,
|
|
11988
11988
|
force,
|
|
11989
11989
|
parallel,
|
|
@@ -11997,7 +11997,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
11997
11997
|
dir,
|
|
11998
11998
|
gitdir,
|
|
11999
11999
|
fs: fs2,
|
|
12000
|
-
filepath: [
|
|
12000
|
+
filepath: [join20(currentFilepath, child)],
|
|
12001
12001
|
index: index3,
|
|
12002
12002
|
force,
|
|
12003
12003
|
parallel,
|
|
@@ -12006,7 +12006,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
12006
12006
|
}
|
|
12007
12007
|
}
|
|
12008
12008
|
} else {
|
|
12009
|
-
const object2 = stats.isSymbolicLink() ? await fs2.readlink(
|
|
12009
|
+
const object2 = stats.isSymbolicLink() ? await fs2.readlink(join20(dir, currentFilepath)).then(posixifyPathBuffer) : await fs2.read(join20(dir, currentFilepath), { autocrlf });
|
|
12010
12010
|
if (object2 === null) throw new NotFoundError(currentFilepath);
|
|
12011
12011
|
const oid = await _writeObject({ fs: fs2, gitdir, type: "blob", object: object2 });
|
|
12012
12012
|
index3.insert({ filepath: currentFilepath, stats, oid });
|
|
@@ -12440,7 +12440,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
12440
12440
|
fs: _fs,
|
|
12441
12441
|
onSign,
|
|
12442
12442
|
dir,
|
|
12443
|
-
gitdir =
|
|
12443
|
+
gitdir = join20(dir, ".git"),
|
|
12444
12444
|
ref = "refs/notes/commits",
|
|
12445
12445
|
oid,
|
|
12446
12446
|
note,
|
|
@@ -12510,7 +12510,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
12510
12510
|
async function addRemote({
|
|
12511
12511
|
fs: fs2,
|
|
12512
12512
|
dir,
|
|
12513
|
-
gitdir =
|
|
12513
|
+
gitdir = join20(dir, ".git"),
|
|
12514
12514
|
remote,
|
|
12515
12515
|
url: url3,
|
|
12516
12516
|
force = false
|
|
@@ -12580,7 +12580,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
12580
12580
|
fs: _fs,
|
|
12581
12581
|
onSign,
|
|
12582
12582
|
dir,
|
|
12583
|
-
gitdir =
|
|
12583
|
+
gitdir = join20(dir, ".git"),
|
|
12584
12584
|
ref,
|
|
12585
12585
|
tagger: _tagger,
|
|
12586
12586
|
message = ref,
|
|
@@ -12661,7 +12661,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
12661
12661
|
async function branch({
|
|
12662
12662
|
fs: fs2,
|
|
12663
12663
|
dir,
|
|
12664
|
-
gitdir =
|
|
12664
|
+
gitdir = join20(dir, ".git"),
|
|
12665
12665
|
ref,
|
|
12666
12666
|
object: object2,
|
|
12667
12667
|
checkout: checkout2 = false,
|
|
@@ -13325,7 +13325,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13325
13325
|
onProgress,
|
|
13326
13326
|
onPostCheckout,
|
|
13327
13327
|
dir,
|
|
13328
|
-
gitdir =
|
|
13328
|
+
gitdir = join20(dir, ".git"),
|
|
13329
13329
|
remote = "origin",
|
|
13330
13330
|
ref: _ref,
|
|
13331
13331
|
filepaths,
|
|
@@ -13406,7 +13406,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13406
13406
|
fs: fs2,
|
|
13407
13407
|
cache,
|
|
13408
13408
|
dir,
|
|
13409
|
-
gitdir =
|
|
13409
|
+
gitdir = join20(dir, ".git"),
|
|
13410
13410
|
index: index3,
|
|
13411
13411
|
ourOid,
|
|
13412
13412
|
baseOid,
|
|
@@ -13676,7 +13676,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13676
13676
|
workdir: WORKDIR
|
|
13677
13677
|
};
|
|
13678
13678
|
async function checkAndWriteBlob(fs2, gitdir, dir, filepath, oid = null) {
|
|
13679
|
-
const currentFilepath =
|
|
13679
|
+
const currentFilepath = join20(dir, filepath);
|
|
13680
13680
|
const stats = await fs2.lstat(currentFilepath);
|
|
13681
13681
|
if (!stats) throw new NotFoundError(currentFilepath);
|
|
13682
13682
|
if (stats.isDirectory())
|
|
@@ -13845,7 +13845,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13845
13845
|
stageUpdated.push({
|
|
13846
13846
|
filepath,
|
|
13847
13847
|
oid,
|
|
13848
|
-
stats: await fs2.lstat(
|
|
13848
|
+
stats: await fs2.lstat(join20(dir, filepath))
|
|
13849
13849
|
});
|
|
13850
13850
|
return {
|
|
13851
13851
|
method: "write",
|
|
@@ -13858,7 +13858,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13858
13858
|
});
|
|
13859
13859
|
await acquireLock(gitdir, async () => {
|
|
13860
13860
|
for (const op of ops) {
|
|
13861
|
-
const currentFilepath =
|
|
13861
|
+
const currentFilepath = join20(dir, op.filepath);
|
|
13862
13862
|
switch (op.method) {
|
|
13863
13863
|
case "rmdir":
|
|
13864
13864
|
await fs2.rmdir(currentFilepath);
|
|
@@ -13992,7 +13992,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13992
13992
|
async function cherryPick({
|
|
13993
13993
|
fs: _fs,
|
|
13994
13994
|
dir,
|
|
13995
|
-
gitdir =
|
|
13995
|
+
gitdir = join20(dir, ".git"),
|
|
13996
13996
|
oid,
|
|
13997
13997
|
cache = {},
|
|
13998
13998
|
committer,
|
|
@@ -14497,7 +14497,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14497
14497
|
* @returns {Promise<Set<string>>} - A set of shallow object IDs.
|
|
14498
14498
|
*/
|
|
14499
14499
|
static async read({ fs: fs2, gitdir }) {
|
|
14500
|
-
const filepath =
|
|
14500
|
+
const filepath = join20(gitdir, "shallow");
|
|
14501
14501
|
const oids = /* @__PURE__ */ new Set();
|
|
14502
14502
|
await acquireLock(filepath, async function() {
|
|
14503
14503
|
const text2 = await fs2.read(filepath, { encoding: "utf8" });
|
|
@@ -14518,7 +14518,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14518
14518
|
* @returns {Promise<void>}
|
|
14519
14519
|
*/
|
|
14520
14520
|
static async write({ fs: fs2, gitdir, oids }) {
|
|
14521
|
-
const filepath =
|
|
14521
|
+
const filepath = join20(gitdir, "shallow");
|
|
14522
14522
|
if (oids.size > 0) {
|
|
14523
14523
|
const text2 = [...oids].join("\n") + "\n";
|
|
14524
14524
|
await acquireLock(filepath, async function() {
|
|
@@ -14544,7 +14544,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14544
14544
|
oid,
|
|
14545
14545
|
getExternalRefDelta
|
|
14546
14546
|
}) {
|
|
14547
|
-
let list3 = await fs2.readdir(
|
|
14547
|
+
let list3 = await fs2.readdir(join20(gitdir, "objects/pack"));
|
|
14548
14548
|
list3 = list3.filter((x2) => x2.endsWith(".idx"));
|
|
14549
14549
|
for (const filename of list3) {
|
|
14550
14550
|
const indexFile = `${gitdir}/objects/pack/${filename}`;
|
|
@@ -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 resolve19 = this._waiting;
|
|
14620
14620
|
this._waiting = null;
|
|
14621
|
-
|
|
14621
|
+
resolve19({ 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 resolve19 = this._waiting;
|
|
14630
14630
|
this._waiting = null;
|
|
14631
|
-
|
|
14631
|
+
resolve19({ 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((resolve19) => {
|
|
14651
|
+
this._waiting = resolve19;
|
|
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((resolve19, 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) : resolve19({ 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) : resolve19({ shallows, unshallows, acks, nak, packfile, progress });
|
|
14838
14838
|
}
|
|
14839
14839
|
});
|
|
14840
14840
|
});
|
|
@@ -15135,7 +15135,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15135
15135
|
}
|
|
15136
15136
|
if (packfileSha !== "" && !emptyPackfile(packfile)) {
|
|
15137
15137
|
res.packfile = `objects/pack/pack-${packfileSha}.pack`;
|
|
15138
|
-
const fullpath =
|
|
15138
|
+
const fullpath = join20(gitdir, res.packfile);
|
|
15139
15139
|
await fs2.write(fullpath, packfile);
|
|
15140
15140
|
const getExternalRefDelta = (oid2) => _readObject({ fs: fs2, cache, gitdir, oid: oid2 });
|
|
15141
15141
|
const idx = await GitPackIndex.fromPack({
|
|
@@ -15151,7 +15151,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15151
15151
|
fs: fs2,
|
|
15152
15152
|
bare = false,
|
|
15153
15153
|
dir,
|
|
15154
|
-
gitdir = bare ? dir :
|
|
15154
|
+
gitdir = bare ? dir : join20(dir, ".git"),
|
|
15155
15155
|
defaultBranch = "master"
|
|
15156
15156
|
}) {
|
|
15157
15157
|
if (await fs2.exists(gitdir + "/config")) return;
|
|
@@ -15265,7 +15265,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15265
15265
|
onAuthFailure,
|
|
15266
15266
|
onPostCheckout,
|
|
15267
15267
|
dir,
|
|
15268
|
-
gitdir =
|
|
15268
|
+
gitdir = join20(dir, ".git"),
|
|
15269
15269
|
url: url3,
|
|
15270
15270
|
corsProxy = void 0,
|
|
15271
15271
|
ref = void 0,
|
|
@@ -15328,7 +15328,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15328
15328
|
fs: _fs,
|
|
15329
15329
|
onSign,
|
|
15330
15330
|
dir,
|
|
15331
|
-
gitdir =
|
|
15331
|
+
gitdir = join20(dir, ".git"),
|
|
15332
15332
|
message,
|
|
15333
15333
|
author,
|
|
15334
15334
|
committer,
|
|
@@ -15377,7 +15377,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15377
15377
|
async function currentBranch({
|
|
15378
15378
|
fs: fs2,
|
|
15379
15379
|
dir,
|
|
15380
|
-
gitdir =
|
|
15380
|
+
gitdir = join20(dir, ".git"),
|
|
15381
15381
|
fullname = false,
|
|
15382
15382
|
test = false
|
|
15383
15383
|
}) {
|
|
@@ -15418,7 +15418,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15418
15418
|
async function deleteBranch({
|
|
15419
15419
|
fs: fs2,
|
|
15420
15420
|
dir,
|
|
15421
|
-
gitdir =
|
|
15421
|
+
gitdir = join20(dir, ".git"),
|
|
15422
15422
|
ref
|
|
15423
15423
|
}) {
|
|
15424
15424
|
try {
|
|
@@ -15436,7 +15436,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15436
15436
|
throw err2;
|
|
15437
15437
|
}
|
|
15438
15438
|
}
|
|
15439
|
-
async function deleteRef({ fs: fs2, dir, gitdir =
|
|
15439
|
+
async function deleteRef({ fs: fs2, dir, gitdir = join20(dir, ".git"), ref }) {
|
|
15440
15440
|
try {
|
|
15441
15441
|
assertParameter("fs", fs2);
|
|
15442
15442
|
assertParameter("ref", ref);
|
|
@@ -15456,7 +15456,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15456
15456
|
async function deleteRemote({
|
|
15457
15457
|
fs: fs2,
|
|
15458
15458
|
dir,
|
|
15459
|
-
gitdir =
|
|
15459
|
+
gitdir = join20(dir, ".git"),
|
|
15460
15460
|
remote
|
|
15461
15461
|
}) {
|
|
15462
15462
|
try {
|
|
@@ -15478,7 +15478,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15478
15478
|
ref = ref.startsWith("refs/tags/") ? ref : `refs/tags/${ref}`;
|
|
15479
15479
|
await GitRefManager.deleteRef({ fs: fs2, gitdir, ref });
|
|
15480
15480
|
}
|
|
15481
|
-
async function deleteTag({ fs: fs2, dir, gitdir =
|
|
15481
|
+
async function deleteTag({ fs: fs2, dir, gitdir = join20(dir, ".git"), ref }) {
|
|
15482
15482
|
try {
|
|
15483
15483
|
assertParameter("fs", fs2);
|
|
15484
15484
|
assertParameter("ref", ref);
|
|
@@ -15507,7 +15507,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15507
15507
|
getExternalRefDelta
|
|
15508
15508
|
}) {
|
|
15509
15509
|
const results = [];
|
|
15510
|
-
let list3 = await fs2.readdir(
|
|
15510
|
+
let list3 = await fs2.readdir(join20(gitdir, "objects/pack"));
|
|
15511
15511
|
list3 = list3.filter((x2) => x2.endsWith(".idx"));
|
|
15512
15512
|
for (const filename of list3) {
|
|
15513
15513
|
const indexFile = `${gitdir}/objects/pack/${filename}`;
|
|
@@ -15550,7 +15550,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15550
15550
|
async function expandOid({
|
|
15551
15551
|
fs: fs2,
|
|
15552
15552
|
dir,
|
|
15553
|
-
gitdir =
|
|
15553
|
+
gitdir = join20(dir, ".git"),
|
|
15554
15554
|
oid,
|
|
15555
15555
|
cache = {}
|
|
15556
15556
|
}) {
|
|
@@ -15571,7 +15571,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15571
15571
|
throw err2;
|
|
15572
15572
|
}
|
|
15573
15573
|
}
|
|
15574
|
-
async function expandRef({ fs: fs2, dir, gitdir =
|
|
15574
|
+
async function expandRef({ fs: fs2, dir, gitdir = join20(dir, ".git"), ref }) {
|
|
15575
15575
|
try {
|
|
15576
15576
|
assertParameter("fs", fs2);
|
|
15577
15577
|
assertParameter("gitdir", gitdir);
|
|
@@ -15862,7 +15862,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15862
15862
|
onAuthSuccess,
|
|
15863
15863
|
onAuthFailure,
|
|
15864
15864
|
dir,
|
|
15865
|
-
gitdir =
|
|
15865
|
+
gitdir = join20(dir, ".git"),
|
|
15866
15866
|
ref,
|
|
15867
15867
|
url: url3,
|
|
15868
15868
|
remote,
|
|
@@ -15920,7 +15920,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15920
15920
|
onAuthSuccess,
|
|
15921
15921
|
onAuthFailure,
|
|
15922
15922
|
dir,
|
|
15923
|
-
gitdir =
|
|
15923
|
+
gitdir = join20(dir, ".git"),
|
|
15924
15924
|
ref,
|
|
15925
15925
|
remote,
|
|
15926
15926
|
remoteRef,
|
|
@@ -15976,7 +15976,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15976
15976
|
async function findMergeBase({
|
|
15977
15977
|
fs: fs2,
|
|
15978
15978
|
dir,
|
|
15979
|
-
gitdir =
|
|
15979
|
+
gitdir = join20(dir, ".git"),
|
|
15980
15980
|
oids,
|
|
15981
15981
|
cache = {}
|
|
15982
15982
|
}) {
|
|
@@ -15998,10 +15998,10 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15998
15998
|
}
|
|
15999
15999
|
}
|
|
16000
16000
|
async function _findRoot({ fs: fs2, filepath }) {
|
|
16001
|
-
if (await fs2.exists(
|
|
16001
|
+
if (await fs2.exists(join20(filepath, ".git"))) {
|
|
16002
16002
|
return filepath;
|
|
16003
16003
|
} else {
|
|
16004
|
-
const parent =
|
|
16004
|
+
const parent = dirname16(filepath);
|
|
16005
16005
|
if (parent === filepath) {
|
|
16006
16006
|
throw new NotFoundError(`git root for ${filepath}`);
|
|
16007
16007
|
}
|
|
@@ -16018,7 +16018,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16018
16018
|
throw err2;
|
|
16019
16019
|
}
|
|
16020
16020
|
}
|
|
16021
|
-
async function getConfig({ fs: fs2, dir, gitdir =
|
|
16021
|
+
async function getConfig({ fs: fs2, dir, gitdir = join20(dir, ".git"), path }) {
|
|
16022
16022
|
try {
|
|
16023
16023
|
assertParameter("fs", fs2);
|
|
16024
16024
|
assertParameter("gitdir", gitdir);
|
|
@@ -16042,7 +16042,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16042
16042
|
async function getConfigAll({
|
|
16043
16043
|
fs: fs2,
|
|
16044
16044
|
dir,
|
|
16045
|
-
gitdir =
|
|
16045
|
+
gitdir = join20(dir, ".git"),
|
|
16046
16046
|
path
|
|
16047
16047
|
}) {
|
|
16048
16048
|
try {
|
|
@@ -16231,7 +16231,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16231
16231
|
filepath
|
|
16232
16232
|
}) {
|
|
16233
16233
|
try {
|
|
16234
|
-
filepath =
|
|
16234
|
+
filepath = join20(dir, filepath);
|
|
16235
16235
|
const pack = await fs2.read(filepath);
|
|
16236
16236
|
const getExternalRefDelta = (oid) => _readObject({ fs: fs2, cache, gitdir, oid });
|
|
16237
16237
|
const idx = await GitPackIndex.fromPack({
|
|
@@ -16252,7 +16252,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16252
16252
|
fs: fs2,
|
|
16253
16253
|
onProgress,
|
|
16254
16254
|
dir,
|
|
16255
|
-
gitdir =
|
|
16255
|
+
gitdir = join20(dir, ".git"),
|
|
16256
16256
|
filepath,
|
|
16257
16257
|
cache = {}
|
|
16258
16258
|
}) {
|
|
@@ -16280,7 +16280,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16280
16280
|
fs: fs2,
|
|
16281
16281
|
bare = false,
|
|
16282
16282
|
dir,
|
|
16283
|
-
gitdir = bare ? dir :
|
|
16283
|
+
gitdir = bare ? dir : join20(dir, ".git"),
|
|
16284
16284
|
defaultBranch = "master"
|
|
16285
16285
|
}) {
|
|
16286
16286
|
try {
|
|
@@ -16354,7 +16354,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16354
16354
|
async function isDescendent({
|
|
16355
16355
|
fs: fs2,
|
|
16356
16356
|
dir,
|
|
16357
|
-
gitdir =
|
|
16357
|
+
gitdir = join20(dir, ".git"),
|
|
16358
16358
|
oid,
|
|
16359
16359
|
ancestor,
|
|
16360
16360
|
depth = -1,
|
|
@@ -16383,7 +16383,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16383
16383
|
async function isIgnored({
|
|
16384
16384
|
fs: fs2,
|
|
16385
16385
|
dir,
|
|
16386
|
-
gitdir =
|
|
16386
|
+
gitdir = join20(dir, ".git"),
|
|
16387
16387
|
filepath
|
|
16388
16388
|
}) {
|
|
16389
16389
|
try {
|
|
@@ -16407,7 +16407,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16407
16407
|
async function listBranches({
|
|
16408
16408
|
fs: fs2,
|
|
16409
16409
|
dir,
|
|
16410
|
-
gitdir =
|
|
16410
|
+
gitdir = join20(dir, ".git"),
|
|
16411
16411
|
remote
|
|
16412
16412
|
}) {
|
|
16413
16413
|
try {
|
|
@@ -16464,17 +16464,17 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16464
16464
|
gitdir,
|
|
16465
16465
|
oid: entry.oid,
|
|
16466
16466
|
filenames,
|
|
16467
|
-
prefix:
|
|
16467
|
+
prefix: join20(prefix, entry.path)
|
|
16468
16468
|
});
|
|
16469
16469
|
} else {
|
|
16470
|
-
filenames.push(
|
|
16470
|
+
filenames.push(join20(prefix, entry.path));
|
|
16471
16471
|
}
|
|
16472
16472
|
}
|
|
16473
16473
|
}
|
|
16474
16474
|
async function listFiles({
|
|
16475
16475
|
fs: fs2,
|
|
16476
16476
|
dir,
|
|
16477
|
-
gitdir =
|
|
16477
|
+
gitdir = join20(dir, ".git"),
|
|
16478
16478
|
ref,
|
|
16479
16479
|
cache = {}
|
|
16480
16480
|
}) {
|
|
@@ -16518,7 +16518,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16518
16518
|
async function listNotes({
|
|
16519
16519
|
fs: fs2,
|
|
16520
16520
|
dir,
|
|
16521
|
-
gitdir =
|
|
16521
|
+
gitdir = join20(dir, ".git"),
|
|
16522
16522
|
ref = "refs/notes/commits",
|
|
16523
16523
|
cache = {}
|
|
16524
16524
|
}) {
|
|
@@ -16542,7 +16542,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16542
16542
|
async function listRefs({
|
|
16543
16543
|
fs: fs2,
|
|
16544
16544
|
dir,
|
|
16545
|
-
gitdir =
|
|
16545
|
+
gitdir = join20(dir, ".git"),
|
|
16546
16546
|
filepath
|
|
16547
16547
|
}) {
|
|
16548
16548
|
try {
|
|
@@ -16567,7 +16567,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16567
16567
|
);
|
|
16568
16568
|
return remotes;
|
|
16569
16569
|
}
|
|
16570
|
-
async function listRemotes({ fs: fs2, dir, gitdir =
|
|
16570
|
+
async function listRemotes({ fs: fs2, dir, gitdir = join20(dir, ".git") }) {
|
|
16571
16571
|
try {
|
|
16572
16572
|
assertParameter("fs", fs2);
|
|
16573
16573
|
assertParameter("gitdir", gitdir);
|
|
@@ -16666,7 +16666,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16666
16666
|
throw err2;
|
|
16667
16667
|
}
|
|
16668
16668
|
}
|
|
16669
|
-
async function listTags({ fs: fs2, dir, gitdir =
|
|
16669
|
+
async function listTags({ fs: fs2, dir, gitdir = join20(dir, ".git") }) {
|
|
16670
16670
|
try {
|
|
16671
16671
|
assertParameter("fs", fs2);
|
|
16672
16672
|
assertParameter("gitdir", gitdir);
|
|
@@ -16719,7 +16719,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16719
16719
|
const walks = tree.entries().map(function(entry) {
|
|
16720
16720
|
let result;
|
|
16721
16721
|
if (entry.oid === fileId) {
|
|
16722
|
-
result =
|
|
16722
|
+
result = join20(parentPath, entry.path);
|
|
16723
16723
|
filepaths.push(result);
|
|
16724
16724
|
} else if (entry.type === "tree") {
|
|
16725
16725
|
result = _readObject({
|
|
@@ -16736,7 +16736,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16736
16736
|
fileId,
|
|
16737
16737
|
oid,
|
|
16738
16738
|
filepaths,
|
|
16739
|
-
parentPath:
|
|
16739
|
+
parentPath: join20(parentPath, entry.path)
|
|
16740
16740
|
});
|
|
16741
16741
|
});
|
|
16742
16742
|
}
|
|
@@ -16911,7 +16911,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16911
16911
|
async function log({
|
|
16912
16912
|
fs: fs2,
|
|
16913
16913
|
dir,
|
|
16914
|
-
gitdir =
|
|
16914
|
+
gitdir = join20(dir, ".git"),
|
|
16915
16915
|
filepath,
|
|
16916
16916
|
ref = "HEAD",
|
|
16917
16917
|
depth,
|
|
@@ -16949,7 +16949,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
16949
16949
|
fs: _fs,
|
|
16950
16950
|
onSign,
|
|
16951
16951
|
dir,
|
|
16952
|
-
gitdir =
|
|
16952
|
+
gitdir = join20(dir, ".git"),
|
|
16953
16953
|
ours,
|
|
16954
16954
|
theirs,
|
|
16955
16955
|
fastForward: fastForward2 = true,
|
|
@@ -17026,7 +17026,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17026
17026
|
fs: fs2,
|
|
17027
17027
|
cache,
|
|
17028
17028
|
dir,
|
|
17029
|
-
gitdir =
|
|
17029
|
+
gitdir = join20(dir, ".git"),
|
|
17030
17030
|
oids
|
|
17031
17031
|
}) {
|
|
17032
17032
|
const hash2 = new Hash();
|
|
@@ -17069,7 +17069,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17069
17069
|
const packfileSha = packfile.slice(-20).toString("hex");
|
|
17070
17070
|
const filename = `pack-${packfileSha}.pack`;
|
|
17071
17071
|
if (write) {
|
|
17072
|
-
await fs2.write(
|
|
17072
|
+
await fs2.write(join20(gitdir, `objects/pack/${filename}`), packfile);
|
|
17073
17073
|
return { filename };
|
|
17074
17074
|
}
|
|
17075
17075
|
return {
|
|
@@ -17080,7 +17080,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17080
17080
|
async function packObjects({
|
|
17081
17081
|
fs: fs2,
|
|
17082
17082
|
dir,
|
|
17083
|
-
gitdir =
|
|
17083
|
+
gitdir = join20(dir, ".git"),
|
|
17084
17084
|
oids,
|
|
17085
17085
|
write = false,
|
|
17086
17086
|
cache = {}
|
|
@@ -17112,7 +17112,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17112
17112
|
onAuthSuccess,
|
|
17113
17113
|
onAuthFailure,
|
|
17114
17114
|
dir,
|
|
17115
|
-
gitdir =
|
|
17115
|
+
gitdir = join20(dir, ".git"),
|
|
17116
17116
|
ref,
|
|
17117
17117
|
url: url3,
|
|
17118
17118
|
remote,
|
|
@@ -17182,7 +17182,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17182
17182
|
fs: fs2,
|
|
17183
17183
|
cache,
|
|
17184
17184
|
dir,
|
|
17185
|
-
gitdir =
|
|
17185
|
+
gitdir = join20(dir, ".git"),
|
|
17186
17186
|
start,
|
|
17187
17187
|
finish
|
|
17188
17188
|
}) {
|
|
@@ -17230,7 +17230,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17230
17230
|
fs: fs2,
|
|
17231
17231
|
cache,
|
|
17232
17232
|
dir,
|
|
17233
|
-
gitdir =
|
|
17233
|
+
gitdir = join20(dir, ".git"),
|
|
17234
17234
|
oids
|
|
17235
17235
|
}) {
|
|
17236
17236
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -17533,7 +17533,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17533
17533
|
onAuthFailure,
|
|
17534
17534
|
onPrePush,
|
|
17535
17535
|
dir,
|
|
17536
|
-
gitdir =
|
|
17536
|
+
gitdir = join20(dir, ".git"),
|
|
17537
17537
|
ref,
|
|
17538
17538
|
remoteRef,
|
|
17539
17539
|
remote = "origin",
|
|
@@ -17609,7 +17609,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17609
17609
|
async function readBlob({
|
|
17610
17610
|
fs: fs2,
|
|
17611
17611
|
dir,
|
|
17612
|
-
gitdir =
|
|
17612
|
+
gitdir = join20(dir, ".git"),
|
|
17613
17613
|
oid,
|
|
17614
17614
|
filepath,
|
|
17615
17615
|
cache = {}
|
|
@@ -17635,7 +17635,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17635
17635
|
async function readCommit({
|
|
17636
17636
|
fs: fs2,
|
|
17637
17637
|
dir,
|
|
17638
|
-
gitdir =
|
|
17638
|
+
gitdir = join20(dir, ".git"),
|
|
17639
17639
|
oid,
|
|
17640
17640
|
cache = {}
|
|
17641
17641
|
}) {
|
|
@@ -17676,7 +17676,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17676
17676
|
async function readNote({
|
|
17677
17677
|
fs: fs2,
|
|
17678
17678
|
dir,
|
|
17679
|
-
gitdir =
|
|
17679
|
+
gitdir = join20(dir, ".git"),
|
|
17680
17680
|
ref = "refs/notes/commits",
|
|
17681
17681
|
oid,
|
|
17682
17682
|
cache = {}
|
|
@@ -17703,7 +17703,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17703
17703
|
async function readObject({
|
|
17704
17704
|
fs: _fs,
|
|
17705
17705
|
dir,
|
|
17706
|
-
gitdir =
|
|
17706
|
+
gitdir = join20(dir, ".git"),
|
|
17707
17707
|
oid,
|
|
17708
17708
|
format = "parsed",
|
|
17709
17709
|
filepath = void 0,
|
|
@@ -17792,7 +17792,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17792
17792
|
async function readTag({
|
|
17793
17793
|
fs: fs2,
|
|
17794
17794
|
dir,
|
|
17795
|
-
gitdir =
|
|
17795
|
+
gitdir = join20(dir, ".git"),
|
|
17796
17796
|
oid,
|
|
17797
17797
|
cache = {}
|
|
17798
17798
|
}) {
|
|
@@ -17816,7 +17816,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17816
17816
|
async function readTree({
|
|
17817
17817
|
fs: fs2,
|
|
17818
17818
|
dir,
|
|
17819
|
-
gitdir =
|
|
17819
|
+
gitdir = join20(dir, ".git"),
|
|
17820
17820
|
oid,
|
|
17821
17821
|
filepath = void 0,
|
|
17822
17822
|
cache = {}
|
|
@@ -17842,7 +17842,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17842
17842
|
async function remove2({
|
|
17843
17843
|
fs: _fs,
|
|
17844
17844
|
dir,
|
|
17845
|
-
gitdir =
|
|
17845
|
+
gitdir = join20(dir, ".git"),
|
|
17846
17846
|
filepath,
|
|
17847
17847
|
cache = {}
|
|
17848
17848
|
}) {
|
|
@@ -17915,7 +17915,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
17915
17915
|
fs: _fs,
|
|
17916
17916
|
onSign,
|
|
17917
17917
|
dir,
|
|
17918
|
-
gitdir =
|
|
17918
|
+
gitdir = join20(dir, ".git"),
|
|
17919
17919
|
ref = "refs/notes/commits",
|
|
17920
17920
|
oid,
|
|
17921
17921
|
author: _author,
|
|
@@ -18003,7 +18003,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18003
18003
|
async function renameBranch({
|
|
18004
18004
|
fs: fs2,
|
|
18005
18005
|
dir,
|
|
18006
|
-
gitdir =
|
|
18006
|
+
gitdir = join20(dir, ".git"),
|
|
18007
18007
|
ref,
|
|
18008
18008
|
oldref,
|
|
18009
18009
|
checkout: checkout2 = false
|
|
@@ -18033,7 +18033,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18033
18033
|
async function resetIndex({
|
|
18034
18034
|
fs: _fs,
|
|
18035
18035
|
dir,
|
|
18036
|
-
gitdir =
|
|
18036
|
+
gitdir = join20(dir, ".git"),
|
|
18037
18037
|
filepath,
|
|
18038
18038
|
ref,
|
|
18039
18039
|
cache = {}
|
|
@@ -18080,7 +18080,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18080
18080
|
gid: 0,
|
|
18081
18081
|
size: 0
|
|
18082
18082
|
};
|
|
18083
|
-
const object2 = dir && await fs2.read(
|
|
18083
|
+
const object2 = dir && await fs2.read(join20(dir, filepath));
|
|
18084
18084
|
if (object2) {
|
|
18085
18085
|
workdirOid = await hashObject$1({
|
|
18086
18086
|
gitdir: updatedGitdir,
|
|
@@ -18088,7 +18088,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18088
18088
|
object: object2
|
|
18089
18089
|
});
|
|
18090
18090
|
if (oid === workdirOid) {
|
|
18091
|
-
stats = await fs2.lstat(
|
|
18091
|
+
stats = await fs2.lstat(join20(dir, filepath));
|
|
18092
18092
|
}
|
|
18093
18093
|
}
|
|
18094
18094
|
await GitIndexManager.acquire(
|
|
@@ -18108,7 +18108,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18108
18108
|
async function resolveRef2({
|
|
18109
18109
|
fs: fs2,
|
|
18110
18110
|
dir,
|
|
18111
|
-
gitdir =
|
|
18111
|
+
gitdir = join20(dir, ".git"),
|
|
18112
18112
|
ref,
|
|
18113
18113
|
depth
|
|
18114
18114
|
}) {
|
|
@@ -18133,7 +18133,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18133
18133
|
async function setConfig({
|
|
18134
18134
|
fs: _fs,
|
|
18135
18135
|
dir,
|
|
18136
|
-
gitdir =
|
|
18136
|
+
gitdir = join20(dir, ".git"),
|
|
18137
18137
|
path,
|
|
18138
18138
|
value,
|
|
18139
18139
|
append = false
|
|
@@ -18201,7 +18201,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18201
18201
|
* @param {string} args.dir - The working directory.
|
|
18202
18202
|
* @param {string}[args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
|
|
18203
18203
|
*/
|
|
18204
|
-
constructor({ fs: fs2, dir, gitdir =
|
|
18204
|
+
constructor({ fs: fs2, dir, gitdir = join20(dir, ".git") }) {
|
|
18205
18205
|
Object.assign(this, {
|
|
18206
18206
|
fs: fs2,
|
|
18207
18207
|
dir,
|
|
@@ -18231,7 +18231,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18231
18231
|
* @returns {string} - The file path for the stash reference.
|
|
18232
18232
|
*/
|
|
18233
18233
|
get refStashPath() {
|
|
18234
|
-
return
|
|
18234
|
+
return join20(this.gitdir, _GitStashManager.refStash);
|
|
18235
18235
|
}
|
|
18236
18236
|
/**
|
|
18237
18237
|
* Gets the file path for the stash reflogs.
|
|
@@ -18239,7 +18239,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18239
18239
|
* @returns {string} - The file path for the stash reflogs.
|
|
18240
18240
|
*/
|
|
18241
18241
|
get refLogsStashPath() {
|
|
18242
|
-
return
|
|
18242
|
+
return join20(this.gitdir, _GitStashManager.refLogsStash);
|
|
18243
18243
|
}
|
|
18244
18244
|
/**
|
|
18245
18245
|
* Retrieves the author information for the stash.
|
|
@@ -18545,7 +18545,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18545
18545
|
async function stash({
|
|
18546
18546
|
fs: fs2,
|
|
18547
18547
|
dir,
|
|
18548
|
-
gitdir =
|
|
18548
|
+
gitdir = join20(dir, ".git"),
|
|
18549
18549
|
op = "push",
|
|
18550
18550
|
message = "",
|
|
18551
18551
|
refIdx = 0
|
|
@@ -18568,7 +18568,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18568
18568
|
const _fs = new FileSystem(fs2);
|
|
18569
18569
|
const updatedGitdir = await discoverGitdir({ fsp: _fs, dotgit: gitdir });
|
|
18570
18570
|
const folders = ["refs", "logs", "logs/refs"];
|
|
18571
|
-
folders.map((f) =>
|
|
18571
|
+
folders.map((f) => join20(updatedGitdir, f)).forEach(async (folder) => {
|
|
18572
18572
|
if (!await _fs.exists(folder)) {
|
|
18573
18573
|
await _fs.mkdir(folder);
|
|
18574
18574
|
}
|
|
@@ -18598,7 +18598,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18598
18598
|
async function status({
|
|
18599
18599
|
fs: _fs,
|
|
18600
18600
|
dir,
|
|
18601
|
-
gitdir =
|
|
18601
|
+
gitdir = join20(dir, ".git"),
|
|
18602
18602
|
filepath,
|
|
18603
18603
|
cache = {},
|
|
18604
18604
|
refresh: refresh2 = true
|
|
@@ -18637,7 +18637,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18637
18637
|
return "ignored";
|
|
18638
18638
|
}
|
|
18639
18639
|
}
|
|
18640
|
-
const stats = await fs2.lstat(
|
|
18640
|
+
const stats = await fs2.lstat(join20(dir, filepath));
|
|
18641
18641
|
const H = treeOid !== null;
|
|
18642
18642
|
const I = indexEntry !== null;
|
|
18643
18643
|
const W = stats !== null;
|
|
@@ -18647,7 +18647,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18647
18647
|
} else {
|
|
18648
18648
|
const config2 = await GitConfigManager.get({ fs: fs2, gitdir: updatedGitdir });
|
|
18649
18649
|
const autocrlf = await config2.get("core.autocrlf");
|
|
18650
|
-
const object2 = await fs2.read(
|
|
18650
|
+
const object2 = await fs2.read(join20(dir, filepath), { autocrlf });
|
|
18651
18651
|
const workdirOid = await hashObject$1({
|
|
18652
18652
|
gitdir: updatedGitdir,
|
|
18653
18653
|
type: "blob",
|
|
@@ -18696,9 +18696,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18696
18696
|
}
|
|
18697
18697
|
async function getOidAtPath({ fs: fs2, cache, gitdir: updatedGitdir, tree, path }) {
|
|
18698
18698
|
if (typeof path === "string") path = path.split("/");
|
|
18699
|
-
const
|
|
18699
|
+
const dirname17 = path.shift();
|
|
18700
18700
|
for (const entry of tree) {
|
|
18701
|
-
if (entry.path ===
|
|
18701
|
+
if (entry.path === dirname17) {
|
|
18702
18702
|
if (path.length === 0) {
|
|
18703
18703
|
return entry.oid;
|
|
18704
18704
|
}
|
|
@@ -18738,7 +18738,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18738
18738
|
async function statusMatrix({
|
|
18739
18739
|
fs: _fs,
|
|
18740
18740
|
dir,
|
|
18741
|
-
gitdir =
|
|
18741
|
+
gitdir = join20(dir, ".git"),
|
|
18742
18742
|
ref = "HEAD",
|
|
18743
18743
|
filepaths = ["."],
|
|
18744
18744
|
filter,
|
|
@@ -18811,7 +18811,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18811
18811
|
async function tag({
|
|
18812
18812
|
fs: _fs,
|
|
18813
18813
|
dir,
|
|
18814
|
-
gitdir =
|
|
18814
|
+
gitdir = join20(dir, ".git"),
|
|
18815
18815
|
ref,
|
|
18816
18816
|
object: object2,
|
|
18817
18817
|
force = false
|
|
@@ -18843,7 +18843,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18843
18843
|
async function updateIndex$1({
|
|
18844
18844
|
fs: _fs,
|
|
18845
18845
|
dir,
|
|
18846
|
-
gitdir =
|
|
18846
|
+
gitdir = join20(dir, ".git"),
|
|
18847
18847
|
cache = {},
|
|
18848
18848
|
filepath,
|
|
18849
18849
|
oid,
|
|
@@ -18863,7 +18863,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18863
18863
|
{ fs: fs2, gitdir: updatedGitdir, cache },
|
|
18864
18864
|
async function(index3) {
|
|
18865
18865
|
if (!force) {
|
|
18866
|
-
const fileStats2 = await fs2.lstat(
|
|
18866
|
+
const fileStats2 = await fs2.lstat(join20(dir, filepath));
|
|
18867
18867
|
if (fileStats2) {
|
|
18868
18868
|
if (fileStats2.isDirectory()) {
|
|
18869
18869
|
throw new InvalidFilepathError("directory");
|
|
@@ -18881,7 +18881,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18881
18881
|
}
|
|
18882
18882
|
let fileStats;
|
|
18883
18883
|
if (!oid) {
|
|
18884
|
-
fileStats = await fs2.lstat(
|
|
18884
|
+
fileStats = await fs2.lstat(join20(dir, filepath));
|
|
18885
18885
|
if (!fileStats) {
|
|
18886
18886
|
throw new NotFoundError(
|
|
18887
18887
|
`file at "${filepath}" on disk and "remove" not set`
|
|
@@ -18902,7 +18902,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18902
18902
|
let stats;
|
|
18903
18903
|
if (!oid) {
|
|
18904
18904
|
stats = fileStats;
|
|
18905
|
-
const object2 = stats.isSymbolicLink() ? await fs2.readlink(
|
|
18905
|
+
const object2 = stats.isSymbolicLink() ? await fs2.readlink(join20(dir, filepath)) : await fs2.read(join20(dir, filepath));
|
|
18906
18906
|
oid = await _writeObject({
|
|
18907
18907
|
fs: fs2,
|
|
18908
18908
|
gitdir: updatedGitdir,
|
|
@@ -18946,7 +18946,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18946
18946
|
async function walk({
|
|
18947
18947
|
fs: fs2,
|
|
18948
18948
|
dir,
|
|
18949
|
-
gitdir =
|
|
18949
|
+
gitdir = join20(dir, ".git"),
|
|
18950
18950
|
trees,
|
|
18951
18951
|
map: map2,
|
|
18952
18952
|
reduce,
|
|
@@ -18974,7 +18974,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18974
18974
|
throw err2;
|
|
18975
18975
|
}
|
|
18976
18976
|
}
|
|
18977
|
-
async function writeBlob({ fs: fs2, dir, gitdir =
|
|
18977
|
+
async function writeBlob({ fs: fs2, dir, gitdir = join20(dir, ".git"), blob: blob2 }) {
|
|
18978
18978
|
try {
|
|
18979
18979
|
assertParameter("fs", fs2);
|
|
18980
18980
|
assertParameter("gitdir", gitdir);
|
|
@@ -18996,7 +18996,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
18996
18996
|
async function writeCommit({
|
|
18997
18997
|
fs: fs2,
|
|
18998
18998
|
dir,
|
|
18999
|
-
gitdir =
|
|
18999
|
+
gitdir = join20(dir, ".git"),
|
|
19000
19000
|
commit: commit2
|
|
19001
19001
|
}) {
|
|
19002
19002
|
try {
|
|
@@ -19018,7 +19018,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
19018
19018
|
async function writeObject({
|
|
19019
19019
|
fs: _fs,
|
|
19020
19020
|
dir,
|
|
19021
|
-
gitdir =
|
|
19021
|
+
gitdir = join20(dir, ".git"),
|
|
19022
19022
|
type,
|
|
19023
19023
|
object: object2,
|
|
19024
19024
|
format = "parsed",
|
|
@@ -19064,7 +19064,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
19064
19064
|
async function writeRef({
|
|
19065
19065
|
fs: _fs,
|
|
19066
19066
|
dir,
|
|
19067
|
-
gitdir =
|
|
19067
|
+
gitdir = join20(dir, ".git"),
|
|
19068
19068
|
ref,
|
|
19069
19069
|
value,
|
|
19070
19070
|
force = false,
|
|
@@ -19119,7 +19119,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
19119
19119
|
});
|
|
19120
19120
|
return oid;
|
|
19121
19121
|
}
|
|
19122
|
-
async function writeTag({ fs: fs2, dir, gitdir =
|
|
19122
|
+
async function writeTag({ fs: fs2, dir, gitdir = join20(dir, ".git"), tag: tag2 }) {
|
|
19123
19123
|
try {
|
|
19124
19124
|
assertParameter("fs", fs2);
|
|
19125
19125
|
assertParameter("gitdir", gitdir);
|
|
@@ -19136,7 +19136,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
19136
19136
|
throw err2;
|
|
19137
19137
|
}
|
|
19138
19138
|
}
|
|
19139
|
-
async function writeTree2({ fs: fs2, dir, gitdir =
|
|
19139
|
+
async function writeTree2({ fs: fs2, dir, gitdir = join20(dir, ".git"), tree }) {
|
|
19140
19140
|
try {
|
|
19141
19141
|
assertParameter("fs", fs2);
|
|
19142
19142
|
assertParameter("gitdir", gitdir);
|
|
@@ -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.29.0",
|
|
19765
19765
|
description: "Agent-friendly AnimaGuru CLI built with CrustJS",
|
|
19766
19766
|
type: "module",
|
|
19767
19767
|
bin: {
|
|
@@ -19978,14 +19978,14 @@ function normalizeFlag(name2, def) {
|
|
|
19978
19978
|
name: name2,
|
|
19979
19979
|
reason: "empty-env"
|
|
19980
19980
|
});
|
|
19981
|
-
for (const [field,
|
|
19982
|
-
if (
|
|
19981
|
+
for (const [field, delimiter3] of [["delimiter", def.delimiter], ["env.delimiter", def.env?.delimiter]]) {
|
|
19982
|
+
if (delimiter3 === void 0) continue;
|
|
19983
19983
|
if (!def.multiple) throw new CrustError("DEFINITION", `Flag "${name2}" ${field} requires multiple: true`, {
|
|
19984
19984
|
subject: "flag",
|
|
19985
19985
|
name: name2,
|
|
19986
19986
|
reason: "delimiter-without-multiple"
|
|
19987
19987
|
});
|
|
19988
|
-
if (
|
|
19988
|
+
if (delimiter3 === "") throw new CrustError("DEFINITION", `Flag "${name2}" ${field} must be non-empty`, {
|
|
19989
19989
|
subject: "flag",
|
|
19990
19990
|
name: name2,
|
|
19991
19991
|
reason: "empty-delimiter"
|
|
@@ -20457,9 +20457,9 @@ function resolveAliases(tokens, spellings) {
|
|
|
20457
20457
|
}
|
|
20458
20458
|
return canonical;
|
|
20459
20459
|
}
|
|
20460
|
-
function splitOccurrences(values,
|
|
20461
|
-
if (
|
|
20462
|
-
return values.flatMap((value) => value.split(
|
|
20460
|
+
function splitOccurrences(values, delimiter3) {
|
|
20461
|
+
if (delimiter3 === void 0) return [...values];
|
|
20462
|
+
return values.flatMap((value) => value.split(delimiter3)).filter((value) => value !== "");
|
|
20463
20463
|
}
|
|
20464
20464
|
function envFlagValue(name2, def, raw) {
|
|
20465
20465
|
const occurrences = def.multiple ? splitOccurrences([raw], def.env?.delimiter) : [raw];
|
|
@@ -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
|
|
24299
|
-
import { dirname as
|
|
24298
|
+
import { mkdir as mkdir16, readFile as readFile20, writeFile as writeFile16 } from "node:fs/promises";
|
|
24299
|
+
import { dirname as dirname15, resolve as resolve18 } from "node:path";
|
|
24300
24300
|
import { setTimeout as delay6 } from "node:timers/promises";
|
|
24301
24301
|
|
|
24302
24302
|
// node_modules/fflate/esm/index.mjs
|
|
@@ -25288,208 +25288,6 @@ function unzipSync(data, opts) {
|
|
|
25288
25288
|
// shared/auth.ts
|
|
25289
25289
|
var CLI_CLIENT_ID = "animaguru-cli";
|
|
25290
25290
|
|
|
25291
|
-
// shared/sprites/styles.ts
|
|
25292
|
-
var GAME_SPRITE_STYLES = ["hd-cartoon", "pixel", "painted", "vector"];
|
|
25293
|
-
var VIDEO_SPRITE_STYLES = [
|
|
25294
|
-
"photoreal-cutout",
|
|
25295
|
-
"photo-collage",
|
|
25296
|
-
"paper-cutout",
|
|
25297
|
-
"photoreal-stop-motion",
|
|
25298
|
-
"cutout-motion-graphics"
|
|
25299
|
-
];
|
|
25300
|
-
var SPRITE_STYLES = [...GAME_SPRITE_STYLES, ...VIDEO_SPRITE_STYLES];
|
|
25301
|
-
|
|
25302
|
-
// shared/credits.ts
|
|
25303
|
-
var UNITS_PER_CREDIT = 10;
|
|
25304
|
-
var toCredits = (units) => Math.round(units) / UNITS_PER_CREDIT;
|
|
25305
|
-
var toUnits = (credits) => Math.round(credits * UNITS_PER_CREDIT);
|
|
25306
|
-
|
|
25307
|
-
// shared/sprites/types.ts
|
|
25308
|
-
var SPRITE_KINDS = ["character", "vehicle", "machine", "effect"];
|
|
25309
|
-
var SPRITE_ACTIONS = ["idle", "walk", "run", "skid-stop", "shoot", "jump", "hurt", "death", "slide", "punch", "kick"];
|
|
25310
|
-
var SPRITE_KIND_ACTIONS = {
|
|
25311
|
-
character: SPRITE_ACTIONS,
|
|
25312
|
-
vehicle: ["idle", "move", "fire", "hurt", "destroyed"],
|
|
25313
|
-
machine: ["idle", "work", "activate", "fire", "hurt", "break"],
|
|
25314
|
-
effect: ["projectile", "charge", "impact", "explosion", "aura"]
|
|
25315
|
-
};
|
|
25316
|
-
var ALL_SPRITE_ACTIONS = [...new Set(Object.values(SPRITE_KIND_ACTIONS).flat())];
|
|
25317
|
-
var SPRITE_TOP_ACTIONS = {
|
|
25318
|
-
vehicle: ["hull-move", "hull-destroyed", "turret-fire"],
|
|
25319
|
-
machine: ["hull-break", "turret-fire"]
|
|
25320
|
-
};
|
|
25321
|
-
var ALL_TOP_ACTIONS = [...new Set(Object.values(SPRITE_TOP_ACTIONS).flat())];
|
|
25322
|
-
var CUSTOM_FRAMES = { min: 2, max: 12 };
|
|
25323
|
-
|
|
25324
|
-
// shared/sprites/models.ts
|
|
25325
|
-
var DEFAULT_SPRITE_IMAGE_MODEL = "fal/gpt-image-2.5-medium";
|
|
25326
|
-
var SPRITE_IMAGE_MODELS = [
|
|
25327
|
-
{ id: DEFAULT_SPRITE_IMAGE_MODEL, label: "GPT Image 2.5 \xB7 medium (fal)", provider: "fal", edit: true, nativeAlpha: true, maxImages: 16, relCost: 0.3, quality: "medium", endpoints: { generate: "openai/gpt-image-2.5/flare/text-to-image", edit: "openai/gpt-image-2.5/flare/edit" } },
|
|
25328
|
-
{ id: "fal/gpt-image-2-low", label: "GPT Image 2 \xB7 low (fal)", provider: "fal", edit: true, spriteBackupCutout: true, maxImages: 16, relCost: 0.2, quality: "low", endpoints: { generate: "openai/gpt-image-2", edit: "openai/gpt-image-2/edit" } },
|
|
25329
|
-
{ id: "fal/muse-image", label: "Muse Image (fal)", provider: "fal", edit: true, maxImages: 10, relCost: 0.2, endpoints: { generate: "meta/muse-image/text-to-image", edit: "meta/muse-image/edit" } },
|
|
25330
|
-
{ id: "fal/krea-2-turbo", label: "Krea 2 Turbo (fal)", provider: "fal", edit: false, maxImages: 0, relCost: 0.16, endpoints: { generate: "fal-ai/krea-2/turbo" } },
|
|
25331
|
-
{ id: "gpt-image-2.5", label: "GPT Image 2.5 (OpenAI)", provider: "openai", edit: true, nativeAlpha: true, maxImages: 16, relCost: 1 },
|
|
25332
|
-
{ id: "black-forest-labs/flux-2-max", label: "FLUX.2 [max]", provider: "workers-ai", edit: true, maxImages: 8, relCost: 3 },
|
|
25333
|
-
{ id: "bytedance/seedream-5-pro", label: "Seedream 5 Pro", provider: "workers-ai", edit: true, maxImages: 10, relCost: 1.5 },
|
|
25334
|
-
{ id: "xai/grok-imagine-image-2.0", label: "Grok Imagine Image 2.0", provider: "workers-ai", edit: true, maxImages: 5, relCost: 1 },
|
|
25335
|
-
{ id: "alibaba/qwen-image-3.0-pro", label: "Qwen Image 3.0 Pro", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.5 },
|
|
25336
|
-
{ id: "krea/krea-2-medium-turbo", label: "Krea 2 Medium Turbo", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.25 }
|
|
25337
|
-
];
|
|
25338
|
-
var SPRITE_IMAGE_MODEL_IDS = SPRITE_IMAGE_MODELS.map((m) => m.id);
|
|
25339
|
-
function spriteImageModel(id2) {
|
|
25340
|
-
return SPRITE_IMAGE_MODELS.find((m) => m.id === id2) ?? SPRITE_IMAGE_MODELS[0];
|
|
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", "keyframes-to-video"];
|
|
25343
|
-
var STUDIO_VIDEO_WORKFLOWS = ["image-to-video", "text-to-video", "extend-video"];
|
|
25344
|
-
var MEDIA_LENGTH_WORKFLOWS = ["lip-sync", "recast", "relight", "3d-to-video"];
|
|
25345
|
-
var lengthFromMedia = (workflow) => MEDIA_LENGTH_WORKFLOWS.includes(workflow);
|
|
25346
|
-
var VIDEO_STYLES = ["vhs", "retro-toon-70s", "low-poly", "hand-drawn", "16bit-pixel"];
|
|
25347
|
-
var VHS_DAMAGE_LEVELS = ["light", "medium", "heavy"];
|
|
25348
|
-
var VIDEO_RESOLUTIONS = ["480p", "720p", "768p", "1080p", "2k"];
|
|
25349
|
-
var H3_RESOLUTIONS = ["480p", "768p", "1080p", "2k"];
|
|
25350
|
-
var VIDEO_ASPECT_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
25351
|
-
var PROMPT_EXPANSION_MODES = ["disabled", "balanced", "quality"];
|
|
25352
|
-
var EXTEND_OUTPUTS = ["extended", "continuation"];
|
|
25353
|
-
var SOUNDTRACK_MAX_BYTES = 15 * 1024 * 1024;
|
|
25354
|
-
var EXTEND_SOURCE_MAX_BYTES = 50 * 1024 * 1024;
|
|
25355
|
-
var MAX_AUDIO_REFERENCES = 3;
|
|
25356
|
-
var MAX_VIDEO_REFERENCE_IMAGES = 9;
|
|
25357
|
-
var MAX_REFERENCE_VIDEOS = 3;
|
|
25358
|
-
var MAX_REFERENCE_FILES = 12;
|
|
25359
|
-
var MAX_RECAST_PEOPLE = 4;
|
|
25360
|
-
var MAX_3D_REFERENCES = 8;
|
|
25361
|
-
var MAX_CAMERA_KEYFRAMES = 12;
|
|
25362
|
-
var MAX_CAMERA_TURNS = 32;
|
|
25363
|
-
var MAX_IMAGE_KEYFRAMES = 10;
|
|
25364
|
-
var KEYFRAME_FPS = 24;
|
|
25365
|
-
var H3_MAX = "minimax/h3-max";
|
|
25366
|
-
var FLUX_3_MAX = "blackforestlabs/flux-3-max";
|
|
25367
|
-
var h3Endpoints = (route) => ({ "image-to-video": `${route}/image-to-video`, "text-to-video": `${route}/text-to-video`, "extend-video": `${route}/extend-video` });
|
|
25368
|
-
var SPRITE_VIDEO_MODELS = [
|
|
25369
|
-
{
|
|
25370
|
-
id: "pruna/p-video-2-pro",
|
|
25371
|
-
label: "Pruna P-Video 2 Pro",
|
|
25372
|
-
provider: "pruna",
|
|
25373
|
-
workflows: ["image-to-video"],
|
|
25374
|
-
resolutions: ["480p", "768p"],
|
|
25375
|
-
modes: ["cost", "speed", "quality"],
|
|
25376
|
-
lastFrame: true,
|
|
25377
|
-
estimatedCreditsPerSecond: { "480p": { cost: 1, speed: 2, quality: 4 }, "768p": { cost: 2.5, speed: 3.5, quality: 7.5 } },
|
|
25378
|
-
seconds: { min: 5, max: 15 }
|
|
25379
|
-
},
|
|
25380
|
-
{
|
|
25381
|
-
id: "heygen/heygen-video-1",
|
|
25382
|
-
label: "HeyGen Video 1",
|
|
25383
|
-
provider: "heygen",
|
|
25384
|
-
workflows: ["image-to-video"],
|
|
25385
|
-
resolutions: ["480p", "768p"],
|
|
25386
|
-
modes: ["cost"],
|
|
25387
|
-
lastFrame: false,
|
|
25388
|
-
estimatedCreditsPerSecond: { "480p": { cost: 1 }, "768p": { cost: 1.5 } },
|
|
25389
|
-
seconds: { min: 5, max: 15 }
|
|
25390
|
-
},
|
|
25391
|
-
{
|
|
25392
|
-
id: "fal/minimax-h3-max",
|
|
25393
|
-
label: "MiniMax H3 Max (fal.ai)",
|
|
25394
|
-
provider: "fal",
|
|
25395
|
-
// Every workflow but FLUX 3 Max's keyframes.
|
|
25396
|
-
workflows: VIDEO_WORKFLOWS.filter((w) => w !== "keyframes-to-video"),
|
|
25397
|
-
endpoints: {
|
|
25398
|
-
...h3Endpoints(H3_MAX),
|
|
25399
|
-
"reference-to-video": `${H3_MAX}/reference-to-video`,
|
|
25400
|
-
"lip-sync": `${H3_MAX}/lip-sync/image-to-video`,
|
|
25401
|
-
"camera-controls": `${H3_MAX}/camera-controls`,
|
|
25402
|
-
"insert-video": `${H3_MAX}/insert-video`,
|
|
25403
|
-
recast: `${H3_MAX}/recast`,
|
|
25404
|
-
relight: `${H3_MAX}/relight`,
|
|
25405
|
-
"3d-to-video": `${H3_MAX}/3d-to-video`,
|
|
25406
|
-
style: `${H3_MAX}/styles`
|
|
25407
|
-
},
|
|
25408
|
-
resolutions: ["480p", "768p", "1080p"],
|
|
25409
|
-
workflowOptions: {
|
|
25410
|
-
"extend-video": { resolutions: H3_RESOLUTIONS },
|
|
25411
|
-
"lip-sync": { resolutions: H3_RESOLUTIONS, seconds: { min: 5, max: 900, fractional: true } },
|
|
25412
|
-
"insert-video": { resolutions: ["480p", "768p"], seconds: { min: 5, max: 13, fractional: true }, creditsPerSecond: { "480p": 5, "768p": 6 } },
|
|
25413
|
-
recast: { resolutions: ["768p", "1080p"], seconds: { min: 5, max: 30, fractional: true }, creditsPerSecond: { "768p": 30, "1080p": 45 } },
|
|
25414
|
-
relight: { resolutions: H3_RESOLUTIONS, seconds: { min: 2.33, max: 15, fractional: true } },
|
|
25415
|
-
"3d-to-video": { seconds: { min: 1, max: 15, fractional: true } },
|
|
25416
|
-
style: { resolutions: ["768p"], seconds: { min: 5, max: 15 } }
|
|
25417
|
-
},
|
|
25418
|
-
modes: ["quality"],
|
|
25419
|
-
lastFrame: true,
|
|
25420
|
-
endFrameOnly: true,
|
|
25421
|
-
seed: true,
|
|
25422
|
-
promptExpansion: PROMPT_EXPANSION_MODES,
|
|
25423
|
-
audio: true,
|
|
25424
|
-
estimatedCreditsPerSecond: { "480p": { quality: 5 }, "768p": { quality: 8 }, "1080p": { quality: 16 }, "2k": { quality: 32 } },
|
|
25425
|
-
seconds: { min: 1, max: 15, fractional: true }
|
|
25426
|
-
},
|
|
25427
|
-
{
|
|
25428
|
-
id: "fal/minimax-h3-max-turbo",
|
|
25429
|
-
label: "MiniMax H3 Max Turbo (fal.ai)",
|
|
25430
|
-
provider: "fal",
|
|
25431
|
-
workflows: STUDIO_VIDEO_WORKFLOWS,
|
|
25432
|
-
endpoints: h3Endpoints("minimax/h3-max-turbo"),
|
|
25433
|
-
resolutions: ["480p", "768p", "1080p"],
|
|
25434
|
-
workflowOptions: { "extend-video": { resolutions: H3_RESOLUTIONS } },
|
|
25435
|
-
modes: ["speed"],
|
|
25436
|
-
lastFrame: true,
|
|
25437
|
-
endFrameOnly: true,
|
|
25438
|
-
seed: true,
|
|
25439
|
-
promptExpansion: PROMPT_EXPANSION_MODES,
|
|
25440
|
-
audio: true,
|
|
25441
|
-
estimatedCreditsPerSecond: { "480p": { speed: 2.5 }, "768p": { speed: 4 }, "1080p": { speed: 8 }, "2k": { speed: 16 } },
|
|
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 }
|
|
25458
|
-
}
|
|
25459
|
-
];
|
|
25460
|
-
var SPRITE_VIDEO_MODEL_IDS = SPRITE_VIDEO_MODELS.map((m) => m.id);
|
|
25461
|
-
var DEFAULT_SPRITE_VIDEO_MODEL = "pruna/p-video-2-pro";
|
|
25462
|
-
function spriteVideoModel(id2) {
|
|
25463
|
-
return SPRITE_VIDEO_MODELS.find((m) => m.id === id2) ?? SPRITE_VIDEO_MODELS[0];
|
|
25464
|
-
}
|
|
25465
|
-
function videoResolutions(model, workflow = "image-to-video") {
|
|
25466
|
-
return model.workflowOptions?.[workflow]?.resolutions ?? model.resolutions;
|
|
25467
|
-
}
|
|
25468
|
-
function videoSeconds(model, workflow = "image-to-video") {
|
|
25469
|
-
return model.workflowOptions?.[workflow]?.seconds ?? model.seconds;
|
|
25470
|
-
}
|
|
25471
|
-
var INCLUDED_REFERENCE_TOKENS = 4096;
|
|
25472
|
-
var imageReferenceTokens = (size) => size && size[0] > 0 && size[1] > 0 ? 32 * Math.ceil(32 * Math.max(...size) / Math.min(...size)) : 1824;
|
|
25473
|
-
var clipReferenceTokens = (seconds2, resolution) => Math.ceil(Math.max(0, seconds2) * (resolution === "480p" ? 2700 : 6900));
|
|
25474
|
-
var audioReferenceTokens = (seconds2) => Math.ceil(Math.max(0, seconds2) * 80);
|
|
25475
|
-
var DEFAULT_GENERATED_REFERENCES = 2;
|
|
25476
|
-
function billedVideoSeconds(model, workflow, seconds2) {
|
|
25477
|
-
const s = videoSeconds(model, workflow).fractional ? seconds2 : Math.round(seconds2);
|
|
25478
|
-
if (workflow === "3d-to-video") return Math.max(5, s);
|
|
25479
|
-
return workflow === "lip-sync" && s > 15 ? s * 1.2 : s;
|
|
25480
|
-
}
|
|
25481
|
-
function videoCreditsPerSecond(model, p) {
|
|
25482
|
-
const override = model.workflowOptions?.[p.workflow ?? "image-to-video"]?.creditsPerSecond?.[p.resolution];
|
|
25483
|
-
if (override !== void 0) return override;
|
|
25484
|
-
const byMode = model.estimatedCreditsPerSecond[p.resolution] ?? model.estimatedCreditsPerSecond[model.resolutions[0]];
|
|
25485
|
-
return byMode[p.mode] ?? byMode[model.modes[0]] ?? 0;
|
|
25486
|
-
}
|
|
25487
|
-
function spriteVideoEstimate(model, p, extras2 = {}) {
|
|
25488
|
-
const seconds2 = billedVideoSeconds(model, p.workflow ?? "image-to-video", p.seconds);
|
|
25489
|
-
const beyond = Math.max(0, (extras2.referenceTokens ?? 0) - INCLUDED_REFERENCE_TOKENS) * 2e-3 + (extras2.generatedReferences ?? 0) * 3;
|
|
25490
|
-
return Math.max(1, Math.ceil((videoCreditsPerSecond(model, p) * seconds2 + beyond) * UNITS_PER_CREDIT));
|
|
25491
|
-
}
|
|
25492
|
-
|
|
25493
25291
|
// node_modules/zod/v4/classic/external.js
|
|
25494
25292
|
var external_exports = {};
|
|
25495
25293
|
__export(external_exports, {
|
|
@@ -27487,8 +27285,8 @@ function emoji2() {
|
|
|
27487
27285
|
}
|
|
27488
27286
|
var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
|
27489
27287
|
var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
|
|
27490
|
-
var mac = (
|
|
27491
|
-
const escapedDelim = escapeRegex(
|
|
27288
|
+
var mac = (delimiter3) => {
|
|
27289
|
+
const escapedDelim = escapeRegex(delimiter3 ?? ":");
|
|
27492
27290
|
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
|
27493
27291
|
};
|
|
27494
27292
|
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
|
@@ -30516,7 +30314,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
30516
30314
|
var NONE = 0;
|
|
30517
30315
|
var ASSUMED = 1;
|
|
30518
30316
|
var PROVEN = 2;
|
|
30519
|
-
function isRecursive(inst, stack,
|
|
30317
|
+
function isRecursive(inst, stack, resolve19) {
|
|
30520
30318
|
const cached2 = recursive.get(inst);
|
|
30521
30319
|
if (cached2 !== void 0)
|
|
30522
30320
|
return cached2 ? PROVEN : NONE;
|
|
@@ -30526,7 +30324,7 @@ function isRecursive(inst, stack, resolve18) {
|
|
|
30526
30324
|
let result = NONE;
|
|
30527
30325
|
const check2 = (child) => {
|
|
30528
30326
|
if (result !== PROVEN && child?._zod) {
|
|
30529
|
-
const answer = isRecursive(child, stack,
|
|
30327
|
+
const answer = isRecursive(child, stack, resolve19);
|
|
30530
30328
|
if (answer > result)
|
|
30531
30329
|
result = answer;
|
|
30532
30330
|
}
|
|
@@ -30537,7 +30335,7 @@ function isRecursive(inst, stack, resolve18) {
|
|
|
30537
30335
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
30538
30336
|
if (spread && !desc.enumerable)
|
|
30539
30337
|
continue;
|
|
30540
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
30338
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve19) : NONE;
|
|
30541
30339
|
if (child > answer)
|
|
30542
30340
|
answer = child;
|
|
30543
30341
|
}
|
|
@@ -30601,7 +30399,7 @@ function isRecursive(inst, stack, resolve18) {
|
|
|
30601
30399
|
break;
|
|
30602
30400
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
30603
30401
|
case "lazy": {
|
|
30604
|
-
const inner = def._cachedInner ?? (
|
|
30402
|
+
const inner = def._cachedInner ?? (resolve19 ? inst._zod.innerType : void 0);
|
|
30605
30403
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
30606
30404
|
break;
|
|
30607
30405
|
}
|
|
@@ -45158,6 +44956,220 @@ function date4(params) {
|
|
|
45158
44956
|
return _coercedDate(ZodDate, params);
|
|
45159
44957
|
}
|
|
45160
44958
|
|
|
44959
|
+
// shared/showcase.ts
|
|
44960
|
+
var SHOWCASE_SECTORS = ["cafe", "restaurant", "food", "retail", "beauty", "fitness", "workspace", "hospitality", "realestate", "education", "health", "events", "technology", "services"];
|
|
44961
|
+
var SHOWCASE_TAGS = ["social", "website", "product", "space", "offer", "brand", "explainer", "event"];
|
|
44962
|
+
var SHOWCASE_LOCALES = ["", "en", "tr", "sv"];
|
|
44963
|
+
var showcaseEntry = external_exports.object({
|
|
44964
|
+
sector: external_exports.enum(SHOWCASE_SECTORS),
|
|
44965
|
+
tags: external_exports.array(external_exports.enum(SHOWCASE_TAGS)).max(SHOWCASE_TAGS.length).default([]).transform((tags) => [...new Set(tags)]),
|
|
44966
|
+
locale: external_exports.enum(SHOWCASE_LOCALES).default(""),
|
|
44967
|
+
/** Lower comes first; films with the same position show newest first. */
|
|
44968
|
+
position: external_exports.number().int().min(0).max(1e3).default(0)
|
|
44969
|
+
}).strict();
|
|
44970
|
+
|
|
44971
|
+
// shared/sprites/styles.ts
|
|
44972
|
+
var GAME_SPRITE_STYLES = ["hd-cartoon", "pixel", "painted", "vector"];
|
|
44973
|
+
var VIDEO_SPRITE_STYLES = [
|
|
44974
|
+
"photoreal-cutout",
|
|
44975
|
+
"photo-collage",
|
|
44976
|
+
"paper-cutout",
|
|
44977
|
+
"photoreal-stop-motion",
|
|
44978
|
+
"cutout-motion-graphics"
|
|
44979
|
+
];
|
|
44980
|
+
var SPRITE_STYLES = [...GAME_SPRITE_STYLES, ...VIDEO_SPRITE_STYLES];
|
|
44981
|
+
|
|
44982
|
+
// shared/credits.ts
|
|
44983
|
+
var UNITS_PER_CREDIT = 10;
|
|
44984
|
+
var toCredits = (units) => Math.round(units) / UNITS_PER_CREDIT;
|
|
44985
|
+
var toUnits = (credits) => Math.round(credits * UNITS_PER_CREDIT);
|
|
44986
|
+
|
|
44987
|
+
// shared/sprites/types.ts
|
|
44988
|
+
var SPRITE_KINDS = ["character", "vehicle", "machine", "effect"];
|
|
44989
|
+
var SPRITE_ACTIONS = ["idle", "walk", "run", "skid-stop", "shoot", "jump", "hurt", "death", "slide", "punch", "kick"];
|
|
44990
|
+
var SPRITE_KIND_ACTIONS = {
|
|
44991
|
+
character: SPRITE_ACTIONS,
|
|
44992
|
+
vehicle: ["idle", "move", "fire", "hurt", "destroyed"],
|
|
44993
|
+
machine: ["idle", "work", "activate", "fire", "hurt", "break"],
|
|
44994
|
+
effect: ["projectile", "charge", "impact", "explosion", "aura"]
|
|
44995
|
+
};
|
|
44996
|
+
var ALL_SPRITE_ACTIONS = [...new Set(Object.values(SPRITE_KIND_ACTIONS).flat())];
|
|
44997
|
+
var SPRITE_TOP_ACTIONS = {
|
|
44998
|
+
vehicle: ["hull-move", "hull-destroyed", "turret-fire"],
|
|
44999
|
+
machine: ["hull-break", "turret-fire"]
|
|
45000
|
+
};
|
|
45001
|
+
var ALL_TOP_ACTIONS = [...new Set(Object.values(SPRITE_TOP_ACTIONS).flat())];
|
|
45002
|
+
var CUSTOM_FRAMES = { min: 2, max: 12 };
|
|
45003
|
+
|
|
45004
|
+
// shared/sprites/models.ts
|
|
45005
|
+
var DEFAULT_SPRITE_IMAGE_MODEL = "fal/gpt-image-2.5-medium";
|
|
45006
|
+
var SPRITE_IMAGE_MODELS = [
|
|
45007
|
+
{ id: DEFAULT_SPRITE_IMAGE_MODEL, label: "GPT Image 2.5 \xB7 medium (fal)", provider: "fal", edit: true, nativeAlpha: true, maxImages: 16, relCost: 0.3, quality: "medium", endpoints: { generate: "openai/gpt-image-2.5/flare/text-to-image", edit: "openai/gpt-image-2.5/flare/edit" } },
|
|
45008
|
+
{ id: "fal/gpt-image-2-low", label: "GPT Image 2 \xB7 low (fal)", provider: "fal", edit: true, spriteBackupCutout: true, maxImages: 16, relCost: 0.2, quality: "low", endpoints: { generate: "openai/gpt-image-2", edit: "openai/gpt-image-2/edit" } },
|
|
45009
|
+
{ id: "fal/muse-image", label: "Muse Image (fal)", provider: "fal", edit: true, maxImages: 10, relCost: 0.2, endpoints: { generate: "meta/muse-image/text-to-image", edit: "meta/muse-image/edit" } },
|
|
45010
|
+
{ id: "fal/krea-2-turbo", label: "Krea 2 Turbo (fal)", provider: "fal", edit: false, maxImages: 0, relCost: 0.16, endpoints: { generate: "fal-ai/krea-2/turbo" } },
|
|
45011
|
+
{ id: "gpt-image-2.5", label: "GPT Image 2.5 (OpenAI)", provider: "openai", edit: true, nativeAlpha: true, maxImages: 16, relCost: 1 },
|
|
45012
|
+
{ id: "black-forest-labs/flux-2-max", label: "FLUX.2 [max]", provider: "workers-ai", edit: true, maxImages: 8, relCost: 3 },
|
|
45013
|
+
{ id: "bytedance/seedream-5-pro", label: "Seedream 5 Pro", provider: "workers-ai", edit: true, maxImages: 10, relCost: 1.5 },
|
|
45014
|
+
{ id: "xai/grok-imagine-image-2.0", label: "Grok Imagine Image 2.0", provider: "workers-ai", edit: true, maxImages: 5, relCost: 1 },
|
|
45015
|
+
{ id: "alibaba/qwen-image-3.0-pro", label: "Qwen Image 3.0 Pro", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.5 },
|
|
45016
|
+
{ id: "krea/krea-2-medium-turbo", label: "Krea 2 Medium Turbo", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.25 }
|
|
45017
|
+
];
|
|
45018
|
+
var SPRITE_IMAGE_MODEL_IDS = SPRITE_IMAGE_MODELS.map((m) => m.id);
|
|
45019
|
+
function spriteImageModel(id2) {
|
|
45020
|
+
return SPRITE_IMAGE_MODELS.find((m) => m.id === id2) ?? SPRITE_IMAGE_MODELS[0];
|
|
45021
|
+
}
|
|
45022
|
+
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"];
|
|
45023
|
+
var STUDIO_VIDEO_WORKFLOWS = ["image-to-video", "text-to-video", "extend-video"];
|
|
45024
|
+
var MEDIA_LENGTH_WORKFLOWS = ["lip-sync", "recast", "relight", "3d-to-video"];
|
|
45025
|
+
var lengthFromMedia = (workflow) => MEDIA_LENGTH_WORKFLOWS.includes(workflow);
|
|
45026
|
+
var VIDEO_STYLES = ["vhs", "retro-toon-70s", "low-poly", "hand-drawn", "16bit-pixel"];
|
|
45027
|
+
var VHS_DAMAGE_LEVELS = ["light", "medium", "heavy"];
|
|
45028
|
+
var VIDEO_RESOLUTIONS = ["480p", "720p", "768p", "1080p", "2k"];
|
|
45029
|
+
var H3_RESOLUTIONS = ["480p", "768p", "1080p", "2k"];
|
|
45030
|
+
var VIDEO_ASPECT_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
|
|
45031
|
+
var PROMPT_EXPANSION_MODES = ["disabled", "balanced", "quality"];
|
|
45032
|
+
var EXTEND_OUTPUTS = ["extended", "continuation"];
|
|
45033
|
+
var SOUNDTRACK_MAX_BYTES = 15 * 1024 * 1024;
|
|
45034
|
+
var EXTEND_SOURCE_MAX_BYTES = 50 * 1024 * 1024;
|
|
45035
|
+
var MAX_AUDIO_REFERENCES = 3;
|
|
45036
|
+
var MAX_VIDEO_REFERENCE_IMAGES = 9;
|
|
45037
|
+
var MAX_REFERENCE_VIDEOS = 3;
|
|
45038
|
+
var MAX_REFERENCE_FILES = 12;
|
|
45039
|
+
var MAX_RECAST_PEOPLE = 4;
|
|
45040
|
+
var MAX_3D_REFERENCES = 8;
|
|
45041
|
+
var MAX_CAMERA_KEYFRAMES = 12;
|
|
45042
|
+
var MAX_CAMERA_TURNS = 32;
|
|
45043
|
+
var MAX_IMAGE_KEYFRAMES = 10;
|
|
45044
|
+
var KEYFRAME_FPS = 24;
|
|
45045
|
+
var H3_MAX = "minimax/h3-max";
|
|
45046
|
+
var FLUX_3_MAX = "blackforestlabs/flux-3-max";
|
|
45047
|
+
var h3Endpoints = (route) => ({ "image-to-video": `${route}/image-to-video`, "text-to-video": `${route}/text-to-video`, "extend-video": `${route}/extend-video` });
|
|
45048
|
+
var SPRITE_VIDEO_MODELS = [
|
|
45049
|
+
{
|
|
45050
|
+
id: "pruna/p-video-2-pro",
|
|
45051
|
+
label: "Pruna P-Video 2 Pro",
|
|
45052
|
+
provider: "pruna",
|
|
45053
|
+
workflows: ["image-to-video"],
|
|
45054
|
+
resolutions: ["480p", "768p"],
|
|
45055
|
+
modes: ["cost", "speed", "quality"],
|
|
45056
|
+
lastFrame: true,
|
|
45057
|
+
estimatedCreditsPerSecond: { "480p": { cost: 1, speed: 2, quality: 4 }, "768p": { cost: 2.5, speed: 3.5, quality: 7.5 } },
|
|
45058
|
+
seconds: { min: 5, max: 15 }
|
|
45059
|
+
},
|
|
45060
|
+
{
|
|
45061
|
+
id: "heygen/heygen-video-1",
|
|
45062
|
+
label: "HeyGen Video 1",
|
|
45063
|
+
provider: "heygen",
|
|
45064
|
+
workflows: ["image-to-video"],
|
|
45065
|
+
resolutions: ["480p", "768p"],
|
|
45066
|
+
modes: ["cost"],
|
|
45067
|
+
lastFrame: false,
|
|
45068
|
+
estimatedCreditsPerSecond: { "480p": { cost: 1 }, "768p": { cost: 1.5 } },
|
|
45069
|
+
seconds: { min: 5, max: 15 }
|
|
45070
|
+
},
|
|
45071
|
+
{
|
|
45072
|
+
id: "fal/minimax-h3-max",
|
|
45073
|
+
label: "MiniMax H3 Max (fal.ai)",
|
|
45074
|
+
provider: "fal",
|
|
45075
|
+
// Every workflow but FLUX 3 Max's keyframes.
|
|
45076
|
+
workflows: VIDEO_WORKFLOWS.filter((w) => w !== "keyframes-to-video"),
|
|
45077
|
+
endpoints: {
|
|
45078
|
+
...h3Endpoints(H3_MAX),
|
|
45079
|
+
"reference-to-video": `${H3_MAX}/reference-to-video`,
|
|
45080
|
+
"lip-sync": `${H3_MAX}/lip-sync/image-to-video`,
|
|
45081
|
+
"camera-controls": `${H3_MAX}/camera-controls`,
|
|
45082
|
+
"insert-video": `${H3_MAX}/insert-video`,
|
|
45083
|
+
recast: `${H3_MAX}/recast`,
|
|
45084
|
+
relight: `${H3_MAX}/relight`,
|
|
45085
|
+
"3d-to-video": `${H3_MAX}/3d-to-video`,
|
|
45086
|
+
style: `${H3_MAX}/styles`
|
|
45087
|
+
},
|
|
45088
|
+
resolutions: ["480p", "768p", "1080p"],
|
|
45089
|
+
workflowOptions: {
|
|
45090
|
+
"extend-video": { resolutions: H3_RESOLUTIONS },
|
|
45091
|
+
"lip-sync": { resolutions: H3_RESOLUTIONS, seconds: { min: 5, max: 900, fractional: true } },
|
|
45092
|
+
"insert-video": { resolutions: ["480p", "768p"], seconds: { min: 5, max: 13, fractional: true }, creditsPerSecond: { "480p": 5, "768p": 6 } },
|
|
45093
|
+
recast: { resolutions: ["768p", "1080p"], seconds: { min: 5, max: 30, fractional: true }, creditsPerSecond: { "768p": 30, "1080p": 45 } },
|
|
45094
|
+
relight: { resolutions: H3_RESOLUTIONS, seconds: { min: 2.33, max: 15, fractional: true } },
|
|
45095
|
+
"3d-to-video": { seconds: { min: 1, max: 15, fractional: true } },
|
|
45096
|
+
style: { resolutions: ["768p"], seconds: { min: 5, max: 15 } }
|
|
45097
|
+
},
|
|
45098
|
+
modes: ["quality"],
|
|
45099
|
+
lastFrame: true,
|
|
45100
|
+
endFrameOnly: true,
|
|
45101
|
+
seed: true,
|
|
45102
|
+
promptExpansion: PROMPT_EXPANSION_MODES,
|
|
45103
|
+
audio: true,
|
|
45104
|
+
estimatedCreditsPerSecond: { "480p": { quality: 5 }, "768p": { quality: 8 }, "1080p": { quality: 16 }, "2k": { quality: 32 } },
|
|
45105
|
+
seconds: { min: 1, max: 15, fractional: true }
|
|
45106
|
+
},
|
|
45107
|
+
{
|
|
45108
|
+
id: "fal/minimax-h3-max-turbo",
|
|
45109
|
+
label: "MiniMax H3 Max Turbo (fal.ai)",
|
|
45110
|
+
provider: "fal",
|
|
45111
|
+
workflows: STUDIO_VIDEO_WORKFLOWS,
|
|
45112
|
+
endpoints: h3Endpoints("minimax/h3-max-turbo"),
|
|
45113
|
+
resolutions: ["480p", "768p", "1080p"],
|
|
45114
|
+
workflowOptions: { "extend-video": { resolutions: H3_RESOLUTIONS } },
|
|
45115
|
+
modes: ["speed"],
|
|
45116
|
+
lastFrame: true,
|
|
45117
|
+
endFrameOnly: true,
|
|
45118
|
+
seed: true,
|
|
45119
|
+
promptExpansion: PROMPT_EXPANSION_MODES,
|
|
45120
|
+
audio: true,
|
|
45121
|
+
estimatedCreditsPerSecond: { "480p": { speed: 2.5 }, "768p": { speed: 4 }, "1080p": { speed: 8 }, "2k": { speed: 16 } },
|
|
45122
|
+
seconds: { min: 1, max: 15, fractional: true }
|
|
45123
|
+
},
|
|
45124
|
+
{
|
|
45125
|
+
id: "fal/flux-3-max",
|
|
45126
|
+
label: "FLUX 3 Max (fal.ai)",
|
|
45127
|
+
provider: "fal",
|
|
45128
|
+
workflows: ["image-to-video", "text-to-video", "keyframes-to-video"],
|
|
45129
|
+
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` },
|
|
45130
|
+
falInputs: "flux",
|
|
45131
|
+
resolutions: ["720p", "1080p"],
|
|
45132
|
+
modes: ["quality"],
|
|
45133
|
+
lastFrame: true,
|
|
45134
|
+
seed: true,
|
|
45135
|
+
promptExpansion: ["balanced", "quality"],
|
|
45136
|
+
estimatedCreditsPerSecond: { "720p": { quality: 17 }, "1080p": { quality: 29 } },
|
|
45137
|
+
seconds: { min: 5, max: 20 }
|
|
45138
|
+
}
|
|
45139
|
+
];
|
|
45140
|
+
var SPRITE_VIDEO_MODEL_IDS = SPRITE_VIDEO_MODELS.map((m) => m.id);
|
|
45141
|
+
var DEFAULT_SPRITE_VIDEO_MODEL = "pruna/p-video-2-pro";
|
|
45142
|
+
function spriteVideoModel(id2) {
|
|
45143
|
+
return SPRITE_VIDEO_MODELS.find((m) => m.id === id2) ?? SPRITE_VIDEO_MODELS[0];
|
|
45144
|
+
}
|
|
45145
|
+
function videoResolutions(model, workflow = "image-to-video") {
|
|
45146
|
+
return model.workflowOptions?.[workflow]?.resolutions ?? model.resolutions;
|
|
45147
|
+
}
|
|
45148
|
+
function videoSeconds(model, workflow = "image-to-video") {
|
|
45149
|
+
return model.workflowOptions?.[workflow]?.seconds ?? model.seconds;
|
|
45150
|
+
}
|
|
45151
|
+
var INCLUDED_REFERENCE_TOKENS = 4096;
|
|
45152
|
+
var imageReferenceTokens = (size) => size && size[0] > 0 && size[1] > 0 ? 32 * Math.ceil(32 * Math.max(...size) / Math.min(...size)) : 1824;
|
|
45153
|
+
var clipReferenceTokens = (seconds2, resolution) => Math.ceil(Math.max(0, seconds2) * (resolution === "480p" ? 2700 : 6900));
|
|
45154
|
+
var audioReferenceTokens = (seconds2) => Math.ceil(Math.max(0, seconds2) * 80);
|
|
45155
|
+
var DEFAULT_GENERATED_REFERENCES = 2;
|
|
45156
|
+
function billedVideoSeconds(model, workflow, seconds2) {
|
|
45157
|
+
const s = videoSeconds(model, workflow).fractional ? seconds2 : Math.round(seconds2);
|
|
45158
|
+
if (workflow === "3d-to-video") return Math.max(5, s);
|
|
45159
|
+
return workflow === "lip-sync" && s > 15 ? s * 1.2 : s;
|
|
45160
|
+
}
|
|
45161
|
+
function videoCreditsPerSecond(model, p) {
|
|
45162
|
+
const override = model.workflowOptions?.[p.workflow ?? "image-to-video"]?.creditsPerSecond?.[p.resolution];
|
|
45163
|
+
if (override !== void 0) return override;
|
|
45164
|
+
const byMode = model.estimatedCreditsPerSecond[p.resolution] ?? model.estimatedCreditsPerSecond[model.resolutions[0]];
|
|
45165
|
+
return byMode[p.mode] ?? byMode[model.modes[0]] ?? 0;
|
|
45166
|
+
}
|
|
45167
|
+
function spriteVideoEstimate(model, p, extras2 = {}) {
|
|
45168
|
+
const seconds2 = billedVideoSeconds(model, p.workflow ?? "image-to-video", p.seconds);
|
|
45169
|
+
const beyond = Math.max(0, (extras2.referenceTokens ?? 0) - INCLUDED_REFERENCE_TOKENS) * 2e-3 + (extras2.generatedReferences ?? 0) * 3;
|
|
45170
|
+
return Math.max(1, Math.ceil((videoCreditsPerSecond(model, p) * seconds2 + beyond) * UNITS_PER_CREDIT));
|
|
45171
|
+
}
|
|
45172
|
+
|
|
45161
45173
|
// shared/sprites/generation-models.ts
|
|
45162
45174
|
var generationModelShape = {
|
|
45163
45175
|
videoModel: external_exports.enum(SPRITE_VIDEO_MODEL_IDS).optional()
|
|
@@ -45293,10 +45305,62 @@ async function initializeSkill(directory = process.cwd()) {
|
|
|
45293
45305
|
return { path, created };
|
|
45294
45306
|
}
|
|
45295
45307
|
|
|
45308
|
+
// cli/src/skills.ts
|
|
45309
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
45310
|
+
import { access, mkdir as mkdir6, readFile as readFile4, readdir as readdir2, stat } from "node:fs/promises";
|
|
45311
|
+
import { delimiter, dirname as dirname5, join as join6, resolve as resolve5 } from "node:path";
|
|
45312
|
+
var SKILLS_CLI = "skills@1.7.4";
|
|
45313
|
+
var SKILL_AGENTS = { "claude-code": ".claude/skills", codex: ".agents/skills" };
|
|
45314
|
+
var skillsSource = (server) => `${new URL(server).origin}/cli/skills`;
|
|
45315
|
+
async function skillsInstallCommand(source, platform = process.platform, execPath = process.execPath) {
|
|
45316
|
+
const args = ["-y", SKILLS_CLI, "add", source, "--skill", "*", ...Object.keys(SKILL_AGENTS).flatMap((agent) => ["--agent", agent]), "--copy", "--yes"];
|
|
45317
|
+
const adjacentNpx = resolve5(dirname5(execPath), "../lib/node_modules/npm/bin/npx-cli.js");
|
|
45318
|
+
try {
|
|
45319
|
+
await access(adjacentNpx);
|
|
45320
|
+
return { command: execPath, args: [adjacentNpx, ...args], shell: false };
|
|
45321
|
+
} catch {
|
|
45322
|
+
return { command: platform === "win32" ? "npx.cmd" : "npx", args, shell: platform === "win32" };
|
|
45323
|
+
}
|
|
45324
|
+
}
|
|
45325
|
+
async function lockedSkills(directory, source) {
|
|
45326
|
+
try {
|
|
45327
|
+
const lock = JSON.parse(await readFile4(join6(directory, "skills-lock.json"), "utf8"));
|
|
45328
|
+
return Object.entries(lock.skills ?? {}).filter(([, skill]) => skill.sourceUrl === source).map(([name2]) => name2).sort();
|
|
45329
|
+
} catch {
|
|
45330
|
+
return [];
|
|
45331
|
+
}
|
|
45332
|
+
}
|
|
45333
|
+
async function installSkills(options) {
|
|
45334
|
+
const directory = resolve5(options.dir ?? ".");
|
|
45335
|
+
await mkdir6(directory, { recursive: true });
|
|
45336
|
+
if (!(await stat(directory)).isDirectory()) throw new Error(`${directory} is not a folder.`);
|
|
45337
|
+
const source = skillsSource(options.url);
|
|
45338
|
+
const { command, args, shell } = await skillsInstallCommand(source);
|
|
45339
|
+
options.log?.(`Installing AnimaGuru skills from ${source} into ${directory}\u2026`);
|
|
45340
|
+
await new Promise((done, reject) => {
|
|
45341
|
+
const child = (options.spawn ?? nodeSpawn)(command, args, {
|
|
45342
|
+
cwd: directory,
|
|
45343
|
+
signal: options.signal,
|
|
45344
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
45345
|
+
shell,
|
|
45346
|
+
// The skills CLI reports installs to skills.sh unless told not to.
|
|
45347
|
+
env: { ...process.env, DISABLE_TELEMETRY: "1", DO_NOT_TRACK: "1", PATH: `${dirname5(process.execPath)}${delimiter}${process.env.PATH ?? ""}` }
|
|
45348
|
+
});
|
|
45349
|
+
child.stdout?.on("data", (chunk) => options.log?.(chunk.toString().trimEnd()));
|
|
45350
|
+
child.stderr?.on("data", (chunk) => options.log?.(chunk.toString().trimEnd()));
|
|
45351
|
+
child.once("error", (error62) => reject(error62.code === "ENOENT" ? new Error("Installing skills needs npx, which comes with npm and Node.js 24. Install Node.js, or run the AnimaGuru installer again.") : error62));
|
|
45352
|
+
child.once("close", (code) => code === 0 ? done() : reject(new Error(`npx ${SKILLS_CLI} add exited with code ${code}; see its output above.`)));
|
|
45353
|
+
});
|
|
45354
|
+
const installed = await lockedSkills(directory, source);
|
|
45355
|
+
const folders = await Promise.all(Object.values(SKILL_AGENTS).map(async (folder) => (await readdir2(join6(directory, folder)).catch(() => [])).length));
|
|
45356
|
+
if (!installed.length || folders.some((count) => count === 0)) throw new Error("The skills CLI finished without installing AnimaGuru skills; see its output above.");
|
|
45357
|
+
return { directory, source, skills: installed.length, installed, agents: SKILL_AGENTS, lockfile: join6(directory, "skills-lock.json"), update: "npx skills update --project --yes" };
|
|
45358
|
+
}
|
|
45359
|
+
|
|
45296
45360
|
// cli/src/create.ts
|
|
45297
45361
|
import { spawn } from "node:child_process";
|
|
45298
|
-
import { cp, mkdir as
|
|
45299
|
-
import { basename as basename2, dirname as
|
|
45362
|
+
import { cp, mkdir as mkdir7, readFile as readFile5, readdir as readdir3, access as access2, writeFile as writeFile6, rename as rename3 } from "node:fs/promises";
|
|
45363
|
+
import { basename as basename2, dirname as dirname6, delimiter as delimiter2, join as join7, resolve as resolve6 } from "node:path";
|
|
45300
45364
|
import { fileURLToPath } from "node:url";
|
|
45301
45365
|
|
|
45302
45366
|
// shared/locales/en/animation-styles.json
|
|
@@ -46275,6 +46339,74 @@ var animation_styles_default = {
|
|
|
46275
46339
|
previewCaption: "One champagne line draws a sun on the horizon, three arches and a woman's profile without lifting, closes a ring that fills with gold from the point where it met, then pulls back to the wordmark. Invented brand, drawn entirely in code.",
|
|
46276
46340
|
family: "graphic",
|
|
46277
46341
|
example: true
|
|
46342
|
+
},
|
|
46343
|
+
"product-turntable-3d": {
|
|
46344
|
+
name: "3D Product Turntable",
|
|
46345
|
+
description: "A real 3D product turns on a studio set while the camera orbits and pushes in, studio light slides across its materials and callouts stay pinned to its parts.",
|
|
46346
|
+
materials: [
|
|
46347
|
+
"Generated PBR product model",
|
|
46348
|
+
"Studio HDR reflections",
|
|
46349
|
+
"Shallow depth of field"
|
|
46350
|
+
],
|
|
46351
|
+
motion: [
|
|
46352
|
+
"Turntable orbit and push-in",
|
|
46353
|
+
"Rack focus between details",
|
|
46354
|
+
"Callouts that track parts"
|
|
46355
|
+
],
|
|
46356
|
+
previewCaption: "Generated headphones turn on a stone plinth as the camera pulls back from a macro of the brushed yoke, focus racking from part to part under pinned callouts, ending on a lockup for an invented brand. Model generated with Tripo H3.1, rendered in three.js.",
|
|
46357
|
+
family: "3d",
|
|
46358
|
+
example: true
|
|
46359
|
+
},
|
|
46360
|
+
"character-stage-3d": {
|
|
46361
|
+
name: "3D Character Stage",
|
|
46362
|
+
description: "A rigged 3D character walks, turns and gestures in front of a painted 2D backdrop, casting real shadows onto the painting while captions carry the story.",
|
|
46363
|
+
materials: [
|
|
46364
|
+
"Rigged character model",
|
|
46365
|
+
"Painted 2D backdrop",
|
|
46366
|
+
"Shadows cast onto the painting"
|
|
46367
|
+
],
|
|
46368
|
+
motion: [
|
|
46369
|
+
"Walk cycles at true speed",
|
|
46370
|
+
"Crossfaded gestures",
|
|
46371
|
+
"A camera that follows the character"
|
|
46372
|
+
],
|
|
46373
|
+
previewCaption: "A generated, auto-rigged baker walks across a painted square, turns to camera, waves and explains, his shadow falling over the painting. Character made with Tripo H3.1 and Meshy's auto-rig, rendered in three.js.",
|
|
46374
|
+
family: "3d",
|
|
46375
|
+
example: true
|
|
46376
|
+
},
|
|
46377
|
+
"toy-diorama-3d": {
|
|
46378
|
+
name: "3D Toy Diorama",
|
|
46379
|
+
description: "A miniature 3D world on a tabletop, seen through tilt-shift focus as a free camera glides over tiny props and characters going about their day.",
|
|
46380
|
+
materials: [
|
|
46381
|
+
"Toy-scale models",
|
|
46382
|
+
"Tilt-shift depth of field",
|
|
46383
|
+
"Warm tabletop light"
|
|
46384
|
+
],
|
|
46385
|
+
motion: [
|
|
46386
|
+
"Free camera glides",
|
|
46387
|
+
"Little cars and figures on loops",
|
|
46388
|
+
"Focus pulled through the scene"
|
|
46389
|
+
],
|
|
46390
|
+
previewCaption: "A camera glides over a toy harbour town as little cars and boats run their loops, everything sharp only in a thin band of focus. Props generated with Tripo H3.1, rendered in three.js.",
|
|
46391
|
+
family: "3d",
|
|
46392
|
+
example: true
|
|
46393
|
+
},
|
|
46394
|
+
"exploded-teardown-3d": {
|
|
46395
|
+
name: "3D Exploded Teardown",
|
|
46396
|
+
description: "A 3D product orbits and comes apart along its assembly axes, each part followed by a leader label that stays with it through the turn.",
|
|
46397
|
+
materials: [
|
|
46398
|
+
"Part-by-part 3D model",
|
|
46399
|
+
"Leader labels and callouts",
|
|
46400
|
+
"Clean studio grey"
|
|
46401
|
+
],
|
|
46402
|
+
motion: [
|
|
46403
|
+
"Orbit while the parts separate",
|
|
46404
|
+
"Parts sliding along their axes",
|
|
46405
|
+
"Labels that follow each part"
|
|
46406
|
+
],
|
|
46407
|
+
previewCaption: "An invented handheld console comes apart along its assembly axes as the camera orbits, every part keeping its label. Modelled and rendered in code.",
|
|
46408
|
+
family: "3d",
|
|
46409
|
+
example: true
|
|
46278
46410
|
}
|
|
46279
46411
|
},
|
|
46280
46412
|
browseStyles: "Browse animation styles",
|
|
@@ -46290,7 +46422,8 @@ var animation_styles_default = {
|
|
|
46290
46422
|
material: "Materials & depth",
|
|
46291
46423
|
cinematic: "Cinema & media",
|
|
46292
46424
|
evidence: "Evidence & data",
|
|
46293
|
-
documentary: "Documentary & broadcast"
|
|
46425
|
+
documentary: "Documentary & broadcast",
|
|
46426
|
+
"3d": "3D scenes"
|
|
46294
46427
|
},
|
|
46295
46428
|
searchLabel: "Search visual styles",
|
|
46296
46429
|
searchPlaceholder: "Try paper, product, typography\u2026",
|
|
@@ -46423,7 +46556,11 @@ var VIDEO_STYLE_IDS = [
|
|
|
46423
46556
|
"synthwave-y2k",
|
|
46424
46557
|
"sticker-explainer",
|
|
46425
46558
|
"variety-captions",
|
|
46426
|
-
"one-line-art"
|
|
46559
|
+
"one-line-art",
|
|
46560
|
+
"product-turntable-3d",
|
|
46561
|
+
"character-stage-3d",
|
|
46562
|
+
"toy-diorama-3d",
|
|
46563
|
+
"exploded-teardown-3d"
|
|
46427
46564
|
];
|
|
46428
46565
|
var VIDEO_WORKFLOW_IDS = [
|
|
46429
46566
|
"product-proof",
|
|
@@ -46483,10 +46620,10 @@ function listTemplates() {
|
|
|
46483
46620
|
return videoTemplateCatalog();
|
|
46484
46621
|
}
|
|
46485
46622
|
async function installDependencies(directory, options) {
|
|
46486
|
-
const adjacentNpm =
|
|
46623
|
+
const adjacentNpm = resolve6(dirname6(process.execPath), "../lib/node_modules/npm/bin/npm-cli.js");
|
|
46487
46624
|
let npmScript;
|
|
46488
46625
|
try {
|
|
46489
|
-
await
|
|
46626
|
+
await access2(adjacentNpm);
|
|
46490
46627
|
npmScript = adjacentNpm;
|
|
46491
46628
|
} catch {
|
|
46492
46629
|
}
|
|
@@ -46497,7 +46634,7 @@ async function installDependencies(directory, options) {
|
|
|
46497
46634
|
signal: options.signal,
|
|
46498
46635
|
stdio: ["ignore", "pipe", "pipe"],
|
|
46499
46636
|
shell: !npmScript && process.platform === "win32",
|
|
46500
|
-
env: { ...process.env, PATH: `${
|
|
46637
|
+
env: { ...process.env, PATH: `${dirname6(process.execPath)}${delimiter2}${process.env.PATH ?? ""}` }
|
|
46501
46638
|
});
|
|
46502
46639
|
child.stdout.on("data", (chunk) => options.log?.(chunk.toString().trimEnd()));
|
|
46503
46640
|
child.stderr.on("data", (chunk) => options.log?.(chunk.toString().trimEnd()));
|
|
@@ -46522,7 +46659,7 @@ var STARTER_STORY = {
|
|
|
46522
46659
|
{ id: "invitation", label: "The invitation", start: 16, end: 24, ending: "Your next story starts here" }
|
|
46523
46660
|
]
|
|
46524
46661
|
};
|
|
46525
|
-
var writeStarterStory = (directory) => writeFile6(
|
|
46662
|
+
var writeStarterStory = (directory) => writeFile6(join7(directory, "story.json"), JSON.stringify(STARTER_STORY, null, 2) + "\n", { flag: "wx" });
|
|
46526
46663
|
function starterQuiz(story = false) {
|
|
46527
46664
|
return {
|
|
46528
46665
|
version: 1,
|
|
@@ -46535,42 +46672,42 @@ function starterQuiz(story = false) {
|
|
|
46535
46672
|
] }
|
|
46536
46673
|
};
|
|
46537
46674
|
}
|
|
46538
|
-
var writeStarterQuiz = (directory, story = false) => writeFile6(
|
|
46675
|
+
var writeStarterQuiz = (directory, story = false) => writeFile6(join7(directory, "quiz.json"), JSON.stringify(starterQuiz(story), null, 2) + "\n", { flag: "wx" });
|
|
46539
46676
|
async function createVideoProject(options, installer = installDependencies) {
|
|
46540
46677
|
if (!options.directory.trim()) throw new Error("Choose a new project folder, for example: animaguru create my-video");
|
|
46541
|
-
const directory =
|
|
46678
|
+
const directory = resolve6(options.directory);
|
|
46542
46679
|
options.signal?.throwIfAborted();
|
|
46543
46680
|
try {
|
|
46544
|
-
await
|
|
46681
|
+
await mkdir7(directory);
|
|
46545
46682
|
} catch (error62) {
|
|
46546
46683
|
if (error62.code === "EEXIST") throw new Error(`Destination already exists: ${directory}. Choose a new folder; existing files were not changed.`);
|
|
46547
46684
|
throw error62;
|
|
46548
46685
|
}
|
|
46549
46686
|
options.log?.(`Creating a video workspace in ${directory}\u2026`);
|
|
46550
|
-
const templateRoot =
|
|
46551
|
-
for (const entry of await
|
|
46687
|
+
const templateRoot = join7(packageRoot, "templates/video");
|
|
46688
|
+
for (const entry of await readdir3(templateRoot)) {
|
|
46552
46689
|
if (entry === "WORKSPACE-AGENTS.md") continue;
|
|
46553
|
-
await cp(
|
|
46690
|
+
await cp(join7(templateRoot, entry), join7(directory, entry), { recursive: true, errorOnExist: true, force: false });
|
|
46554
46691
|
}
|
|
46555
|
-
await rename3(
|
|
46556
|
-
await
|
|
46557
|
-
await
|
|
46558
|
-
const packagePath =
|
|
46559
|
-
const manifest = JSON.parse(await
|
|
46692
|
+
await rename3(join7(directory, "gitignore"), join7(directory, ".gitignore"));
|
|
46693
|
+
await mkdir7(join7(directory, "public/assets"), { recursive: true });
|
|
46694
|
+
await mkdir7(join7(directory, "production"), { recursive: true });
|
|
46695
|
+
const packagePath = join7(directory, "package.json");
|
|
46696
|
+
const manifest = JSON.parse(await readFile5(packagePath, "utf8"));
|
|
46560
46697
|
manifest.name = basename2(directory).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 100) || "animaguru-video";
|
|
46561
46698
|
await writeFile6(packagePath, JSON.stringify(manifest, null, 2) + "\n");
|
|
46562
|
-
const skills = [.../* @__PURE__ */ new Set(["animaguru", "animaguru-video", "animaguru-brand-kit", "animaguru-cutcraft", "animaguru-art-motion", "animaguru-branching-story", "animaguru-quiz", ...VIDEO_PURPOSE_SKILLS, ...VIDEO_TEMPLATES.map((template) => template.skill)])];
|
|
46563
|
-
const pixiSkillsRoot =
|
|
46564
|
-
const pixiSkills = (await
|
|
46699
|
+
const skills = [.../* @__PURE__ */ new Set(["animaguru", "animaguru-video", "animaguru-brand-kit", "animaguru-cutcraft", "animaguru-art-motion", "animaguru-branching-story", "animaguru-quiz", "animaguru-3d-models", ...VIDEO_PURPOSE_SKILLS, ...VIDEO_TEMPLATES.map((template) => template.skill)])];
|
|
46700
|
+
const pixiSkillsRoot = join7(packageRoot, "vendor/pixijs-skills/skills");
|
|
46701
|
+
const pixiSkills = (await readdir3(pixiSkillsRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
46565
46702
|
for (const agent of [".agents", ".claude"]) {
|
|
46566
|
-
const skillRoot =
|
|
46567
|
-
await
|
|
46568
|
-
for (const skill of skills) await cp(
|
|
46569
|
-
for (const skill of pixiSkills) await cp(
|
|
46570
|
-
}
|
|
46571
|
-
await cp(
|
|
46572
|
-
await cp(
|
|
46573
|
-
await writeFile6(
|
|
46703
|
+
const skillRoot = join7(directory, agent, "skills");
|
|
46704
|
+
await mkdir7(skillRoot, { recursive: true });
|
|
46705
|
+
for (const skill of skills) await cp(join7(packageRoot, "skills", skill), join7(skillRoot, skill), { recursive: true });
|
|
46706
|
+
for (const skill of pixiSkills) await cp(join7(pixiSkillsRoot, skill), join7(skillRoot, skill), { recursive: true });
|
|
46707
|
+
}
|
|
46708
|
+
await cp(join7(packageRoot, "vendor/pixijs-skills/LICENSE"), join7(directory, "PIXIJS-SKILLS-LICENSE.txt"));
|
|
46709
|
+
await cp(join7(packageRoot, "vendor/pixijs-skills/provenance.json"), join7(directory, "production/pixijs-skills-provenance.json"));
|
|
46710
|
+
await writeFile6(join7(directory, "animaguru.project.json"), JSON.stringify({
|
|
46574
46711
|
schemaVersion: 3,
|
|
46575
46712
|
cliVersion: package_default.version,
|
|
46576
46713
|
category: null,
|
|
@@ -46582,7 +46719,7 @@ async function createVideoProject(options, installer = installDependencies) {
|
|
|
46582
46719
|
interview: "pending",
|
|
46583
46720
|
animaguruProjectId: null
|
|
46584
46721
|
}, null, 2) + "\n");
|
|
46585
|
-
await writeFile6(
|
|
46722
|
+
await writeFile6(join7(directory, "animaguru.templates.json"), JSON.stringify(listTemplates(), null, 2) + "\n");
|
|
46586
46723
|
if (options.story) await writeStarterStory(directory);
|
|
46587
46724
|
if (options.quiz) await writeStarterQuiz(directory, options.story);
|
|
46588
46725
|
if (options.install !== false) {
|
|
@@ -46609,28 +46746,28 @@ ${options.install === false ? "Run npm install, then " : "Run "}npm run dev insi
|
|
|
46609
46746
|
}
|
|
46610
46747
|
async function createWorkspace(options, installer = installDependencies) {
|
|
46611
46748
|
const result = await createVideoProject({ ...options, install: false, log: (message) => {
|
|
46612
|
-
if (message.startsWith("Creating")) options.log?.(`Creating a shared-brand workspace in ${
|
|
46749
|
+
if (message.startsWith("Creating")) options.log?.(`Creating a shared-brand workspace in ${resolve6(options.directory)}\u2026`);
|
|
46613
46750
|
} }, installer);
|
|
46614
46751
|
const directory = result.path;
|
|
46615
46752
|
const { rm: rm3 } = await import("node:fs/promises");
|
|
46616
|
-
await rename3(
|
|
46617
|
-
await
|
|
46618
|
-
await
|
|
46753
|
+
await rename3(join7(directory, "src"), join7(directory, "runtime"));
|
|
46754
|
+
await mkdir7(join7(directory, "templates/animation/src"), { recursive: true });
|
|
46755
|
+
await mkdir7(join7(directory, "templates/animation/shared/locales/en"), { recursive: true });
|
|
46619
46756
|
for (const file2 of ["film.ts", "film-resources.ts"]) {
|
|
46620
|
-
const original = await
|
|
46757
|
+
const original = await readFile5(join7(directory, "runtime", file2), "utf8");
|
|
46621
46758
|
const rewritten = original.replace('"./player-types"', '"../../../runtime/player-types"').replace('"./timeline-model"', '"../../../runtime/timeline-model"').replace('"./kit"', '"../../../runtime/kit"').replace('"../shared/locales/en/timeline.json"', '"../../../shared/locales/en/timeline.json"');
|
|
46622
|
-
await writeFile6(
|
|
46623
|
-
await rm3(
|
|
46759
|
+
await writeFile6(join7(directory, "templates/animation/src", file2), rewritten);
|
|
46760
|
+
await rm3(join7(directory, "runtime", file2));
|
|
46624
46761
|
}
|
|
46625
|
-
await rm3(
|
|
46626
|
-
await rename3(
|
|
46627
|
-
await rename3(
|
|
46762
|
+
await rm3(join7(directory, "runtime/main.ts"));
|
|
46763
|
+
await rename3(join7(directory, "film.config.json"), join7(directory, "templates/animation/film.config.json"));
|
|
46764
|
+
await rename3(join7(directory, "shared/locales/en/film.json"), join7(directory, "templates/animation/shared/locales/en/film.json"));
|
|
46628
46765
|
const { createHash: createHash7 } = await import("node:crypto");
|
|
46629
|
-
await writeFile6(
|
|
46630
|
-
await rm3(
|
|
46631
|
-
await
|
|
46632
|
-
await
|
|
46633
|
-
await writeFile6(
|
|
46766
|
+
await writeFile6(join7(directory, "templates/animation/starter-film.sha256"), createHash7("sha256").update(await readFile5(join7(directory, "templates/animation/src/film.ts"))).digest("hex") + "\n");
|
|
46767
|
+
await rm3(join7(directory, "animaguru.project.json"));
|
|
46768
|
+
await mkdir7(join7(directory, "animations"));
|
|
46769
|
+
await mkdir7(join7(directory, "branding"));
|
|
46770
|
+
await writeFile6(join7(directory, "branding/brand.json"), JSON.stringify({
|
|
46634
46771
|
name: "Your brand",
|
|
46635
46772
|
tagline: "Your next story starts here",
|
|
46636
46773
|
logo: null,
|
|
@@ -46638,18 +46775,18 @@ async function createWorkspace(options, installer = installDependencies) {
|
|
|
46638
46775
|
fonts: { heading: { family: "Arial, sans-serif", file: null }, body: { family: "Arial, sans-serif", file: null } },
|
|
46639
46776
|
assets: []
|
|
46640
46777
|
}, null, 2) + "\n");
|
|
46641
|
-
await writeFile6(
|
|
46642
|
-
await writeFile6(
|
|
46643
|
-
const pkg = JSON.parse(await
|
|
46778
|
+
await writeFile6(join7(directory, "branding/README.md"), "# Shared branding\n\nThe starter brand.json contains placeholders. On the first creative request, the agent asks for your official website or brand guide unless you already supplied one. It researches the identity and records sources and usage notes in brand-guide.md. You can also provide logos, fonts and guides here or proceed without a website. Register reusable web assets in brand.json with workspace-relative paths, such as branding/logo.svg. All animations inherit this brand. Only registered web assets are included in exports; guides and other local documents remain in this workspace.\n");
|
|
46779
|
+
await writeFile6(join7(directory, "animaguru.workspace.json"), JSON.stringify({ schemaVersion: 1, cliVersion: package_default.version, name: basename2(directory), animationsDirectory: "animations", branding: "branding/brand.json" }, null, 2) + "\n");
|
|
46780
|
+
const pkg = JSON.parse(await readFile5(join7(directory, "package.json"), "utf8"));
|
|
46644
46781
|
pkg.scripts.dev = "node scripts/dev.mjs";
|
|
46645
|
-
await writeFile6(
|
|
46646
|
-
const tsconfig = JSON.parse(await
|
|
46782
|
+
await writeFile6(join7(directory, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
46783
|
+
const tsconfig = JSON.parse(await readFile5(join7(directory, "tsconfig.json"), "utf8"));
|
|
46647
46784
|
tsconfig.include = ["runtime", "animations/*/src"];
|
|
46648
|
-
await writeFile6(
|
|
46649
|
-
await writeFile6(
|
|
46650
|
-
await writeFile6(
|
|
46651
|
-
await rm3(
|
|
46652
|
-
await writeFile6(
|
|
46785
|
+
await writeFile6(join7(directory, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
|
|
46786
|
+
await writeFile6(join7(directory, "AGENTS.md"), await readFile5(join7(packageRoot, "templates/video/WORKSPACE-AGENTS.md"), "utf8"));
|
|
46787
|
+
await writeFile6(join7(directory, "CLAUDE.md"), "# AnimaGuru workspace\n\nRead AGENTS.md for the multi-animation workflow, shared branding and commands. Claude skills are in .claude/skills. For an incomplete shared kit, read .claude/skills/animaguru-brand-kit/SKILL.md and ask for the official website or brand guide if the user did not supply one. Select the animation folder before editing; reuse shared runtime/ and scripts/.\n");
|
|
46788
|
+
await rm3(join7(directory, "WORKSPACE-AGENTS.md"), { force: true });
|
|
46789
|
+
await writeFile6(join7(directory, "README.md"), "# Your AnimaGuru workspace\n\nOpen this root folder in Codex or Claude Code and describe a film. If you have an official website or brand guide, include it; otherwise the agent asks for it while setting up the shared branding/ kit. You can also provide local brand assets or proceed without a website. Create a film with animaguru create animation my-video.\n\nRun npm run dev for the workspace hub. Run npm run build -- --animation my-video, npm run export:html -- --animation my-video, or npm run export:mp4 -- --animation my-video. Player code, dependencies, skills and export tools are shared once; animation folders contain only their own production files.\n");
|
|
46653
46790
|
if (options.install !== false) {
|
|
46654
46791
|
try {
|
|
46655
46792
|
await installer(directory, options);
|
|
@@ -46665,23 +46802,23 @@ async function createWorkspace(options, installer = installDependencies) {
|
|
|
46665
46802
|
skills: result.skills,
|
|
46666
46803
|
agents: result.agents,
|
|
46667
46804
|
installed: options.install !== false,
|
|
46668
|
-
branding:
|
|
46669
|
-
animations:
|
|
46805
|
+
branding: join7(directory, "branding"),
|
|
46806
|
+
animations: join7(directory, "animations"),
|
|
46670
46807
|
nextSteps: ["Open this workspace in Codex or Claude Code and provide your website or brand guide; the agent asks if it is missing.", "Build the shared brand kit in branding/.", "Run animaguru create animation my-video.", "Run npm run dev for the animation hub."]
|
|
46671
46808
|
};
|
|
46672
46809
|
}
|
|
46673
46810
|
async function findWorkspace(start = process.cwd()) {
|
|
46674
46811
|
const { realpath } = await import("node:fs/promises");
|
|
46675
|
-
let directory = await realpath(
|
|
46812
|
+
let directory = await realpath(resolve6(start));
|
|
46676
46813
|
while (true) {
|
|
46677
46814
|
try {
|
|
46678
|
-
const info = JSON.parse(await
|
|
46815
|
+
const info = JSON.parse(await readFile5(join7(directory, "animaguru.workspace.json"), "utf8"));
|
|
46679
46816
|
if (info.schemaVersion !== 1 || info.animationsDirectory !== "animations" || info.branding !== "branding/brand.json") throw new Error("Unsupported AnimaGuru workspace.");
|
|
46680
46817
|
return directory;
|
|
46681
46818
|
} catch (error62) {
|
|
46682
46819
|
if (error62.code !== "ENOENT") throw error62;
|
|
46683
46820
|
}
|
|
46684
|
-
const parent =
|
|
46821
|
+
const parent = dirname6(directory);
|
|
46685
46822
|
if (parent === directory) throw new Error("Run this inside an AnimaGuru workspace, or pass --workspace PATH. Create one with animaguru create workspace NAME.");
|
|
46686
46823
|
directory = parent;
|
|
46687
46824
|
}
|
|
@@ -46690,23 +46827,23 @@ async function createAnimation(options) {
|
|
|
46690
46827
|
if (!/^[a-z0-9][a-z0-9-]{0,79}$/.test(options.name)) throw new Error("Choose a lowercase, hyphenated animation name, such as product-launch.");
|
|
46691
46828
|
options.signal?.throwIfAborted();
|
|
46692
46829
|
const root = await findWorkspace(options.workspace);
|
|
46693
|
-
const directory =
|
|
46830
|
+
const directory = join7(root, "animations", options.name);
|
|
46694
46831
|
try {
|
|
46695
|
-
await
|
|
46832
|
+
await mkdir7(directory);
|
|
46696
46833
|
} catch (error62) {
|
|
46697
46834
|
if (error62.code === "EEXIST") throw new Error(`Animation already exists: ${options.name}. Existing files were not changed.`);
|
|
46698
46835
|
throw error62;
|
|
46699
46836
|
}
|
|
46700
|
-
for (const file2 of await
|
|
46701
|
-
if (file2 !== "starter-film.sha256") await cp(
|
|
46837
|
+
for (const file2 of await readdir3(join7(root, "templates/animation"))) {
|
|
46838
|
+
if (file2 !== "starter-film.sha256") await cp(join7(root, "templates/animation", file2), join7(directory, file2), { recursive: true, errorOnExist: true, force: false });
|
|
46702
46839
|
}
|
|
46703
|
-
const config2 = JSON.parse(await
|
|
46840
|
+
const config2 = JSON.parse(await readFile5(join7(directory, "film.config.json"), "utf8"));
|
|
46704
46841
|
config2.slug = options.name;
|
|
46705
46842
|
config2.title = options.name.replaceAll("-", " ").replace(/^./, (value) => value.toUpperCase());
|
|
46706
|
-
await writeFile6(
|
|
46707
|
-
await
|
|
46708
|
-
await
|
|
46709
|
-
await writeFile6(
|
|
46843
|
+
await writeFile6(join7(directory, "film.config.json"), JSON.stringify(config2, null, 2) + "\n");
|
|
46844
|
+
await mkdir7(join7(directory, "public/assets"), { recursive: true });
|
|
46845
|
+
await mkdir7(join7(directory, "production"), { recursive: true });
|
|
46846
|
+
await writeFile6(join7(directory, "animaguru.project.json"), JSON.stringify({ schemaVersion: 4, cliVersion: package_default.version, workspace: "../..", category: null, template: null, workflow: null, skill: null, setupStage: "category", galleryUrl: ANIMATION_STYLE_GALLERY_URL, interview: "pending", animaguruProjectId: null, branding: "inherit" }, null, 2) + "\n");
|
|
46710
46847
|
if (options.story) await writeStarterStory(directory);
|
|
46711
46848
|
if (options.quiz) await writeStarterQuiz(directory, options.story);
|
|
46712
46849
|
const kind = options.story && options.quiz ? "Branching story with a quiz" : options.story ? "Branching story" : options.quiz ? "Quiz film" : "Animation";
|
|
@@ -46725,8 +46862,65 @@ async function createAnimation(options) {
|
|
|
46725
46862
|
};
|
|
46726
46863
|
}
|
|
46727
46864
|
|
|
46865
|
+
// shared/model-assets.ts
|
|
46866
|
+
var MODEL_GENERATORS = [
|
|
46867
|
+
{
|
|
46868
|
+
id: "tripo-h3.1",
|
|
46869
|
+
label: "Tripo H3.1",
|
|
46870
|
+
endpoints: { image: "tripo3d/h3.1/image-to-3d", text: "tripo3d/h3.1/text-to-3d" },
|
|
46871
|
+
faces: { min: 1e3, max: 2e6 },
|
|
46872
|
+
/** The direction the generated model faces; saved models are turned to +Z. */
|
|
46873
|
+
facing: "+x"
|
|
46874
|
+
},
|
|
46875
|
+
{
|
|
46876
|
+
id: "hunyuan-3d-3.1-pro",
|
|
46877
|
+
label: "Hunyuan3D 3.1 Pro",
|
|
46878
|
+
endpoints: { image: "fal-ai/hunyuan-3d/v3.1/pro/image-to-3d", text: "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d" },
|
|
46879
|
+
faces: { min: 4e4, max: 15e5 },
|
|
46880
|
+
facing: "+z"
|
|
46881
|
+
}
|
|
46882
|
+
];
|
|
46883
|
+
var MODEL_GENERATOR_IDS = MODEL_GENERATORS.map((m) => m.id);
|
|
46884
|
+
var DEFAULT_MODEL_GENERATOR = "tripo-h3.1";
|
|
46885
|
+
var modelGenerator = (id2) => MODEL_GENERATORS.find((m) => m.id === id2) ?? MODEL_GENERATORS[0];
|
|
46886
|
+
var MAX_MODEL_CLIPS = 10;
|
|
46887
|
+
var MAX_RIG_FACES = 3e5;
|
|
46888
|
+
var MAX_MESHY_ACTION = 696;
|
|
46889
|
+
var MAX_MODEL_PROMPT = 1e3;
|
|
46890
|
+
var MODEL_ANIMATIONS = [
|
|
46891
|
+
{ id: "idle", action: 0, label: "Idle" },
|
|
46892
|
+
{ id: "idle-2", action: 11, label: "Idle 2" },
|
|
46893
|
+
{ id: "idle-3", action: 12, label: "Idle 3" },
|
|
46894
|
+
{ id: "walk", action: 30, label: "Casual walk" },
|
|
46895
|
+
{ id: "walk-woman", action: 1, label: "Walking (woman)" },
|
|
46896
|
+
{ id: "stage-walk", action: 55, label: "Stage walk" },
|
|
46897
|
+
{ id: "thoughtful-walk", action: 121, label: "Thoughtful walk" },
|
|
46898
|
+
{ id: "run", action: 14, label: "Run" },
|
|
46899
|
+
{ id: "run-fast", action: 16, label: "Fast run" },
|
|
46900
|
+
{ id: "wave", action: 28, label: "Big wave hello" },
|
|
46901
|
+
{ id: "wave-one-hand", action: 290, label: "One-hand wave" },
|
|
46902
|
+
{ id: "cheer", action: 59, label: "Victory cheer" },
|
|
46903
|
+
{ id: "cheer-hands-up", action: 298, label: "Cheer with both hands up" },
|
|
46904
|
+
{ id: "fist-pump", action: 403, label: "Victory fist pump" },
|
|
46905
|
+
{ id: "talk", action: 313, label: "Talk with open hands" },
|
|
46906
|
+
{ id: "talk-passionately", action: 308, label: "Talk passionately" },
|
|
46907
|
+
{ id: "phone-call", action: 312, label: "Phone conversation" },
|
|
46908
|
+
{ id: "agree", action: 25, label: "Agree gesture" },
|
|
46909
|
+
{ id: "jump", action: 466, label: "Jump" },
|
|
46910
|
+
{ id: "jump-arms-open", action: 460, label: "Jump with arms open" },
|
|
46911
|
+
{ id: "dance", action: 22, label: "Funny dance" },
|
|
46912
|
+
{ id: "dance-2", action: 64, label: "All-night dance" },
|
|
46913
|
+
{ id: "shuffle", action: 63, label: "Arm-circle shuffle" }
|
|
46914
|
+
];
|
|
46915
|
+
var MODEL_ANIMATION_IDS = MODEL_ANIMATIONS.map((a) => a.id);
|
|
46916
|
+
var DEFAULT_MODEL_ANIMATIONS = ["idle", "walk"];
|
|
46917
|
+
var animationAction = (clip) => typeof clip === "number" ? clip : MODEL_ANIMATIONS.find((a) => a.id === clip).action;
|
|
46918
|
+
var generationCostUsd = (p) => p.model === "hunyuan-3d-3.1-pro" ? 0.375 + (p.texture && p.pbr ? 0.15 : 0) + (p.faces !== void 0 ? 0.15 : 0) : p.texture ? 0.3 : 0.2;
|
|
46919
|
+
var rigCostUsd = (clips2) => 0.2 + 0.12 * clips2;
|
|
46920
|
+
var modelCostUsd = (p) => generationCostUsd(p) + (p.rig ? rigCostUsd(p.animations.length) : 0);
|
|
46921
|
+
|
|
46728
46922
|
// shared/assets.ts
|
|
46729
|
-
var ASSET_TYPES = ["image", "vector", "video", "music", "speech", "sfx"];
|
|
46923
|
+
var ASSET_TYPES = ["image", "vector", "video", "music", "speech", "sfx", "model"];
|
|
46730
46924
|
var SPEECH_MODELS = [
|
|
46731
46925
|
{ id: "gemini-3.8-flash-tts", label: "Gemini 3.8 Flash TTS" },
|
|
46732
46926
|
{ id: "gemini-3.8-flash-lite-tts", label: "Gemini 3.8 Flash-Lite TTS" },
|
|
@@ -47022,6 +47216,43 @@ function vectorChecks(p, ctx) {
|
|
|
47022
47216
|
if (p.references.length) issue2("references", "image-to-vector traces its source alone and takes no references.");
|
|
47023
47217
|
}
|
|
47024
47218
|
var vectorDefaults = (p) => p.workflow === "text-to-vector" ? { ...p, quality: p.quality ?? "medium", aspectRatio: p.aspectRatio ?? "auto" } : { ...p, shapes: p.shapes ?? "detailed" };
|
|
47219
|
+
var animationClip = external_exports.union([external_exports.enum(MODEL_ANIMATION_IDS), external_exports.number().int().min(0).max(MAX_MESHY_ACTION)]);
|
|
47220
|
+
var modelAsset = external_exports.object({
|
|
47221
|
+
name: base.name,
|
|
47222
|
+
/** Describes the model for text-to-3D; with a reference image it is only a note. */
|
|
47223
|
+
prompt: external_exports.string().trim().max(4e3).default(""),
|
|
47224
|
+
type: external_exports.literal("model"),
|
|
47225
|
+
model: external_exports.enum(MODEL_GENERATOR_IDS).default(DEFAULT_MODEL_GENERATOR),
|
|
47226
|
+
/** A saved image or sprite art the model is built from. */
|
|
47227
|
+
reference: blob.optional(),
|
|
47228
|
+
/** Textured (default), or a plain white model. */
|
|
47229
|
+
texture: external_exports.boolean().default(true),
|
|
47230
|
+
/** Metallic, roughness and normal maps with the texture, so scene lights shape the surface. */
|
|
47231
|
+
pbr: external_exports.boolean().default(true),
|
|
47232
|
+
/** Target face count, within the generator's range; Hunyuan3D charges extra for it. */
|
|
47233
|
+
faces: external_exports.number().int().optional(),
|
|
47234
|
+
/** Auto-rig a humanoid character standing in a T- or A-pose. */
|
|
47235
|
+
rig: external_exports.boolean().default(false),
|
|
47236
|
+
/** Clips the rig gets (idle and walk when none are named). */
|
|
47237
|
+
animations: external_exports.array(animationClip).max(MAX_MODEL_CLIPS).default([]),
|
|
47238
|
+
/** The rigged character's height in metres (default 1.7). */
|
|
47239
|
+
height: external_exports.number().min(0.3).max(5).optional()
|
|
47240
|
+
});
|
|
47241
|
+
function modelChecks(p, ctx) {
|
|
47242
|
+
const issue2 = (path, message) => ctx.addIssue({ code: "custom", message, path: [path] });
|
|
47243
|
+
const generator = modelGenerator(p.model);
|
|
47244
|
+
if (!p.reference && p.prompt.length < 3) issue2("prompt", "Describe the model in at least 3 characters, or choose a saved image to build it from.");
|
|
47245
|
+
if (!p.reference && p.prompt.length > MAX_MODEL_PROMPT) issue2("prompt", `Describe the model in at most ${MAX_MODEL_PROMPT.toLocaleString("en-US")} characters.`);
|
|
47246
|
+
if (p.faces !== void 0 && (p.faces < generator.faces.min || p.faces > generator.faces.max)) issue2("faces", `${generator.label} makes ${generator.faces.min.toLocaleString("en-US")}\u2013${generator.faces.max.toLocaleString("en-US")} faces.`);
|
|
47247
|
+
if (!p.rig && p.animations.length) issue2("animations", "Animation clips need rig: true.");
|
|
47248
|
+
if (!p.rig && p.height !== void 0) issue2("height", "height is the rigged character's height; it needs rig: true.");
|
|
47249
|
+
if (!p.rig) return;
|
|
47250
|
+
if (p.faces === void 0 && p.model === "hunyuan-3d-3.1-pro") issue2("faces", `Rigging takes at most ${MAX_RIG_FACES.toLocaleString("en-US")} faces, and Hunyuan3D makes 500,000 unless you set faces.`);
|
|
47251
|
+
else if (p.faces !== void 0 && p.faces > MAX_RIG_FACES) issue2("faces", `Rigging takes at most ${MAX_RIG_FACES.toLocaleString("en-US")} faces.`);
|
|
47252
|
+
const actions2 = p.animations.map(animationAction);
|
|
47253
|
+
if (new Set(actions2).size !== actions2.length) issue2("animations", "Choose each clip once.");
|
|
47254
|
+
}
|
|
47255
|
+
var modelDefaults = (p) => ({ ...p, animations: p.rig && !p.animations.length ? [...DEFAULT_MODEL_ANIMATIONS] : p.animations });
|
|
47025
47256
|
var assetRequest = external_exports.discriminatedUnion("type", [
|
|
47026
47257
|
imageAsset.superRefine(imageChecks),
|
|
47027
47258
|
videoAsset.superRefine(videoChecks).transform(videoDefaults),
|
|
@@ -47031,7 +47262,8 @@ var assetRequest = external_exports.discriminatedUnion("type", [
|
|
|
47031
47262
|
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"] });
|
|
47032
47263
|
}).transform((p) => ({ ...p, voice: p.voice || (isElevenLabsSpeech(p.model) ? DEFAULT_ELEVENLABS_VOICE : "Kore") })),
|
|
47033
47264
|
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)
|
|
47265
|
+
vectorAsset.superRefine(vectorChecks).transform(vectorDefaults),
|
|
47266
|
+
modelAsset.superRefine(modelChecks).transform(modelDefaults)
|
|
47035
47267
|
]);
|
|
47036
47268
|
var assetGenerationRequest = external_exports.discriminatedUnion("type", [imageAsset.omit({ model: true }).superRefine(imageChecks), ...assetRequest.options.slice(1)]);
|
|
47037
47269
|
var LIBRARY_AUDIO_MODEL = "library-audio";
|
|
@@ -47047,13 +47279,15 @@ function videoExtras(p, facts = {}) {
|
|
|
47047
47279
|
if (w !== "reference-to-video" && w !== "insert-video" && w !== "3d-to-video") return {};
|
|
47048
47280
|
const images = (p.references ?? []).reduce((sum, sha2) => sum + imageReferenceTokens(facts.size?.(sha2)), 0);
|
|
47049
47281
|
if (w === "3d-to-video") return { referenceTokens: images + clipReferenceTokens(p.seconds, p.resolution), generatedReferences: p.references?.length ? 0 : p.generatedReferences ?? DEFAULT_GENERATED_REFERENCES };
|
|
47050
|
-
const
|
|
47282
|
+
const clips2 = Math.min(15, (p.referenceVideos ?? []).reduce((sum, sha2) => sum + Math.min(p.seconds, facts.seconds?.(sha2) ?? p.seconds), 0));
|
|
47051
47283
|
const audio = Math.min(15, p.audioReferences.reduce((sum, sha2) => sum + (facts.seconds?.(sha2) ?? 15), 0));
|
|
47052
|
-
return { referenceTokens: images + clipReferenceTokens(
|
|
47284
|
+
return { referenceTokens: images + clipReferenceTokens(clips2, p.resolution) + (w === "reference-to-video" ? audioReferenceTokens(audio) : 0) };
|
|
47053
47285
|
}
|
|
47286
|
+
var modelEstimate = (p) => Math.max(1, Math.ceil(modelCostUsd(p) / 1e-3));
|
|
47054
47287
|
function assetEstimate(p, now = Date.now()) {
|
|
47055
47288
|
if (p.type === "image") return imageEstimate(p);
|
|
47056
47289
|
if (p.type === "vector") return vectorEstimate(p);
|
|
47290
|
+
if (p.type === "model") return modelEstimate(p);
|
|
47057
47291
|
if (p.type === "video") return spriteVideoEstimate(spriteVideoModel(p.model), p, videoExtras(p));
|
|
47058
47292
|
if (p.type === "music") return 80;
|
|
47059
47293
|
const units = (credits) => Math.max(1, Math.ceil(credits * UNITS_PER_CREDIT));
|
|
@@ -47070,8 +47304,8 @@ function assetEstimate(p, now = Date.now()) {
|
|
|
47070
47304
|
}
|
|
47071
47305
|
|
|
47072
47306
|
// cli/src/videos.ts
|
|
47073
|
-
import { open as open4, readFile as
|
|
47074
|
-
import { basename as basename4, join as
|
|
47307
|
+
import { open as open4, readFile as readFile9, stat as stat4 } from "node:fs/promises";
|
|
47308
|
+
import { basename as basename4, join as join10, resolve as resolve10 } from "node:path";
|
|
47075
47309
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
47076
47310
|
import { spawn as spawn2 } from "node:child_process";
|
|
47077
47311
|
import { createHash as createHash4 } from "node:crypto";
|
|
@@ -47114,7 +47348,9 @@ var videoSubmission = videoDetails.and(external_exports.object({
|
|
|
47114
47348
|
bytes: external_exports.number().int().positive(),
|
|
47115
47349
|
width: external_exports.number().int().min(1).max(4096).default(1920),
|
|
47116
47350
|
height: external_exports.number().int().min(1).max(4096).default(1080),
|
|
47117
|
-
duration: external_exports.number().positive().max(7200).optional()
|
|
47351
|
+
duration: external_exports.number().positive().max(7200).optional(),
|
|
47352
|
+
/** Admins only: adds the video to the showcase (shared/showcase.ts), where it shows once it is public and approved. */
|
|
47353
|
+
showcase: showcaseEntry.optional()
|
|
47118
47354
|
})).refine((value) => value.bytes <= VIDEO_MAX_BYTES[value.format], "HTML5 ZIPs support up to 64 MiB; MP4s support up to 512 MiB.").refine((value) => !value.animation || value.project, "Name the project of the animation.");
|
|
47119
47355
|
var videoMove = external_exports.object({ workspace: videoWorkspace }).strict();
|
|
47120
47356
|
function videoPosterType(bytes) {
|
|
@@ -47167,12 +47403,12 @@ function parseSubtitles(input2, duration3) {
|
|
|
47167
47403
|
}
|
|
47168
47404
|
|
|
47169
47405
|
// cli/src/export-files.ts
|
|
47170
|
-
import { open as open2, readFile as
|
|
47171
|
-
import { basename as basename3, resolve as
|
|
47406
|
+
import { open as open2, readFile as readFile6, stat as stat2 } from "node:fs/promises";
|
|
47407
|
+
import { basename as basename3, resolve as resolve7 } from "node:path";
|
|
47172
47408
|
import { createHash as createHash2 } from "node:crypto";
|
|
47173
47409
|
async function exportReceipt(file2) {
|
|
47174
47410
|
try {
|
|
47175
|
-
const receipt = JSON.parse(await
|
|
47411
|
+
const receipt = JSON.parse(await readFile6(file2.replace(/\.mp4$/i, ".json"), "utf8"));
|
|
47176
47412
|
if (receipt.file !== basename3(file2)) return {};
|
|
47177
47413
|
return { title: typeof receipt.title === "string" ? receipt.title : void 0, language: typeof receipt.settings?.language === "string" ? receipt.settings.language : void 0 };
|
|
47178
47414
|
} catch {
|
|
@@ -47182,22 +47418,22 @@ async function exportReceipt(file2) {
|
|
|
47182
47418
|
async function readSubtitleFile(file2, maxBytes) {
|
|
47183
47419
|
let info;
|
|
47184
47420
|
try {
|
|
47185
|
-
info = await
|
|
47421
|
+
info = await stat2(file2);
|
|
47186
47422
|
} catch {
|
|
47187
47423
|
throw new Error(`Cannot read the subtitle file ${file2}.`);
|
|
47188
47424
|
}
|
|
47189
47425
|
if (!info.isFile() || !/\.(?:srt|vtt)$/i.test(file2) || info.size < 1 || info.size > maxBytes) throw new Error(`Use a .srt or .vtt subtitle file up to ${maxBytes / 1024 / 1024} MiB, such as the one npm run export:mp4 writes beside the MP4.`);
|
|
47190
|
-
const content = await
|
|
47426
|
+
const content = await readFile6(file2);
|
|
47191
47427
|
const text2 = content.toString("utf8");
|
|
47192
47428
|
if (text2.includes("\uFFFD") || !/\d\d:\d\d[,.]\d{3} --> /.test(text2)) throw new Error("Use a UTF-8 .srt or .vtt subtitle file with timed captions.");
|
|
47193
47429
|
return { content, sha256: createHash2("sha256").update(content).digest("hex"), language: /^\uFEFF?WEBVTT[^\n]*\n(?:[^\n]+\n)*?Language:[ \t]*([^\s]+)/.exec(text2)?.[1] };
|
|
47194
47430
|
}
|
|
47195
47431
|
async function subtitleFile(root, mp4, choice, extensions) {
|
|
47196
47432
|
if (choice === "none") return null;
|
|
47197
|
-
if (choice !== "auto") return { file:
|
|
47433
|
+
if (choice !== "auto") return { file: resolve7(root, choice), explicit: true };
|
|
47198
47434
|
for (const extension of extensions) {
|
|
47199
47435
|
const file2 = mp4.replace(/\.mp4$/i, extension);
|
|
47200
|
-
if (await
|
|
47436
|
+
if (await stat2(file2).then((info) => info.isFile(), () => false)) return { file: file2, explicit: false };
|
|
47201
47437
|
}
|
|
47202
47438
|
return null;
|
|
47203
47439
|
}
|
|
@@ -47272,10 +47508,10 @@ async function mp4Info(file2) {
|
|
|
47272
47508
|
}
|
|
47273
47509
|
|
|
47274
47510
|
// cli/src/local-project.ts
|
|
47275
|
-
import { readFile as
|
|
47276
|
-
import { join as
|
|
47511
|
+
import { readFile as readFile7, readdir as readdir4 } from "node:fs/promises";
|
|
47512
|
+
import { join as join8, relative, resolve as resolve8, sep } from "node:path";
|
|
47277
47513
|
async function localProject(directory, selected) {
|
|
47278
|
-
const root =
|
|
47514
|
+
const root = resolve8(directory);
|
|
47279
47515
|
let workspace3;
|
|
47280
47516
|
try {
|
|
47281
47517
|
workspace3 = await findWorkspace(root);
|
|
@@ -47287,10 +47523,10 @@ async function localProject(directory, selected) {
|
|
|
47287
47523
|
let animation = selected ?? (location[0] === "animations" ? location[1] : void 0);
|
|
47288
47524
|
if (!animation) {
|
|
47289
47525
|
const names = [];
|
|
47290
|
-
for (const entry of await
|
|
47526
|
+
for (const entry of await readdir4(join8(workspace3, "animations"), { withFileTypes: true })) {
|
|
47291
47527
|
if (!entry.isDirectory()) continue;
|
|
47292
47528
|
try {
|
|
47293
|
-
await
|
|
47529
|
+
await readFile7(join8(workspace3, "animations", entry.name, "animaguru.project.json"));
|
|
47294
47530
|
names.push(entry.name);
|
|
47295
47531
|
} catch (error62) {
|
|
47296
47532
|
if (error62.code !== "ENOENT") throw error62;
|
|
@@ -47300,17 +47536,17 @@ async function localProject(directory, selected) {
|
|
|
47300
47536
|
animation = names[0];
|
|
47301
47537
|
}
|
|
47302
47538
|
if (!/^[a-z0-9][a-z0-9-]{0,79}$/.test(animation)) throw new Error("Use a lowercase, hyphenated animation name.");
|
|
47303
|
-
const projectRoot =
|
|
47304
|
-
await
|
|
47539
|
+
const projectRoot = join8(workspace3, "animations", animation);
|
|
47540
|
+
await readFile7(join8(projectRoot, "animaguru.project.json"));
|
|
47305
47541
|
return { toolsRoot: workspace3, projectRoot, animation };
|
|
47306
47542
|
}
|
|
47307
47543
|
|
|
47308
47544
|
// cli/src/cloud-sync.ts
|
|
47309
47545
|
var import_isomorphic_git = __toESM(require_isomorphic_git(), 1);
|
|
47310
47546
|
import * as fs from "node:fs";
|
|
47311
|
-
import { chmod as chmod3, lstat, mkdir as
|
|
47547
|
+
import { chmod as chmod3, lstat, mkdir as mkdir8, open as open3, readFile as readFile8, readdir as readdir5, rename as rename4, rm as rm2, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
|
|
47312
47548
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
47313
|
-
import { dirname as
|
|
47549
|
+
import { dirname as dirname7, join as join9, resolve as resolve9 } from "node:path";
|
|
47314
47550
|
import { Readable } from "node:stream";
|
|
47315
47551
|
import { pipeline } from "node:stream/promises";
|
|
47316
47552
|
import { setTimeout as delay } from "node:timers/promises";
|
|
@@ -47529,37 +47765,37 @@ var list = (paths, limit2 = 200) => paths.length > limit2 ? [...paths.slice(0, l
|
|
|
47529
47765
|
var short = (oid) => oid.slice(0, 12);
|
|
47530
47766
|
var executable = (mode) => (mode & 73) !== 0;
|
|
47531
47767
|
async function cloudRootFor(start) {
|
|
47532
|
-
let directory =
|
|
47768
|
+
let directory = resolve9(start);
|
|
47533
47769
|
while (true) {
|
|
47534
|
-
if (await exists(
|
|
47770
|
+
if (await exists(join9(directory, LINK_FILE)) || await exists(join9(directory, "animaguru.workspace.json"))) return directory;
|
|
47535
47771
|
try {
|
|
47536
|
-
const project = JSON.parse(await
|
|
47772
|
+
const project = JSON.parse(await readFile8(join9(directory, "animaguru.project.json"), "utf8"));
|
|
47537
47773
|
if (!project.workspace) return directory;
|
|
47538
47774
|
} catch (error62) {
|
|
47539
47775
|
if (error62.code !== "ENOENT" && !(error62 instanceof SyntaxError)) throw error62;
|
|
47540
47776
|
}
|
|
47541
|
-
const parent =
|
|
47777
|
+
const parent = dirname7(directory);
|
|
47542
47778
|
if (parent === directory) throw new Error("Run this inside an AnimaGuru video workspace or project, or pass --dir. Create one with animaguru create workspace NAME.");
|
|
47543
47779
|
directory = parent;
|
|
47544
47780
|
}
|
|
47545
47781
|
}
|
|
47546
47782
|
async function readJson2(path) {
|
|
47547
47783
|
try {
|
|
47548
|
-
return JSON.parse(await
|
|
47784
|
+
return JSON.parse(await readFile8(path, "utf8"));
|
|
47549
47785
|
} catch (error62) {
|
|
47550
47786
|
if (error62.code === "ENOENT") return null;
|
|
47551
47787
|
throw error62;
|
|
47552
47788
|
}
|
|
47553
47789
|
}
|
|
47554
47790
|
async function writeJson2(path, value) {
|
|
47555
|
-
await
|
|
47791
|
+
await mkdir8(dirname7(path), { recursive: true });
|
|
47556
47792
|
const temp = `${path}.${randomUUID2()}.tmp`;
|
|
47557
47793
|
await writeFile7(temp, JSON.stringify(value, null, 2) + "\n", { mode: 384 });
|
|
47558
47794
|
await rename4(temp, path);
|
|
47559
47795
|
}
|
|
47560
47796
|
async function withLock(root, run) {
|
|
47561
|
-
const path =
|
|
47562
|
-
await
|
|
47797
|
+
const path = join9(root, SYNC_DIR, "lock");
|
|
47798
|
+
await mkdir8(dirname7(path), { recursive: true });
|
|
47563
47799
|
for (let attempt = 0; ; attempt++) {
|
|
47564
47800
|
try {
|
|
47565
47801
|
await writeFile7(path, JSON.stringify({ pid: process.pid, at: Date.now() }), { flag: "wx" });
|
|
@@ -47587,27 +47823,27 @@ async function withLock(root, run) {
|
|
|
47587
47823
|
}
|
|
47588
47824
|
async function openContext(dir, options, url3) {
|
|
47589
47825
|
const root = await cloudRootFor(dir);
|
|
47590
|
-
const link2 = await readJson2(
|
|
47826
|
+
const link2 = await readJson2(join9(root, LINK_FILE));
|
|
47591
47827
|
if (!link2) throw new Error("This folder is not linked to a project. Run animaguru cloud link, or animaguru cloud clone PROJECT_ID.");
|
|
47592
47828
|
if (link2.schemaVersion !== 1 || !cloudProjectId.safeParse(link2.projectId).success) throw new Error(`Unsupported cloud link in ${LINK_FILE}. Run animaguru cloud unlink and link again.`);
|
|
47593
|
-
const state = await readJson2(
|
|
47594
|
-
return { root, gitdir:
|
|
47829
|
+
const state = await readJson2(join9(root, STATE_FILE)) ?? { schemaVersion: 1, base: null, files: {} };
|
|
47830
|
+
return { root, gitdir: join9(root, GIT_DIR), link: link2, state, client: new Client(url3 ?? link2.origin, options.signal), options };
|
|
47595
47831
|
}
|
|
47596
47832
|
async function cloudLink(dir) {
|
|
47597
|
-
const link2 = await readJson2(
|
|
47833
|
+
const link2 = await readJson2(join9(await cloudRootFor(dir), LINK_FILE));
|
|
47598
47834
|
if (!link2) throw new Error("This folder is not linked to a project. Pass a project ID.");
|
|
47599
47835
|
return link2;
|
|
47600
47836
|
}
|
|
47601
|
-
var saveState = (context) => writeJson2(
|
|
47837
|
+
var saveState = (context) => writeJson2(join9(context.root, STATE_FILE), context.state);
|
|
47602
47838
|
async function scanFiles(root) {
|
|
47603
47839
|
const files = /* @__PURE__ */ new Map();
|
|
47604
47840
|
const skipped = [];
|
|
47605
47841
|
const tooLarge = [];
|
|
47606
47842
|
async function walk(directory, prefix, rules) {
|
|
47607
|
-
const entries = (await
|
|
47843
|
+
const entries = (await readdir5(directory, { withFileTypes: true })).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
47608
47844
|
const scoped = [...rules];
|
|
47609
47845
|
for (const name2 of [".gitignore", ".animaguruignore"]) {
|
|
47610
|
-
if (entries.some((entry) => entry.name === name2 && entry.isFile())) scoped.push({ base: prefix, rules: (0, import_ignore.default)().add(await
|
|
47846
|
+
if (entries.some((entry) => entry.name === name2 && entry.isFile())) scoped.push({ base: prefix, rules: (0, import_ignore.default)().add(await readFile8(join9(directory, name2), "utf8")) });
|
|
47611
47847
|
}
|
|
47612
47848
|
for (const entry of entries) {
|
|
47613
47849
|
const path = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
@@ -47618,7 +47854,7 @@ async function scanFiles(root) {
|
|
|
47618
47854
|
continue;
|
|
47619
47855
|
}
|
|
47620
47856
|
if (entry.isDirectory()) {
|
|
47621
|
-
await walk(
|
|
47857
|
+
await walk(join9(directory, entry.name), path, scoped);
|
|
47622
47858
|
continue;
|
|
47623
47859
|
}
|
|
47624
47860
|
if (!entry.isFile()) continue;
|
|
@@ -47629,7 +47865,7 @@ async function scanFiles(root) {
|
|
|
47629
47865
|
skipped.push(`${path} (unsupported name)`);
|
|
47630
47866
|
continue;
|
|
47631
47867
|
}
|
|
47632
|
-
const info = await
|
|
47868
|
+
const info = await stat3(join9(directory, entry.name));
|
|
47633
47869
|
if (info.size > CLOUD_OBJECT_MAX_BYTES) {
|
|
47634
47870
|
skipped.push(`${path} (larger than ${CLOUD_OBJECT_MAX_BYTES / 1024 ** 3} GB)`);
|
|
47635
47871
|
continue;
|
|
@@ -47638,7 +47874,7 @@ async function scanFiles(root) {
|
|
|
47638
47874
|
tooLarge.push(safe);
|
|
47639
47875
|
continue;
|
|
47640
47876
|
}
|
|
47641
|
-
files.set(safe, { path: safe, absolute:
|
|
47877
|
+
files.set(safe, { path: safe, absolute: join9(directory, entry.name), size: info.size, mtimeMs: info.mtimeMs, mode: executable(info.mode) ? "100755" : "100644" });
|
|
47642
47878
|
if (files.size > CLOUD_MAX_FILES) throw new Error(`Cloud sync supports up to ${CLOUD_MAX_FILES} files. Add generated folders to .animaguruignore.`);
|
|
47643
47879
|
}
|
|
47644
47880
|
}
|
|
@@ -47670,7 +47906,7 @@ async function describeFiles(context, scanned) {
|
|
|
47670
47906
|
const sha256 = await fileSha256(file2.absolute);
|
|
47671
47907
|
local.set(file2.path, { oid: (await import_isomorphic_git.default.hashBlob({ object: cloudPointer(sha256, file2.size) })).oid, mode: file2.mode, size: file2.size, mtimeMs: file2.mtimeMs, sha256 });
|
|
47672
47908
|
} else {
|
|
47673
|
-
local.set(file2.path, { oid: (await import_isomorphic_git.default.hashBlob({ object: await
|
|
47909
|
+
local.set(file2.path, { oid: (await import_isomorphic_git.default.hashBlob({ object: await readFile8(file2.absolute) })).oid, mode: file2.mode, size: file2.size, mtimeMs: file2.mtimeMs });
|
|
47674
47910
|
}
|
|
47675
47911
|
}
|
|
47676
47912
|
return local;
|
|
@@ -47734,14 +47970,14 @@ ${entries.join(",\n")}
|
|
|
47734
47970
|
}}
|
|
47735
47971
|
`;
|
|
47736
47972
|
}
|
|
47737
|
-
async function token(context,
|
|
47738
|
-
const result = await context.client.request(`/api/v1/cloud/${context.link.projectId}/token`, { method: "POST", body: { access:
|
|
47973
|
+
async function token(context, access4) {
|
|
47974
|
+
const result = await context.client.request(`/api/v1/cloud/${context.link.projectId}/token`, { method: "POST", body: { access: access4 } });
|
|
47739
47975
|
const remote = new URL(result.remote);
|
|
47740
47976
|
if (remote.protocol !== "https:" && !(remote.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(remote.hostname))) throw new Error("The server returned an unsafe cloud remote.");
|
|
47741
47977
|
return { ...result, onAuth: () => ({ username: "x", password: result.token.split("?expires=")[0] }) };
|
|
47742
47978
|
}
|
|
47743
47979
|
async function ensureRepo(gitdir) {
|
|
47744
|
-
if (await exists(
|
|
47980
|
+
if (await exists(join9(gitdir, "HEAD"))) return;
|
|
47745
47981
|
await import_isomorphic_git.default.init({ fs, gitdir, bare: true, defaultBranch: CLOUD_BRANCH });
|
|
47746
47982
|
await import_isomorphic_git.default.setConfig({ fs, gitdir, path: "remote.origin.fetch", value: `+refs/heads/${CLOUD_BRANCH}:refs/remotes/origin/${CLOUD_BRANCH}` });
|
|
47747
47983
|
}
|
|
@@ -47807,12 +48043,12 @@ async function target(root, path) {
|
|
|
47807
48043
|
if (builtIn.ignores(path)) throw new Error(`Refusing to write ${path}: cloud sync never writes ignored or secret files.`);
|
|
47808
48044
|
let current = root;
|
|
47809
48045
|
for (const part of parts.slice(0, -1)) {
|
|
47810
|
-
current =
|
|
48046
|
+
current = join9(current, part);
|
|
47811
48047
|
const info2 = await lstat(current).catch(() => null);
|
|
47812
|
-
if (!info2) await
|
|
48048
|
+
if (!info2) await mkdir8(current);
|
|
47813
48049
|
else if (info2.isSymbolicLink() || !info2.isDirectory()) throw new Error(`Cannot write ${path}: ${part} is not a folder.`);
|
|
47814
48050
|
}
|
|
47815
|
-
const file2 =
|
|
48051
|
+
const file2 = join9(current, parts.at(-1));
|
|
47816
48052
|
const info = await lstat(file2).catch(() => null);
|
|
47817
48053
|
if (info && !info.isFile()) throw new Error(`Cannot replace ${path}: it is a link or folder.`);
|
|
47818
48054
|
return file2;
|
|
@@ -47838,7 +48074,7 @@ async function materialize(context, path, entry) {
|
|
|
47838
48074
|
} else await writeFile7(temp, blob2, { mode: 420 });
|
|
47839
48075
|
await chmod3(temp, entry.mode === "100755" ? 493 : 420);
|
|
47840
48076
|
await rename4(temp, file2);
|
|
47841
|
-
const info = await
|
|
48077
|
+
const info = await stat3(file2);
|
|
47842
48078
|
return { ...entry, size: info.size, mtimeMs: info.mtimeMs, ...pointer ? { sha256: pointer.sha256 } : {} };
|
|
47843
48079
|
} catch (error62) {
|
|
47844
48080
|
await rm2(temp, { force: true });
|
|
@@ -47846,10 +48082,10 @@ async function materialize(context, path, entry) {
|
|
|
47846
48082
|
}
|
|
47847
48083
|
}
|
|
47848
48084
|
async function backup(context, folder, path) {
|
|
47849
|
-
const source =
|
|
48085
|
+
const source = join9(context.root, path);
|
|
47850
48086
|
if (!await exists(source)) return;
|
|
47851
|
-
const destination =
|
|
47852
|
-
await
|
|
48087
|
+
const destination = join9(context.root, SYNC_DIR, "backups", folder, path);
|
|
48088
|
+
await mkdir8(dirname7(destination), { recursive: true });
|
|
47853
48089
|
await fs.promises.copyFile(source, destination);
|
|
47854
48090
|
}
|
|
47855
48091
|
async function remove(context, path) {
|
|
@@ -47869,24 +48105,24 @@ async function apply(context, local, writes, deletes) {
|
|
|
47869
48105
|
}
|
|
47870
48106
|
async function linkCloud(client, options) {
|
|
47871
48107
|
const root = await cloudRootFor(options.dir);
|
|
47872
|
-
if (await exists(
|
|
48108
|
+
if (await exists(join9(root, LINK_FILE))) throw new Error(`This folder is already linked. Run animaguru cloud status, or animaguru cloud unlink first.`);
|
|
47873
48109
|
const id2 = options.project ?? (await client.request("/api/v1/sprites", { method: "POST", body: { owner: options.workspace, name: (options.name ?? root.split(/[\\/]/).pop() ?? "Animations").slice(0, 80) } })).project.id;
|
|
47874
48110
|
const { project } = await client.request("/api/v1/cloud", { method: "POST", body: { project: id2 } });
|
|
47875
|
-
await writeJson2(
|
|
48111
|
+
await writeJson2(join9(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
|
|
47876
48112
|
await keepOutOfGit(root);
|
|
47877
48113
|
return { project, path: root, nextSteps: project.head ? ["Run animaguru cloud pull to combine the cloud versions with this folder."] : ['Run animaguru cloud push -m "First version" to save the first version.'] };
|
|
47878
48114
|
}
|
|
47879
48115
|
async function keepOutOfGit(root) {
|
|
47880
|
-
const path =
|
|
47881
|
-
const text2 = await
|
|
48116
|
+
const path = join9(root, ".gitignore");
|
|
48117
|
+
const text2 = await readFile8(path, "utf8").catch(() => null);
|
|
47882
48118
|
if (text2 !== null && !/^\/?\.animaguru\/(?:sync\/?)?$/m.test(text2)) await writeFile7(path, `${text2}${text2.endsWith("\n") || !text2 ? "" : "\n"}.animaguru/sync/
|
|
47883
48119
|
`);
|
|
47884
48120
|
}
|
|
47885
48121
|
async function unlinkCloud(options) {
|
|
47886
48122
|
const root = await cloudRootFor(options.dir);
|
|
47887
|
-
if (!await exists(
|
|
48123
|
+
if (!await exists(join9(root, LINK_FILE))) throw new Error("This folder is not linked to a project.");
|
|
47888
48124
|
await withLock(root, async () => {
|
|
47889
|
-
for (const name2 of ["link.json", "state.json", "repo.git"]) await rm2(
|
|
48125
|
+
for (const name2 of ["link.json", "state.json", "repo.git"]) await rm2(join9(root, SYNC_DIR, name2), { recursive: true, force: true });
|
|
47890
48126
|
});
|
|
47891
48127
|
return { unlinked: true, path: root, note: "The project's animations and versions were not changed." };
|
|
47892
48128
|
}
|
|
@@ -47936,13 +48172,13 @@ async function pushCloud(options) {
|
|
|
47936
48172
|
if (!local.size) throw new Error("There are no files to save.");
|
|
47937
48173
|
for (const [path, entry] of local) {
|
|
47938
48174
|
if (base2.get(path)?.oid === entry.oid) continue;
|
|
47939
|
-
const bytes = entry.sha256 ? new TextEncoder().encode(cloudPointer(entry.sha256, entry.size)) : await
|
|
48175
|
+
const bytes = entry.sha256 ? new TextEncoder().encode(cloudPointer(entry.sha256, entry.size)) : await readFile8(join9(context.root, path));
|
|
47940
48176
|
if (await import_isomorphic_git.default.writeBlob({ fs, gitdir: context.gitdir, blob: bytes }) !== entry.oid) throw new Error(`${path} changed while saving. Run the push again.`);
|
|
47941
48177
|
}
|
|
47942
|
-
const uploaded = await uploadObjects(context, local, (path) =>
|
|
48178
|
+
const uploaded = await uploadObjects(context, local, (path) => join9(context.root, path));
|
|
47943
48179
|
for (const [path, entry] of local) {
|
|
47944
48180
|
if (!entry.sha256 || base2.get(path)?.oid === entry.oid) continue;
|
|
47945
|
-
const info = await
|
|
48181
|
+
const info = await stat3(join9(context.root, path));
|
|
47946
48182
|
if (info.size !== entry.size || info.mtimeMs !== entry.mtimeMs) throw new Error(`${path} changed while saving. Run the push again.`);
|
|
47947
48183
|
}
|
|
47948
48184
|
const tree = await writeTree(context.gitdir, local, manifestText(local));
|
|
@@ -48017,10 +48253,10 @@ async function pullCloud(options) {
|
|
|
48017
48253
|
async function cloneCloud(client, options) {
|
|
48018
48254
|
const { project } = await client.request(`/api/v1/cloud/${encodeURIComponent(options.id)}`);
|
|
48019
48255
|
if (!project) throw new Error("This project has no synced animations yet. Link a folder with animaguru cloud link --project ID, then push.");
|
|
48020
|
-
const root =
|
|
48021
|
-
if (await exists(root) && (await
|
|
48022
|
-
await
|
|
48023
|
-
await writeJson2(
|
|
48256
|
+
const root = resolve9(options.dir ?? (project.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || project.id));
|
|
48257
|
+
if (await exists(root) && (await readdir5(root)).length) throw new Error(`Destination is not empty: ${root}. Choose a new folder; existing files were not changed.`);
|
|
48258
|
+
await mkdir8(root, { recursive: true });
|
|
48259
|
+
await writeJson2(join9(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
|
|
48024
48260
|
const pulled = await pullCloud({ ...options, dir: root });
|
|
48025
48261
|
return { project, path: root, version: pulled.version, files: "written" in pulled ? pulled.written : 0, nextSteps: ["Run npm install in the folder before previewing or exporting."] };
|
|
48026
48262
|
}
|
|
@@ -48060,6 +48296,17 @@ async function restoreCloud(options) {
|
|
|
48060
48296
|
}
|
|
48061
48297
|
|
|
48062
48298
|
// cli/src/videos.ts
|
|
48299
|
+
function showcaseOption(options) {
|
|
48300
|
+
const extra = options["showcase-tags"] !== void 0 || options["showcase-language"] !== void 0 || options["showcase-position"] !== void 0;
|
|
48301
|
+
if (!options.showcase) {
|
|
48302
|
+
if (extra) throw new Error("Pass --showcase SECTOR to add the video to the showcase.");
|
|
48303
|
+
return {};
|
|
48304
|
+
}
|
|
48305
|
+
const tags = options["showcase-tags"] ? options["showcase-tags"].split(",").map((tag) => tag.trim()).filter(Boolean) : [];
|
|
48306
|
+
const parsed = showcaseEntry.safeParse({ sector: options.showcase, tags, locale: options["showcase-language"] === "none" ? "" : options["showcase-language"] ?? "", position: options["showcase-position"] ?? 0 });
|
|
48307
|
+
if (!parsed.success) throw new Error(`Check the showcase tags: ${parsed.error.issues[0]?.message ?? "invalid"} (tags are ${SHOWCASE_TAGS.join(", ")}).`);
|
|
48308
|
+
return { showcase: parsed.data };
|
|
48309
|
+
}
|
|
48063
48310
|
var subtitlesBody = (content) => new Blob([new Uint8Array(content)], { type: "text/plain; charset=utf-8" });
|
|
48064
48311
|
function libraryWorkspace(value) {
|
|
48065
48312
|
if (value === "personal" || value === "me") return "me";
|
|
@@ -48070,8 +48317,8 @@ function sharingEmails(value) {
|
|
|
48070
48317
|
return value ? value.split(",").map((email3) => email3.trim()).filter(Boolean) : [];
|
|
48071
48318
|
}
|
|
48072
48319
|
async function exportHtml(root, animation, signal, log) {
|
|
48073
|
-
const script =
|
|
48074
|
-
await
|
|
48320
|
+
const script = join10(root, "scripts/export-html.mjs");
|
|
48321
|
+
await stat4(script).catch(() => {
|
|
48075
48322
|
throw new Error("Choose an AnimaGuru video project, or pass --file for an exported HTML5 ZIP or MP4.");
|
|
48076
48323
|
});
|
|
48077
48324
|
log?.("Building the portable HTML5 animation\u2026");
|
|
@@ -48104,23 +48351,24 @@ async function exportHtml(root, animation, signal, log) {
|
|
|
48104
48351
|
async function submitVideo(client, options) {
|
|
48105
48352
|
if (!options.yes && !options["dry-run"]) throw new Error("Pass --yes to authorize uploading and sharing this animation, or --dry-run to inspect the submission.");
|
|
48106
48353
|
const workspace3 = options.workspace === void 0 ? void 0 : libraryWorkspace(options.workspace);
|
|
48107
|
-
const
|
|
48354
|
+
const showcase = showcaseOption(options);
|
|
48355
|
+
const root = resolve10(options.directory ?? ".");
|
|
48108
48356
|
const context = await localProject(root, options.animation);
|
|
48109
|
-
const file2 = options.file ?
|
|
48110
|
-
const info = await
|
|
48357
|
+
const file2 = options.file ? resolve10(root, options.file) : await exportHtml(context.toolsRoot, context.animation, options.signal, options.log);
|
|
48358
|
+
const info = await stat4(file2);
|
|
48111
48359
|
const format = file2.toLowerCase().endsWith(".zip") ? "html5" : file2.toLowerCase().endsWith(".mp4") ? "mp4" : null;
|
|
48112
48360
|
if (!info.isFile() || !format) throw new Error("Submit an AnimaGuru HTML5 .zip export or an .mp4 file.");
|
|
48113
48361
|
videoSubmission.parse({ title: options.title ?? "Video", format, bytes: info.size });
|
|
48114
48362
|
let metadata = {};
|
|
48115
48363
|
let receipt = {};
|
|
48116
48364
|
if (format === "html5") {
|
|
48117
|
-
const files = unzipSync(new Uint8Array(await
|
|
48365
|
+
const files = unzipSync(new Uint8Array(await readFile9(file2)), { filter: (entry) => entry.name === "manifest.json" && entry.originalSize <= 256 * 1024 });
|
|
48118
48366
|
if (!files["manifest.json"]) throw new Error("Use an AnimaGuru HTML5 export with manifest.json.");
|
|
48119
48367
|
metadata = JSON.parse(strFromU8(files["manifest.json"]));
|
|
48120
48368
|
if (metadata.format !== "spriteguru-html5" || metadata.version !== 1) throw new Error("Use an AnimaGuru HTML5 export.");
|
|
48121
48369
|
} else {
|
|
48122
48370
|
try {
|
|
48123
|
-
metadata = JSON.parse(await
|
|
48371
|
+
metadata = JSON.parse(await readFile9(join10(context.projectRoot, "film.config.json"), "utf8"));
|
|
48124
48372
|
} catch {
|
|
48125
48373
|
}
|
|
48126
48374
|
const handle2 = await open4(file2, "r");
|
|
@@ -48148,7 +48396,8 @@ async function submitVideo(client, options) {
|
|
|
48148
48396
|
bytes: info.size,
|
|
48149
48397
|
width: metadata.width,
|
|
48150
48398
|
height: metadata.height,
|
|
48151
|
-
duration: metadata.duration
|
|
48399
|
+
duration: metadata.duration,
|
|
48400
|
+
...showcase
|
|
48152
48401
|
});
|
|
48153
48402
|
let subtitles = null;
|
|
48154
48403
|
const choice = options.subtitles ?? "auto";
|
|
@@ -48163,10 +48412,10 @@ async function submitVideo(client, options) {
|
|
|
48163
48412
|
}
|
|
48164
48413
|
let poster;
|
|
48165
48414
|
if (options.poster) {
|
|
48166
|
-
const path =
|
|
48167
|
-
const info2 = await
|
|
48415
|
+
const path = resolve10(root, options.poster);
|
|
48416
|
+
const info2 = await stat4(path);
|
|
48168
48417
|
if (!info2.isFile() || info2.size > 2 * 1024 * 1024) throw new Error("Poster must be a PNG, JPEG or WebP up to 2 MiB.");
|
|
48169
|
-
poster = await
|
|
48418
|
+
poster = await readFile9(path);
|
|
48170
48419
|
videoPosterType(poster);
|
|
48171
48420
|
}
|
|
48172
48421
|
if (options["dry-run"]) return { dryRun: true, file: file2, submission: body, poster: options.poster ?? null, subtitles: subtitles && { file: subtitles.file, language: subtitles.language } };
|
|
@@ -48216,7 +48465,7 @@ async function changeVideoSubtitles(client, id2, options) {
|
|
|
48216
48465
|
return client.request(path + encodeURIComponent(options.remove), { method: "DELETE" });
|
|
48217
48466
|
}
|
|
48218
48467
|
if (!options.file) throw new Error("Pass --file with a .srt or .vtt subtitle file, or --remove LANGUAGE.");
|
|
48219
|
-
const file2 =
|
|
48468
|
+
const file2 = resolve10(options.file);
|
|
48220
48469
|
const { content, language: header } = await readSubtitleFile(file2, SUBTITLE_MAX_BYTES);
|
|
48221
48470
|
const language = subtitleLanguage.safeParse(options.language ?? header ?? (await exportReceipt(file2.replace(/\.(?:srt|vtt)$/i, ".mp4"))).language);
|
|
48222
48471
|
if (!language.success) throw new Error("Pass --language with the subtitles' language code, such as en or tr.");
|
|
@@ -48250,8 +48499,8 @@ async function moveVideos(client, ids, options) {
|
|
|
48250
48499
|
}
|
|
48251
48500
|
|
|
48252
48501
|
// cli/src/assets.ts
|
|
48253
|
-
import { mkdir as
|
|
48254
|
-
import { dirname as
|
|
48502
|
+
import { mkdir as mkdir9, readFile as readFile10, stat as stat5, writeFile as writeFile8 } from "node:fs/promises";
|
|
48503
|
+
import { dirname as dirname8, join as join11, resolve as resolve11 } from "node:path";
|
|
48255
48504
|
import { setTimeout as delay3 } from "node:timers/promises";
|
|
48256
48505
|
var extras = {
|
|
48257
48506
|
image: ["aspect-ratio", "transparent", "references", "mask"],
|
|
@@ -48289,6 +48538,7 @@ var extras = {
|
|
|
48289
48538
|
music: [],
|
|
48290
48539
|
speech: ["voice", "delivery"],
|
|
48291
48540
|
sfx: ["seconds", "loop", "prompt-influence"],
|
|
48541
|
+
model: ["reference", "texture", "pbr", "faces", "rig", "animations", "height"],
|
|
48292
48542
|
vector: ["workflow", "references", "source", "aspect-ratio", "quality", "shapes", "seed"]
|
|
48293
48543
|
};
|
|
48294
48544
|
var list2 = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
|
|
@@ -48310,6 +48560,7 @@ var regions = (value) => value?.split(";").filter((region) => region.trim()).map
|
|
|
48310
48560
|
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.`);
|
|
48311
48561
|
return { x: x2, y, width, height };
|
|
48312
48562
|
});
|
|
48563
|
+
var clips = (value) => value?.split(",").map((clip) => clip.trim()).filter(Boolean).map((clip) => /^\d+$/.test(clip) ? Number(clip) : clip);
|
|
48313
48564
|
var cameraKeyframes = (value) => value?.split(";").filter((frame) => frame.trim()).map((frame) => {
|
|
48314
48565
|
const [time3, azimuth, elevation, distance, ...rest] = frame.split(",").map((n) => n.trim() ? Number(n) : NaN);
|
|
48315
48566
|
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.`);
|
|
@@ -48324,9 +48575,10 @@ function assetFromFlags(flags) {
|
|
|
48324
48575
|
if (flags.type === "image" && flags.model) throw new Error("Image models are managed by staff. Omit --model.");
|
|
48325
48576
|
for (const name2 of Object.values(extras).flat()) {
|
|
48326
48577
|
const value = flags[name2];
|
|
48327
|
-
|
|
48578
|
+
const given2 = value !== void 0 && (value !== false || (name2 === "texture" || name2 === "pbr") && flags.type !== "model");
|
|
48579
|
+
if (given2 && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets. ${accepted(flags.type)}`.trim());
|
|
48328
48580
|
}
|
|
48329
|
-
if (flags.type !== "video" && flags.type !== "vector" && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets.`);
|
|
48581
|
+
if (flags.type !== "video" && flags.type !== "vector" && !(flags.type === "model" && flags.reference) && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets${flags.type === "model" ? " unless --reference names an image to build from" : ""}.`);
|
|
48330
48582
|
const base2 = { type: flags.type, name: flags.name, prompt: flags.prompt, model: flags.model };
|
|
48331
48583
|
if (flags.type === "image") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], transparent: flags.transparent, references: shas(flags.references), mask: regions(flags.mask) });
|
|
48332
48584
|
if (flags.type === "video") {
|
|
@@ -48364,11 +48616,12 @@ function assetFromFlags(flags) {
|
|
|
48364
48616
|
});
|
|
48365
48617
|
}
|
|
48366
48618
|
if (flags.type === "sfx") return parseAsset({ ...base2, seconds: flags.seconds, loop: flags.loop, promptInfluence: flags["prompt-influence"] });
|
|
48619
|
+
if (flags.type === "model") return parseAsset({ ...base2, reference: flags.reference, texture: flags.texture, pbr: flags.pbr, faces: flags.faces, rig: flags.rig, animations: clips(flags.animations), height: flags.height });
|
|
48367
48620
|
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 });
|
|
48368
48621
|
return parseAsset({ ...base2, ...flags.type === "speech" ? { voice: flags.voice, delivery: flags.delivery } : {} });
|
|
48369
48622
|
}
|
|
48370
48623
|
async function assetFromFile(file2, model) {
|
|
48371
|
-
const input2 = JSON.parse(await
|
|
48624
|
+
const input2 = JSON.parse(await readFile10(file2, "utf8"));
|
|
48372
48625
|
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) throw new Error("The asset file must contain a JSON object.");
|
|
48373
48626
|
return parseAsset({ ...input2, ...model ? { model } : {} });
|
|
48374
48627
|
}
|
|
@@ -48376,7 +48629,7 @@ var MAX_BATCH = 50;
|
|
|
48376
48629
|
var isObject2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
48377
48630
|
var fileName = (name2) => name2.normalize("NFKD").replace(/[^\w.-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
48378
48631
|
async function assetsFromBatchFile(file2, model) {
|
|
48379
|
-
const input2 = JSON.parse(await
|
|
48632
|
+
const input2 = JSON.parse(await readFile10(file2, "utf8"));
|
|
48380
48633
|
let defaults = {};
|
|
48381
48634
|
let items;
|
|
48382
48635
|
if (Array.isArray(input2)) items = input2;
|
|
@@ -48462,18 +48715,19 @@ var MIME_EXTENSIONS = {
|
|
|
48462
48715
|
"image/webp": "webp",
|
|
48463
48716
|
"image/svg+xml": "svg",
|
|
48464
48717
|
"video/mp4": "mp4",
|
|
48465
|
-
"video/webm": "webm"
|
|
48718
|
+
"video/webm": "webm",
|
|
48719
|
+
"model/gltf-binary": "glb"
|
|
48466
48720
|
};
|
|
48467
48721
|
var extensionFor = (asset) => MIME_EXTENSIONS[asset.mimeType?.split(";")[0].trim().toLowerCase()] ?? /\.([a-z0-9]{1,5})$/i.exec(asset.file ?? "")?.[1]?.toLowerCase() ?? "bin";
|
|
48468
48722
|
async function downloadTarget(output2, asset, folder = false) {
|
|
48469
|
-
const path =
|
|
48470
|
-
const isFolder = folder || /[\\/]$/.test(output2) || await
|
|
48723
|
+
const path = resolve11(output2);
|
|
48724
|
+
const isFolder = folder || /[\\/]$/.test(output2) || await stat5(path).then((info) => info.isDirectory(), () => false);
|
|
48471
48725
|
if (!isFolder) {
|
|
48472
|
-
await
|
|
48726
|
+
await mkdir9(dirname8(path), { recursive: true });
|
|
48473
48727
|
return path;
|
|
48474
48728
|
}
|
|
48475
|
-
await
|
|
48476
|
-
return
|
|
48729
|
+
await mkdir9(path, { recursive: true });
|
|
48730
|
+
return join11(path, `${fileName(asset.name) || asset.id}.${extensionFor(asset)}`);
|
|
48477
48731
|
}
|
|
48478
48732
|
async function saveAsset(client, library, asset, path) {
|
|
48479
48733
|
if (!library.ownerId || !/^[a-f0-9]{64}$/.test(asset.file)) throw new Error("Invalid asset download metadata.");
|
|
@@ -48497,7 +48751,7 @@ async function downloadAsset(client, project, assetId, output2) {
|
|
|
48497
48751
|
const library = await client.request(assetsPath(project));
|
|
48498
48752
|
const asset = library.assets.find((a) => a.id === assetId);
|
|
48499
48753
|
if (!asset) throw new Error("Asset not found in this project. Run assets list to find its id.");
|
|
48500
|
-
return saveAsset(client, library, asset,
|
|
48754
|
+
return saveAsset(client, library, asset, resolve11(output2));
|
|
48501
48755
|
}
|
|
48502
48756
|
async function generateAsset(client, project, body, options, signal) {
|
|
48503
48757
|
const waiting = !options["dry-run"] && Boolean(options.wait || options.download);
|
|
@@ -48574,7 +48828,7 @@ async function submitAssetBatch(client, project, requests, options, signal) {
|
|
|
48574
48828
|
}
|
|
48575
48829
|
|
|
48576
48830
|
// cli/src/avatars.ts
|
|
48577
|
-
import { readFile as
|
|
48831
|
+
import { readFile as readFile11, stat as stat6 } from "node:fs/promises";
|
|
48578
48832
|
import { extname } from "node:path";
|
|
48579
48833
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
48580
48834
|
|
|
@@ -48680,8 +48934,8 @@ async function avatarFile2(value) {
|
|
|
48680
48934
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) throw new Error("Use an HTTPS URL, a project file SHA or a local file.");
|
|
48681
48935
|
const mediaType = MEDIA_TYPES[extname(value).toLowerCase()];
|
|
48682
48936
|
if (!mediaType) throw new Error("Use a PNG, JPEG or WebP image, or MP4, MOV or WebM footage.");
|
|
48683
|
-
if ((await
|
|
48684
|
-
return { type: "base64", mediaType, data: (await
|
|
48937
|
+
if ((await stat6(value)).size > AVATAR_INLINE_MAX_BYTES) throw new Error("Local files must be at most 8 MB. Use an HTTPS URL for larger footage.");
|
|
48938
|
+
return { type: "base64", mediaType, data: (await readFile11(value)).toString("base64") };
|
|
48685
48939
|
}
|
|
48686
48940
|
async function avatarFromFlags(flags) {
|
|
48687
48941
|
const prompt = flags.type === "prompt";
|
|
@@ -48729,11 +48983,11 @@ async function waitForLook(client, project, lookId, timeout, signal, interval =
|
|
|
48729
48983
|
// cli/src/youtube-auth.ts
|
|
48730
48984
|
import { createServer } from "node:http";
|
|
48731
48985
|
import { randomBytes, createHash as createHash5, timingSafeEqual } from "node:crypto";
|
|
48732
|
-
import { readFile as
|
|
48986
|
+
import { readFile as readFile13, stat as stat7 } from "node:fs/promises";
|
|
48733
48987
|
|
|
48734
48988
|
// cli/src/youtube-store.ts
|
|
48735
|
-
import { chmod as chmod4, lstat as lstat2, mkdir as
|
|
48736
|
-
import { dirname as
|
|
48989
|
+
import { chmod as chmod4, lstat as lstat2, mkdir as mkdir10, open as open5, readFile as readFile12, readdir as readdir6, rename as rename5, unlink, writeFile as writeFile9 } from "node:fs/promises";
|
|
48990
|
+
import { dirname as dirname9, join as join12 } from "node:path";
|
|
48737
48991
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
48738
48992
|
function refuseInAnimator() {
|
|
48739
48993
|
if (process.env.ANIMAGURU_CLOUD_WORKSPACE) throw new Error("YouTube uploads are not available in the cloud Animator. The user exports the MP4 from the draft page in their browser, then uploads it under Publishing \u2192 YouTube.");
|
|
@@ -48791,14 +49045,14 @@ var youtubeJob = external_exports.object({
|
|
|
48791
49045
|
captions: youtubeCaptions.optional(),
|
|
48792
49046
|
thumbnail: youtubeThumbnail.optional()
|
|
48793
49047
|
}).strict();
|
|
48794
|
-
var youtubeDirectory = () =>
|
|
48795
|
-
var credentialFile = () =>
|
|
49048
|
+
var youtubeDirectory = () => join12(dirname9(credentialsPath()), "youtube");
|
|
49049
|
+
var credentialFile = () => join12(youtubeDirectory(), "credentials.json");
|
|
48796
49050
|
function jobFile(id2) {
|
|
48797
49051
|
if (!external_exports.uuid().safeParse(id2).success) throw new Error("Use an upload ID returned by animaguru youtube uploads list.");
|
|
48798
|
-
return
|
|
49052
|
+
return join12(youtubeDirectory(), "uploads", `${id2}.json`);
|
|
48799
49053
|
}
|
|
48800
49054
|
async function privateDirectory(directory) {
|
|
48801
|
-
await
|
|
49055
|
+
await mkdir10(directory, { recursive: true, mode: 448 });
|
|
48802
49056
|
const info = await lstat2(directory);
|
|
48803
49057
|
if (info.isSymbolicLink() || !info.isDirectory()) throw new Error("YouTube configuration must use a real directory.");
|
|
48804
49058
|
await chmod4(directory, 448);
|
|
@@ -48815,11 +49069,11 @@ async function existingDirectory(directory) {
|
|
|
48815
49069
|
}
|
|
48816
49070
|
async function readPrivate(file2) {
|
|
48817
49071
|
try {
|
|
48818
|
-
if (!await existingDirectory(youtubeDirectory()) || !await existingDirectory(
|
|
49072
|
+
if (!await existingDirectory(youtubeDirectory()) || !await existingDirectory(dirname9(file2))) return null;
|
|
48819
49073
|
const info = await lstat2(file2);
|
|
48820
49074
|
if (info.isSymbolicLink() || !info.isFile() || info.size > 65536) throw new Error("Invalid local YouTube state file.");
|
|
48821
49075
|
await chmod4(file2, 384);
|
|
48822
|
-
return JSON.parse(await
|
|
49076
|
+
return JSON.parse(await readFile12(file2, "utf8"));
|
|
48823
49077
|
} catch (error62) {
|
|
48824
49078
|
if (error62.code === "ENOENT") return null;
|
|
48825
49079
|
throw new Error("Cannot read local YouTube state. Check your AnimaGuru configuration directory.");
|
|
@@ -48827,7 +49081,7 @@ async function readPrivate(file2) {
|
|
|
48827
49081
|
}
|
|
48828
49082
|
async function writePrivate(file2, value) {
|
|
48829
49083
|
await privateDirectory(youtubeDirectory());
|
|
48830
|
-
await privateDirectory(
|
|
49084
|
+
await privateDirectory(dirname9(file2));
|
|
48831
49085
|
const temporary = `${file2}.${randomUUID3()}.tmp`;
|
|
48832
49086
|
try {
|
|
48833
49087
|
await writeFile9(temporary, JSON.stringify(value) + "\n", { flag: "wx", mode: 384 });
|
|
@@ -48859,11 +49113,11 @@ function youtubeJobSummary(job) {
|
|
|
48859
49113
|
return { id: job.id, file: job.file, title: job.metadata.title, channelId: job.channelId, status: job.status, bytes: job.bytes, bytesUploaded: job.bytesUploaded, privacy: job.privacy, youtubeId: job.youtubeId, url: job.youtubeId ? `https://www.youtube.com/watch?v=${job.youtubeId}` : null, createdAt: job.createdAt, captions: job.captions ? { file: job.captions.file, language: job.captions.language, name: job.captions.name, status: job.captions.status } : null, thumbnail: job.thumbnail ? { file: job.thumbnail.file, status: job.thumbnail.status } : null };
|
|
48860
49114
|
}
|
|
48861
49115
|
async function localYouTubeJobs() {
|
|
48862
|
-
const directory =
|
|
49116
|
+
const directory = join12(youtubeDirectory(), "uploads");
|
|
48863
49117
|
if (!await existingDirectory(directory)) return [];
|
|
48864
49118
|
let files;
|
|
48865
49119
|
try {
|
|
48866
|
-
files = await
|
|
49120
|
+
files = await readdir6(directory);
|
|
48867
49121
|
} catch (error62) {
|
|
48868
49122
|
if (error62.code === "ENOENT") return [];
|
|
48869
49123
|
throw error62;
|
|
@@ -48880,10 +49134,10 @@ async function clearYouTubeData() {
|
|
|
48880
49134
|
await unlink(credentialFile()).catch((error62) => {
|
|
48881
49135
|
if (error62.code !== "ENOENT") throw error62;
|
|
48882
49136
|
});
|
|
48883
|
-
if (!await existingDirectory(
|
|
49137
|
+
if (!await existingDirectory(join12(youtubeDirectory(), "uploads"))) return;
|
|
48884
49138
|
let files;
|
|
48885
49139
|
try {
|
|
48886
|
-
files = await
|
|
49140
|
+
files = await readdir6(join12(youtubeDirectory(), "uploads"));
|
|
48887
49141
|
} catch (error62) {
|
|
48888
49142
|
if (error62.code === "ENOENT") return;
|
|
48889
49143
|
throw error62;
|
|
@@ -48893,7 +49147,7 @@ async function clearYouTubeData() {
|
|
|
48893
49147
|
async function withYouTubeLock(operation) {
|
|
48894
49148
|
refuseInAnimator();
|
|
48895
49149
|
await privateDirectory(youtubeDirectory());
|
|
48896
|
-
const file2 =
|
|
49150
|
+
const file2 = join12(youtubeDirectory(), "operation.lock");
|
|
48897
49151
|
const lock = await open5(file2, "wx", 384).catch((error62) => {
|
|
48898
49152
|
if (error62.code === "EEXIST") throw new Error(`Another YouTube command is running. If a previous command was killed, verify it has stopped before removing ${file2}.`);
|
|
48899
49153
|
throw error62;
|
|
@@ -49041,11 +49295,11 @@ async function youtubeLogin(options) {
|
|
|
49041
49295
|
if (existing && options.captions && !canAddCaptions(existing)) throw new Error("A YouTube channel is already connected without caption permission. Run youtube auth logout --yes, then youtube auth login --captions.");
|
|
49042
49296
|
if (existing) throw new Error("A YouTube channel is already connected. Run youtube auth logout --yes before switching channels.");
|
|
49043
49297
|
const file2 = options["client-file"];
|
|
49044
|
-
const info = await
|
|
49298
|
+
const info = await stat7(file2);
|
|
49045
49299
|
if (!info.isFile() || info.size > 65536) throw new Error("Use Google's downloaded Desktop app OAuth client JSON.");
|
|
49046
49300
|
let installed;
|
|
49047
49301
|
try {
|
|
49048
|
-
installed = JSON.parse(await
|
|
49302
|
+
installed = JSON.parse(await readFile13(file2, "utf8")).installed;
|
|
49049
49303
|
} catch {
|
|
49050
49304
|
}
|
|
49051
49305
|
if (!installed || typeof installed.client_id !== "string" || !installed.client_id.endsWith(".apps.googleusercontent.com") || installed.client_secret !== void 0 && typeof installed.client_secret !== "string") throw new Error("Use Google's Desktop app OAuth client JSON (installed), not a web client or API key.");
|
|
@@ -49055,8 +49309,8 @@ async function youtubeLogin(options) {
|
|
|
49055
49309
|
let receive;
|
|
49056
49310
|
let fail;
|
|
49057
49311
|
let used = false;
|
|
49058
|
-
const callback = new Promise((
|
|
49059
|
-
receive =
|
|
49312
|
+
const callback = new Promise((resolve19, reject) => {
|
|
49313
|
+
receive = resolve19;
|
|
49060
49314
|
fail = reject;
|
|
49061
49315
|
});
|
|
49062
49316
|
void callback.catch(() => {
|
|
@@ -49094,9 +49348,9 @@ async function youtubeLogin(options) {
|
|
|
49094
49348
|
response.end("Authorization received. Return to your AnimaGuru terminal.");
|
|
49095
49349
|
receive(code);
|
|
49096
49350
|
});
|
|
49097
|
-
await new Promise((
|
|
49351
|
+
await new Promise((resolve19, reject) => {
|
|
49098
49352
|
server.once("error", reject);
|
|
49099
|
-
server.listen(0, "127.0.0.1",
|
|
49353
|
+
server.listen(0, "127.0.0.1", resolve19);
|
|
49100
49354
|
});
|
|
49101
49355
|
const address = server.address();
|
|
49102
49356
|
if (!address || typeof address === "string") throw new Error("Cannot open the local YouTube authorization listener.");
|
|
@@ -49131,7 +49385,7 @@ async function youtubeLogin(options) {
|
|
|
49131
49385
|
clearTimeout(timer);
|
|
49132
49386
|
options.signal?.removeEventListener("abort", abort);
|
|
49133
49387
|
server.closeAllConnections();
|
|
49134
|
-
await new Promise((
|
|
49388
|
+
await new Promise((resolve19) => server.close(() => resolve19()));
|
|
49135
49389
|
}
|
|
49136
49390
|
});
|
|
49137
49391
|
}
|
|
@@ -49162,8 +49416,8 @@ async function youtubeLogout(options) {
|
|
|
49162
49416
|
|
|
49163
49417
|
// cli/src/youtube-upload.ts
|
|
49164
49418
|
import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
|
|
49165
|
-
import { open as open6, readFile as
|
|
49166
|
-
import { basename as basename5, join as
|
|
49419
|
+
import { open as open6, readFile as readFile14, stat as stat8 } from "node:fs/promises";
|
|
49420
|
+
import { basename as basename5, join as join13, resolve as resolve12 } from "node:path";
|
|
49167
49421
|
import { setTimeout as delay5 } from "node:timers/promises";
|
|
49168
49422
|
var YOUTUBE_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
49169
49423
|
function safeYouTubeSession(value) {
|
|
@@ -49214,23 +49468,23 @@ async function planCaptions(root, mp4, options, fallbackLanguage) {
|
|
|
49214
49468
|
async function readThumbnail(file2) {
|
|
49215
49469
|
let info;
|
|
49216
49470
|
try {
|
|
49217
|
-
info = await
|
|
49471
|
+
info = await stat8(file2);
|
|
49218
49472
|
} catch {
|
|
49219
49473
|
throw new Error(`Cannot read the thumbnail ${file2}.`);
|
|
49220
49474
|
}
|
|
49221
49475
|
if (!info.isFile() || info.size < 8 || info.size > 2 * 1024 * 1024) throw new Error("Use a JPEG or PNG thumbnail up to 2 MiB, such as the one npm run export:mp4 saves beside the MP4.");
|
|
49222
|
-
const content = await
|
|
49476
|
+
const content = await readFile14(file2);
|
|
49223
49477
|
const type = content[0] === 255 && content[1] === 216 && content[2] === 255 ? "image/jpeg" : content.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) ? "image/png" : null;
|
|
49224
49478
|
if (!type) throw new Error("Use a JPEG or PNG thumbnail.");
|
|
49225
49479
|
return { content, type, sha256: createHash6("sha256").update(content).digest("hex") };
|
|
49226
49480
|
}
|
|
49227
49481
|
async function planThumbnail(root, mp4, choice = "auto") {
|
|
49228
49482
|
if (choice === "none") return null;
|
|
49229
|
-
let file2 = choice === "auto" ? void 0 :
|
|
49483
|
+
let file2 = choice === "auto" ? void 0 : resolve12(root, choice);
|
|
49230
49484
|
if (!file2) {
|
|
49231
49485
|
for (const extension of [".jpg", ".jpeg", ".png"]) {
|
|
49232
49486
|
const candidate = mp4.replace(/\.mp4$/i, extension);
|
|
49233
|
-
if (await
|
|
49487
|
+
if (await stat8(candidate).then((info) => info.isFile(), () => false)) {
|
|
49234
49488
|
file2 = candidate;
|
|
49235
49489
|
break;
|
|
49236
49490
|
}
|
|
@@ -49415,12 +49669,12 @@ async function uploadYouTube(options) {
|
|
|
49415
49669
|
refuseInAnimator();
|
|
49416
49670
|
if (!options.yes && !options["dry-run"]) throw new Error("Pass --yes to authorize the YouTube upload, or --dry-run to inspect it locally.");
|
|
49417
49671
|
if (!["yes", "no"].includes(options["made-for-kids"]) || !["yes", "no"].includes(options["synthetic-media"])) throw new Error("Set --made-for-kids yes|no and --synthetic-media yes|no explicitly.");
|
|
49418
|
-
const root =
|
|
49419
|
-
const file2 =
|
|
49672
|
+
const root = resolve12(options.directory ?? ".");
|
|
49673
|
+
const file2 = resolve12(root, options.file);
|
|
49420
49674
|
const context = await localProject(root, options.animation);
|
|
49421
49675
|
let config2 = {};
|
|
49422
49676
|
try {
|
|
49423
|
-
config2 = JSON.parse(await
|
|
49677
|
+
config2 = JSON.parse(await readFile14(join13(context.projectRoot, "film.config.json"), "utf8"));
|
|
49424
49678
|
} catch {
|
|
49425
49679
|
}
|
|
49426
49680
|
const receipt = await exportReceipt(file2);
|
|
@@ -49497,8 +49751,8 @@ async function resumeYouTube(id2, options) {
|
|
|
49497
49751
|
var listYouTubeUploads = () => withYouTubeLock(async () => ({ uploads: (await localYouTubeJobs()).map(youtubeJobSummary) }));
|
|
49498
49752
|
|
|
49499
49753
|
// cli/src/motion.ts
|
|
49500
|
-
import { access as
|
|
49501
|
-
import { dirname as
|
|
49754
|
+
import { access as access3, mkdir as mkdir11, writeFile as writeFile10 } from "node:fs/promises";
|
|
49755
|
+
import { dirname as dirname10, join as join14, relative as relative2, resolve as resolve13, sep as sep2 } from "node:path";
|
|
49502
49756
|
|
|
49503
49757
|
// shared/motion-library.ts
|
|
49504
49758
|
var MOTION_CATEGORIES = [
|
|
@@ -49547,18 +49801,18 @@ async function searchMotion(client, query, flags) {
|
|
|
49547
49801
|
if (flags.code) params.set("include_code", "true");
|
|
49548
49802
|
return client.request(`/api/v1/motion-library/search?${params}`);
|
|
49549
49803
|
}
|
|
49550
|
-
var exists2 = (path) =>
|
|
49804
|
+
var exists2 = (path) => access3(path).then(() => true, () => false);
|
|
49551
49805
|
async function workspaceRoot(start) {
|
|
49552
|
-
for (let directory = start; ; directory =
|
|
49553
|
-
if (await exists2(
|
|
49554
|
-
if (
|
|
49806
|
+
for (let directory = start; ; directory = dirname10(directory)) {
|
|
49807
|
+
if (await exists2(join14(directory, "animaguru.workspace.json"))) return directory;
|
|
49808
|
+
if (dirname10(directory) === directory) return null;
|
|
49555
49809
|
}
|
|
49556
49810
|
}
|
|
49557
49811
|
async function writeMotionExample(example, directory, { force = false } = {}) {
|
|
49558
|
-
const target2 =
|
|
49812
|
+
const target2 = resolve13(directory);
|
|
49559
49813
|
const workspace3 = await workspaceRoot(target2);
|
|
49560
49814
|
const inAnimation = Boolean(workspace3 && relative2(workspace3, target2).split(sep2)[0] === "animations");
|
|
49561
|
-
const files = example.files.map((file2) => ({ path:
|
|
49815
|
+
const files = example.files.map((file2) => ({ path: join14(target2, safeProjectPath(file2.path)), code: inAnimation ? motionCodeForWorkspace(file2.code) : file2.code }));
|
|
49562
49816
|
if (!force) {
|
|
49563
49817
|
const clashes = [];
|
|
49564
49818
|
for (const [index2, file2] of files.entries()) if (index2 === 0 && await exists2(file2.path)) clashes.push(file2.path);
|
|
@@ -49570,7 +49824,7 @@ async function writeMotionExample(example, directory, { force = false } = {}) {
|
|
|
49570
49824
|
kept.push(file2.path);
|
|
49571
49825
|
continue;
|
|
49572
49826
|
}
|
|
49573
|
-
await
|
|
49827
|
+
await mkdir11(dirname10(file2.path), { recursive: true });
|
|
49574
49828
|
await writeFile10(file2.path, file2.code);
|
|
49575
49829
|
written.push(file2.path);
|
|
49576
49830
|
}
|
|
@@ -49578,8 +49832,8 @@ async function writeMotionExample(example, directory, { force = false } = {}) {
|
|
|
49578
49832
|
}
|
|
49579
49833
|
|
|
49580
49834
|
// cli/src/library.ts
|
|
49581
|
-
import { mkdir as
|
|
49582
|
-
import { dirname as
|
|
49835
|
+
import { mkdir as mkdir12, readFile as readFile15, writeFile as writeFile11 } from "node:fs/promises";
|
|
49836
|
+
import { dirname as dirname11, join as join15, resolve as resolve14 } from "node:path";
|
|
49583
49837
|
|
|
49584
49838
|
// shared/asset-library.ts
|
|
49585
49839
|
var LIBRARY_ASSET_TYPES = ["sprite", "image", "video", "music", "speech", "sfx"];
|
|
@@ -49666,23 +49920,23 @@ function searchLibrary(client, query, flags) {
|
|
|
49666
49920
|
var getLibraryAsset = (client, id2) => client.request(libraryPath(id2));
|
|
49667
49921
|
async function downloadLibraryAsset(client, id2, output2, { force = false } = {}) {
|
|
49668
49922
|
const asset = await getLibraryAsset(client, id2);
|
|
49669
|
-
const root =
|
|
49923
|
+
const root = resolve14(output2, asset.type === "sprite" ? safeProjectPath(asset.id) : ".");
|
|
49670
49924
|
const written = [];
|
|
49671
49925
|
for (const file2 of asset.files) {
|
|
49672
|
-
const path =
|
|
49926
|
+
const path = join15(root, safeProjectPath(file2.path));
|
|
49673
49927
|
const response = await client.request(`${libraryPath(asset.id)}/files/${file2.path.split("/").map(encodeURIComponent).join("/")}?download=1`, { raw: true, timeout: 3e5 });
|
|
49674
49928
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
49675
|
-
await
|
|
49929
|
+
await mkdir12(dirname11(path), { recursive: true });
|
|
49676
49930
|
await writeFile11(path, bytes, { flag: force ? "w" : "wx" }).catch((error62) => {
|
|
49677
49931
|
throw error62.code === "EEXIST" ? new Error(`Already exists: ${path}. Pass --force to replace it.`) : error62;
|
|
49678
49932
|
});
|
|
49679
49933
|
written.push({ path, size: bytes.byteLength, mimeType: file2.mimeType });
|
|
49680
49934
|
}
|
|
49681
|
-
return { id: asset.id, type: asset.type, files: written, ...asset.type === "sprite" ? { animations: asset.details.animations?.map(({ action, sheet, data, frames, fps, loop }) => ({ action, sheet:
|
|
49935
|
+
return { id: asset.id, type: asset.type, files: written, ...asset.type === "sprite" ? { animations: asset.details.animations?.map(({ action, sheet, data, frames, fps, loop }) => ({ action, sheet: join15(root, sheet), data: join15(root, data), frames, fps, loop })) } : {} };
|
|
49682
49936
|
}
|
|
49683
49937
|
var importLibraryAsset = (client, id2, project, name2) => client.request(`${libraryPath(id2)}/import`, { method: "POST", body: { projectId: project, ...name2 ? { name: name2 } : {} } });
|
|
49684
49938
|
async function words(flags) {
|
|
49685
|
-
const input2 = flags.file ? JSON.parse(await
|
|
49939
|
+
const input2 = flags.file ? JSON.parse(await readFile15(flags.file, "utf8")) : {};
|
|
49686
49940
|
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) throw new Error("The file must contain a JSON object.");
|
|
49687
49941
|
return {
|
|
49688
49942
|
...input2,
|
|
@@ -49727,8 +49981,8 @@ async function moveWork(client, project, flags) {
|
|
|
49727
49981
|
}
|
|
49728
49982
|
|
|
49729
49983
|
// cli/src/release.ts
|
|
49730
|
-
import { mkdir as
|
|
49731
|
-
import { dirname as
|
|
49984
|
+
import { mkdir as mkdir13, readFile as readFile16, rename as rename6, unlink as unlink2, writeFile as writeFile12 } from "node:fs/promises";
|
|
49985
|
+
import { dirname as dirname12, join as join16 } from "node:path";
|
|
49732
49986
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
49733
49987
|
var releaseUrl = "https://animaguru.com/cli/release.json";
|
|
49734
49988
|
function versionParts(version3) {
|
|
@@ -49749,10 +50003,10 @@ function parseRelease(value) {
|
|
|
49749
50003
|
versionParts(value.version);
|
|
49750
50004
|
return { name: value.name, version: value.version };
|
|
49751
50005
|
}
|
|
49752
|
-
var cachePath = () =>
|
|
50006
|
+
var cachePath = () => join16(dirname12(credentialsPath()), "cli-release.json");
|
|
49753
50007
|
async function cachedRelease() {
|
|
49754
50008
|
try {
|
|
49755
|
-
return parseRelease(JSON.parse(await
|
|
50009
|
+
return parseRelease(JSON.parse(await readFile16(cachePath(), "utf8")));
|
|
49756
50010
|
} catch {
|
|
49757
50011
|
return void 0;
|
|
49758
50012
|
}
|
|
@@ -49768,7 +50022,7 @@ async function latestRelease(signal) {
|
|
|
49768
50022
|
const path = cachePath();
|
|
49769
50023
|
const temp = `${path}.${randomUUID5()}.tmp`;
|
|
49770
50024
|
try {
|
|
49771
|
-
await
|
|
50025
|
+
await mkdir13(dirname12(path), { recursive: true, mode: 448 });
|
|
49772
50026
|
await writeFile12(temp, JSON.stringify(release) + "\n", { flag: "wx", mode: 384 });
|
|
49773
50027
|
await rename6(temp, path);
|
|
49774
50028
|
} catch {
|
|
@@ -49810,8 +50064,8 @@ async function requireCurrentRelease(argv, stderr) {
|
|
|
49810
50064
|
}
|
|
49811
50065
|
|
|
49812
50066
|
// cli/src/brands.ts
|
|
49813
|
-
import { lstat as lstat3, mkdir as
|
|
49814
|
-
import { basename as basename6, dirname as
|
|
50067
|
+
import { lstat as lstat3, mkdir as mkdir14, readFile as readFile17, stat as stat9, writeFile as writeFile13 } from "node:fs/promises";
|
|
50068
|
+
import { basename as basename6, dirname as dirname13, extname as extname2, join as join17, resolve as resolve15 } from "node:path";
|
|
49815
50069
|
|
|
49816
50070
|
// shared/brands.ts
|
|
49817
50071
|
var brandId = external_exports.string().regex(/^br_[a-f0-9]{24}$/);
|
|
@@ -49864,6 +50118,7 @@ var brandCreate = brandFields.extend({ requestId: external_exports.string().uuid
|
|
|
49864
50118
|
var brandUpdate = external_exports.object(fieldShape).partial().strict();
|
|
49865
50119
|
var brandResearch = external_exports.object({ requestId: external_exports.string().uuid(), workspace, url: brandWebsite, name: external_exports.string().trim().min(1).max(120).optional() }).strict();
|
|
49866
50120
|
var brandRefresh = external_exports.object({ requestId: external_exports.string().uuid(), url: brandWebsite.optional() }).strict();
|
|
50121
|
+
var brandTransfer = external_exports.object({ workspace }).strict();
|
|
49867
50122
|
var DEFAULT_BRAND_COLORS = { primary: "#2563eb", background: "#ffffff", text: "#111827", accent: null, palette: [] };
|
|
49868
50123
|
var DEFAULT_BRAND_FONTS = { heading: { family: "Inter, sans-serif", file: null }, body: { family: "Inter, sans-serif", file: null } };
|
|
49869
50124
|
var brandDraftFields = brandFields.extend({
|
|
@@ -49930,7 +50185,7 @@ async function listBrands(client, selected) {
|
|
|
49930
50185
|
}
|
|
49931
50186
|
var getBrand = (client, id2) => client.request(brandPath(id2));
|
|
49932
50187
|
async function jsonObject(file2) {
|
|
49933
|
-
const value = JSON.parse(await
|
|
50188
|
+
const value = JSON.parse(await readFile17(file2, "utf8"));
|
|
49934
50189
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("The file must contain a JSON object.");
|
|
49935
50190
|
return value;
|
|
49936
50191
|
}
|
|
@@ -49957,12 +50212,12 @@ async function uploadBrandFile(client, id2, file2, flags) {
|
|
|
49957
50212
|
const path = brandPath(id2);
|
|
49958
50213
|
if (!flags.yes) throw new Error("Pass --yes to authorize uploading this file to the brand.");
|
|
49959
50214
|
if (flags.kind && !BRAND_FILE_KINDS.includes(flags.kind)) throw new Error("Unknown brand file kind.");
|
|
49960
|
-
const info = await
|
|
50215
|
+
const info = await stat9(file2);
|
|
49961
50216
|
if (!info.isFile() || !info.size || info.size > BRAND_FILE_BYTES) throw new Error("A brand file must be between 1 byte and 32 MiB.");
|
|
49962
50217
|
const extension = extname2(file2).slice(1).toLowerCase().replace(/^jpeg$/, "jpg");
|
|
49963
50218
|
const mimeType = flags["mime-type"] ?? Object.entries(BRAND_FILE_TYPES).find(([, ext]) => ext === extension)?.[0];
|
|
49964
50219
|
if (!mimeType || !BRAND_FILE_TYPES[mimeType]) throw new Error("Unsupported brand file type. Use a web image, font, audio or video file, or specify --mime-type.");
|
|
49965
|
-
const bytes = new Uint8Array(await
|
|
50220
|
+
const bytes = new Uint8Array(await readFile17(file2));
|
|
49966
50221
|
if (!bytes.byteLength || bytes.byteLength > BRAND_FILE_BYTES) throw new Error("A brand file must be between 1 byte and 32 MiB.");
|
|
49967
50222
|
const form = new FormData();
|
|
49968
50223
|
form.set("file", new File([bytes], basename6(file2), { type: mimeType }));
|
|
@@ -49980,22 +50235,22 @@ async function downloadBrand(client, id2, output2, flags = {}) {
|
|
|
49980
50235
|
`, mimeType: "application/json" },
|
|
49981
50236
|
{ path: "branding/brand-guide.md", content: brandGuide(brand), mimeType: "text/markdown" }
|
|
49982
50237
|
];
|
|
49983
|
-
const root =
|
|
49984
|
-
const targets = [...textFiles.map((file2) => file2.path), ...files.map(brandFilePath)].map((path) =>
|
|
50238
|
+
const root = resolve15(output2);
|
|
50239
|
+
const targets = [...textFiles.map((file2) => file2.path), ...files.map(brandFilePath)].map((path) => join17(root, safeProjectPath(path)));
|
|
49985
50240
|
if (new Set(targets).size !== targets.length) throw new Error("The brand contains conflicting file names.");
|
|
49986
|
-
for (const path of [
|
|
50241
|
+
for (const path of [join17(root, "branding"), ...targets]) {
|
|
49987
50242
|
const info = await lstat3(path).catch((error62) => {
|
|
49988
50243
|
if (error62.code !== "ENOENT") throw error62;
|
|
49989
50244
|
return null;
|
|
49990
50245
|
});
|
|
49991
50246
|
if (info?.isSymbolicLink()) throw new Error(`Refusing to write through a symbolic link: ${path}`);
|
|
49992
|
-
if (path !==
|
|
50247
|
+
if (path !== join17(root, "branding") && info && (!flags.force || !info.isFile())) throw new Error(`Already exists: ${path}. Pass --force to replace files.`);
|
|
49993
50248
|
}
|
|
49994
|
-
await
|
|
50249
|
+
await mkdir14(join17(root, "branding"), { recursive: true });
|
|
49995
50250
|
const written = [];
|
|
49996
50251
|
const save = async (path, bytes, mimeType) => {
|
|
49997
|
-
const target2 =
|
|
49998
|
-
await
|
|
50252
|
+
const target2 = join17(root, safeProjectPath(path));
|
|
50253
|
+
await mkdir14(dirname13(target2), { recursive: true });
|
|
49999
50254
|
await writeFile13(target2, bytes, { flag: flags.force ? "w" : "wx" });
|
|
50000
50255
|
written.push({ path: target2, size: bytes.byteLength, mimeType });
|
|
50001
50256
|
};
|
|
@@ -50008,8 +50263,8 @@ async function downloadBrand(client, id2, output2, flags = {}) {
|
|
|
50008
50263
|
}
|
|
50009
50264
|
|
|
50010
50265
|
// cli/src/review-check.ts
|
|
50011
|
-
import { readFile as
|
|
50012
|
-
import { join as
|
|
50266
|
+
import { readFile as readFile18, readdir as readdir7, stat as stat10, writeFile as writeFile14 } from "node:fs/promises";
|
|
50267
|
+
import { join as join18 } from "node:path";
|
|
50013
50268
|
|
|
50014
50269
|
// shared/frame-checks.ts
|
|
50015
50270
|
var FRAME_CHECK_MAX_FRAMES = 12;
|
|
@@ -50053,17 +50308,17 @@ var frameCheckRequest = external_exports.object({
|
|
|
50053
50308
|
// cli/src/review-check.ts
|
|
50054
50309
|
async function framesToCheck(projectRoot, source, report2) {
|
|
50055
50310
|
if (source === "frames") {
|
|
50056
|
-
const folder2 =
|
|
50057
|
-
const names2 = await
|
|
50058
|
-
const frames = names2.map((name2) => /^frame-([\d.]+)s\.jpg$/.exec(name2)).filter((match) => match !== null).map((match) => ({ file:
|
|
50311
|
+
const folder2 = join18(projectRoot, "production/review/frames");
|
|
50312
|
+
const names2 = await readdir7(folder2).catch(() => []);
|
|
50313
|
+
const frames = names2.map((name2) => /^frame-([\d.]+)s\.jpg$/.exec(name2)).filter((match) => match !== null).map((match) => ({ file: join18(folder2, match[0]), time: Number(match[1]) })).sort((a, b) => a.time - b.time);
|
|
50059
50314
|
if (!frames.length) throw new Error("No full-size frames found. Run npm run frames -- --full (with --at TIMES for the moments to check) first.");
|
|
50060
50315
|
return frames;
|
|
50061
50316
|
}
|
|
50062
|
-
const folder =
|
|
50317
|
+
const folder = join18(projectRoot, "production/review");
|
|
50063
50318
|
const times = [...report2.seekMatches ?? []].map((match) => match.time).sort((a, b) => a - b);
|
|
50064
|
-
const names = (await
|
|
50319
|
+
const names = (await readdir7(folder)).filter((name2) => /^frame-\d{2}\.jpg$/.test(name2)).sort();
|
|
50065
50320
|
if (!names.length || names.length !== times.length) throw new Error("The review frames do not match report.json. Run npm run review again.");
|
|
50066
|
-
return names.map((name2, index2) => ({ file:
|
|
50321
|
+
return names.map((name2, index2) => ({ file: join18(folder, name2), time: times[index2] }));
|
|
50067
50322
|
}
|
|
50068
50323
|
function filmContext(report2, brief, extra) {
|
|
50069
50324
|
const config2 = report2.config ?? {};
|
|
@@ -50078,29 +50333,29 @@ function compact(answers) {
|
|
|
50078
50333
|
async function reviewCheck(client, options) {
|
|
50079
50334
|
if (!options.yes && !options["dry-run"]) throw new Error("Pass --yes to authorize spending credits on the check, or --dry-run for its most.");
|
|
50080
50335
|
const context = await localProject(options.directory, options.animation);
|
|
50081
|
-
const reportFile =
|
|
50082
|
-
const report2 = JSON.parse(await
|
|
50336
|
+
const reportFile = join18(context.projectRoot, "production/review/report.json");
|
|
50337
|
+
const report2 = JSON.parse(await readFile18(reportFile, "utf8").catch(() => {
|
|
50083
50338
|
throw new Error("Run npm run review first: production/review/report.json is missing.");
|
|
50084
50339
|
}));
|
|
50085
50340
|
const frames = await framesToCheck(context.projectRoot, options.source ?? "review", report2);
|
|
50086
50341
|
if (frames.length > FRAME_CHECK_MAX_FRAMES) throw new Error(`Check at most ${FRAME_CHECK_MAX_FRAMES} frames at once; run npm run frames -- --full --at with fewer times.`);
|
|
50087
|
-
const sizes = await Promise.all(frames.map(async (frame) => (await
|
|
50342
|
+
const sizes = await Promise.all(frames.map(async (frame) => (await stat10(frame.file)).size));
|
|
50088
50343
|
if (sizes.reduce((sum, size) => sum + size, 0) > FRAME_CHECK_TOTAL_BYTES) throw new Error("These frames total over 8 MiB. Check fewer at once.");
|
|
50089
|
-
const questions = options.questions ? frameCheckQuestions.parse(JSON.parse(await
|
|
50090
|
-
const brief = await
|
|
50344
|
+
const questions = options.questions ? frameCheckQuestions.parse(JSON.parse(await readFile18(options.questions, "utf8"))) : void 0;
|
|
50345
|
+
const brief = await readFile18(join18(context.projectRoot, "production/brief.md"), "utf8").catch(() => "");
|
|
50091
50346
|
const link2 = await cloudLink(context.toolsRoot).catch(() => null);
|
|
50092
50347
|
const body = {
|
|
50093
50348
|
...link2?.origin === client.origin ? { projectId: link2.projectId } : { workspace: await selectedWorkspace(client.origin) },
|
|
50094
50349
|
context: filmContext(report2, brief, options.context),
|
|
50095
50350
|
...report2.config?.duration ? { duration: report2.config.duration } : {},
|
|
50096
|
-
frames: await Promise.all(frames.map(async (frame) => ({ time: Math.round(frame.time * 1e3) / 1e3, image: `data:image/jpeg;base64,${(await
|
|
50351
|
+
frames: await Promise.all(frames.map(async (frame) => ({ time: Math.round(frame.time * 1e3) / 1e3, image: `data:image/jpeg;base64,${(await readFile18(frame.file)).toString("base64")}` }))),
|
|
50097
50352
|
...questions ? { questions } : {},
|
|
50098
50353
|
...options["dry-run"] ? { dryRun: true } : {}
|
|
50099
50354
|
};
|
|
50100
50355
|
if (options["dry-run"]) return client.request("/api/v1/frame-checks", { method: "POST", body, timeout: 12e4 });
|
|
50101
50356
|
const result = await client.request("/api/v1/frame-checks", { method: "POST", body, timeout: 12e4 });
|
|
50102
50357
|
const fileAt = (time3) => frames.find((frame) => Math.abs(frame.time - time3) < 1e-3)?.file.slice(context.projectRoot.length + 1);
|
|
50103
|
-
const saved =
|
|
50358
|
+
const saved = join18(context.projectRoot, "production/review/check.json");
|
|
50104
50359
|
await writeFile14(saved, `${JSON.stringify({ ...result, frames: result.frames.map((frame) => ({ file: fileAt(frame.time), ...frame })) }, null, 2)}
|
|
50105
50360
|
`);
|
|
50106
50361
|
return {
|
|
@@ -50114,8 +50369,8 @@ async function reviewCheck(client, options) {
|
|
|
50114
50369
|
|
|
50115
50370
|
// cli/src/reference.ts
|
|
50116
50371
|
import { openAsBlob } from "node:fs";
|
|
50117
|
-
import { mkdir as
|
|
50118
|
-
import { basename as basename7, dirname as
|
|
50372
|
+
import { mkdir as mkdir15, stat as stat11, writeFile as writeFile15 } from "node:fs/promises";
|
|
50373
|
+
import { basename as basename7, dirname as dirname14, extname as extname3, join as join19, relative as relative3, resolve as resolve16 } from "node:path";
|
|
50119
50374
|
|
|
50120
50375
|
// shared/video-analysis.ts
|
|
50121
50376
|
var VIDEO_ANALYSIS_MAX_BYTES = 100 * 1024 * 1024;
|
|
@@ -50146,11 +50401,11 @@ var TYPES = { ".mp4": "video/mp4", ".m4v": "video/mp4", ".mov": "video/quicktime
|
|
|
50146
50401
|
var POLL_MS = 1e4;
|
|
50147
50402
|
var WAIT_LIMIT_MS = 70 * 6e4;
|
|
50148
50403
|
async function briefFile(options, name2) {
|
|
50149
|
-
if (options.out) return
|
|
50404
|
+
if (options.out) return resolve16(options.out);
|
|
50150
50405
|
const slug2 = name2.replace(/\.[a-z0-9]{2,4}$/i, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60) || "reference";
|
|
50151
50406
|
const project = await localProject(options.directory ?? ".", options.animation).catch(() => null);
|
|
50152
|
-
const film = project && await
|
|
50153
|
-
return film ?
|
|
50407
|
+
const film = project && await stat11(join19(project.projectRoot, "animaguru.project.json")).then(() => true, () => false);
|
|
50408
|
+
return film ? join19(project.projectRoot, "production/references", `${slug2}.json`) : resolve16(options.directory ?? ".", `${slug2}.analysis.json`);
|
|
50154
50409
|
}
|
|
50155
50410
|
var pause = (ms, signal) => new Promise((done, fail) => {
|
|
50156
50411
|
signal?.throwIfAborted();
|
|
@@ -50189,7 +50444,7 @@ async function report(analysis, options) {
|
|
|
50189
50444
|
if (analysis.status === "failed") throw new Error(analysis.error ?? "The analysis failed.");
|
|
50190
50445
|
if (analysis.status !== "completed") return { id: analysis.id, status: analysis.status, next: `animaguru reference get ${analysis.id} --wait` };
|
|
50191
50446
|
const file2 = await briefFile(options, sourceName(analysis));
|
|
50192
|
-
await
|
|
50447
|
+
await mkdir15(dirname14(file2), { recursive: true });
|
|
50193
50448
|
await writeFile15(file2, `${JSON.stringify(analysis, null, 2)}
|
|
50194
50449
|
`);
|
|
50195
50450
|
const brief = analysis.result?.brief;
|
|
@@ -50214,8 +50469,8 @@ async function referenceAnalyze(client, options) {
|
|
|
50214
50469
|
if (!options.video.startsWith("https://")) throw new Error("Use an HTTPS link to the video file.");
|
|
50215
50470
|
started = await client.request("/api/v1/video-analyses", { method: "POST", body: { ...settings2, url: options.video, ...dryRun ? { dryRun: true } : {} }, timeout: 12e4 });
|
|
50216
50471
|
} else {
|
|
50217
|
-
const file2 =
|
|
50218
|
-
const info = await
|
|
50472
|
+
const file2 = resolve16(options.video);
|
|
50473
|
+
const info = await stat11(file2).catch(() => null);
|
|
50219
50474
|
if (!info?.isFile()) throw new Error(`No video file at ${options.video}. Give a file path, or an HTTPS link to the video file itself.`);
|
|
50220
50475
|
const type = TYPES[extname3(file2).toLowerCase()];
|
|
50221
50476
|
if (!type) throw new Error("Analyse an MP4, MOV or WebM video.");
|
|
@@ -50237,8 +50492,8 @@ async function referenceGet(client, id2, options) {
|
|
|
50237
50492
|
|
|
50238
50493
|
// cli/src/curl.ts
|
|
50239
50494
|
import { createWriteStream as createWriteStream2, openAsBlob as openAsBlob2 } from "node:fs";
|
|
50240
|
-
import { readFile as
|
|
50241
|
-
import { extname as extname4, resolve as
|
|
50495
|
+
import { readFile as readFile19, unlink as unlink3 } from "node:fs/promises";
|
|
50496
|
+
import { extname as extname4, resolve as resolve17 } from "node:path";
|
|
50242
50497
|
import { Readable as Readable2 } from "node:stream";
|
|
50243
50498
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
50244
50499
|
function curlUrl(server, target2) {
|
|
@@ -50278,7 +50533,7 @@ var readStdin = async () => {
|
|
|
50278
50533
|
};
|
|
50279
50534
|
async function bodyValue(value, io) {
|
|
50280
50535
|
if (value === "@-") return (io.stdin ?? readStdin)();
|
|
50281
|
-
return value.startsWith("@") ?
|
|
50536
|
+
return value.startsWith("@") ? readFile19(resolve17(value.slice(1))) : value;
|
|
50282
50537
|
}
|
|
50283
50538
|
var parsesAsJson = (body) => {
|
|
50284
50539
|
try {
|
|
@@ -50294,7 +50549,7 @@ async function curl(options, io) {
|
|
|
50294
50549
|
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.");
|
|
50295
50550
|
let body;
|
|
50296
50551
|
if (options.uploadFile !== void 0) {
|
|
50297
|
-
const file2 =
|
|
50552
|
+
const file2 = resolve17(options.uploadFile);
|
|
50298
50553
|
body = await openAsBlob2(file2);
|
|
50299
50554
|
if (!headers.has("content-type")) headers.set("Content-Type", UPLOAD_TYPES[extname4(file2).toLowerCase()] ?? "application/octet-stream");
|
|
50300
50555
|
} else if (options.json !== void 0) {
|
|
@@ -50314,7 +50569,7 @@ async function curl(options, io) {
|
|
|
50314
50569
|
const type = response.headers.get("content-type") ?? "";
|
|
50315
50570
|
const failed = options.fail && response.status >= 400;
|
|
50316
50571
|
if (options.output !== void 0 && !failed) {
|
|
50317
|
-
const file2 =
|
|
50572
|
+
const file2 = resolve17(options.output);
|
|
50318
50573
|
let bytes = 0;
|
|
50319
50574
|
try {
|
|
50320
50575
|
await pipeline2(
|
|
@@ -50344,7 +50599,7 @@ async function curl(options, io) {
|
|
|
50344
50599
|
}
|
|
50345
50600
|
|
|
50346
50601
|
// cli/src/commands.ts
|
|
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)];
|
|
50602
|
+
var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id), ...VECTOR_MODELS.map((m) => m.id), ...MODEL_GENERATOR_IDS];
|
|
50348
50603
|
var assetAuthorizationFlags = [
|
|
50349
50604
|
{ name: "yes", type: "boolean", description: "Authorize spending credits" },
|
|
50350
50605
|
{ name: "dry-run", type: "boolean", description: "Validate and estimate locally without submitting a paid job" }
|
|
@@ -50361,9 +50616,10 @@ var catalogSections = {
|
|
|
50361
50616
|
music: ["assetTypes", "musicModels"],
|
|
50362
50617
|
speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices"],
|
|
50363
50618
|
sfx: ["assetTypes", "sfxModels"],
|
|
50619
|
+
model: ["assetTypes", "modelGenerators", "modelAnimations"],
|
|
50364
50620
|
avatars: ["avatarTypes", "avatarLookTypes"]
|
|
50365
50621
|
};
|
|
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 });
|
|
50622
|
+
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), modelGenerators: MODEL_GENERATORS.map(({ id: id2, label: label3, faces }) => ({ id: id2, label: label3, faces })), modelAnimations: MODEL_ANIMATIONS, vectorModels: VECTOR_MODELS.map((m) => m.id), vectorOptions: { workflows: VECTOR_WORKFLOWS, qualities: VECTOR_QUALITIES, aspectRatios: VECTOR_ASPECT_RATIOS, shapes: VECTOR_SHAPES, maxReferences: MAX_VECTOR_REFERENCES }, elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
|
|
50367
50623
|
var modelFlags = [
|
|
50368
50624
|
{ name: "video-model", type: "string", choices: SPRITE_VIDEO_MODEL_IDS, description: "Video model override for this operation" }
|
|
50369
50625
|
];
|
|
@@ -50394,12 +50650,12 @@ var workspaceQuery = async (client) => {
|
|
|
50394
50650
|
async function openBrowser(url3) {
|
|
50395
50651
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32" : "xdg-open";
|
|
50396
50652
|
const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url3] : [url3];
|
|
50397
|
-
await new Promise((
|
|
50653
|
+
await new Promise((resolve19) => {
|
|
50398
50654
|
const child = spawn3(command, args, { stdio: "ignore", detached: true });
|
|
50399
|
-
child.once("error", () =>
|
|
50655
|
+
child.once("error", () => resolve19());
|
|
50400
50656
|
child.once("spawn", () => {
|
|
50401
50657
|
child.unref();
|
|
50402
|
-
|
|
50658
|
+
resolve19();
|
|
50403
50659
|
});
|
|
50404
50660
|
});
|
|
50405
50661
|
}
|
|
@@ -50425,7 +50681,10 @@ function createCli() {
|
|
|
50425
50681
|
{ name: "thumbnail", type: "string", default: "auto", description: "JPEG or PNG thumbnail up to 2 MiB to set after the upload; auto uses FILM.jpg beside FILM.mp4; none skips" },
|
|
50426
50682
|
{ name: "yes", type: "boolean", description: "Authorize sending this video, its subtitles and thumbnail to the selected channel and privacy; confirm upload rights" },
|
|
50427
50683
|
{ name: "dry-run", type: "boolean", description: "Inspect MP4 and metadata locally without Google authorization or network calls" }
|
|
50428
|
-
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await uploadYouTube({ ...flags, directory: args.directory, log: stderr, signal }))))).command("uploads", (uploads) => uploads.add(defineCommand("list", { description: "List local upload receipts without tokens or session URLs" }, (command) => command.action(async ({ stdout }) => out(stdout, await listYouTubeUploads())))).add(defineCommand("resume", { description: "Resume the same local MP4 and Google upload session after an interruption" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Upload ID returned by youtube uploads list" }).flags({ name: "yes", type: "boolean", description: "Authorize resuming the saved upload and visibility" }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await resumeYouTube(args.id, { ...flags, log: stderr, signal }))))))).add(defineCommand("init", { description: "Install or refresh the AnimaGuru agent skill in the current folder" }, (command) => command.action(async ({ stdout }) => out(stdout, await initializeSkill())))).
|
|
50684
|
+
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await uploadYouTube({ ...flags, directory: args.directory, log: stderr, signal }))))).command("uploads", (uploads) => uploads.add(defineCommand("list", { description: "List local upload receipts without tokens or session URLs" }, (command) => command.action(async ({ stdout }) => out(stdout, await listYouTubeUploads())))).add(defineCommand("resume", { description: "Resume the same local MP4 and Google upload session after an interruption" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Upload ID returned by youtube uploads list" }).flags({ name: "yes", type: "boolean", description: "Authorize resuming the saved upload and visibility" }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await resumeYouTube(args.id, { ...flags, log: stderr, signal }))))))).add(defineCommand("init", { description: "Install or refresh the core AnimaGuru agent skill in the current folder; skills install adds every skill" }, (command) => command.action(async ({ stdout }) => out(stdout, await initializeSkill())))).command("skills", (skills) => skills.add(defineCommand("install", { description: "Install the latest AnimaGuru and PixiJS agent skills into a folder for Claude Code (.claude/skills) and Codex (.agents/skills), with npx skills; npx skills update refreshes them" }, (command) => command.flags(
|
|
50685
|
+
{ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin whose skills to install" },
|
|
50686
|
+
{ name: "dir", type: "string", default: ".", description: "Folder to install into (created if missing)" }
|
|
50687
|
+
).action(async ({ flags, stdout, stderr, signal }) => out(stdout, await installSkills({ url: flags.url, dir: flags.dir, signal, log: stderr })))))).add(defineCommand("templates", { description: "List video categories and available starter templates" }, (command) => command.action(({ stdout }) => out(stdout, listTemplates())))).command("review", (review) => review.add(defineCommand("check", { description: "Check a film's review frames for visual faults with AnimaGuru's frame checker (Clef-omni): empty frames, cut-off or overlapping text, broken letters, hard-to-read text and a polish score. Run npm run review first; open the flagged frames first. Charges a fraction of a credit per frame" }, (command) => command.args({ name: "directory", type: "string", default: ".", description: "Video workspace or animation folder" }).flags(
|
|
50429
50688
|
{ name: "animation", type: "string", description: "Animation in a multi-animation workspace" },
|
|
50430
50689
|
{ name: "source", type: "string", choices: ["review", "frames"], default: "review", description: "review: npm run review's five frames; frames: the full-size frames of npm run frames -- --full" },
|
|
50431
50690
|
{ name: "context", type: "string", description: "What the film should show, added to its title, format and brief" },
|
|
@@ -50471,6 +50730,10 @@ function createCli() {
|
|
|
50471
50730
|
{ name: "poster", type: "string", description: "PNG, JPEG or WebP cover image" },
|
|
50472
50731
|
{ name: "subtitles", type: "string", default: "auto", description: "MP4 subtitle file (.vtt or .srt) the player shows over the picture; auto uses FILM.vtt or FILM.srt beside FILM.mp4; none skips" },
|
|
50473
50732
|
{ name: "subtitle-language", type: "string", description: "Subtitle language code such as en or tr; defaults to the MP4's export receipt or film.config.json" },
|
|
50733
|
+
{ name: "showcase", type: "string", choices: [...SHOWCASE_SECTORS], description: "Admins: add the video to the showcase under this sector; it shows on lead pages once public and approved" },
|
|
50734
|
+
{ name: "showcase-tags", type: "string", description: `Admins: what the film is for, comma-separated: ${SHOWCASE_TAGS.join(", ")}` },
|
|
50735
|
+
{ name: "showcase-language", type: "string", choices: ["en", "tr", "sv", "none"], description: "Admins: the language the film speaks or shows; none for music and pictures only (default)" },
|
|
50736
|
+
{ name: "showcase-position", type: "number", description: "Admins: order in the showcase, lower first (default 0)" },
|
|
50474
50737
|
{ name: "yes", type: "boolean", description: "Authorize upload and chosen sharing" },
|
|
50475
50738
|
{ name: "dry-run", type: "boolean", description: "Inspect locally without uploading" }
|
|
50476
50739
|
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await submitVideo(new Client(flags.url, signal), { ...flags, directory: args.directory, log: stderr, signal }))))).command("videos", (videos) => videos.add(defineCommand("list", { description: "List a video library (the selected workspace's by default), privately shared videos, or the public gallery" }, (command) => command.flags(
|
|
@@ -50592,7 +50855,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50592
50855
|
})))).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 }) => {
|
|
50593
50856
|
const client = new Client(flags.url, signal);
|
|
50594
50857
|
out(stdout, await client.request(`/api/v1/credits${await workspaceQuery(client)}`));
|
|
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 }) => {
|
|
50858
|
+
}))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings, speech voices and avatar types" }, (command) => command.flags({ name: "type", type: "string", choices: Object.keys(catalogSections), description: "Only one part: sprites, image, vector, video, music, speech, sfx, model or avatars" }).action(({ flags, stdout }) => {
|
|
50596
50859
|
const full = catalog();
|
|
50597
50860
|
const section = flags.type;
|
|
50598
50861
|
out(stdout, section ? Object.fromEntries(catalogSections[section].map((key) => [key, full[key]])) : full);
|
|
@@ -50659,7 +50922,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50659
50922
|
).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 }) => {
|
|
50660
50923
|
if (!flags.yes) throw new Error("Pass --yes to delete this project.");
|
|
50661
50924
|
out(stdout, await new Client(flags.url, signal).request(`/api/v1/projects/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
|
|
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
|
|
50925
|
+
})))).command("assets", (assets) => assets.add(defineCommand("list", { description: "List saved assets, their blob hashes, and configured generation models" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/assets`))))).add(defineCommand("generate", { description: "Generate an image, vector (SVG), video, music, speech, sound-effect or 3D model asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
|
50663
50926
|
{ name: "type", type: "string", required: true, choices: ASSET_TYPES },
|
|
50664
50927
|
{ name: "name", type: "string", required: true },
|
|
50665
50928
|
{ 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" },
|
|
@@ -50669,7 +50932,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50669
50932
|
{ 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)" },
|
|
50670
50933
|
{ 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" },
|
|
50671
50934
|
{ 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" },
|
|
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" },
|
|
50935
|
+
{ name: "reference", type: "string", description: "Video: starting image blob SHA from this project's assets or sprites; the speaking face for lip-sync, the image the camera moves around for camera-controls. Model: the image or sprite art to build it from (image-to-3D); without one the prompt describes it" },
|
|
50673
50936
|
{ name: "end-reference", type: "string", description: "Video: ending image blob SHA; models with endFrameOnly accept it without --reference" },
|
|
50674
50937
|
{ name: "middle-reference", type: "string", description: "Reference-to-video: image blob SHA reached at --middle-seconds; needs --reference and --end-reference, 480p or 768p" },
|
|
50675
50938
|
{ name: "middle-seconds", type: "number", description: "Reference-to-video: when the middle image is reached, in seconds" },
|
|
@@ -50698,6 +50961,12 @@ Confirm code: ${device.user_code}`);
|
|
|
50698
50961
|
{ name: "voice", type: "string", description: "Gemini voice name or ElevenLabs voice ID (defaults: Kore / George)" },
|
|
50699
50962
|
{ name: "delivery", type: "string", description: "Gemini speech delivery instructions; ElevenLabs uses audio tags in the transcript" },
|
|
50700
50963
|
{ name: "loop", type: "boolean", description: "SFX: create a seamless loop" },
|
|
50964
|
+
{ name: "texture", type: "boolean", description: "Model: textured (default on); --no-texture makes a plain white model" },
|
|
50965
|
+
{ name: "pbr", type: "boolean", description: "Model: metallic, roughness and normal maps with the texture (default on); --no-pbr leaves them out" },
|
|
50966
|
+
{ name: "faces", type: "number", description: "Model: target face count; Tripo H3.1 1,000\u20132,000,000, Hunyuan3D 40,000\u20131,500,000 (charged extra). Rigged models take at most 300,000" },
|
|
50967
|
+
{ name: "rig", type: "boolean", description: "Model: auto-rig a humanoid character standing in a T- or A-pose, with animation clips" },
|
|
50968
|
+
{ name: "animations", type: "string", description: "Model with --rig: up to 10 comma-separated clips, by name (catalog --type model) or Meshy library number 0\u2013696; default idle,walk" },
|
|
50969
|
+
{ name: "height", type: "number", description: "Model with --rig: the character's height in metres (default 1.7)" },
|
|
50701
50970
|
{ name: "prompt-influence", type: "number", description: "SFX: prompt adherence, 0\u20131 (default 0.3)" },
|
|
50702
50971
|
{ 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
50972
|
{ name: "shapes", type: "string", choices: VECTOR_SHAPES, description: "Vector image-to-vector (10 credits): detailed (default) keeps fine detail, simple uses fewer, simpler shapes" },
|
|
@@ -50746,7 +51015,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50746
51015
|
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" }));
|
|
50747
51016
|
})))).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 }) => {
|
|
50748
51017
|
if (!flags.yes) throw new Error("Pass --yes to authorize spending credits.");
|
|
50749
|
-
const body = spriteJobBody.parse({ ...JSON.parse(await
|
|
51018
|
+
const body = spriteJobBody.parse({ ...JSON.parse(await readFile20(flags.file, "utf8")), ...selectedModels(flags) });
|
|
50750
51019
|
out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/jobs`, { method: "POST", body }));
|
|
50751
51020
|
}))).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 }) => {
|
|
50752
51021
|
const body = selectedModels(flags);
|
|
@@ -50761,7 +51030,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50761
51030
|
const extension = flags.file.split(".").at(-1)?.toLowerCase();
|
|
50762
51031
|
const type = extension === "png" ? "image/png" : extension === "jpg" || extension === "jpeg" ? "image/jpeg" : extension === "webp" ? "image/webp" : void 0;
|
|
50763
51032
|
if (!type) throw new Error("Use a PNG, JPEG or WebP image.");
|
|
50764
|
-
const bytes = await
|
|
51033
|
+
const bytes = await readFile20(flags.file);
|
|
50765
51034
|
if (bytes.length > 10 * 1024 * 1024) throw new Error("Image must be at most 10 MB.");
|
|
50766
51035
|
const form = new FormData();
|
|
50767
51036
|
form.set("image", new Blob([bytes], { type }), `reference.${extension}`);
|
|
@@ -50777,8 +51046,8 @@ Confirm code: ${device.user_code}`);
|
|
|
50777
51046
|
if (!file2) throw new Error(`No file at ${args.path} in this project. List them with animaguru files list.`);
|
|
50778
51047
|
if (!/^[a-f0-9]{64}$/.test(file2.sha)) throw new Error("Invalid blob hash in manifest.");
|
|
50779
51048
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
50780
|
-
const path =
|
|
50781
|
-
await
|
|
51049
|
+
const path = resolve18(flags.output);
|
|
51050
|
+
await mkdir16(dirname15(path), { recursive: true });
|
|
50782
51051
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
50783
51052
|
await writeFile16(path, bytes, { flag: "wx" });
|
|
50784
51053
|
out(stdout, { path, bytes: bytes.length });
|
|
@@ -50792,7 +51061,7 @@ Confirm code: ${device.user_code}`);
|
|
|
50792
51061
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
50793
51062
|
entries[path2] = new Uint8Array(await response.arrayBuffer());
|
|
50794
51063
|
}
|
|
50795
|
-
const path =
|
|
51064
|
+
const path = resolve18(flags.output);
|
|
50796
51065
|
await writeFile16(path, zipSync(entries, { level: 0 }), { flag: "wx" });
|
|
50797
51066
|
out(stdout, { path, files: manifest.files.length });
|
|
50798
51067
|
})))).extend(version(package_default.version, { format: "plain" })).extend(help()).extend(completion());
|