@docyrus/animaguru 0.18.0 → 0.20.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 +63 -1
- package/dist/animaguru.js +581 -268
- package/package.json +1 -1
- package/skills/animaguru/SKILL.md +16 -0
- package/skills/animaguru/references/sharing.md +4 -1
- package/skills/animaguru-branching-story/SKILL.md +72 -0
- package/skills/animaguru-general-video/SKILL.md +1 -0
- package/skills/animaguru-general-video/references/branching-story.md +13 -0
- package/skills/animaguru-quiz/SKILL.md +80 -0
- package/skills/animaguru-video/SKILL.md +16 -2
- package/skills/animaguru-video/references/short-form-ad.md +1 -0
- package/templates/video/AGENTS.md +2 -0
- package/templates/video/README.md +8 -0
- package/templates/video/WORKSPACE-AGENTS.md +3 -1
- package/templates/video/index.html +1 -1
- package/templates/video/scripts/build.mjs +4 -1
- package/templates/video/scripts/export-mp4.mjs +5 -0
- package/templates/video/scripts/html-export.mjs +12 -4
- package/templates/video/scripts/project-context.mjs +20 -3
- package/templates/video/scripts/quiz.d.mts +31 -0
- package/templates/video/scripts/quiz.mjs +126 -0
- package/templates/video/scripts/review.mjs +9 -1
- package/templates/video/scripts/story.d.mts +36 -0
- package/templates/video/scripts/story.mjs +139 -0
- package/templates/video/scripts/workspace-plugin.mjs +9 -4
- package/templates/video/shared/locales/en/player.json +30 -1
- package/templates/video/src/kit/index.ts +1 -0
- package/templates/video/src/kit/story.ts +19 -0
- package/templates/video/src/main.ts +6 -1
- package/templates/video/src/player-types.ts +6 -0
- package/templates/video/src/player.ts +232 -21
- package/templates/video/src/quiz.ts +315 -0
- package/templates/video/src/story.ts +112 -0
- package/templates/video/src/style.css +93 -1
package/dist/animaguru.js
CHANGED
|
@@ -2312,8 +2312,8 @@ var require_lib = __commonJS({
|
|
|
2312
2312
|
if (typeof cb !== "function") {
|
|
2313
2313
|
opts = cb;
|
|
2314
2314
|
cb = null;
|
|
2315
|
-
deferred = new this.Promise(function(
|
|
2316
|
-
deferredResolve =
|
|
2315
|
+
deferred = new this.Promise(function(resolve17, reject) {
|
|
2316
|
+
deferredResolve = resolve17;
|
|
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(resolve17, 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
|
+
resolve17(ret);
|
|
2471
2471
|
}
|
|
2472
2472
|
});
|
|
2473
2473
|
} else {
|
|
2474
|
-
|
|
2474
|
+
resolve17(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((resolve17, 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
|
+
resolve17(result);
|
|
6874
6874
|
}
|
|
6875
6875
|
} else {
|
|
6876
|
-
|
|
6876
|
+
resolve17(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
|
+
resolve17(result);
|
|
6885
6885
|
}
|
|
6886
6886
|
});
|
|
6887
6887
|
} else {
|
|
6888
|
-
args.push(
|
|
6888
|
+
args.push(resolve17);
|
|
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 stat11 = normalizeStats(entry);
|
|
8087
|
+
writer.writeUInt32BE(stat11.ctimeSeconds);
|
|
8088
|
+
writer.writeUInt32BE(stat11.ctimeNanoseconds);
|
|
8089
|
+
writer.writeUInt32BE(stat11.mtimeSeconds);
|
|
8090
|
+
writer.writeUInt32BE(stat11.mtimeNanoseconds);
|
|
8091
|
+
writer.writeUInt32BE(stat11.dev);
|
|
8092
|
+
writer.writeUInt32BE(stat11.ino);
|
|
8093
|
+
writer.writeUInt32BE(stat11.mode);
|
|
8094
|
+
writer.writeUInt32BE(stat11.uid);
|
|
8095
|
+
writer.writeUInt32BE(stat11.gid);
|
|
8096
|
+
writer.writeUInt32BE(stat11.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 [stat11, 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, stat11);
|
|
8155
8155
|
}
|
|
8156
8156
|
async function isIndexStale(fs2, filepath, cache) {
|
|
8157
8157
|
const savedStats = cache.stats.get(filepath);
|
|
@@ -8201,14 +8201,14 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8201
8201
|
return result;
|
|
8202
8202
|
}
|
|
8203
8203
|
};
|
|
8204
|
-
function
|
|
8204
|
+
function basename8(path) {
|
|
8205
8205
|
const last = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
8206
8206
|
if (last > -1) {
|
|
8207
8207
|
path = path.slice(last + 1);
|
|
8208
8208
|
}
|
|
8209
8209
|
return path;
|
|
8210
8210
|
}
|
|
8211
|
-
function
|
|
8211
|
+
function dirname15(path) {
|
|
8212
8212
|
const last = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
8213
8213
|
if (last === -1) return ".";
|
|
8214
8214
|
if (last === 0) return "/";
|
|
@@ -8216,17 +8216,17 @@ 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 mkdir16 = function(name2) {
|
|
8220
8220
|
if (!inodes.has(name2)) {
|
|
8221
8221
|
const dir = {
|
|
8222
8222
|
type: "tree",
|
|
8223
8223
|
fullpath: name2,
|
|
8224
|
-
basename:
|
|
8224
|
+
basename: basename8(name2),
|
|
8225
8225
|
metadata: {},
|
|
8226
8226
|
children: []
|
|
8227
8227
|
};
|
|
8228
8228
|
inodes.set(name2, dir);
|
|
8229
|
-
dir.parent =
|
|
8229
|
+
dir.parent = mkdir16(dirname15(name2));
|
|
8230
8230
|
if (dir.parent && dir.parent !== dir) dir.parent.children.push(dir);
|
|
8231
8231
|
}
|
|
8232
8232
|
return inodes.get(name2);
|
|
@@ -8236,10 +8236,10 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
|
|
|
8236
8236
|
const file2 = {
|
|
8237
8237
|
type: "blob",
|
|
8238
8238
|
fullpath: name2,
|
|
8239
|
-
basename:
|
|
8239
|
+
basename: basename8(name2),
|
|
8240
8240
|
metadata,
|
|
8241
8241
|
// This recursively generates any missing parent folders.
|
|
8242
|
-
parent:
|
|
8242
|
+
parent: mkdir16(dirname15(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
|
+
mkdir16(".");
|
|
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 join19(...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(join19(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(join19(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(join19(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(join19(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(join19(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(join19(filepath, entry2.path), entry2);
|
|
11069
11069
|
}
|
|
11070
|
-
return tree.entries().map((entry2) =>
|
|
11070
|
+
return tree.entries().map((entry2) => join19(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(join19(dir, filepath));
|
|
11164
11164
|
if (names === null) return null;
|
|
11165
|
-
return names.map((name2) =>
|
|
11165
|
+
return names.map((name2) => join19(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 stat11 = await fs2.lstat(`${dir}/${entry._fullpath}`);
|
|
11183
|
+
if (!stat11) {
|
|
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 = stat11.isDirectory() ? "tree" : "blob";
|
|
11189
|
+
if (type === "blob" && !stat11.isFile() && !stat11.isSymbolicLink()) {
|
|
11190
11190
|
type = "special";
|
|
11191
11191
|
}
|
|
11192
11192
|
entry._type = type;
|
|
11193
|
-
|
|
11194
|
-
entry._mode =
|
|
11195
|
-
if (
|
|
11196
|
-
|
|
11193
|
+
stat11 = normalizeStats(stat11);
|
|
11194
|
+
entry._mode = stat11.mode;
|
|
11195
|
+
if (stat11.size === -1 && entry._actualSize) {
|
|
11196
|
+
stat11.size = entry._actualSize;
|
|
11197
11197
|
}
|
|
11198
|
-
entry._stat =
|
|
11198
|
+
entry._stat = stat11;
|
|
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(mkdir16, filepath, retries = 10) {
|
|
11387
11387
|
try {
|
|
11388
|
-
await
|
|
11388
|
+
await mkdir16(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 = dirname15(filepath);
|
|
11394
11394
|
if (parent === "." || parent === "/" || parent === filepath) throw err2;
|
|
11395
|
-
await mkdirp(
|
|
11395
|
+
await mkdirp(mkdir16, parent, retries);
|
|
11396
11396
|
for (let attempt = 0; ; attempt++) {
|
|
11397
11397
|
try {
|
|
11398
|
-
await
|
|
11398
|
+
await mkdir16(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((resolve17) => setTimeout(resolve17, 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 = join19(filepath, entry);
|
|
11419
|
+
return fs2.lstat(subpath).then((stat11) => {
|
|
11420
|
+
if (!stat11) return;
|
|
11421
|
+
return stat11.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(dirname15(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 = join19(dirname15(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 = join19(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 =
|
|
11807
|
-
if (
|
|
11806
|
+
static async isIgnored({ fs: fs2, dir, gitdir = join19(dir, ".git"), filepath }) {
|
|
11807
|
+
if (basename8(filepath) === ".git") return true;
|
|
11808
11808
|
if (filepath === ".") return false;
|
|
11809
11809
|
let excludes = "";
|
|
11810
|
-
const excludesFile =
|
|
11810
|
+
const excludesFile = join19(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: join19(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: join19(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 = dirname15(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 = join19(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(join19(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(join19(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: [join19(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: [join19(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(join19(dir, currentFilepath)).then(posixifyPathBuffer) : await fs2.read(join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(dir, ".git"),
|
|
13410
13410
|
index: index3,
|
|
13411
13411
|
ourOid,
|
|
13412
13412
|
baseOid,
|
|
@@ -13432,7 +13432,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
13432
13432
|
gitdir,
|
|
13433
13433
|
trees: [ourTree, baseTree, theirTree],
|
|
13434
13434
|
map: async function(filepath, [ours, base2, theirs]) {
|
|
13435
|
-
const path =
|
|
13435
|
+
const path = basename8(filepath);
|
|
13436
13436
|
const ourChange = await modified(ours, base2);
|
|
13437
13437
|
const theirChange = await modified(theirs, base2);
|
|
13438
13438
|
switch (`${ourChange}-${theirChange}`) {
|
|
@@ -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 = join19(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(join19(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 = join19(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 = join19(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 = join19(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 = join19(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(join19(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 resolve17 = this._waiting;
|
|
14620
14620
|
this._waiting = null;
|
|
14621
|
-
|
|
14621
|
+
resolve17({ 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 resolve17 = this._waiting;
|
|
14630
14630
|
this._waiting = null;
|
|
14631
|
-
|
|
14631
|
+
resolve17({ 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((resolve17) => {
|
|
14651
|
+
this._waiting = resolve17;
|
|
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((resolve17, 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) : resolve17({ 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) : resolve17({ shallows, unshallows, acks, nak, packfile, progress });
|
|
14838
14838
|
}
|
|
14839
14839
|
});
|
|
14840
14840
|
});
|
|
@@ -14901,7 +14901,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14901
14901
|
depth = null,
|
|
14902
14902
|
since = null,
|
|
14903
14903
|
exclude = [],
|
|
14904
|
-
relative:
|
|
14904
|
+
relative: relative4 = false,
|
|
14905
14905
|
tags = false,
|
|
14906
14906
|
singleBranch = false,
|
|
14907
14907
|
headers = {},
|
|
@@ -14949,7 +14949,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14949
14949
|
if (exclude.length > 0 && !remoteHTTP.capabilities.has("deepen-not")) {
|
|
14950
14950
|
throw new RemoteCapabilityError("deepen-not", "exclude");
|
|
14951
14951
|
}
|
|
14952
|
-
if (
|
|
14952
|
+
if (relative4 === true && !remoteHTTP.capabilities.has("deepen-relative")) {
|
|
14953
14953
|
throw new RemoteCapabilityError("deepen-relative", "relative");
|
|
14954
14954
|
}
|
|
14955
14955
|
const { oid, fullref } = GitRefManager.resolveAgainstMap({
|
|
@@ -14977,7 +14977,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
14977
14977
|
`agent=${pkg.agent}`
|
|
14978
14978
|
]
|
|
14979
14979
|
);
|
|
14980
|
-
if (
|
|
14980
|
+
if (relative4) capabilities.push("deepen-relative");
|
|
14981
14981
|
const wants = singleBranch ? [oid] : remoteRefs.values();
|
|
14982
14982
|
const haveRefs = singleBranch ? [ref] : await GitRefManager.listRefs({
|
|
14983
14983
|
fs: fs2,
|
|
@@ -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 = join19(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 : join19(dir, ".git"),
|
|
15155
15155
|
defaultBranch = "master"
|
|
15156
15156
|
}) {
|
|
15157
15157
|
if (await fs2.exists(gitdir + "/config")) return;
|
|
@@ -15197,7 +15197,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15197
15197
|
depth,
|
|
15198
15198
|
since,
|
|
15199
15199
|
exclude,
|
|
15200
|
-
relative:
|
|
15200
|
+
relative: relative4,
|
|
15201
15201
|
singleBranch,
|
|
15202
15202
|
noCheckout,
|
|
15203
15203
|
noTags,
|
|
@@ -15229,7 +15229,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15229
15229
|
depth,
|
|
15230
15230
|
since,
|
|
15231
15231
|
exclude,
|
|
15232
|
-
relative:
|
|
15232
|
+
relative: relative4,
|
|
15233
15233
|
singleBranch,
|
|
15234
15234
|
headers,
|
|
15235
15235
|
tags: !noTags
|
|
@@ -15265,7 +15265,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15265
15265
|
onAuthFailure,
|
|
15266
15266
|
onPostCheckout,
|
|
15267
15267
|
dir,
|
|
15268
|
-
gitdir =
|
|
15268
|
+
gitdir = join19(dir, ".git"),
|
|
15269
15269
|
url: url3,
|
|
15270
15270
|
corsProxy = void 0,
|
|
15271
15271
|
ref = void 0,
|
|
@@ -15273,7 +15273,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15273
15273
|
depth = void 0,
|
|
15274
15274
|
since = void 0,
|
|
15275
15275
|
exclude = [],
|
|
15276
|
-
relative:
|
|
15276
|
+
relative: relative4 = false,
|
|
15277
15277
|
singleBranch = false,
|
|
15278
15278
|
noCheckout = false,
|
|
15279
15279
|
noTags = false,
|
|
@@ -15311,7 +15311,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15311
15311
|
depth,
|
|
15312
15312
|
since,
|
|
15313
15313
|
exclude,
|
|
15314
|
-
relative:
|
|
15314
|
+
relative: relative4,
|
|
15315
15315
|
singleBranch,
|
|
15316
15316
|
noCheckout,
|
|
15317
15317
|
noTags,
|
|
@@ -15328,7 +15328,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15328
15328
|
fs: _fs,
|
|
15329
15329
|
onSign,
|
|
15330
15330
|
dir,
|
|
15331
|
-
gitdir =
|
|
15331
|
+
gitdir = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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(join19(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 = join19(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 = join19(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 = join19(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 = join19(dir, ".git"),
|
|
15924
15924
|
ref,
|
|
15925
15925
|
remote,
|
|
15926
15926
|
remoteRef,
|
|
@@ -15929,7 +15929,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15929
15929
|
depth = null,
|
|
15930
15930
|
since = null,
|
|
15931
15931
|
exclude = [],
|
|
15932
|
-
relative:
|
|
15932
|
+
relative: relative4 = false,
|
|
15933
15933
|
tags = false,
|
|
15934
15934
|
singleBranch = false,
|
|
15935
15935
|
headers = {},
|
|
@@ -15961,7 +15961,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15961
15961
|
depth,
|
|
15962
15962
|
since,
|
|
15963
15963
|
exclude,
|
|
15964
|
-
relative:
|
|
15964
|
+
relative: relative4,
|
|
15965
15965
|
tags,
|
|
15966
15966
|
singleBranch,
|
|
15967
15967
|
headers,
|
|
@@ -15976,7 +15976,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15976
15976
|
async function findMergeBase({
|
|
15977
15977
|
fs: fs2,
|
|
15978
15978
|
dir,
|
|
15979
|
-
gitdir =
|
|
15979
|
+
gitdir = join19(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(join19(filepath, ".git"))) {
|
|
16002
16002
|
return filepath;
|
|
16003
16003
|
} else {
|
|
16004
|
-
const parent =
|
|
16004
|
+
const parent = dirname15(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 = join19(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 = join19(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 = join19(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 = join19(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 : join19(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 = join19(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 = join19(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 = join19(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: join19(prefix, entry.path)
|
|
16468
16468
|
});
|
|
16469
16469
|
} else {
|
|
16470
|
-
filenames.push(
|
|
16470
|
+
filenames.push(join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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: join19(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 = join19(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 = join19(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 = join19(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(join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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(join19(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(join19(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 = join19(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 = join19(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 = join19(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 join19(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 join19(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 = join19(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) => join19(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 = join19(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(join19(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(join19(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 dirname16 = path.shift();
|
|
18700
18700
|
for (const entry of tree) {
|
|
18701
|
-
if (entry.path ===
|
|
18701
|
+
if (entry.path === dirname16) {
|
|
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 = join19(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 = join19(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 = join19(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(join19(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(join19(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(join19(dir, filepath)) : await fs2.read(join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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 = join19(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.20.0",
|
|
19765
19765
|
description: "Agent-friendly AnimaGuru CLI built with CrustJS",
|
|
19766
19766
|
type: "module",
|
|
19767
19767
|
bin: {
|
|
@@ -24295,8 +24295,8 @@ var version = defineExtension(VERSION).factory((extension, value, options = {})
|
|
|
24295
24295
|
|
|
24296
24296
|
// cli/src/commands.ts
|
|
24297
24297
|
import { spawn as spawn3 } from "node:child_process";
|
|
24298
|
-
import { mkdir as
|
|
24299
|
-
import { dirname as
|
|
24298
|
+
import { mkdir as mkdir15, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
|
|
24299
|
+
import { dirname as dirname14, resolve as resolve16 } from "node:path";
|
|
24300
24300
|
import { setTimeout as delay6 } from "node:timers/promises";
|
|
24301
24301
|
|
|
24302
24302
|
// node_modules/fflate/esm/index.mjs
|
|
@@ -30496,7 +30496,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
30496
30496
|
var NONE = 0;
|
|
30497
30497
|
var ASSUMED = 1;
|
|
30498
30498
|
var PROVEN = 2;
|
|
30499
|
-
function isRecursive(inst, stack,
|
|
30499
|
+
function isRecursive(inst, stack, resolve17) {
|
|
30500
30500
|
const cached2 = recursive.get(inst);
|
|
30501
30501
|
if (cached2 !== void 0)
|
|
30502
30502
|
return cached2 ? PROVEN : NONE;
|
|
@@ -30506,7 +30506,7 @@ function isRecursive(inst, stack, resolve16) {
|
|
|
30506
30506
|
let result = NONE;
|
|
30507
30507
|
const check2 = (child) => {
|
|
30508
30508
|
if (result !== PROVEN && child?._zod) {
|
|
30509
|
-
const answer = isRecursive(child, stack,
|
|
30509
|
+
const answer = isRecursive(child, stack, resolve17);
|
|
30510
30510
|
if (answer > result)
|
|
30511
30511
|
result = answer;
|
|
30512
30512
|
}
|
|
@@ -30517,7 +30517,7 @@ function isRecursive(inst, stack, resolve16) {
|
|
|
30517
30517
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
30518
30518
|
if (spread && !desc.enumerable)
|
|
30519
30519
|
continue;
|
|
30520
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
30520
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve17) : NONE;
|
|
30521
30521
|
if (child > answer)
|
|
30522
30522
|
answer = child;
|
|
30523
30523
|
}
|
|
@@ -30581,7 +30581,7 @@ function isRecursive(inst, stack, resolve16) {
|
|
|
30581
30581
|
break;
|
|
30582
30582
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
30583
30583
|
case "lazy": {
|
|
30584
|
-
const inner = def._cachedInner ?? (
|
|
30584
|
+
const inner = def._cachedInner ?? (resolve17 ? inst._zod.innerType : void 0);
|
|
30585
30585
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
30586
30586
|
break;
|
|
30587
30587
|
}
|
|
@@ -46078,6 +46078,10 @@ var animation_styles_default = {
|
|
|
46078
46078
|
"visual-essay": {
|
|
46079
46079
|
name: "Visual Essay & Podcast",
|
|
46080
46080
|
description: "Add accurate graphics and chapters to source text or recorded speech."
|
|
46081
|
+
},
|
|
46082
|
+
"branching-story": {
|
|
46083
|
+
name: "Branching Story",
|
|
46084
|
+
description: "Let viewers choose what happens next and reach one of several endings; plays as an interactive HTML5 film."
|
|
46081
46085
|
}
|
|
46082
46086
|
},
|
|
46083
46087
|
artMotionLink: "Explore Art Motion styles \u2192"
|
|
@@ -46134,7 +46138,8 @@ var VIDEO_WORKFLOW_IDS = [
|
|
|
46134
46138
|
"music-lyrics",
|
|
46135
46139
|
"titles-event",
|
|
46136
46140
|
"ambient-loop",
|
|
46137
|
-
"visual-essay"
|
|
46141
|
+
"visual-essay",
|
|
46142
|
+
"branching-story"
|
|
46138
46143
|
];
|
|
46139
46144
|
var VIDEO_WORKFLOWS2 = VIDEO_WORKFLOW_IDS.map((id2, index2) => ({
|
|
46140
46145
|
id: id2,
|
|
@@ -46200,6 +46205,37 @@ async function installDependencies(directory, options) {
|
|
|
46200
46205
|
child.once("close", (code) => code === 0 ? resolveInstall() : reject(new Error(`npm install exited with code ${code}.`)));
|
|
46201
46206
|
});
|
|
46202
46207
|
}
|
|
46208
|
+
var STARTER_STORY = {
|
|
46209
|
+
version: 1,
|
|
46210
|
+
start: "opening",
|
|
46211
|
+
segments: [
|
|
46212
|
+
{
|
|
46213
|
+
id: "opening",
|
|
46214
|
+
label: "The spark",
|
|
46215
|
+
start: 0,
|
|
46216
|
+
end: 8,
|
|
46217
|
+
prompt: "Where should the story go?",
|
|
46218
|
+
choiceAt: 5,
|
|
46219
|
+
choices: [{ label: "Show the wonder", to: "wonder" }, { label: "Make the invitation", to: "invitation" }]
|
|
46220
|
+
},
|
|
46221
|
+
{ id: "wonder", label: "The possibility", start: 8, end: 16, ending: "A world worth exploring" },
|
|
46222
|
+
{ id: "invitation", label: "The invitation", start: 16, end: 24, ending: "Your next story starts here" }
|
|
46223
|
+
]
|
|
46224
|
+
};
|
|
46225
|
+
var writeStarterStory = (directory) => writeFile6(join6(directory, "story.json"), JSON.stringify(STARTER_STORY, null, 2) + "\n", { flag: "wx" });
|
|
46226
|
+
function starterQuiz(story = false) {
|
|
46227
|
+
return {
|
|
46228
|
+
version: 1,
|
|
46229
|
+
checkpoints: [{ id: "spark", at: story ? 4.5 : 7.5, title: "Quick check", questions: [
|
|
46230
|
+
{ prompt: "Where does every great story begin?", options: ["With a big budget", "With a little spark", "With the ending"], answer: 1, explanation: "The opening scene says it: every great story begins with a little spark." }
|
|
46231
|
+
] }],
|
|
46232
|
+
final: { title: "Quiz", pass: 50, questions: [
|
|
46233
|
+
{ prompt: "What does a quiz film do at a checkpoint?", options: ["Skips to the end", "Pauses and asks a question", "Plays faster"], answer: 1, explanation: "A checkpoint pauses the film on its own frame, and the film goes on once the viewer answers." },
|
|
46234
|
+
{ prompt: "Which of these can a question have?", options: ["One right answer", "Several right answers", "A countdown timer"], answer: [0, 1], explanation: "A question has one right answer, or several when it asks to select all that apply. Questions wait for the viewer." }
|
|
46235
|
+
] }
|
|
46236
|
+
};
|
|
46237
|
+
}
|
|
46238
|
+
var writeStarterQuiz = (directory, story = false) => writeFile6(join6(directory, "quiz.json"), JSON.stringify(starterQuiz(story), null, 2) + "\n", { flag: "wx" });
|
|
46203
46239
|
async function createVideoProject(options, installer = installDependencies) {
|
|
46204
46240
|
if (!options.directory.trim()) throw new Error("Choose a new project folder, for example: animaguru create my-video");
|
|
46205
46241
|
const directory = resolve5(options.directory);
|
|
@@ -46223,7 +46259,7 @@ async function createVideoProject(options, installer = installDependencies) {
|
|
|
46223
46259
|
const manifest = JSON.parse(await readFile4(packagePath, "utf8"));
|
|
46224
46260
|
manifest.name = basename2(directory).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 100) || "animaguru-video";
|
|
46225
46261
|
await writeFile6(packagePath, JSON.stringify(manifest, null, 2) + "\n");
|
|
46226
|
-
const skills = [.../* @__PURE__ */ new Set(["animaguru", "animaguru-video", "animaguru-brand-kit", "animaguru-cutcraft", "animaguru-art-motion", ...VIDEO_PURPOSE_SKILLS, ...VIDEO_TEMPLATES.map((template) => template.skill)])];
|
|
46262
|
+
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)])];
|
|
46227
46263
|
const pixiSkillsRoot = join6(packageRoot, "vendor/pixijs-skills/skills");
|
|
46228
46264
|
const pixiSkills = (await readdir2(pixiSkillsRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
46229
46265
|
for (const agent of [".agents", ".claude"]) {
|
|
@@ -46247,6 +46283,8 @@ async function createVideoProject(options, installer = installDependencies) {
|
|
|
46247
46283
|
animaguruProjectId: null
|
|
46248
46284
|
}, null, 2) + "\n");
|
|
46249
46285
|
await writeFile6(join6(directory, "animaguru.templates.json"), JSON.stringify(listTemplates(), null, 2) + "\n");
|
|
46286
|
+
if (options.story) await writeStarterStory(directory);
|
|
46287
|
+
if (options.quiz) await writeStarterQuiz(directory, options.story);
|
|
46250
46288
|
if (options.install !== false) {
|
|
46251
46289
|
options.log?.("Installing PixiJS, Vite, TypeScript, and the MP4 tools\u2026");
|
|
46252
46290
|
try {
|
|
@@ -46333,8 +46371,8 @@ async function createWorkspace(options, installer = installDependencies) {
|
|
|
46333
46371
|
};
|
|
46334
46372
|
}
|
|
46335
46373
|
async function findWorkspace(start = process.cwd()) {
|
|
46336
|
-
const { realpath
|
|
46337
|
-
let directory = await
|
|
46374
|
+
const { realpath } = await import("node:fs/promises");
|
|
46375
|
+
let directory = await realpath(resolve5(start));
|
|
46338
46376
|
while (true) {
|
|
46339
46377
|
try {
|
|
46340
46378
|
const info = JSON.parse(await readFile4(join6(directory, "animaguru.workspace.json"), "utf8"));
|
|
@@ -46369,7 +46407,11 @@ async function createAnimation(options) {
|
|
|
46369
46407
|
await mkdir6(join6(directory, "public/assets"), { recursive: true });
|
|
46370
46408
|
await mkdir6(join6(directory, "production"), { recursive: true });
|
|
46371
46409
|
await writeFile6(join6(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");
|
|
46372
|
-
options.
|
|
46410
|
+
if (options.story) await writeStarterStory(directory);
|
|
46411
|
+
if (options.quiz) await writeStarterQuiz(directory, options.story);
|
|
46412
|
+
const kind = options.story && options.quiz ? "Branching story with a quiz" : options.story ? "Branching story" : options.quiz ? "Quiz film" : "Animation";
|
|
46413
|
+
options.log?.(`${kind} ready: ${directory}. It uses the workspace's branding, player and export tools.`);
|
|
46414
|
+
const skills = [...options.story ? ["animaguru-branching-story"] : [], ...options.quiz ? ["animaguru-quiz"] : []];
|
|
46373
46415
|
return {
|
|
46374
46416
|
type: "animation",
|
|
46375
46417
|
path: directory,
|
|
@@ -46377,7 +46419,9 @@ async function createAnimation(options) {
|
|
|
46377
46419
|
name: options.name,
|
|
46378
46420
|
category: null,
|
|
46379
46421
|
template: null,
|
|
46380
|
-
|
|
46422
|
+
...options.story ? { story: "story.json" } : {},
|
|
46423
|
+
...options.quiz ? { quiz: "quiz.json" } : {},
|
|
46424
|
+
nextSteps: skills.length ? [`Describe the ${options.story ? "story" : "film"} in Codex or Claude Code, working in animations/${options.name}; the agent follows the ${skills.join(" and ")} skill${skills.length > 1 ? "s" : ""} and replaces the starter ${[...options.story ? ["story.json"] : [], ...options.quiz ? ["quiz.json"] : []].join(" and ")}.`, `Run npm run dev to play it; ${options.story ? "a branching story" : "a quiz film"} plays as HTML5 only, delivered with npm run export:html -- --animation ${options.name} or animaguru submit.`] : [`Describe the film in Codex or Claude Code, working in animations/${options.name}.`, `Run npm run dev to preview, or npm run export:html -- --animation ${options.name}.`]
|
|
46381
46425
|
};
|
|
46382
46426
|
}
|
|
46383
46427
|
|
|
@@ -46678,6 +46722,7 @@ import { createHash as createHash4 } from "node:crypto";
|
|
|
46678
46722
|
// shared/videos.ts
|
|
46679
46723
|
var VIDEO_PART_BYTES = 8 * 1024 * 1024;
|
|
46680
46724
|
var VIDEO_MAX_BYTES = { html5: 64 * 1024 * 1024, mp4: 512 * 1024 * 1024 };
|
|
46725
|
+
var VIDEO_LIBRARY_BYTES = { user: 2 * 1024 ** 3, team: 10 * 1024 ** 3 };
|
|
46681
46726
|
var VIDEO_VISIBILITIES = ["private", "public"];
|
|
46682
46727
|
var VIDEO_SHARING_AGREEMENT_VERSION = "2026-10-15-draft-2";
|
|
46683
46728
|
var videoAgreementAcceptance = external_exports.object({
|
|
@@ -46702,9 +46747,10 @@ var videoDetails = external_exports.object({
|
|
|
46702
46747
|
agreement: videoAgreementAcceptance.optional()
|
|
46703
46748
|
}).refine((value) => value.visibility !== "public" || !value.recipients.length, "Public videos do not use a recipient list.");
|
|
46704
46749
|
var videoAnimationName = external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,79}$/, "Use the animation's folder name.");
|
|
46750
|
+
var videoWorkspace = external_exports.union([external_exports.literal("me"), external_exports.string().regex(/^team_[a-f0-9]{32}$/)]);
|
|
46705
46751
|
var videoSubmission = videoDetails.and(external_exports.object({
|
|
46706
46752
|
/** The workspace that keeps the video; a project's video goes to the project's workspace. */
|
|
46707
|
-
workspace:
|
|
46753
|
+
workspace: videoWorkspace.optional(),
|
|
46708
46754
|
project: external_exports.string().regex(/^prj_[A-Za-z0-9]{8,40}$/).optional(),
|
|
46709
46755
|
animation: videoAnimationName.optional(),
|
|
46710
46756
|
format: external_exports.enum(["html5", "mp4"]),
|
|
@@ -46713,6 +46759,7 @@ var videoSubmission = videoDetails.and(external_exports.object({
|
|
|
46713
46759
|
height: external_exports.number().int().min(1).max(4096).default(1080),
|
|
46714
46760
|
duration: external_exports.number().positive().max(7200).optional()
|
|
46715
46761
|
})).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.");
|
|
46762
|
+
var videoMove = external_exports.object({ workspace: videoWorkspace }).strict();
|
|
46716
46763
|
function videoPosterType(bytes) {
|
|
46717
46764
|
if (bytes.length >= 8 && bytes.slice(0, 8).every((b, i2) => b === [137, 80, 78, 71, 13, 10, 26, 10][i2])) return "image/png";
|
|
46718
46765
|
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
@@ -46904,7 +46951,7 @@ async function localProject(directory, selected) {
|
|
|
46904
46951
|
// cli/src/cloud-sync.ts
|
|
46905
46952
|
var import_isomorphic_git = __toESM(require_isomorphic_git(), 1);
|
|
46906
46953
|
import * as fs from "node:fs";
|
|
46907
|
-
import { chmod as chmod3, lstat, mkdir as mkdir7, open as open3, readFile as readFile7, readdir as readdir4,
|
|
46954
|
+
import { chmod as chmod3, lstat, mkdir as mkdir7, open as open3, readFile as readFile7, readdir as readdir4, rename as rename4, rm as rm2, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
|
|
46908
46955
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
46909
46956
|
import { dirname as dirname6, join as join8, resolve as resolve8 } from "node:path";
|
|
46910
46957
|
import { Readable } from "node:stream";
|
|
@@ -47388,15 +47435,6 @@ async function uploadObjects(context, files, absolute) {
|
|
|
47388
47435
|
}
|
|
47389
47436
|
return missing.size;
|
|
47390
47437
|
}
|
|
47391
|
-
async function stageCloudVideo(options) {
|
|
47392
|
-
const context = await openContext(options.dir, options);
|
|
47393
|
-
const root = await realpath(context.root);
|
|
47394
|
-
const file2 = await realpath(options.file);
|
|
47395
|
-
if (!file2.startsWith(root + "/") || !file2.endsWith(".mp4") || options.size > CLOUD_OBJECT_MAX_BYTES || !/^[a-f0-9]{64}$/.test(options.sha256)) throw new Error("Choose a cloud workspace MP4 up to 4 GiB.");
|
|
47396
|
-
const info = await stat2(file2);
|
|
47397
|
-
if (!info.isFile() || info.size !== options.size) throw new Error("The MP4 changed before staging.");
|
|
47398
|
-
await uploadObjects(context, /* @__PURE__ */ new Map([[file2.slice(root.length + 1), { oid: "0".repeat(40), mode: "100644", size: options.size, mtimeMs: info.mtimeMs, sha256: options.sha256 }]]), () => file2);
|
|
47399
|
-
}
|
|
47400
47438
|
async function retry(context, run) {
|
|
47401
47439
|
for (let attempt = 0; ; attempt++) {
|
|
47402
47440
|
try {
|
|
@@ -47666,6 +47704,11 @@ async function restoreCloud(options) {
|
|
|
47666
47704
|
|
|
47667
47705
|
// cli/src/videos.ts
|
|
47668
47706
|
var subtitlesBody = (content) => new Blob([new Uint8Array(content)], { type: "text/plain; charset=utf-8" });
|
|
47707
|
+
function libraryWorkspace(value) {
|
|
47708
|
+
if (value === "personal" || value === "me") return "me";
|
|
47709
|
+
if (!/^team_[a-f0-9]{32}$/.test(value)) throw new Error("Pass --workspace personal or a team ID from animaguru workspaces list.");
|
|
47710
|
+
return value;
|
|
47711
|
+
}
|
|
47669
47712
|
function sharingEmails(value) {
|
|
47670
47713
|
return value ? value.split(",").map((email3) => email3.trim()).filter(Boolean) : [];
|
|
47671
47714
|
}
|
|
@@ -47703,6 +47746,7 @@ async function exportHtml(root, animation, signal, log) {
|
|
|
47703
47746
|
}
|
|
47704
47747
|
async function submitVideo(client, options) {
|
|
47705
47748
|
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.");
|
|
47749
|
+
const workspace3 = options.workspace === void 0 ? void 0 : libraryWorkspace(options.workspace);
|
|
47706
47750
|
const root = resolve9(options.directory ?? ".");
|
|
47707
47751
|
const context = await localProject(root, options.animation);
|
|
47708
47752
|
const file2 = options.file ? resolve9(root, options.file) : await exportHtml(context.toolsRoot, context.animation, options.signal, options.log);
|
|
@@ -47736,7 +47780,7 @@ async function submitVideo(client, options) {
|
|
|
47736
47780
|
metadata = { ...metadata, ...receipt.title ? { title: receipt.title } : {}, ...probe };
|
|
47737
47781
|
}
|
|
47738
47782
|
const link2 = await cloudLink(context.toolsRoot).catch(() => null);
|
|
47739
|
-
const home = link2?.origin === client.origin ? { project: link2.projectId, ...context.animation ? { animation: context.animation } : {} } : { workspace: await selectedWorkspace(client.origin) };
|
|
47783
|
+
const home = link2?.origin === client.origin ? { project: link2.projectId, ...context.animation ? { animation: context.animation } : {}, ...workspace3 ? { workspace: workspace3 } : {} } : { workspace: workspace3 ?? await selectedWorkspace(client.origin) };
|
|
47740
47784
|
const body = videoSubmission.parse({
|
|
47741
47785
|
...home,
|
|
47742
47786
|
title: options.title ?? metadata.title ?? basename4(file2).replace(/\.(zip|mp4)$/i, ""),
|
|
@@ -47822,6 +47866,31 @@ async function changeVideoSubtitles(client, id2, options) {
|
|
|
47822
47866
|
parseSubtitles(content.toString("utf8"));
|
|
47823
47867
|
return client.request(path + language.data, { method: "PUT", body: subtitlesBody(content) });
|
|
47824
47868
|
}
|
|
47869
|
+
async function listVideos(client, options) {
|
|
47870
|
+
const scope = options.scope ?? "mine";
|
|
47871
|
+
const page = options.page ?? 1;
|
|
47872
|
+
if (options.workspace !== void 0 && scope !== "mine") throw new Error("--workspace chooses a library; use it with --scope mine.");
|
|
47873
|
+
if (scope === "public") return client.request(`/api/videos?page=${page}`, { authenticated: false });
|
|
47874
|
+
if (scope !== "mine") return client.request(`/api/v1/videos?scope=${scope}&page=${page}`);
|
|
47875
|
+
const workspace3 = options.workspace === void 0 ? await selectedWorkspace(client.origin) : libraryWorkspace(options.workspace);
|
|
47876
|
+
return client.request(`/api/v1/videos?scope=mine&page=${page}${workspace3 === "me" ? "" : `&workspace=${encodeURIComponent(workspace3)}`}`);
|
|
47877
|
+
}
|
|
47878
|
+
async function moveVideos(client, ids, options) {
|
|
47879
|
+
if (!options.yes) throw new Error("Pass --yes to authorize moving these videos. Everyone in a team can watch the videos in its library.");
|
|
47880
|
+
if (!ids.length) throw new Error("Name the videos to move with their IDs from animaguru videos list.");
|
|
47881
|
+
if (options.workspace === void 0) throw new Error("Pass --workspace personal or a team ID from animaguru workspaces list.");
|
|
47882
|
+
const workspace3 = libraryWorkspace(options.workspace);
|
|
47883
|
+
const moved = [];
|
|
47884
|
+
for (const [index2, id2] of ids.entries()) {
|
|
47885
|
+
try {
|
|
47886
|
+
const { video } = await client.request(`/api/v1/videos/${encodeURIComponent(id2)}/workspace`, { method: "PATCH", body: { workspace: workspace3 } });
|
|
47887
|
+
moved.push({ id: video.id, title: video.title, workspaceId: video.workspaceId });
|
|
47888
|
+
} catch (error62) {
|
|
47889
|
+
return { moved, error: `${id2} was not moved: ${error62 instanceof Error ? error62.message : String(error62)}`, notMoved: ids.slice(index2) };
|
|
47890
|
+
}
|
|
47891
|
+
}
|
|
47892
|
+
return { moved };
|
|
47893
|
+
}
|
|
47825
47894
|
|
|
47826
47895
|
// cli/src/assets.ts
|
|
47827
47896
|
import { mkdir as mkdir8, readFile as readFile9, stat as stat4, writeFile as writeFile8 } from "node:fs/promises";
|
|
@@ -48299,12 +48368,8 @@ import { readFile as readFile12, stat as stat6 } from "node:fs/promises";
|
|
|
48299
48368
|
import { chmod as chmod4, lstat as lstat2, mkdir as mkdir9, open as open5, readFile as readFile11, readdir as readdir5, rename as rename5, unlink, writeFile as writeFile9 } from "node:fs/promises";
|
|
48300
48369
|
import { dirname as dirname8, join as join11 } from "node:path";
|
|
48301
48370
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
48302
|
-
function
|
|
48303
|
-
|
|
48304
|
-
const workspace3 = process.env.ANIMAGURU_CLOUD_WORKSPACE;
|
|
48305
|
-
if (!project || !workspace3) return null;
|
|
48306
|
-
if (!/^prj_[A-Za-z0-9]{8,40}$/.test(project) || !/^aw_[a-f0-9]{32}$/.test(workspace3)) throw new Error("Invalid Animator context.");
|
|
48307
|
-
return { client: new Client(process.env.ANIMAGURU_URL ?? "https://animaguru.com"), path: `/api/v1/cloud/${project}/animator/${workspace3}/youtube` };
|
|
48371
|
+
function refuseInAnimator() {
|
|
48372
|
+
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.");
|
|
48308
48373
|
}
|
|
48309
48374
|
var youtubeMetadata = external_exports.object({
|
|
48310
48375
|
title: external_exports.string().trim().min(1).max(100).refine((value) => !/[<>]/.test(value)),
|
|
@@ -48407,34 +48472,18 @@ async function writePrivate(file2, value) {
|
|
|
48407
48472
|
}
|
|
48408
48473
|
}
|
|
48409
48474
|
async function readYouTubeCredentials() {
|
|
48410
|
-
const cloud = cloudYouTube();
|
|
48411
|
-
if (cloud) {
|
|
48412
|
-
const result = await cloud.client.request(`${cloud.path}/credentials`);
|
|
48413
|
-
return result.credentials === null ? null : youtubeCredentials.parse(result.credentials);
|
|
48414
|
-
}
|
|
48415
48475
|
const value = await readPrivate(credentialFile());
|
|
48416
48476
|
if (value === null) return null;
|
|
48417
48477
|
const parsed = youtubeCredentials.safeParse(value);
|
|
48418
48478
|
if (!parsed.success) throw new Error("Invalid saved YouTube credentials. Run youtube auth logout, then login again.");
|
|
48419
48479
|
return parsed.data;
|
|
48420
48480
|
}
|
|
48421
|
-
var saveYouTubeCredentials = (value) =>
|
|
48481
|
+
var saveYouTubeCredentials = (value) => writePrivate(credentialFile(), youtubeCredentials.parse(value));
|
|
48422
48482
|
async function saveYouTubeJob(value) {
|
|
48423
48483
|
const job = youtubeJob.parse(value);
|
|
48424
|
-
const cloud = cloudYouTube();
|
|
48425
|
-
if (cloud) {
|
|
48426
|
-
await cloud.client.request(`${cloud.path}/uploads/${job.id}`, { method: "PUT", body: job });
|
|
48427
|
-
return;
|
|
48428
|
-
}
|
|
48429
48484
|
await writePrivate(jobFile(job.id), job);
|
|
48430
48485
|
}
|
|
48431
48486
|
async function readYouTubeJob(id2) {
|
|
48432
|
-
const cloud = cloudYouTube();
|
|
48433
|
-
if (cloud) {
|
|
48434
|
-
const job = (await localYouTubeJobs()).find((job2) => job2.id === id2);
|
|
48435
|
-
if (!job) throw new Error("Cloud YouTube upload not found.");
|
|
48436
|
-
return job;
|
|
48437
|
-
}
|
|
48438
48487
|
const parsed = youtubeJob.safeParse(await readPrivate(jobFile(id2)));
|
|
48439
48488
|
if (!parsed.success || parsed.data.id !== id2) throw new Error("Upload not found or local upload state is invalid.");
|
|
48440
48489
|
return parsed.data;
|
|
@@ -48443,11 +48492,6 @@ function youtubeJobSummary(job) {
|
|
|
48443
48492
|
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 };
|
|
48444
48493
|
}
|
|
48445
48494
|
async function localYouTubeJobs() {
|
|
48446
|
-
const cloud = cloudYouTube();
|
|
48447
|
-
if (cloud) {
|
|
48448
|
-
const result = await cloud.client.request(`${cloud.path}/uploads`);
|
|
48449
|
-
return result.jobs.map((job) => youtubeJob.parse(job));
|
|
48450
|
-
}
|
|
48451
48495
|
const directory = join11(youtubeDirectory(), "uploads");
|
|
48452
48496
|
if (!await existingDirectory(directory)) return [];
|
|
48453
48497
|
let files;
|
|
@@ -48480,6 +48524,7 @@ async function clearYouTubeData() {
|
|
|
48480
48524
|
for (const file2 of files.filter((name2) => name2.endsWith(".json") && external_exports.uuid().safeParse(name2.slice(0, -5)).success)) await unlink(jobFile(file2.slice(0, -5)));
|
|
48481
48525
|
}
|
|
48482
48526
|
async function withYouTubeLock(operation) {
|
|
48527
|
+
refuseInAnimator();
|
|
48483
48528
|
await privateDirectory(youtubeDirectory());
|
|
48484
48529
|
const file2 = join11(youtubeDirectory(), "operation.lock");
|
|
48485
48530
|
const lock = await open5(file2, "wx", 384).catch((error62) => {
|
|
@@ -48534,7 +48579,6 @@ async function googleJson(response) {
|
|
|
48534
48579
|
}
|
|
48535
48580
|
async function providerError(response) {
|
|
48536
48581
|
const body = await googleJson(response);
|
|
48537
|
-
if (cloudYouTube() && typeof body.error?.message === "string") return new YouTubeError(String(body.error.message).slice(0, 512));
|
|
48538
48582
|
const error62 = body.error;
|
|
48539
48583
|
const raw = typeof error62 === "object" ? error62?.errors?.[0]?.reason : error62;
|
|
48540
48584
|
const reason = typeof raw === "string" && /^[A-Za-z_]{1,64}$/.test(raw) ? raw : void 0;
|
|
@@ -48567,7 +48611,6 @@ async function tokenRequest(client, params, signal) {
|
|
|
48567
48611
|
return googleJson(response);
|
|
48568
48612
|
}
|
|
48569
48613
|
async function accessToken(credentials, signal, force = false) {
|
|
48570
|
-
if (cloudYouTube()) return "provided-by-worker";
|
|
48571
48614
|
if (!force && credentials.expiresAt > Date.now() + 6e4) return credentials.accessToken;
|
|
48572
48615
|
const body = await tokenRequest(credentials, { grant_type: "refresh_token", refresh_token: credentials.refreshToken }, signal);
|
|
48573
48616
|
const scopes = typeof body.scope === "string" ? body.scope.split(" ") : null;
|
|
@@ -48621,7 +48664,7 @@ async function revoke(token3, signal) {
|
|
|
48621
48664
|
}
|
|
48622
48665
|
}
|
|
48623
48666
|
async function youtubeLogin(options) {
|
|
48624
|
-
|
|
48667
|
+
refuseInAnimator();
|
|
48625
48668
|
if (!options.yes) throw new Error("Pass --yes to accept YouTube's Terms of Service and authorize saving YouTube credentials locally. Review https://www.youtube.com/t/terms and https://policies.google.com/privacy first.");
|
|
48626
48669
|
const seconds2 = options.timeout ?? 300;
|
|
48627
48670
|
if (!Number.isFinite(seconds2) || seconds2 < 1 || seconds2 > 600) throw new Error("Use an authorization timeout between 1 and 600 seconds.");
|
|
@@ -48645,8 +48688,8 @@ async function youtubeLogin(options) {
|
|
|
48645
48688
|
let receive;
|
|
48646
48689
|
let fail;
|
|
48647
48690
|
let used = false;
|
|
48648
|
-
const callback = new Promise((
|
|
48649
|
-
receive =
|
|
48691
|
+
const callback = new Promise((resolve17, reject) => {
|
|
48692
|
+
receive = resolve17;
|
|
48650
48693
|
fail = reject;
|
|
48651
48694
|
});
|
|
48652
48695
|
void callback.catch(() => {
|
|
@@ -48684,9 +48727,9 @@ async function youtubeLogin(options) {
|
|
|
48684
48727
|
response.end("Authorization received. Return to your AnimaGuru terminal.");
|
|
48685
48728
|
receive(code);
|
|
48686
48729
|
});
|
|
48687
|
-
await new Promise((
|
|
48730
|
+
await new Promise((resolve17, reject) => {
|
|
48688
48731
|
server.once("error", reject);
|
|
48689
|
-
server.listen(0, "127.0.0.1",
|
|
48732
|
+
server.listen(0, "127.0.0.1", resolve17);
|
|
48690
48733
|
});
|
|
48691
48734
|
const address = server.address();
|
|
48692
48735
|
if (!address || typeof address === "string") throw new Error("Cannot open the local YouTube authorization listener.");
|
|
@@ -48721,7 +48764,7 @@ async function youtubeLogin(options) {
|
|
|
48721
48764
|
clearTimeout(timer);
|
|
48722
48765
|
options.signal?.removeEventListener("abort", abort);
|
|
48723
48766
|
server.closeAllConnections();
|
|
48724
|
-
await new Promise((
|
|
48767
|
+
await new Promise((resolve17) => server.close(() => resolve17()));
|
|
48725
48768
|
}
|
|
48726
48769
|
});
|
|
48727
48770
|
}
|
|
@@ -48733,7 +48776,7 @@ async function youtubeStatus(options = {}) {
|
|
|
48733
48776
|
});
|
|
48734
48777
|
}
|
|
48735
48778
|
async function youtubeLogout(options) {
|
|
48736
|
-
|
|
48779
|
+
refuseInAnimator();
|
|
48737
48780
|
if (!options.yes) throw new Error("Pass --yes to revoke YouTube authorization and remove local credentials and upload receipts.");
|
|
48738
48781
|
return withYouTubeLock(async () => {
|
|
48739
48782
|
let credentials = null;
|
|
@@ -49002,6 +49045,7 @@ async function transfer(credentials, job, source, options) {
|
|
|
49002
49045
|
}
|
|
49003
49046
|
}
|
|
49004
49047
|
async function uploadYouTube(options) {
|
|
49048
|
+
refuseInAnimator();
|
|
49005
49049
|
if (!options.yes && !options["dry-run"]) throw new Error("Pass --yes to authorize the YouTube upload, or --dry-run to inspect it locally.");
|
|
49006
49050
|
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.");
|
|
49007
49051
|
const root = resolve11(options.directory ?? ".");
|
|
@@ -49042,12 +49086,8 @@ async function uploadYouTube(options) {
|
|
|
49042
49086
|
return { ...await finishUpload(credentials, previous, options), alreadyUploaded: true };
|
|
49043
49087
|
}
|
|
49044
49088
|
await source.check();
|
|
49045
|
-
if (cloudYouTube()) {
|
|
49046
|
-
await stageCloudVideo({ dir: root, file: file2, sha256: source.sha256, size: source.bytes, signal: options.signal, log: options.log });
|
|
49047
|
-
await source.check();
|
|
49048
|
-
}
|
|
49049
49089
|
options.log?.(`Uploading ${file2} to ${credentials.channelTitle} (${credentials.channelId}) with ${metadata.privacy} visibility${pending ? `, then adding ${pending.language} captions from ${pending.file}` : ""}${thumbnail ? `${pending ? " and" : ", then setting"} the thumbnail ${thumbnail.file}` : ""}. You confirm you have the rights to upload this video. YouTube terms: https://www.youtube.com/t/terms`);
|
|
49050
|
-
const response = await youtubeRequest(credentials, "https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status¬ifySubscribers=false", { method: "POST", headers: { "Content-Type": "application/json; charset=UTF-8", "X-Upload-Content-Length": String(source.bytes), "X-Upload-Content-Type": "video/mp4"
|
|
49090
|
+
const response = await youtubeRequest(credentials, "https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status¬ifySubscribers=false", { method: "POST", headers: { "Content-Type": "application/json; charset=UTF-8", "X-Upload-Content-Length": String(source.bytes), "X-Upload-Content-Type": "video/mp4" }, body: JSON.stringify({ snippet: { title: metadata.title, description: metadata.description, categoryId: "22" }, status: { privacyStatus: metadata.privacy, selfDeclaredMadeForKids: metadata.madeForKids, containsSyntheticMedia: metadata.syntheticMedia } }) }, options.signal);
|
|
49051
49091
|
const location = response.headers.get("Location");
|
|
49052
49092
|
await response.body?.cancel();
|
|
49053
49093
|
if (!location) throw new YouTubeError("Google did not return an upload session. No video bytes were sent.");
|
|
@@ -49600,6 +49640,234 @@ async function downloadBrand(client, id2, output2, flags = {}) {
|
|
|
49600
49640
|
return { id: brand.id, name: brand.name, files: written };
|
|
49601
49641
|
}
|
|
49602
49642
|
|
|
49643
|
+
// cli/src/review-check.ts
|
|
49644
|
+
import { readFile as readFile17, readdir as readdir6, stat as stat9, writeFile as writeFile14 } from "node:fs/promises";
|
|
49645
|
+
import { join as join17 } from "node:path";
|
|
49646
|
+
|
|
49647
|
+
// shared/frame-checks.ts
|
|
49648
|
+
var FRAME_CHECK_MAX_FRAMES = 12;
|
|
49649
|
+
var FRAME_CHECK_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
49650
|
+
var FRAME_CHECK_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
49651
|
+
var FRAME_CHECKS = {
|
|
49652
|
+
empty: { type: "noul", instructions: "Is this frame empty or nearly empty: a plain background with no readable text, product, interface or main subject?" },
|
|
49653
|
+
cut_off: { type: "noul", instructions: "Is any text, logo or important element cut off by the edge of the frame?" },
|
|
49654
|
+
overlap: { type: "noul", instructions: "Does any text overlap other text, a logo or an interface element so that it is hard to read?" },
|
|
49655
|
+
broken_text: { type: "noul", instructions: "Does any text show broken or missing letters, gaps inside words, wrong characters or placeholder boxes?" },
|
|
49656
|
+
hard_to_read: { type: "noul", instructions: "Is the main text too small, too faint or too low in contrast to read comfortably on a phone?" },
|
|
49657
|
+
polish: { type: "score", instructions: "How finished and professional does this frame look as a frame of an advertisement or explainer video?", criteria: ["Broken", "Unfinished or unbalanced", "Acceptable", "Polished"] }
|
|
49658
|
+
};
|
|
49659
|
+
var questionId = external_exports.string().regex(/^[A-Za-z0-9_.-]{1,60}$/, "Use letters, digits, '_', '.' or '-' in a question ID.").refine((id2) => !(id2 in FRAME_CHECKS), "Built-in checks are always asked; give your question another ID.");
|
|
49660
|
+
var instructions = external_exports.string().trim().min(3).max(500);
|
|
49661
|
+
var frameCheckQuestion = external_exports.discriminatedUnion("type", [
|
|
49662
|
+
external_exports.object({ type: external_exports.literal("noul"), instructions }).strict(),
|
|
49663
|
+
external_exports.object({ type: external_exports.literal("choice"), instructions, criteria: external_exports.record(external_exports.string().regex(/^[A-Za-z0-9_.-]{1,40}$/), external_exports.string().trim().min(1).max(200)).refine((options) => Object.keys(options).length >= 2 && Object.keys(options).length <= 12, "A choice needs 2\u201312 options.") }).strict(),
|
|
49664
|
+
external_exports.object({ type: external_exports.literal("score"), instructions, criteria: external_exports.array(external_exports.string().trim().min(1).max(200)).min(2).max(10) }).strict()
|
|
49665
|
+
]);
|
|
49666
|
+
var frameCheckQuestions = external_exports.record(questionId, frameCheckQuestion).refine((questions) => Object.keys(questions).length <= 16, "Ask at most 16 questions of your own.");
|
|
49667
|
+
function dataUrlBytes(image) {
|
|
49668
|
+
const data = image.slice(image.indexOf(",") + 1);
|
|
49669
|
+
return Math.floor(data.length * 3 / 4) - (data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0);
|
|
49670
|
+
}
|
|
49671
|
+
var frameImage = external_exports.string().regex(/^data:image\/(?:jpeg|png|webp);base64,[A-Za-z0-9+/]+={0,2}$/, "Send each frame as a base64 JPEG, PNG or WebP data URL.").refine((image) => dataUrlBytes(image) <= FRAME_CHECK_IMAGE_BYTES, "Each frame can be up to 4 MiB.");
|
|
49672
|
+
var frameCheckFrame = external_exports.object({ time: external_exports.number().min(0).max(3600), image: frameImage }).strict();
|
|
49673
|
+
var frameCheckRequest = external_exports.object({
|
|
49674
|
+
/** 'me' or a team ID; a project's or Animator draft's own workspace takes precedence. */
|
|
49675
|
+
workspace: external_exports.string().max(80).optional(),
|
|
49676
|
+
projectId: external_exports.string().regex(/^prj_[A-Za-z0-9]+$/).optional(),
|
|
49677
|
+
/** What the film is: its title, format, audience, brief. Each frame is judged with it. */
|
|
49678
|
+
context: external_exports.string().max(2e3).default(""),
|
|
49679
|
+
duration: external_exports.number().positive().max(3600).optional(),
|
|
49680
|
+
frames: external_exports.array(frameCheckFrame).min(1).max(FRAME_CHECK_MAX_FRAMES),
|
|
49681
|
+
questions: frameCheckQuestions.optional(),
|
|
49682
|
+
/** Validate and return the most the check can cost, without running it. */
|
|
49683
|
+
dryRun: external_exports.boolean().optional()
|
|
49684
|
+
}).strict().refine((input2) => input2.frames.reduce((sum, frame) => sum + dataUrlBytes(frame.image), 0) <= FRAME_CHECK_TOTAL_BYTES, "A check's frames can total up to 8 MiB; send fewer or smaller frames.");
|
|
49685
|
+
|
|
49686
|
+
// cli/src/review-check.ts
|
|
49687
|
+
async function framesToCheck(projectRoot, source, report2) {
|
|
49688
|
+
if (source === "frames") {
|
|
49689
|
+
const folder2 = join17(projectRoot, "production/review/frames");
|
|
49690
|
+
const names2 = await readdir6(folder2).catch(() => []);
|
|
49691
|
+
const frames = names2.map((name2) => /^frame-([\d.]+)s\.jpg$/.exec(name2)).filter((match) => match !== null).map((match) => ({ file: join17(folder2, match[0]), time: Number(match[1]) })).sort((a, b) => a.time - b.time);
|
|
49692
|
+
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.");
|
|
49693
|
+
return frames;
|
|
49694
|
+
}
|
|
49695
|
+
const folder = join17(projectRoot, "production/review");
|
|
49696
|
+
const times = [...report2.seekMatches ?? []].map((match) => match.time).sort((a, b) => a - b);
|
|
49697
|
+
const names = (await readdir6(folder)).filter((name2) => /^frame-\d{2}\.jpg$/.test(name2)).sort();
|
|
49698
|
+
if (!names.length || names.length !== times.length) throw new Error("The review frames do not match report.json. Run npm run review again.");
|
|
49699
|
+
return names.map((name2, index2) => ({ file: join17(folder, name2), time: times[index2] }));
|
|
49700
|
+
}
|
|
49701
|
+
function filmContext(report2, brief, extra) {
|
|
49702
|
+
const config2 = report2.config ?? {};
|
|
49703
|
+
const film = [config2.title ? `Title: ${config2.title}` : "", config2.width && config2.height ? `Format: ${config2.width}\xD7${config2.height}${config2.height > config2.width ? ", vertical for phones" : ""}` : ""].filter(Boolean).join("\n");
|
|
49704
|
+
const text2 = [film, extra?.trim() ?? "", brief ? `Brief:
|
|
49705
|
+
${brief.trim()}` : ""].filter(Boolean).join("\n\n");
|
|
49706
|
+
return text2.length > 2e3 ? `${text2.slice(0, 1999)}\u2026` : text2;
|
|
49707
|
+
}
|
|
49708
|
+
function compact(answers) {
|
|
49709
|
+
return Object.fromEntries(Object.entries(answers).map(([id2, answer]) => [id2, typeof answer === "number" ? answer : "score" in answer ? answer.score : answer.choice]));
|
|
49710
|
+
}
|
|
49711
|
+
async function reviewCheck(client, options) {
|
|
49712
|
+
if (!options.yes && !options["dry-run"]) throw new Error("Pass --yes to authorize spending credits on the check, or --dry-run for its most.");
|
|
49713
|
+
const context = await localProject(options.directory, options.animation);
|
|
49714
|
+
const reportFile = join17(context.projectRoot, "production/review/report.json");
|
|
49715
|
+
const report2 = JSON.parse(await readFile17(reportFile, "utf8").catch(() => {
|
|
49716
|
+
throw new Error("Run npm run review first: production/review/report.json is missing.");
|
|
49717
|
+
}));
|
|
49718
|
+
const frames = await framesToCheck(context.projectRoot, options.source ?? "review", report2);
|
|
49719
|
+
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.`);
|
|
49720
|
+
const sizes = await Promise.all(frames.map(async (frame) => (await stat9(frame.file)).size));
|
|
49721
|
+
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.");
|
|
49722
|
+
const questions = options.questions ? frameCheckQuestions.parse(JSON.parse(await readFile17(options.questions, "utf8"))) : void 0;
|
|
49723
|
+
const brief = await readFile17(join17(context.projectRoot, "production/brief.md"), "utf8").catch(() => "");
|
|
49724
|
+
const link2 = await cloudLink(context.toolsRoot).catch(() => null);
|
|
49725
|
+
const body = {
|
|
49726
|
+
...link2?.origin === client.origin ? { projectId: link2.projectId } : { workspace: await selectedWorkspace(client.origin) },
|
|
49727
|
+
context: filmContext(report2, brief, options.context),
|
|
49728
|
+
...report2.config?.duration ? { duration: report2.config.duration } : {},
|
|
49729
|
+
frames: await Promise.all(frames.map(async (frame) => ({ time: Math.round(frame.time * 1e3) / 1e3, image: `data:image/jpeg;base64,${(await readFile17(frame.file)).toString("base64")}` }))),
|
|
49730
|
+
...questions ? { questions } : {},
|
|
49731
|
+
...options["dry-run"] ? { dryRun: true } : {}
|
|
49732
|
+
};
|
|
49733
|
+
if (options["dry-run"]) return client.request("/api/v1/frame-checks", { method: "POST", body, timeout: 12e4 });
|
|
49734
|
+
const result = await client.request("/api/v1/frame-checks", { method: "POST", body, timeout: 12e4 });
|
|
49735
|
+
const fileAt = (time3) => frames.find((frame) => Math.abs(frame.time - time3) < 1e-3)?.file.slice(context.projectRoot.length + 1);
|
|
49736
|
+
const saved = join17(context.projectRoot, "production/review/check.json");
|
|
49737
|
+
await writeFile14(saved, `${JSON.stringify({ ...result, frames: result.frames.map((frame) => ({ file: fileAt(frame.time), ...frame })) }, null, 2)}
|
|
49738
|
+
`);
|
|
49739
|
+
return {
|
|
49740
|
+
flagged: result.flagged.map((flag) => ({ file: fileAt(flag.time), ...flag })),
|
|
49741
|
+
frames: result.frames.map((frame) => "error" in frame ? { file: fileAt(frame.time), ...frame } : { file: fileAt(frame.time), time: frame.time, flags: frame.flags, answers: compact(frame.answers) }),
|
|
49742
|
+
credits: result.credits,
|
|
49743
|
+
saved: saved.slice(context.projectRoot.length + 1),
|
|
49744
|
+
note: result.flagged.length ? "Open the flagged frames first; the check estimates probabilities and does not replace watching the film." : "No check flagged a frame. It estimates probabilities: still watch the film before calling it finished."
|
|
49745
|
+
};
|
|
49746
|
+
}
|
|
49747
|
+
|
|
49748
|
+
// cli/src/reference.ts
|
|
49749
|
+
import { openAsBlob } from "node:fs";
|
|
49750
|
+
import { mkdir as mkdir14, stat as stat10, writeFile as writeFile15 } from "node:fs/promises";
|
|
49751
|
+
import { basename as basename7, dirname as dirname13, extname as extname3, join as join18, relative as relative3, resolve as resolve15 } from "node:path";
|
|
49752
|
+
|
|
49753
|
+
// shared/video-analysis.ts
|
|
49754
|
+
var VIDEO_ANALYSIS_MAX_BYTES = 100 * 1024 * 1024;
|
|
49755
|
+
var videoAnalysisEffort = external_exports.enum(["low", "medium", "xhigh"]);
|
|
49756
|
+
var settings = {
|
|
49757
|
+
workspace: external_exports.string().min(1).max(100).optional(),
|
|
49758
|
+
projectId: external_exports.string().regex(/^prj_[A-Za-z0-9]{1,64}$/).optional(),
|
|
49759
|
+
/** What the person cares about most, such as "the transitions" or "how the offer is introduced". */
|
|
49760
|
+
focus: external_exports.string().trim().max(2e3).optional(),
|
|
49761
|
+
effort: videoAnalysisEffort.default("low"),
|
|
49762
|
+
dryRun: external_exports.boolean().optional()
|
|
49763
|
+
};
|
|
49764
|
+
var videoAnalysisRequest = external_exports.object({ ...settings, url: external_exports.string().trim().max(2048).url().refine((url3) => url3.startsWith("https://"), "Use an HTTPS link to the video file.") }).strict();
|
|
49765
|
+
var videoAnalysisUpload = external_exports.object({ ...settings, name: external_exports.string().trim().min(1).max(255).optional(), dryRun: external_exports.enum(["true", "false"]).transform((value) => value === "true").optional() }).strict();
|
|
49766
|
+
var videoAnalysisBrief = external_exports.object({
|
|
49767
|
+
summary: external_exports.string().optional(),
|
|
49768
|
+
format: external_exports.object({ aspect_ratio: external_exports.string().optional(), duration_s: external_exports.number().optional(), pace: external_exports.string().optional() }).passthrough().optional(),
|
|
49769
|
+
story: external_exports.object({ structure: external_exports.string().optional(), hook: external_exports.string().optional(), message: external_exports.string().optional(), call_to_action: external_exports.string().optional() }).passthrough().optional(),
|
|
49770
|
+
style: external_exports.object({ look: external_exports.string().optional(), palette: external_exports.array(external_exports.string()).optional(), typography: external_exports.string().optional(), motion: external_exports.string().optional(), transitions: external_exports.string().optional() }).passthrough().optional(),
|
|
49771
|
+
audio: external_exports.object({ voice: external_exports.string().optional(), music: external_exports.string().optional(), effects: external_exports.string().optional(), transcript: external_exports.array(external_exports.object({ start_s: external_exports.number().optional(), end_s: external_exports.number().optional(), text: external_exports.string() }).passthrough()).optional() }).passthrough().optional(),
|
|
49772
|
+
scenes: external_exports.array(external_exports.object({ start_s: external_exports.number().optional(), end_s: external_exports.number().optional(), shown: external_exports.string().optional(), framing: external_exports.string().optional(), motion: external_exports.string().optional(), on_screen_text: external_exports.string().optional(), audio: external_exports.string().optional(), purpose: external_exports.string().optional() }).passthrough()),
|
|
49773
|
+
brand_elements: external_exports.array(external_exports.object({ element: external_exports.string(), where: external_exports.string().optional(), replace_with: external_exports.string().optional() }).passthrough()).optional(),
|
|
49774
|
+
remake_notes: external_exports.array(external_exports.string()).optional()
|
|
49775
|
+
}).passthrough();
|
|
49776
|
+
|
|
49777
|
+
// cli/src/reference.ts
|
|
49778
|
+
var TYPES = { ".mp4": "video/mp4", ".m4v": "video/mp4", ".mov": "video/quicktime", ".webm": "video/webm" };
|
|
49779
|
+
var POLL_MS = 1e4;
|
|
49780
|
+
var WAIT_LIMIT_MS = 70 * 6e4;
|
|
49781
|
+
async function briefFile(options, name2) {
|
|
49782
|
+
if (options.out) return resolve15(options.out);
|
|
49783
|
+
const slug2 = name2.replace(/\.[a-z0-9]{2,4}$/i, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60) || "reference";
|
|
49784
|
+
const project = await localProject(options.directory ?? ".", options.animation).catch(() => null);
|
|
49785
|
+
const film = project && await stat10(join18(project.projectRoot, "animaguru.project.json")).then(() => true, () => false);
|
|
49786
|
+
return film ? join18(project.projectRoot, "production/references", `${slug2}.json`) : resolve15(options.directory ?? ".", `${slug2}.analysis.json`);
|
|
49787
|
+
}
|
|
49788
|
+
var pause = (ms, signal) => new Promise((done, fail) => {
|
|
49789
|
+
signal?.throwIfAborted();
|
|
49790
|
+
const stop = () => {
|
|
49791
|
+
clearTimeout(timer);
|
|
49792
|
+
fail(signal.reason);
|
|
49793
|
+
};
|
|
49794
|
+
const timer = setTimeout(() => {
|
|
49795
|
+
signal?.removeEventListener("abort", stop);
|
|
49796
|
+
done();
|
|
49797
|
+
}, ms);
|
|
49798
|
+
signal?.addEventListener("abort", stop, { once: true });
|
|
49799
|
+
});
|
|
49800
|
+
var sourceName = (analysis) => analysis.source.kind === "file" ? analysis.source.name : decodeURIComponent(new URL(analysis.source.url).pathname.split("/").filter(Boolean).at(-1) ?? "reference");
|
|
49801
|
+
async function finished(client, analysis, log) {
|
|
49802
|
+
const started = Date.now();
|
|
49803
|
+
let last = analysis.status;
|
|
49804
|
+
while (analysis.status === "processing" || analysis.status === "running") {
|
|
49805
|
+
if (Date.now() - started > WAIT_LIMIT_MS) throw new Error(`Analysis ${analysis.id} is still ${analysis.status}. Check it later with animaguru reference get ${analysis.id}.`);
|
|
49806
|
+
await pause(POLL_MS, client.signal);
|
|
49807
|
+
try {
|
|
49808
|
+
analysis = (await client.request(`/api/v1/video-analyses/${analysis.id}`, { timeout: 6e4 })).analysis;
|
|
49809
|
+
} catch (error62) {
|
|
49810
|
+
if (error62 instanceof ServiceError && error62.status < 500) throw error62;
|
|
49811
|
+
log?.("The connection dropped; asking again.");
|
|
49812
|
+
continue;
|
|
49813
|
+
}
|
|
49814
|
+
if (analysis.status !== last) {
|
|
49815
|
+
last = analysis.status;
|
|
49816
|
+
log?.(analysis.status === "running" ? "Elorian is watching the video." : `Analysis ${analysis.status}.`);
|
|
49817
|
+
}
|
|
49818
|
+
}
|
|
49819
|
+
return analysis;
|
|
49820
|
+
}
|
|
49821
|
+
async function report(analysis, options) {
|
|
49822
|
+
if (analysis.status === "failed") throw new Error(analysis.error ?? "The analysis failed.");
|
|
49823
|
+
if (analysis.status !== "completed") return { id: analysis.id, status: analysis.status, next: `animaguru reference get ${analysis.id} --wait` };
|
|
49824
|
+
const file2 = await briefFile(options, sourceName(analysis));
|
|
49825
|
+
await mkdir14(dirname13(file2), { recursive: true });
|
|
49826
|
+
await writeFile15(file2, `${JSON.stringify(analysis, null, 2)}
|
|
49827
|
+
`);
|
|
49828
|
+
const brief = analysis.result?.brief;
|
|
49829
|
+
return {
|
|
49830
|
+
id: analysis.id,
|
|
49831
|
+
status: analysis.status,
|
|
49832
|
+
credits: analysis.credits,
|
|
49833
|
+
video: analysis.result?.video,
|
|
49834
|
+
saved: relative3(process.cwd(), file2) || file2,
|
|
49835
|
+
...brief ? { summary: brief.summary, format: brief.format, story: brief.story, scenes: brief.scenes.length, brandElements: brief.brand_elements?.map((item) => item.element) ?? [] } : { note: "The answer is not a JSON brief; read result.text in the saved file." },
|
|
49836
|
+
next: "Read the saved brief scene by scene, then plan the remake with the user's own brand kit and story: keep the reference's structure, pacing and techniques, never its brand, claims, people or footage."
|
|
49837
|
+
};
|
|
49838
|
+
}
|
|
49839
|
+
async function referenceAnalyze(client, options) {
|
|
49840
|
+
const dryRun = Boolean(options["dry-run"]);
|
|
49841
|
+
if (!options.yes && !dryRun) throw new Error("Pass --yes to authorize spending credits on the analysis, or --dry-run for its most.");
|
|
49842
|
+
const project = await localProject(options.directory ?? ".", options.animation).catch(() => null);
|
|
49843
|
+
const link2 = project ? await cloudLink(project.toolsRoot).catch(() => null) : null;
|
|
49844
|
+
const settings2 = { ...link2?.origin === client.origin ? { projectId: link2.projectId } : { workspace: await selectedWorkspace(client.origin) }, effort: options.effort ?? "low", ...options.focus ? { focus: options.focus } : {} };
|
|
49845
|
+
let started;
|
|
49846
|
+
if (/^[a-z]+:\/\//i.test(options.video)) {
|
|
49847
|
+
if (!options.video.startsWith("https://")) throw new Error("Use an HTTPS link to the video file.");
|
|
49848
|
+
started = await client.request("/api/v1/video-analyses", { method: "POST", body: { ...settings2, url: options.video, ...dryRun ? { dryRun: true } : {} }, timeout: 12e4 });
|
|
49849
|
+
} else {
|
|
49850
|
+
const file2 = resolve15(options.video);
|
|
49851
|
+
const info = await stat10(file2).catch(() => null);
|
|
49852
|
+
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.`);
|
|
49853
|
+
const type = TYPES[extname3(file2).toLowerCase()];
|
|
49854
|
+
if (!type) throw new Error("Analyse an MP4, MOV or WebM video.");
|
|
49855
|
+
if (info.size > VIDEO_ANALYSIS_MAX_BYTES) throw new Error("The video is over 100 MB. Trim or compress it first, for example to 720p.");
|
|
49856
|
+
const query = new URLSearchParams({ ...settings2, name: basename7(file2), ...dryRun ? { dryRun: "true" } : {} });
|
|
49857
|
+
if (!dryRun) options.log?.(`Uploading ${basename7(file2)} (${(info.size / 1024 ** 2).toFixed(1)} MB).`);
|
|
49858
|
+
started = await client.request(`/api/v1/video-analyses/upload?${query}`, { method: "POST", ...dryRun ? {} : { body: await openAsBlob(file2, { type }) }, timeout: 6e5 });
|
|
49859
|
+
}
|
|
49860
|
+
if (dryRun || !started.analysis) return started;
|
|
49861
|
+
options.log?.(`Analysis ${started.analysis.id} started. It takes several minutes.`);
|
|
49862
|
+
if (options.wait === false) return { id: started.analysis.id, status: started.analysis.status, next: `animaguru reference get ${started.analysis.id} --wait` };
|
|
49863
|
+
return report(await finished(client, started.analysis, options.log), options);
|
|
49864
|
+
}
|
|
49865
|
+
async function referenceGet(client, id2, options) {
|
|
49866
|
+
if (!/^va_[a-f0-9]{32}$/.test(id2)) throw new Error("Use an analysis ID returned by animaguru reference analyze.");
|
|
49867
|
+
const { analysis } = await client.request(`/api/v1/video-analyses/${id2}`, { timeout: 6e4 });
|
|
49868
|
+
return report(options.wait ? await finished(client, analysis, options.log) : analysis, options);
|
|
49869
|
+
}
|
|
49870
|
+
|
|
49603
49871
|
// cli/src/commands.ts
|
|
49604
49872
|
var assetModelIds = [...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id)];
|
|
49605
49873
|
var assetAuthorizationFlags = [
|
|
@@ -49650,12 +49918,12 @@ var workspaceQuery = async (client) => {
|
|
|
49650
49918
|
async function openBrowser(url3) {
|
|
49651
49919
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32" : "xdg-open";
|
|
49652
49920
|
const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url3] : [url3];
|
|
49653
|
-
await new Promise((
|
|
49921
|
+
await new Promise((resolve17) => {
|
|
49654
49922
|
const child = spawn3(command, args, { stdio: "ignore", detached: true });
|
|
49655
|
-
child.once("error", () =>
|
|
49923
|
+
child.once("error", () => resolve17());
|
|
49656
49924
|
child.once("spawn", () => {
|
|
49657
49925
|
child.unref();
|
|
49658
|
-
|
|
49926
|
+
resolve17();
|
|
49659
49927
|
});
|
|
49660
49928
|
});
|
|
49661
49929
|
}
|
|
@@ -49681,12 +49949,44 @@ function createCli() {
|
|
|
49681
49949
|
{ 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" },
|
|
49682
49950
|
{ name: "yes", type: "boolean", description: "Authorize sending this video, its subtitles and thumbnail to the selected channel and privacy; confirm upload rights" },
|
|
49683
49951
|
{ name: "dry-run", type: "boolean", description: "Inspect MP4 and metadata locally without Google authorization or network calls" }
|
|
49684
|
-
).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())))).add(defineCommand("templates", { description: "List video categories and available starter templates" }, (command) => command.action(({ stdout }) => out(stdout, listTemplates())))).command("
|
|
49952
|
+
).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())))).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(
|
|
49953
|
+
{ name: "animation", type: "string", description: "Animation in a multi-animation workspace" },
|
|
49954
|
+
{ 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" },
|
|
49955
|
+
{ name: "context", type: "string", description: "What the film should show, added to its title, format and brief" },
|
|
49956
|
+
{ name: "questions", type: "string", description: 'JSON file of up to 16 extra questions asked of every frame, e.g. {"logo": {"type": "noul", "instructions": "Is the Acme logo visible?"}}' },
|
|
49957
|
+
{ name: "yes", type: "boolean", description: "Authorize spending credits" },
|
|
49958
|
+
{ name: "dry-run", type: "boolean", description: "Validate the frames and return the check's most credits without running it" },
|
|
49959
|
+
urlFlag
|
|
49960
|
+
).action(async ({ args, flags, stdout, signal }) => out(stdout, await reviewCheck(new Client(flags.url, signal), { ...flags, directory: args.directory })))))).command("reference", (reference) => reference.add(defineCommand("analyze", { description: "Analyse a reference video someone wants remade for their own brand or story: Elorian's Glimpse watches and listens to it and returns a remake brief (format, story, style, palette, typography, motion, transitions, audio and transcript, timed scenes, the original brand's elements to replace). Saves it to production/references/NAME.json in a video project. Takes several minutes; charged what it costs, about 22 to 36 credits for a 6-second clip in testing and more for a longer video" }, (command) => command.args({ name: "video", type: "string", required: true, description: "Video file (MP4, MOV or WebM, up to 100 MB and ten minutes) or an HTTPS link to the video file itself; YouTube, Instagram and TikTok pages cannot be fetched" }).flags(
|
|
49961
|
+
{ name: "directory", type: "string", default: ".", description: "Video workspace or animation folder to save the brief in" },
|
|
49962
|
+
{ name: "animation", type: "string", description: "Animation in a multi-animation workspace" },
|
|
49963
|
+
{ name: "focus", type: "string", description: 'What matters most, such as "the transitions" or "how the offer is introduced"' },
|
|
49964
|
+
{ name: "effort", type: "string", choices: ["low", "medium", "xhigh"], default: "low", description: "How long Glimpse thinks: low is quickest and cheapest, xhigh most thorough" },
|
|
49965
|
+
{ name: "out", type: "string", description: "Write the analysis to this file instead" },
|
|
49966
|
+
{ name: "wait", type: "boolean", default: true, description: "Wait for the brief; --no-wait returns the analysis ID at once" },
|
|
49967
|
+
{ name: "yes", type: "boolean", description: "Authorize spending credits" },
|
|
49968
|
+
{ name: "dry-run", type: "boolean", description: "Return the most credits the analysis can hold without starting it" },
|
|
49969
|
+
urlFlag
|
|
49970
|
+
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await referenceAnalyze(new Client(flags.url, signal), { ...flags, video: args.video, log: stderr }))))).add(defineCommand("get", { description: "Read an analysis started with reference analyze; --wait waits for it to finish. A completed one is saved like a new one" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Analysis ID (va_\u2026)" }).flags(
|
|
49971
|
+
{ name: "directory", type: "string", default: ".", description: "Video workspace or animation folder to save the brief in" },
|
|
49972
|
+
{ name: "animation", type: "string", description: "Animation in a multi-animation workspace" },
|
|
49973
|
+
{ name: "out", type: "string", description: "Write the analysis to this file instead" },
|
|
49974
|
+
{ name: "wait", type: "boolean", description: "Wait until the analysis finishes" },
|
|
49975
|
+
urlFlag
|
|
49976
|
+
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await referenceGet(new Client(flags.url, signal), args.id, { ...flags, log: stderr })))))).command("create", (creation) => creation.args({ name: "name", type: "string", description: "Legacy standalone project folder; prefer create workspace NAME" }).flags(
|
|
49977
|
+
{ name: "story", type: "boolean", description: "Start a branching story: viewers choose its path, and it plays as HTML5 only" },
|
|
49978
|
+
{ name: "quiz", type: "boolean", description: "Start a quiz film: questions pause the film at checkpoints and a final quiz follows it (HTML5 only, never MP4)" }
|
|
49979
|
+
).action(async ({ args, flags, stdout, stderr, signal }) => {
|
|
49685
49980
|
if (!args.name) throw new Error("Use animaguru create workspace NAME, or animaguru create animation NAME inside a workspace.");
|
|
49686
|
-
out(stdout, await createVideoProject({ directory: args.name, log: stderr, signal }));
|
|
49687
|
-
}).add(defineCommand("workspace", { description: "Create a shared-brand workspace with one player, dependencies, skills and export toolchain" }, (command) => command.args({ name: "name", type: "string", required: true }).flags({ name: "skip-install", type: "boolean", default: false, description: "Create source files without installing dependencies" }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await createWorkspace({ directory: args.name, install: !flags["skip-install"], log: stderr, signal }))))).add(defineCommand("animation", { description: "Add an animation to a workspace without copying shared runtime, dependencies or skills" }, (command) => command.args({ name: "name", type: "string", required: true }).flags(
|
|
49981
|
+
out(stdout, await createVideoProject({ directory: args.name, story: flags.story, quiz: flags.quiz, log: stderr, signal }));
|
|
49982
|
+
}).add(defineCommand("workspace", { description: "Create a shared-brand workspace with one player, dependencies, skills and export toolchain" }, (command) => command.args({ name: "name", type: "string", required: true }).flags({ name: "skip-install", type: "boolean", default: false, description: "Create source files without installing dependencies" }).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await createWorkspace({ directory: args.name, install: !flags["skip-install"], log: stderr, signal }))))).add(defineCommand("animation", { description: "Add an animation to a workspace without copying shared runtime, dependencies or skills" }, (command) => command.args({ name: "name", type: "string", required: true }).flags(
|
|
49983
|
+
{ name: "workspace", type: "string", description: "Workspace folder; otherwise finds it from the current directory" },
|
|
49984
|
+
{ name: "story", type: "boolean", description: "Start a branching story: viewers choose its path at choices, and it plays as HTML5 only (never MP4)" },
|
|
49985
|
+
{ name: "quiz", type: "boolean", description: "Start a quiz film (an educational explainer): checkpoints pause the film to ask questions, a final quiz and score follow its end; it plays as HTML5 only (never MP4)" }
|
|
49986
|
+
).action(async ({ args, flags, stdout, stderr, signal }) => out(stdout, await createAnimation({ name: args.name, workspace: flags.workspace, story: flags.story, quiz: flags.quiz, log: stderr, signal })))))).add(defineCommand("submit", { description: "Upload a finished HTML5 animation or MP4 to AnimaGuru; private unless --visibility public" }, (command) => command.args({ name: "directory", type: "string", default: ".", description: "Video project folder; defaults to current folder" }).flags(
|
|
49688
49987
|
{ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } },
|
|
49689
49988
|
{ name: "animation", type: "string", description: "Animation name when submitting from a multi-animation workspace" },
|
|
49989
|
+
{ name: "workspace", type: "string", description: "Video library: personal or a team ID; defaults to the selected workspace, or a synced project's" },
|
|
49690
49990
|
{ name: "file", type: "string", description: "Exported HTML5 ZIP or MP4; otherwise builds the project's HTML5 export" },
|
|
49691
49991
|
{ name: "title", type: "string" },
|
|
49692
49992
|
{ name: "description", type: "string" },
|
|
@@ -49697,11 +49997,24 @@ function createCli() {
|
|
|
49697
49997
|
{ 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" },
|
|
49698
49998
|
{ name: "yes", type: "boolean", description: "Authorize upload and chosen sharing" },
|
|
49699
49999
|
{ name: "dry-run", type: "boolean", description: "Inspect locally without uploading" }
|
|
49700
|
-
).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
|
|
50000
|
+
).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(
|
|
50001
|
+
{ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } },
|
|
50002
|
+
{ name: "scope", type: "string", choices: ["mine", "shared", "public"], default: "mine" },
|
|
50003
|
+
{ name: "page", type: "number", default: 1 },
|
|
50004
|
+
{ name: "workspace", type: "string", description: "The library to list with --scope mine: 'personal' or a team ID from workspaces list" }
|
|
50005
|
+
).action(async ({ flags, stdout, signal }) => out(stdout, await listVideos(new Client(flags.url, signal), flags))))).add(defineCommand("get", { description: "Get a video's details or the state of your unfinished upload" }, (command) => command.args({ name: "id", type: "string", required: true }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`/api/v1/videos/${encodeURIComponent(args.id)}`))))).add(defineCommand("complete", { description: "Retry completion of an already uploaded animation" }, (command) => command.args({ name: "id", type: "string", required: true }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`/api/v1/videos/${encodeURIComponent(args.id)}/complete`, { method: "POST", timeout: 3e5 }))))).add(defineCommand("share", { description: "Replace a video's visibility and recipient list" }, (command) => command.args({ name: "id", type: "string", required: true }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }, { name: "visibility", type: "string", required: true, choices: ["private", "public"] }, { name: "share", type: "string" }, { name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
49701
50006
|
if (!flags.yes) throw new Error("Pass --yes to authorize changing who can see this video.");
|
|
49702
50007
|
const client = new Client(flags.url, signal);
|
|
49703
50008
|
const { video } = await client.request(`/api/videos/${encodeURIComponent(args.id)}`);
|
|
49704
50009
|
out(stdout, await client.request(`/api/v1/videos/${encodeURIComponent(args.id)}`, { method: "PATCH", body: videoDetails.parse({ ...video, visibility: flags.visibility, recipients: sharingEmails(flags.share) }) }));
|
|
50010
|
+
}))).add(defineCommand("move", { description: "Move your videos to another library, Personal or a team you belong to; their links, subtitles and sharing stay" }, (command) => command.args({ name: "ids", type: "string", variadic: true, description: "Video IDs from videos list" }).flags(
|
|
50011
|
+
{ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } },
|
|
50012
|
+
{ name: "workspace", type: "string", required: true, description: "'personal' or a team ID from workspaces list" },
|
|
50013
|
+
{ name: "yes", type: "boolean", required: true }
|
|
50014
|
+
).action(async ({ args, flags, stdout, signal }) => {
|
|
50015
|
+
const result = await moveVideos(new Client(flags.url, signal), args.ids ?? [], flags);
|
|
50016
|
+
out(stdout, result);
|
|
50017
|
+
if (result.error) throw new Error(result.error);
|
|
49705
50018
|
}))).add(defineCommand("subtitles", { description: "Add or replace an MP4's subtitles in one language, or remove a language" }, (command) => command.args({ name: "id", type: "string", required: true }).flags(
|
|
49706
50019
|
{ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } },
|
|
49707
50020
|
{ name: "file", type: "string", description: ".srt or .vtt subtitle file" },
|
|
@@ -49930,7 +50243,7 @@ Confirm code: ${device.user_code}`);
|
|
|
49930
50243
|
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" }));
|
|
49931
50244
|
})))).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 }) => {
|
|
49932
50245
|
if (!flags.yes) throw new Error("Pass --yes to authorize spending credits.");
|
|
49933
|
-
const body = spriteJobBody.parse({ ...JSON.parse(await
|
|
50246
|
+
const body = spriteJobBody.parse({ ...JSON.parse(await readFile18(flags.file, "utf8")), ...selectedModels(flags) });
|
|
49934
50247
|
out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/jobs`, { method: "POST", body }));
|
|
49935
50248
|
}))).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 }) => {
|
|
49936
50249
|
const body = selectedModels(flags);
|
|
@@ -49945,7 +50258,7 @@ Confirm code: ${device.user_code}`);
|
|
|
49945
50258
|
const extension = flags.file.split(".").at(-1)?.toLowerCase();
|
|
49946
50259
|
const type = extension === "png" ? "image/png" : extension === "jpg" || extension === "jpeg" ? "image/jpeg" : extension === "webp" ? "image/webp" : void 0;
|
|
49947
50260
|
if (!type) throw new Error("Use a PNG, JPEG or WebP image.");
|
|
49948
|
-
const bytes = await
|
|
50261
|
+
const bytes = await readFile18(flags.file);
|
|
49949
50262
|
if (bytes.length > 10 * 1024 * 1024) throw new Error("Image must be at most 10 MB.");
|
|
49950
50263
|
const form = new FormData();
|
|
49951
50264
|
form.set("image", new Blob([bytes], { type }), `reference.${extension}`);
|
|
@@ -49961,10 +50274,10 @@ Confirm code: ${device.user_code}`);
|
|
|
49961
50274
|
if (!file2) throw new Error(`No file at ${args.path} in this project. List them with animaguru files list.`);
|
|
49962
50275
|
if (!/^[a-f0-9]{64}$/.test(file2.sha)) throw new Error("Invalid blob hash in manifest.");
|
|
49963
50276
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
49964
|
-
const path =
|
|
49965
|
-
await
|
|
50277
|
+
const path = resolve16(flags.output);
|
|
50278
|
+
await mkdir15(dirname14(path), { recursive: true });
|
|
49966
50279
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
49967
|
-
await
|
|
50280
|
+
await writeFile16(path, bytes, { flag: "wx" });
|
|
49968
50281
|
out(stdout, { path, bytes: bytes.length });
|
|
49969
50282
|
}))).add(defineCommand("export", { description: "Download all project assets as a ZIP; refuses to overwrite" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags({ name: "output", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
49970
50283
|
const client = new Client(flags.url, signal);
|
|
@@ -49976,8 +50289,8 @@ Confirm code: ${device.user_code}`);
|
|
|
49976
50289
|
const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
|
|
49977
50290
|
entries[path2] = new Uint8Array(await response.arrayBuffer());
|
|
49978
50291
|
}
|
|
49979
|
-
const path =
|
|
49980
|
-
await
|
|
50292
|
+
const path = resolve16(flags.output);
|
|
50293
|
+
await writeFile16(path, zipSync(entries, { level: 0 }), { flag: "wx" });
|
|
49981
50294
|
out(stdout, { path, files: manifest.files.length });
|
|
49982
50295
|
})))).extend(version(package_default.version, { format: "plain" })).extend(help()).extend(completion());
|
|
49983
50296
|
}
|