@docyrus/animaguru 0.13.0 → 0.15.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.
Files changed (76) hide show
  1. package/README.md +54 -3
  2. package/dist/animaguru.js +1025 -591
  3. package/package.json +1 -1
  4. package/skills/animaguru/SKILL.md +19 -89
  5. package/skills/animaguru/references/avatars.md +22 -0
  6. package/skills/animaguru/references/cloud.md +19 -0
  7. package/skills/animaguru/references/sharing.md +33 -0
  8. package/skills/animaguru/references/sprites.md +29 -0
  9. package/skills/animaguru-advertising/SKILL.md +2 -2
  10. package/skills/animaguru-analog-film-tape/SKILL.md +1 -0
  11. package/skills/animaguru-animated-data-visualization/SKILL.md +1 -0
  12. package/skills/animaguru-art-deco-motion/SKILL.md +1 -0
  13. package/skills/animaguru-ascii-crt/SKILL.md +1 -0
  14. package/skills/animaguru-blueprint-drafting/SKILL.md +1 -0
  15. package/skills/animaguru-brand-kit/SKILL.md +1 -1
  16. package/skills/animaguru-cartoon-character-animation/SKILL.md +1 -0
  17. package/skills/animaguru-cutout-animation/SKILL.md +1 -0
  18. package/skills/animaguru-dark-tech-stage/SKILL.md +2 -1
  19. package/skills/animaguru-dark-tech-stage/references/recipe.md +10 -0
  20. package/skills/animaguru-diagram-formula-motion/SKILL.md +1 -0
  21. package/skills/animaguru-engraved-relief-print/SKILL.md +1 -0
  22. package/skills/animaguru-flat-vector-motion/SKILL.md +1 -0
  23. package/skills/animaguru-generative-light-signal/SKILL.md +1 -0
  24. package/skills/animaguru-glass-mosaic/SKILL.md +1 -0
  25. package/skills/animaguru-halftone-editorial/SKILL.md +1 -0
  26. package/skills/animaguru-holographic-scan/SKILL.md +1 -0
  27. package/skills/animaguru-interface-motion/SKILL.md +1 -0
  28. package/skills/animaguru-isometric-worlds/SKILL.md +1 -0
  29. package/skills/animaguru-kinetic-typography/SKILL.md +1 -0
  30. package/skills/animaguru-miniature-diorama/SKILL.md +1 -0
  31. package/skills/animaguru-painterly-depth-animation/SKILL.md +1 -0
  32. package/skills/animaguru-paper-popup/SKILL.md +1 -0
  33. package/skills/animaguru-photo-footage-editorial/SKILL.md +1 -0
  34. package/skills/animaguru-pixel-art-animation/SKILL.md +1 -0
  35. package/skills/animaguru-portal-zoom/SKILL.md +1 -0
  36. package/skills/animaguru-risograph-print/SKILL.md +1 -0
  37. package/skills/animaguru-sand-drawing/SKILL.md +1 -0
  38. package/skills/animaguru-shadow-theatre/SKILL.md +1 -0
  39. package/skills/animaguru-silkscreen-poster/SKILL.md +1 -0
  40. package/skills/animaguru-stop-motion-objects/SKILL.md +1 -0
  41. package/skills/animaguru-studio-product-reveal/SKILL.md +1 -0
  42. package/skills/animaguru-video/SKILL.md +37 -5
  43. package/skills/animaguru-video/references/short-form-ad.md +57 -0
  44. package/skills/animaguru-whiteboard-line-drawing/SKILL.md +1 -0
  45. package/templates/video/AGENTS.md +2 -1
  46. package/templates/video/WORKSPACE-AGENTS.md +6 -2
  47. package/templates/video/package.json +7 -1
  48. package/templates/video/scripts/audio-mix.mjs +101 -0
  49. package/templates/video/scripts/audio-music.mjs +175 -0
  50. package/templates/video/scripts/audio-tools.mjs +241 -0
  51. package/templates/video/scripts/audio-vo.mjs +158 -0
  52. package/templates/video/scripts/export-mp4.mjs +5 -3
  53. package/templates/video/scripts/frames.mjs +81 -0
  54. package/templates/video/scripts/headless-browser.mjs +83 -10
  55. package/templates/video/scripts/review-analysis.mjs +71 -1
  56. package/templates/video/scripts/review-audio.mjs +2 -1
  57. package/templates/video/scripts/review.mjs +8 -5
  58. package/templates/video/scripts/site-inspect.mjs +128 -0
  59. package/templates/video/scripts/starter-film.sha256 +1 -1
  60. package/templates/video/scripts/workspace-plugin.mjs +2 -1
  61. package/templates/video/shared/safe-areas.json +7 -0
  62. package/templates/video/src/film.ts +97 -125
  63. package/templates/video/src/kit/components.ts +95 -0
  64. package/templates/video/src/kit/dark-stage.ts +55 -0
  65. package/templates/video/src/kit/film-base.ts +108 -0
  66. package/templates/video/src/kit/fonts.ts +29 -0
  67. package/templates/video/src/kit/index.ts +11 -0
  68. package/templates/video/src/kit/layout.ts +40 -0
  69. package/templates/video/src/kit/motion.ts +37 -0
  70. package/templates/video/src/kit/shapes.ts +68 -0
  71. package/templates/video/src/kit/text.ts +34 -0
  72. package/templates/video/src/kit/textures.ts +42 -0
  73. package/templates/video/src/kit/timing.ts +48 -0
  74. package/templates/video/src/player-types.ts +7 -1
  75. package/templates/video/src/player.ts +3 -5
  76. package/templates/video/src/review.ts +2 -0
package/dist/animaguru.js CHANGED
@@ -369,19 +369,19 @@ function jsonInstabilityIssues(document2) {
369
369
  return issues;
370
370
  }
371
371
  function createStore(options) {
372
- const { dirPath, name: name2, fields, pruneUnknown, access: access2 } = options;
372
+ const { dirPath, name: name2, fields, pruneUnknown, access: access3 } = options;
373
373
  const validators = /* @__PURE__ */ new Map();
374
374
  for (const [key, def] of Object.entries(fields)) if (def.schema !== void 0) {
375
375
  for (const option of ["default", "validate"]) if (def[option] !== void 0) throw new CrustStoreError("DEFINITION", `field "${key}" mixes "schema" with "${option}" \u2014 the schema exclusively owns validation, transformation, defaults, and optionality`);
376
376
  validators.set(key, makeSchemaValidator(def.schema));
377
377
  } else if (def.validate !== void 0) validators.set(key, def.validate);
378
378
  const filePath = resolveStorePath(dirPath, name2);
379
- const writeOptions = access2 === "private" ? {
379
+ const writeOptions = access3 === "private" ? {
380
380
  fileMode: 384,
381
381
  directoryMode: 448
382
- } : access2 === void 0 || access2 === "default" ? {} : {
383
- fileMode: access2.file,
384
- directoryMode: access2.directory
382
+ } : access3 === void 0 || access3 === "default" ? {} : {
383
+ fileMode: access3.file,
384
+ directoryMode: access3.directory
385
385
  };
386
386
  function normalizeStateTypes(state) {
387
387
  const normalized = { ...state };
@@ -1674,7 +1674,7 @@ var require_for_each = __commonJS({
1674
1674
  function isArray(x2) {
1675
1675
  return toStr.call(x2) === "[object Array]";
1676
1676
  }
1677
- module.exports = function forEach(list2, iterator, thisArg) {
1677
+ module.exports = function forEach(list3, iterator, thisArg) {
1678
1678
  if (!isCallable(iterator)) {
1679
1679
  throw new TypeError("iterator must be a function");
1680
1680
  }
@@ -1682,12 +1682,12 @@ var require_for_each = __commonJS({
1682
1682
  if (arguments.length >= 3) {
1683
1683
  receiver = thisArg;
1684
1684
  }
1685
- if (isArray(list2)) {
1686
- forEachArray(list2, iterator, receiver);
1687
- } else if (typeof list2 === "string") {
1688
- forEachString(list2, iterator, receiver);
1685
+ if (isArray(list3)) {
1686
+ forEachArray(list3, iterator, receiver);
1687
+ } else if (typeof list3 === "string") {
1688
+ forEachString(list3, iterator, receiver);
1689
1689
  } else {
1690
- forEachObject(list2, iterator, receiver);
1690
+ forEachObject(list3, iterator, receiver);
1691
1691
  }
1692
1692
  };
1693
1693
  }
@@ -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(resolve13, reject) {
2316
- deferredResolve = resolve13;
2315
+ deferred = new this.Promise(function(resolve15, reject) {
2316
+ deferredResolve = resolve15;
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(resolve13, reject) {
2464
+ return new this.Promise(function(resolve15, 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
- resolve13(ret);
2470
+ resolve15(ret);
2471
2471
  }
2472
2472
  });
2473
2473
  } else {
2474
- resolve13(fnx());
2474
+ resolve15(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((resolve13, reject) => {
6865
+ return new P((resolve15, 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
- resolve13(result);
6873
+ resolve15(result);
6874
6874
  }
6875
6875
  } else {
6876
- resolve13(result);
6876
+ resolve15(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
- resolve13(result);
6884
+ resolve15(result);
6885
6885
  }
6886
6886
  });
6887
6887
  } else {
6888
- args.push(resolve13);
6888
+ args.push(resolve15);
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 stat7 = normalizeStats(entry);
8087
- writer.writeUInt32BE(stat7.ctimeSeconds);
8088
- writer.writeUInt32BE(stat7.ctimeNanoseconds);
8089
- writer.writeUInt32BE(stat7.mtimeSeconds);
8090
- writer.writeUInt32BE(stat7.mtimeNanoseconds);
8091
- writer.writeUInt32BE(stat7.dev);
8092
- writer.writeUInt32BE(stat7.ino);
8093
- writer.writeUInt32BE(stat7.mode);
8094
- writer.writeUInt32BE(stat7.uid);
8095
- writer.writeUInt32BE(stat7.gid);
8096
- writer.writeUInt32BE(stat7.size);
8086
+ const stat8 = normalizeStats(entry);
8087
+ writer.writeUInt32BE(stat8.ctimeSeconds);
8088
+ writer.writeUInt32BE(stat8.ctimeNanoseconds);
8089
+ writer.writeUInt32BE(stat8.mtimeSeconds);
8090
+ writer.writeUInt32BE(stat8.mtimeNanoseconds);
8091
+ writer.writeUInt32BE(stat8.dev);
8092
+ writer.writeUInt32BE(stat8.ino);
8093
+ writer.writeUInt32BE(stat8.mode);
8094
+ writer.writeUInt32BE(stat8.uid);
8095
+ writer.writeUInt32BE(stat8.gid);
8096
+ writer.writeUInt32BE(stat8.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 [stat7, rawIndexFile] = await Promise.all([
8148
+ const [stat8, 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, stat7);
8154
+ cache.stats.set(filepath, stat8);
8155
8155
  }
8156
8156
  async function isIndexStale(fs2, filepath, cache) {
8157
8157
  const savedStats = cache.stats.get(filepath);
@@ -8208,7 +8208,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8208
8208
  }
8209
8209
  return path;
8210
8210
  }
8211
- function dirname8(path) {
8211
+ function dirname11(path) {
8212
8212
  const last = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
8213
8213
  if (last === -1) return ".";
8214
8214
  if (last === 0) return "/";
@@ -8216,7 +8216,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8216
8216
  }
8217
8217
  function flatFileListToDirectoryStructure(files) {
8218
8218
  const inodes = /* @__PURE__ */ new Map();
8219
- const mkdir9 = function(name2) {
8219
+ const mkdir12 = function(name2) {
8220
8220
  if (!inodes.has(name2)) {
8221
8221
  const dir = {
8222
8222
  type: "tree",
@@ -8226,7 +8226,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8226
8226
  children: []
8227
8227
  };
8228
8228
  inodes.set(name2, dir);
8229
- dir.parent = mkdir9(dirname8(name2));
8229
+ dir.parent = mkdir12(dirname11(name2));
8230
8230
  if (dir.parent && dir.parent !== dir) dir.parent.children.push(dir);
8231
8231
  }
8232
8232
  return inodes.get(name2);
@@ -8239,7 +8239,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8239
8239
  basename: basename6(name2),
8240
8240
  metadata,
8241
8241
  // This recursively generates any missing parent folders.
8242
- parent: mkdir9(dirname8(name2)),
8242
+ parent: mkdir12(dirname11(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
- mkdir9(".");
8250
+ mkdir12(".");
8251
8251
  for (const file2 of files) {
8252
8252
  mkfile(file2.path, file2);
8253
8253
  }
@@ -8437,12 +8437,12 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8437
8437
  };
8438
8438
  NoRefspecError.code = "NoRefspecError";
8439
8439
  var GitPackedRefs = class _GitPackedRefs {
8440
- constructor(text) {
8440
+ constructor(text2) {
8441
8441
  this.refs = /* @__PURE__ */ new Map();
8442
8442
  this.parsedConfig = [];
8443
- if (text) {
8443
+ if (text2) {
8444
8444
  let key = null;
8445
- this.parsedConfig = text.trim().split("\n").map((line) => {
8445
+ this.parsedConfig = text2.trim().split("\n").map((line) => {
8446
8446
  if (/^\s*#/.test(line)) {
8447
8447
  return { line, comment: true };
8448
8448
  }
@@ -8461,8 +8461,8 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8461
8461
  }
8462
8462
  return this;
8463
8463
  }
8464
- static from(text) {
8465
- return new _GitPackedRefs(text);
8464
+ static from(text2) {
8465
+ return new _GitPackedRefs(text2);
8466
8466
  }
8467
8467
  delete(ref) {
8468
8468
  this.parsedConfig = this.parsedConfig.filter((entry) => entry.ref !== ref);
@@ -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 join11(...args) {
8653
+ function join15(...args) {
8654
8654
  if (args.length === 0) return ".";
8655
8655
  let joined;
8656
8656
  for (let i2 = 0; i2 < args.length; ++i2) {
@@ -8732,22 +8732,22 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8732
8732
  }
8733
8733
  return valueWithoutComment;
8734
8734
  };
8735
- var hasOddNumberOfQuotes = (text) => {
8736
- const numberOfQuotes = (text.match(/(?:^|[^\\])"/g) || []).length;
8735
+ var hasOddNumberOfQuotes = (text2) => {
8736
+ const numberOfQuotes = (text2.match(/(?:^|[^\\])"/g) || []).length;
8737
8737
  return numberOfQuotes % 2 !== 0;
8738
8738
  };
8739
- var removeQuotes = (text) => {
8740
- return text.split("").reduce((newText, c, idx, text2) => {
8741
- const isQuote = c === '"' && text2[idx - 1] !== "\\";
8742
- const isEscapeForQuote = c === "\\" && text2[idx + 1] === '"';
8739
+ var removeQuotes = (text2) => {
8740
+ return text2.split("").reduce((newText, c, idx, text3) => {
8741
+ const isQuote = c === '"' && text3[idx - 1] !== "\\";
8742
+ const isEscapeForQuote = c === "\\" && text3[idx + 1] === '"';
8743
8743
  if (isQuote || isEscapeForQuote) {
8744
8744
  return newText;
8745
8745
  }
8746
8746
  return newText + c;
8747
8747
  }, "");
8748
8748
  };
8749
- var lower = (text) => {
8750
- return text != null ? text.toLowerCase() : null;
8749
+ var lower = (text2) => {
8750
+ return text2 != null ? text2.toLowerCase() : null;
8751
8751
  };
8752
8752
  var getPath = (section, subsection, name2) => {
8753
8753
  return [lower(section), subsection, lower(name2)].filter((a) => a != null).join(".");
@@ -8772,10 +8772,10 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8772
8772
  }, -1);
8773
8773
  };
8774
8774
  var GitConfig = class _GitConfig {
8775
- constructor(text) {
8775
+ constructor(text2) {
8776
8776
  let section = null;
8777
8777
  let subsection = null;
8778
- this.parsedConfig = text ? text.split("\n").map((line) => {
8778
+ this.parsedConfig = text2 ? text2.split("\n").map((line) => {
8779
8779
  let name2 = null;
8780
8780
  let value = null;
8781
8781
  const trimmedLine = line.trim();
@@ -8796,8 +8796,8 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8796
8796
  return { line, isSection, section, subsection, name: name2, value, path };
8797
8797
  }) : [];
8798
8798
  }
8799
- static from(text) {
8800
- return new _GitConfig(text);
8799
+ static from(text2) {
8800
+ return new _GitConfig(text2);
8801
8801
  }
8802
8802
  async get(path, getall = false) {
8803
8803
  const normalizedPath = normalizePath(path).path;
@@ -8908,8 +8908,8 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
8908
8908
  * @returns {Promise<GitConfig>} A `GitConfig` object representing the parsed configuration.
8909
8909
  */
8910
8910
  static async get({ fs: fs2, gitdir }) {
8911
- const text = await fs2.read(`${gitdir}/config`, { encoding: "utf8" });
8912
- return GitConfig.from(text);
8911
+ const text2 = await fs2.read(`${gitdir}/config`, { encoding: "utf8" });
8912
+ return GitConfig.from(text2);
8913
8913
  }
8914
8914
  /**
8915
8915
  * Saves the provided Git configuration to the specified `.git` directory.
@@ -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(join11(gitdir, key), `${value.trim()}
9055
+ async () => fs2.write(join15(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(join11(gitdir, ref), `${value.trim()}
9079
+ async () => fs2.write(join15(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(join11(gitdir, ref), `ref: ${value.trim()}
9097
+ async () => fs2.write(join15(gitdir, ref), `ref: ${value.trim()}
9098
9098
  `, "utf8")
9099
9099
  );
9100
9100
  }
@@ -9121,12 +9121,12 @@ 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(join11(gitdir, ref))));
9125
- let text = await acquireLock(
9124
+ await Promise.all(refs.map((ref) => fs2.rm(join15(gitdir, ref))));
9125
+ let text2 = await acquireLock(
9126
9126
  "packed-refs",
9127
9127
  async () => fs2.read(`${gitdir}/packed-refs`, { encoding: "utf8" })
9128
9128
  );
9129
- const packed = GitPackedRefs.from(text);
9129
+ const packed = GitPackedRefs.from(text2);
9130
9130
  const beforeSize = packed.refs.size;
9131
9131
  for (const ref of refs) {
9132
9132
  if (packed.refs.has(ref)) {
@@ -9134,10 +9134,10 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
9134
9134
  }
9135
9135
  }
9136
9136
  if (packed.refs.size < beforeSize) {
9137
- text = packed.toString();
9137
+ text2 = packed.toString();
9138
9138
  await acquireLock(
9139
9139
  "packed-refs",
9140
- async () => fs2.write(`${gitdir}/packed-refs`, text, { encoding: "utf8" })
9140
+ async () => fs2.write(`${gitdir}/packed-refs`, text2, { encoding: "utf8" })
9141
9141
  );
9142
9142
  }
9143
9143
  }
@@ -9330,11 +9330,11 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
9330
9330
  * @returns {Promise<Map<string, string>>} - A map of packed refs.
9331
9331
  */
9332
9332
  static async packedRefs({ fs: fs2, gitdir }) {
9333
- const text = await acquireLock(
9333
+ const text2 = await acquireLock(
9334
9334
  "packed-refs",
9335
9335
  async () => fs2.read(`${gitdir}/packed-refs`, { encoding: "utf8" })
9336
9336
  );
9337
- const packed = GitPackedRefs.from(text);
9337
+ const packed = GitPackedRefs.from(text2);
9338
9338
  return packed.refs;
9339
9339
  }
9340
9340
  /**
@@ -10208,9 +10208,9 @@ 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 list2 = await fs2.readdir(join11(gitdir, "objects/pack"));
10212
- list2 = list2.filter((x2) => x2.endsWith(".idx"));
10213
- for (const filename of list2) {
10211
+ let list3 = await fs2.readdir(join15(gitdir, "objects/pack"));
10212
+ list3 = list3.filter((x2) => x2.endsWith(".idx"));
10213
+ for (const filename of list3) {
10214
10214
  const indexFile = `${gitdir}/objects/pack/${filename}`;
10215
10215
  const p = await readPackIndex({
10216
10216
  fs: fs2,
@@ -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(join11(filepath, entry2.path), entry2);
11068
+ map2.set(join15(filepath, entry2.path), entry2);
11069
11069
  }
11070
- return tree.entries().map((entry2) => join11(filepath, entry2.path));
11070
+ return tree.entries().map((entry2) => join15(filepath, entry2.path));
11071
11071
  }
11072
11072
  async type(entry) {
11073
11073
  if (entry._type === false) {
@@ -11122,12 +11122,12 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
11122
11122
  return o;
11123
11123
  }
11124
11124
  var GitWalkerFs = class {
11125
- constructor({ fs: fs2, dir, gitdir, cache, refresh = true }) {
11125
+ constructor({ fs: fs2, dir, gitdir, cache, refresh: refresh2 = true }) {
11126
11126
  this.fs = fs2;
11127
11127
  this.cache = cache;
11128
11128
  this.dir = dir;
11129
11129
  this.gitdir = gitdir;
11130
- this.refresh = refresh;
11130
+ this.refresh = refresh2;
11131
11131
  this.config = null;
11132
11132
  const walker = this;
11133
11133
  this.ConstructEntry = class WorkdirEntry {
@@ -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(join11(dir, filepath));
11163
+ const names = await fs2.readdir(join15(dir, filepath));
11164
11164
  if (names === null) return null;
11165
- return names.map((name2) => join11(filepath, name2));
11165
+ return names.map((name2) => join15(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 stat7 = await fs2.lstat(`${dir}/${entry._fullpath}`);
11183
- if (!stat7) {
11182
+ let stat8 = await fs2.lstat(`${dir}/${entry._fullpath}`);
11183
+ if (!stat8) {
11184
11184
  throw new Error(
11185
11185
  `ENOENT: no such file or directory, lstat '${entry._fullpath}'`
11186
11186
  );
11187
11187
  }
11188
- let type = stat7.isDirectory() ? "tree" : "blob";
11189
- if (type === "blob" && !stat7.isFile() && !stat7.isSymbolicLink()) {
11188
+ let type = stat8.isDirectory() ? "tree" : "blob";
11189
+ if (type === "blob" && !stat8.isFile() && !stat8.isSymbolicLink()) {
11190
11190
  type = "special";
11191
11191
  }
11192
11192
  entry._type = type;
11193
- stat7 = normalizeStats(stat7);
11194
- entry._mode = stat7.mode;
11195
- if (stat7.size === -1 && entry._actualSize) {
11196
- stat7.size = entry._actualSize;
11193
+ stat8 = normalizeStats(stat8);
11194
+ entry._mode = stat8.mode;
11195
+ if (stat8.size === -1 && entry._actualSize) {
11196
+ stat8.size = entry._actualSize;
11197
11197
  }
11198
- entry._stat = stat7;
11198
+ entry._stat = stat8;
11199
11199
  }
11200
11200
  return entry._stat;
11201
11201
  }
@@ -11268,11 +11268,11 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
11268
11268
  return this.config;
11269
11269
  }
11270
11270
  };
11271
- function WORKDIR({ refresh = true } = {}) {
11271
+ function WORKDIR({ refresh: refresh2 = true } = {}) {
11272
11272
  const o = /* @__PURE__ */ Object.create(null);
11273
11273
  Object.defineProperty(o, GitWalkSymbol, {
11274
11274
  value: function({ fs: fs2, dir, gitdir, cache }) {
11275
- return new GitWalkerFs({ fs: fs2, dir, gitdir, cache, refresh });
11275
+ return new GitWalkerFs({ fs: fs2, dir, gitdir, cache, refresh: refresh2 });
11276
11276
  }
11277
11277
  });
11278
11278
  Object.freeze(o);
@@ -11383,24 +11383,24 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
11383
11383
  };
11384
11384
  return walk2(root);
11385
11385
  }
11386
- async function mkdirp(mkdir9, filepath, retries = 10) {
11386
+ async function mkdirp(mkdir12, filepath, retries = 10) {
11387
11387
  try {
11388
- await mkdir9(filepath);
11388
+ await mkdir12(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 = dirname8(filepath);
11393
+ const parent = dirname11(filepath);
11394
11394
  if (parent === "." || parent === "/" || parent === filepath) throw err2;
11395
- await mkdirp(mkdir9, parent, retries);
11395
+ await mkdirp(mkdir12, parent, retries);
11396
11396
  for (let attempt = 0; ; attempt++) {
11397
11397
  try {
11398
- await mkdir9(filepath);
11398
+ await mkdir12(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((resolve13) => setTimeout(resolve13, 0));
11403
+ await new Promise((resolve15) => setTimeout(resolve15, 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 = join11(filepath, entry);
11419
- return fs2.lstat(subpath).then((stat7) => {
11420
- if (!stat7) return;
11421
- return stat7.isDirectory() ? rmRecursive(fs2, subpath) : fs2.rm(subpath);
11418
+ const subpath = join15(filepath, entry);
11419
+ return fs2.lstat(subpath).then((stat8) => {
11420
+ if (!stat8) return;
11421
+ return stat8.isDirectory() ? rmRecursive(fs2, subpath) : fs2.rm(subpath);
11422
11422
  });
11423
11423
  })
11424
11424
  ).then(() => fs2.rmdir(filepath));
@@ -11427,9 +11427,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
11427
11427
  }
11428
11428
  }
11429
11429
  function isPromiseLike(obj) {
11430
- return isObject2(obj) && isFunction(obj.then) && isFunction(obj.catch);
11430
+ return isObject3(obj) && isFunction(obj.then) && isFunction(obj.catch);
11431
11431
  }
11432
- function isObject2(obj) {
11432
+ function isObject3(obj) {
11433
11433
  return obj && typeof obj === "object";
11434
11434
  }
11435
11435
  function isFunction(obj) {
@@ -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(dirname8(filepath));
11557
+ await this.mkdir(dirname11(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 = join11(dirname8(dotgit), submoduleGitdir);
11703
+ const gitdir = join15(dirname11(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 = join11(dir, ".git"),
11725
+ gitdir = join15(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 = join11(dir, ".git"), filepath }) {
11806
+ static async isIgnored({ fs: fs2, dir, gitdir = join15(dir, ".git"), filepath }) {
11807
11807
  if (basename6(filepath) === ".git") return true;
11808
11808
  if (filepath === ".") return false;
11809
11809
  let excludes = "";
11810
- const excludesFile = join11(gitdir, "info", "exclude");
11810
+ const excludesFile = join15(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: join11(dir, ".gitignore"),
11816
+ gitignore: join15(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: join11(dir, folder, ".gitignore"),
11825
+ gitignore: join15(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 = dirname8(p.filepath);
11839
+ const parentdir = dirname11(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 = join11(dir, ".git"),
11912
+ gitdir = join15(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(join11(dir, currentFilepath));
11976
+ const stats = await fs2.lstat(join15(dir, currentFilepath));
11977
11977
  if (!stats) throw new NotFoundError(currentFilepath);
11978
11978
  if (stats.isDirectory()) {
11979
- const children = await fs2.readdir(join11(dir, currentFilepath));
11979
+ const children = await fs2.readdir(join15(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: [join11(currentFilepath, child)],
11986
+ filepath: [join15(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: [join11(currentFilepath, child)],
12000
+ filepath: [join15(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(join11(dir, currentFilepath)).then(posixifyPathBuffer) : await fs2.read(join11(dir, currentFilepath), { autocrlf });
12009
+ const object2 = stats.isSymbolicLink() ? await fs2.readlink(join15(dir, currentFilepath)).then(posixifyPathBuffer) : await fs2.read(join15(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 = join11(dir, ".git"),
12443
+ gitdir = join15(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 = join11(dir, ".git"),
12513
+ gitdir = join15(dir, ".git"),
12514
12514
  remote,
12515
12515
  url: url2,
12516
12516
  force = false
@@ -12580,7 +12580,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
12580
12580
  fs: _fs,
12581
12581
  onSign,
12582
12582
  dir,
12583
- gitdir = join11(dir, ".git"),
12583
+ gitdir = join15(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 = join11(dir, ".git"),
12664
+ gitdir = join15(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 = join11(dir, ".git"),
13328
+ gitdir = join15(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 = join11(dir, ".git"),
13409
+ gitdir = join15(dir, ".git"),
13410
13410
  index: index3,
13411
13411
  ourOid,
13412
13412
  baseOid,
@@ -13676,7 +13676,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
13676
13676
  workdir: WORKDIR
13677
13677
  };
13678
13678
  async function checkAndWriteBlob(fs2, gitdir, dir, filepath, oid = null) {
13679
- const currentFilepath = join11(dir, filepath);
13679
+ const currentFilepath = join15(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(join11(dir, filepath))
13848
+ stats: await fs2.lstat(join15(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 = join11(dir, op.filepath);
13861
+ const currentFilepath = join15(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 = join11(dir, ".git"),
13995
+ gitdir = join15(dir, ".git"),
13996
13996
  oid,
13997
13997
  cache = {},
13998
13998
  committer,
@@ -14259,8 +14259,8 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
14259
14259
  }
14260
14260
  return { protocolVersion: 1, capabilities, refs, symrefs };
14261
14261
  }
14262
- function splitAndAssert(line, sep2, expected) {
14263
- const split = line.trim().split(sep2);
14262
+ function splitAndAssert(line, sep3, expected) {
14263
+ const split = line.trim().split(sep3);
14264
14264
  if (split.length !== 2) {
14265
14265
  throw new ParseError(
14266
14266
  `Two strings separated by '${expected}'`,
@@ -14497,13 +14497,13 @@ ${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 = join11(gitdir, "shallow");
14500
+ const filepath = join15(gitdir, "shallow");
14501
14501
  const oids = /* @__PURE__ */ new Set();
14502
14502
  await acquireLock(filepath, async function() {
14503
- const text = await fs2.read(filepath, { encoding: "utf8" });
14504
- if (text === null) return oids;
14505
- if (text.trim() === "") return oids;
14506
- text.trim().split("\n").map((oid) => oids.add(oid));
14503
+ const text2 = await fs2.read(filepath, { encoding: "utf8" });
14504
+ if (text2 === null) return oids;
14505
+ if (text2.trim() === "") return oids;
14506
+ text2.trim().split("\n").map((oid) => oids.add(oid));
14507
14507
  });
14508
14508
  return oids;
14509
14509
  }
@@ -14518,11 +14518,11 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
14518
14518
  * @returns {Promise<void>}
14519
14519
  */
14520
14520
  static async write({ fs: fs2, gitdir, oids }) {
14521
- const filepath = join11(gitdir, "shallow");
14521
+ const filepath = join15(gitdir, "shallow");
14522
14522
  if (oids.size > 0) {
14523
- const text = [...oids].join("\n") + "\n";
14523
+ const text2 = [...oids].join("\n") + "\n";
14524
14524
  await acquireLock(filepath, async function() {
14525
- await fs2.write(filepath, text, {
14525
+ await fs2.write(filepath, text2, {
14526
14526
  encoding: "utf8"
14527
14527
  });
14528
14528
  });
@@ -14544,9 +14544,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
14544
14544
  oid,
14545
14545
  getExternalRefDelta
14546
14546
  }) {
14547
- let list2 = await fs2.readdir(join11(gitdir, "objects/pack"));
14548
- list2 = list2.filter((x2) => x2.endsWith(".idx"));
14549
- for (const filename of list2) {
14547
+ let list3 = await fs2.readdir(join15(gitdir, "objects/pack"));
14548
+ list3 = list3.filter((x2) => x2.endsWith(".idx"));
14549
+ for (const filename of list3) {
14550
14550
  const indexFile = `${gitdir}/objects/pack/${filename}`;
14551
14551
  const p = await readPackIndex({
14552
14552
  fs: fs2,
@@ -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 resolve13 = this._waiting;
14619
+ const resolve15 = this._waiting;
14620
14620
  this._waiting = null;
14621
- resolve13({ value: chunk });
14621
+ resolve15({ 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 resolve13 = this._waiting;
14629
+ const resolve15 = this._waiting;
14630
14630
  this._waiting = null;
14631
- resolve13({ done: true });
14631
+ resolve15({ 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((resolve13) => {
14651
- this._waiting = resolve13;
14650
+ return new Promise((resolve15) => {
14651
+ this._waiting = resolve15;
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((resolve13, reject) => {
14806
+ return new Promise((resolve15, 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) : resolve13({ shallows, unshallows, acks, nak, packfile, progress });
14833
+ stream.error ? reject(stream.error) : resolve15({ shallows, unshallows, acks, nak, packfile, progress });
14834
14834
  }
14835
14835
  }).finally(() => {
14836
14836
  if (!done) {
14837
- stream.error ? reject(stream.error) : resolve13({ shallows, unshallows, acks, nak, packfile, progress });
14837
+ stream.error ? reject(stream.error) : resolve15({ 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: relative2 = false,
14904
+ relative: relative3 = 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 (relative2 === true && !remoteHTTP.capabilities.has("deepen-relative")) {
14952
+ if (relative3 === 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 (relative2) capabilities.push("deepen-relative");
14980
+ if (relative3) 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 = join11(gitdir, res.packfile);
15138
+ const fullpath = join15(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 : join11(dir, ".git"),
15154
+ gitdir = bare ? dir : join15(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: relative2,
15200
+ relative: relative3,
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: relative2,
15232
+ relative: relative3,
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 = join11(dir, ".git"),
15268
+ gitdir = join15(dir, ".git"),
15269
15269
  url: url2,
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: relative2 = false,
15276
+ relative: relative3 = 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: relative2,
15314
+ relative: relative3,
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 = join11(dir, ".git"),
15331
+ gitdir = join15(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 = join11(dir, ".git"),
15380
+ gitdir = join15(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 = join11(dir, ".git"),
15421
+ gitdir = join15(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 = join11(dir, ".git"), ref }) {
15439
+ async function deleteRef({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git"),
15459
+ gitdir = join15(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 = join11(dir, ".git"), ref }) {
15481
+ async function deleteTag({ fs: fs2, dir, gitdir = join15(dir, ".git"), ref }) {
15482
15482
  try {
15483
15483
  assertParameter("fs", fs2);
15484
15484
  assertParameter("ref", ref);
@@ -15507,9 +15507,9 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
15507
15507
  getExternalRefDelta
15508
15508
  }) {
15509
15509
  const results = [];
15510
- let list2 = await fs2.readdir(join11(gitdir, "objects/pack"));
15511
- list2 = list2.filter((x2) => x2.endsWith(".idx"));
15512
- for (const filename of list2) {
15510
+ let list3 = await fs2.readdir(join15(gitdir, "objects/pack"));
15511
+ list3 = list3.filter((x2) => x2.endsWith(".idx"));
15512
+ for (const filename of list3) {
15513
15513
  const indexFile = `${gitdir}/objects/pack/${filename}`;
15514
15514
  const p = await readPackIndex({
15515
15515
  fs: fs2,
@@ -15550,7 +15550,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
15550
15550
  async function expandOid({
15551
15551
  fs: fs2,
15552
15552
  dir,
15553
- gitdir = join11(dir, ".git"),
15553
+ gitdir = join15(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 = join11(dir, ".git"), ref }) {
15574
+ async function expandRef({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git"),
15865
+ gitdir = join15(dir, ".git"),
15866
15866
  ref,
15867
15867
  url: url2,
15868
15868
  remote,
@@ -15920,7 +15920,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
15920
15920
  onAuthSuccess,
15921
15921
  onAuthFailure,
15922
15922
  dir,
15923
- gitdir = join11(dir, ".git"),
15923
+ gitdir = join15(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: relative2 = false,
15932
+ relative: relative3 = 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: relative2,
15964
+ relative: relative3,
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 = join11(dir, ".git"),
15979
+ gitdir = join15(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(join11(filepath, ".git"))) {
16001
+ if (await fs2.exists(join15(filepath, ".git"))) {
16002
16002
  return filepath;
16003
16003
  } else {
16004
- const parent = dirname8(filepath);
16004
+ const parent = dirname11(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 = join11(dir, ".git"), path }) {
16021
+ async function getConfig({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git"),
16045
+ gitdir = join15(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 = join11(dir, filepath);
16234
+ filepath = join15(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 = join11(dir, ".git"),
16255
+ gitdir = join15(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 : join11(dir, ".git"),
16283
+ gitdir = bare ? dir : join15(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 = join11(dir, ".git"),
16357
+ gitdir = join15(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 = join11(dir, ".git"),
16386
+ gitdir = join15(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 = join11(dir, ".git"),
16410
+ gitdir = join15(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: join11(prefix, entry.path)
16467
+ prefix: join15(prefix, entry.path)
16468
16468
  });
16469
16469
  } else {
16470
- filenames.push(join11(prefix, entry.path));
16470
+ filenames.push(join15(prefix, entry.path));
16471
16471
  }
16472
16472
  }
16473
16473
  }
16474
16474
  async function listFiles({
16475
16475
  fs: fs2,
16476
16476
  dir,
16477
- gitdir = join11(dir, ".git"),
16477
+ gitdir = join15(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 = join11(dir, ".git"),
16521
+ gitdir = join15(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 = join11(dir, ".git"),
16545
+ gitdir = join15(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 = join11(dir, ".git") }) {
16570
+ async function listRemotes({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git") }) {
16669
+ async function listTags({ fs: fs2, dir, gitdir = join15(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 = join11(parentPath, entry.path);
16722
+ result = join15(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: join11(parentPath, entry.path)
16739
+ parentPath: join15(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 = join11(dir, ".git"),
16914
+ gitdir = join15(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 = join11(dir, ".git"),
16952
+ gitdir = join15(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 = join11(dir, ".git"),
17029
+ gitdir = join15(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(join11(gitdir, `objects/pack/${filename}`), packfile);
17072
+ await fs2.write(join15(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 = join11(dir, ".git"),
17083
+ gitdir = join15(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 = join11(dir, ".git"),
17115
+ gitdir = join15(dir, ".git"),
17116
17116
  ref,
17117
17117
  url: url2,
17118
17118
  remote,
@@ -17182,7 +17182,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
17182
17182
  fs: fs2,
17183
17183
  cache,
17184
17184
  dir,
17185
- gitdir = join11(dir, ".git"),
17185
+ gitdir = join15(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 = join11(dir, ".git"),
17233
+ gitdir = join15(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 = join11(dir, ".git"),
17536
+ gitdir = join15(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 = join11(dir, ".git"),
17612
+ gitdir = join15(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 = join11(dir, ".git"),
17638
+ gitdir = join15(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 = join11(dir, ".git"),
17679
+ gitdir = join15(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 = join11(dir, ".git"),
17706
+ gitdir = join15(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 = join11(dir, ".git"),
17795
+ gitdir = join15(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 = join11(dir, ".git"),
17819
+ gitdir = join15(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 = join11(dir, ".git"),
17845
+ gitdir = join15(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 = join11(dir, ".git"),
17918
+ gitdir = join15(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 = join11(dir, ".git"),
18006
+ gitdir = join15(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 = join11(dir, ".git"),
18036
+ gitdir = join15(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(join11(dir, filepath));
18083
+ const object2 = dir && await fs2.read(join15(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(join11(dir, filepath));
18091
+ stats = await fs2.lstat(join15(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 = join11(dir, ".git"),
18111
+ gitdir = join15(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 = join11(dir, ".git"),
18136
+ gitdir = join15(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 = join11(dir, ".git") }) {
18204
+ constructor({ fs: fs2, dir, gitdir = join15(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 join11(this.gitdir, _GitStashManager.refStash);
18234
+ return join15(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 join11(this.gitdir, _GitStashManager.refLogsStash);
18242
+ return join15(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 = join11(dir, ".git"),
18548
+ gitdir = join15(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) => join11(updatedGitdir, f)).forEach(async (folder) => {
18571
+ folders.map((f) => join15(updatedGitdir, f)).forEach(async (folder) => {
18572
18572
  if (!await _fs.exists(folder)) {
18573
18573
  await _fs.mkdir(folder);
18574
18574
  }
@@ -18598,10 +18598,10 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18598
18598
  async function status({
18599
18599
  fs: _fs,
18600
18600
  dir,
18601
- gitdir = join11(dir, ".git"),
18601
+ gitdir = join15(dir, ".git"),
18602
18602
  filepath,
18603
18603
  cache = {},
18604
- refresh = true
18604
+ refresh: refresh2 = true
18605
18605
  }) {
18606
18606
  try {
18607
18607
  assertParameter("fs", _fs);
@@ -18637,7 +18637,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18637
18637
  return "ignored";
18638
18638
  }
18639
18639
  }
18640
- const stats = await fs2.lstat(join11(dir, filepath));
18640
+ const stats = await fs2.lstat(join15(dir, filepath));
18641
18641
  const H = treeOid !== null;
18642
18642
  const I = indexEntry !== null;
18643
18643
  const W = stats !== null;
@@ -18647,13 +18647,13 @@ ${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(join11(dir, filepath), { autocrlf });
18650
+ const object2 = await fs2.read(join15(dir, filepath), { autocrlf });
18651
18651
  const workdirOid = await hashObject$1({
18652
18652
  gitdir: updatedGitdir,
18653
18653
  type: "blob",
18654
18654
  object: object2
18655
18655
  });
18656
- if (refresh && I && indexEntry.oid === workdirOid) {
18656
+ if (refresh2 && I && indexEntry.oid === workdirOid) {
18657
18657
  if (stats.size !== -1) {
18658
18658
  GitIndexManager.acquire(
18659
18659
  { fs: fs2, gitdir: updatedGitdir, cache },
@@ -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 dirname9 = path.shift();
18699
+ const dirname12 = path.shift();
18700
18700
  for (const entry of tree) {
18701
- if (entry.path === dirname9) {
18701
+ if (entry.path === dirname12) {
18702
18702
  if (path.length === 0) {
18703
18703
  return entry.oid;
18704
18704
  }
@@ -18738,13 +18738,13 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18738
18738
  async function statusMatrix({
18739
18739
  fs: _fs,
18740
18740
  dir,
18741
- gitdir = join11(dir, ".git"),
18741
+ gitdir = join15(dir, ".git"),
18742
18742
  ref = "HEAD",
18743
18743
  filepaths = ["."],
18744
18744
  filter,
18745
18745
  cache = {},
18746
18746
  ignored: shouldIgnore = false,
18747
- refresh = true
18747
+ refresh: refresh2 = true
18748
18748
  }) {
18749
18749
  try {
18750
18750
  assertParameter("fs", _fs);
@@ -18757,7 +18757,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18757
18757
  cache,
18758
18758
  dir,
18759
18759
  gitdir: updatedGitdir,
18760
- trees: [TREE({ ref }), WORKDIR({ refresh }), STAGE()],
18760
+ trees: [TREE({ ref }), WORKDIR({ refresh: refresh2 }), STAGE()],
18761
18761
  map: async function(filepath, [head, workdir, stage]) {
18762
18762
  if (!head && !stage && workdir) {
18763
18763
  if (!shouldIgnore) {
@@ -18811,7 +18811,7 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
18811
18811
  async function tag({
18812
18812
  fs: _fs,
18813
18813
  dir,
18814
- gitdir = join11(dir, ".git"),
18814
+ gitdir = join15(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 = join11(dir, ".git"),
18846
+ gitdir = join15(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(join11(dir, filepath));
18866
+ const fileStats2 = await fs2.lstat(join15(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(join11(dir, filepath));
18884
+ fileStats = await fs2.lstat(join15(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(join11(dir, filepath)) : await fs2.read(join11(dir, filepath));
18905
+ const object2 = stats.isSymbolicLink() ? await fs2.readlink(join15(dir, filepath)) : await fs2.read(join15(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 = join11(dir, ".git"),
18949
+ gitdir = join15(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 = join11(dir, ".git"), blob: blob2 }) {
18977
+ async function writeBlob({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git"),
18999
+ gitdir = join15(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 = join11(dir, ".git"),
19021
+ gitdir = join15(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 = join11(dir, ".git"),
19067
+ gitdir = join15(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 = join11(dir, ".git"), tag: tag2 }) {
19122
+ async function writeTag({ fs: fs2, dir, gitdir = join15(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 = join11(dir, ".git"), tree }) {
19139
+ async function writeTree2({ fs: fs2, dir, gitdir = join15(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.13.0",
19764
+ version: "0.15.0",
19765
19765
  description: "Agent-friendly AnimaGuru CLI built with CrustJS",
19766
19766
  type: "module",
19767
19767
  bin: {
@@ -20027,8 +20027,8 @@ var sectionOwnerLabels = {
20027
20027
  extension: "Extension"
20028
20028
  };
20029
20029
  function invalidSections({ subject, name: name2 }) {
20030
- const label = sectionOwnerLabels[subject];
20031
- return new CrustError("DEFINITION", `${label} "${name2}" contains invalid documentation sections`, {
20030
+ const label3 = sectionOwnerLabels[subject];
20031
+ return new CrustError("DEFINITION", `${label3} "${name2}" contains invalid documentation sections`, {
20032
20032
  subject,
20033
20033
  name: name2,
20034
20034
  reason: "invalid-sections"
@@ -20317,23 +20317,23 @@ function installExtensionContexts(node2, extensions, reRegisteredIds) {
20317
20317
  }
20318
20318
  return cloned;
20319
20319
  }
20320
- function coerceUrl(raw, label) {
20320
+ function coerceUrl(raw, label3) {
20321
20321
  try {
20322
20322
  return new URL(raw);
20323
20323
  } catch (err2) {
20324
- throw new CrustError("PARSE", `Invalid URL for ${label}: "${raw}"${/^[a-z][a-z0-9+.-]*:/i.test(raw) ? "" : " (missing protocol \u2014 e.g. https://example.com)"}`).withCause(err2);
20324
+ throw new CrustError("PARSE", `Invalid URL for ${label3}: "${raw}"${/^[a-z][a-z0-9+.-]*:/i.test(raw) ? "" : " (missing protocol \u2014 e.g. https://example.com)"}`).withCause(err2);
20325
20325
  }
20326
20326
  }
20327
- function coercePath(raw, label) {
20328
- if (raw === "") throw new CrustError("PARSE", `Path for ${label} cannot be empty`);
20327
+ function coercePath(raw, label3) {
20328
+ if (raw === "") throw new CrustError("PARSE", `Path for ${label3} cannot be empty`);
20329
20329
  const expanded = raw.replace(/^~(?=\/|$)/, () => homedir());
20330
20330
  return resolve(process.cwd(), expanded);
20331
20331
  }
20332
- function coerceJson(raw, label) {
20332
+ function coerceJson(raw, label3) {
20333
20333
  try {
20334
20334
  return JSON.parse(raw);
20335
20335
  } catch (err2) {
20336
- throw new CrustError("PARSE", `Invalid JSON for ${label}: ${err2 instanceof Error ? err2.message : String(err2)}. Tip: wrap JSON in single quotes on the command line, e.g. --flag '{"k":1}'`).withCause(err2);
20336
+ throw new CrustError("PARSE", `Invalid JSON for ${label3}: ${err2 instanceof Error ? err2.message : String(err2)}. Tip: wrap JSON in single quotes on the command line, e.g. --flag '{"k":1}'`).withCause(err2);
20337
20337
  }
20338
20338
  }
20339
20339
  async function runSchema(schema, raw, path, issues) {
@@ -20379,23 +20379,23 @@ function buildParseArgsOptionDescriptor(spellings) {
20379
20379
  }
20380
20380
  return options;
20381
20381
  }
20382
- function coerceValue(value, type, label) {
20382
+ function coerceValue(value, type, label3) {
20383
20383
  if (type === "number") {
20384
20384
  const num = tryCoerceNumber(value);
20385
- if (num === void 0) throw new CrustError("PARSE", `Expected number for ${label}, got "${value}"`);
20385
+ if (num === void 0) throw new CrustError("PARSE", `Expected number for ${label3}, got "${value}"`);
20386
20386
  return num;
20387
20387
  }
20388
20388
  if (type === "boolean") return coerceBooleanString(value);
20389
- if (type === "url") return coerceUrl(value, label);
20390
- if (type === "path") return coercePath(value, label);
20391
- if (type === "json") return coerceJson(value, label);
20389
+ if (type === "url") return coerceUrl(value, label3);
20390
+ if (type === "path") return coercePath(value, label3);
20391
+ if (type === "json") return coerceJson(value, label3);
20392
20392
  return value;
20393
20393
  }
20394
- function validateChoice(raw, choices, label) {
20395
- if (!choices.includes(raw)) throw new CrustError("PARSE", `Invalid value "${raw}" for ${label}. Expected one of: ${choices.join(", ")}`);
20394
+ function validateChoice(raw, choices, label3) {
20395
+ if (!choices.includes(raw)) throw new CrustError("PARSE", `Invalid value "${raw}" for ${label3}. Expected one of: ${choices.join(", ")}`);
20396
20396
  }
20397
- function invokeParse(parse4, raw, label, index2) {
20398
- const location = index2 === void 0 ? label : `${label} element [${index2}]`;
20397
+ function invokeParse(parse4, raw, label3, index2) {
20398
+ const location = index2 === void 0 ? label3 : `${label3} element [${index2}]`;
20399
20399
  let result;
20400
20400
  try {
20401
20401
  result = parse4(raw);
@@ -20409,29 +20409,29 @@ function invokeParse(parse4, raw, label, index2) {
20409
20409
  }
20410
20410
  return result;
20411
20411
  }
20412
- function resolveDefault(def, label) {
20412
+ function resolveDefault(def, label3) {
20413
20413
  const { default: defaultValue, parse: parse4 } = def;
20414
20414
  if (defaultValue === void 0) return void 0;
20415
20415
  if (parse4) {
20416
- if (Array.isArray(defaultValue)) return defaultValue.map((v, i2) => invokeParse(parse4, String(v), label, i2));
20417
- return invokeParse(parse4, String(defaultValue), label);
20416
+ if (Array.isArray(defaultValue)) return defaultValue.map((v, i2) => invokeParse(parse4, String(v), label3, i2));
20417
+ return invokeParse(parse4, String(defaultValue), label3);
20418
20418
  }
20419
20419
  if (def.type === "path") {
20420
- if (Array.isArray(defaultValue)) return defaultValue.map((v) => coercePath(String(v), label));
20421
- return coercePath(String(defaultValue), label);
20420
+ if (Array.isArray(defaultValue)) return defaultValue.map((v) => coercePath(String(v), label3));
20421
+ return coercePath(String(defaultValue), label3);
20422
20422
  }
20423
20423
  return "multiple" in def && def.multiple && Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
20424
20424
  }
20425
- function coerceToken(def, raw, label, index2) {
20425
+ function coerceToken(def, raw, label3, index2) {
20426
20426
  if (def.schema) return raw;
20427
- if (def.choices) validateChoice(raw, def.choices, label);
20428
- if (def.parse) return invokeParse(def.parse, raw, label, index2);
20429
- return coerceValue(raw, def.type, label);
20427
+ if (def.choices) validateChoice(raw, def.choices, label3);
20428
+ if (def.parse) return invokeParse(def.parse, raw, label3, index2);
20429
+ return coerceValue(raw, def.type, label3);
20430
20430
  }
20431
20431
  function coerceFlagValue(name2, def, parsed) {
20432
20432
  if (parsed.kind === "boolean") return parsed.value;
20433
- const label = `--${name2}`;
20434
- return Array.isArray(parsed.value) ? parsed.value.map((value, i2) => coerceToken(def, value, label, i2)) : coerceToken(def, parsed.value, label);
20433
+ const label3 = `--${name2}`;
20434
+ return Array.isArray(parsed.value) ? parsed.value.map((value, i2) => coerceToken(def, value, label3, i2)) : coerceToken(def, parsed.value, label3);
20435
20435
  }
20436
20436
  function resolveAliases(tokens, spellings) {
20437
20437
  const canonical = {};
@@ -20524,7 +20524,7 @@ function resolveArgs(argsDef, positionals, coerce) {
20524
20524
  let index2 = 0;
20525
20525
  for (const def of argsDef) {
20526
20526
  const { name: name2 } = def;
20527
- const label = `<${name2}>`;
20527
+ const label3 = `<${name2}>`;
20528
20528
  Object.defineProperty(resolved, name2, {
20529
20529
  value: void 0,
20530
20530
  writable: true,
@@ -20533,12 +20533,12 @@ function resolveArgs(argsDef, positionals, coerce) {
20533
20533
  });
20534
20534
  if (def.variadic) {
20535
20535
  const remaining = positionals.slice(index2);
20536
- resolved[name2] = remaining.length === 0 && def.default !== void 0 ? [resolveDefault(def, label)] : remaining.map((v, i2) => coerce(def, v, label, i2));
20536
+ resolved[name2] = remaining.length === 0 && def.default !== void 0 ? [resolveDefault(def, label3)] : remaining.map((v, i2) => coerce(def, v, label3, i2));
20537
20537
  index2 = positionals.length;
20538
20538
  } else if (index2 < positionals.length) {
20539
- resolved[name2] = coerce(def, positionals[index2], label);
20539
+ resolved[name2] = coerce(def, positionals[index2], label3);
20540
20540
  index2++;
20541
- } else resolved[name2] = resolveDefault(def, label);
20541
+ } else resolved[name2] = resolveDefault(def, label3);
20542
20542
  }
20543
20543
  return {
20544
20544
  args: resolved,
@@ -20600,7 +20600,7 @@ function tokenizeArgv(command, argv) {
20600
20600
  function isOccurrenceArray(value) {
20601
20601
  return Array.isArray(value);
20602
20602
  }
20603
- function validateStructuredValue(def, value, label) {
20603
+ function validateStructuredValue(def, value, label3) {
20604
20604
  const type = def.schema ? def.type === "boolean" ? "boolean" : "string" : def.type;
20605
20605
  let valid;
20606
20606
  if (type === "url") valid = value instanceof URL;
@@ -20620,21 +20620,21 @@ function validateStructuredValue(def, value, label) {
20620
20620
  }
20621
20621
  }
20622
20622
  } else valid = typeof value === (type === "path" ? "string" : type);
20623
- if (!valid) throw new CrustError("PARSE", `Expected ${type} for ${label}`);
20624
- if (value === false && "noNegate" in def && def.noNegate) throw new CrustError("PARSE", `Flag "${label}" does not support negation`);
20623
+ if (!valid) throw new CrustError("PARSE", `Expected ${type} for ${label3}`);
20624
+ if (value === false && "noNegate" in def && def.noNegate) throw new CrustError("PARSE", `Flag "${label3}" does not support negation`);
20625
20625
  }
20626
- function coerceStructuredValue(def, value, label, index2) {
20627
- validateStructuredValue(def, value, label);
20626
+ function coerceStructuredValue(def, value, label3, index2) {
20627
+ validateStructuredValue(def, value, label3);
20628
20628
  if (def.type !== "string" && def.type !== "path") return value;
20629
- return coerceToken(def, String(value), label, index2);
20629
+ return coerceToken(def, String(value), label3, index2);
20630
20630
  }
20631
20631
  function coerceStructuredFlag(name2, def, value) {
20632
- const label = `--${name2}`;
20632
+ const label3 = `--${name2}`;
20633
20633
  if (def.multiple) {
20634
- if (!isOccurrenceArray(value)) throw new CrustError("PARSE", `Expected an occurrence array for ${label}`);
20635
- return value.map((item, i2) => coerceStructuredValue(def, item, label, i2));
20634
+ if (!isOccurrenceArray(value)) throw new CrustError("PARSE", `Expected an occurrence array for ${label3}`);
20635
+ return value.map((item, i2) => coerceStructuredValue(def, item, label3, i2));
20636
20636
  }
20637
- return coerceStructuredValue(def, value, label);
20637
+ return coerceStructuredValue(def, value, label3);
20638
20638
  }
20639
20639
  function bind(command, positionals, flagValues, coerceArg, coerceFlag) {
20640
20640
  const flags = resolveFlags(command.effectiveFlags, flagValues, coerceFlag);
@@ -21017,13 +21017,13 @@ function resolveCommand(command, argv) {
21017
21017
  }
21018
21018
  var ignoreStreamError = () => {
21019
21019
  };
21020
- function writeLine(stream, text) {
21020
+ function writeLine(stream, text2) {
21021
21021
  const absorb = () => {
21022
21022
  if (stream.listenerCount("error") === 0) stream.once("error", ignoreStreamError);
21023
21023
  };
21024
21024
  try {
21025
21025
  absorb();
21026
- stream.write(`${text}
21026
+ stream.write(`${text2}
21027
21027
  `, (error62) => {
21028
21028
  if (error62) absorb();
21029
21029
  });
@@ -21033,8 +21033,8 @@ function writeLine(stream, text) {
21033
21033
  }
21034
21034
  }
21035
21035
  var DEFAULT_IO = {
21036
- stdout: (text) => writeLine(process.stdout, text),
21037
- stderr: (text) => writeLine(process.stderr, text)
21036
+ stdout: (text2) => writeLine(process.stdout, text2),
21037
+ stderr: (text2) => writeLine(process.stderr, text2)
21038
21038
  };
21039
21039
  var SNAPSHOT_PATH_ENV = "CRUST_INTERNAL_SNAPSHOT_PATH";
21040
21040
  var EXIT_CODE_CANCELLED = 130;
@@ -21048,7 +21048,7 @@ function isSuppressedError(error62) {
21048
21048
  function isObjectLike(value) {
21049
21049
  return typeof value === "object" && value !== null;
21050
21050
  }
21051
- function describeFailure(error62, label = "Error") {
21051
+ function describeFailure(error62, label3 = "Error") {
21052
21052
  const messages = [];
21053
21053
  const seen = /* @__PURE__ */ new Set();
21054
21054
  let remaining = 256;
@@ -21097,7 +21097,7 @@ function describeFailure(error62, label = "Error") {
21097
21097
  }
21098
21098
  };
21099
21099
  visitMember(() => error62);
21100
- return messages.map((message) => `${label}: ${message}`).join("\n");
21100
+ return messages.map((message) => `${label3}: ${message}`).join("\n");
21101
21101
  }
21102
21102
  function freezeTree(node2) {
21103
21103
  Object.freeze(node2);
@@ -21305,13 +21305,13 @@ async function runInvocation(node2, input2, options, materializeCommandDefinitio
21305
21305
  try {
21306
21306
  const { signal = new AbortController().signal, ...sinks } = options ?? {};
21307
21307
  const resolvedIO = {
21308
- stdout(text) {
21309
- stdout.push(text);
21310
- sinks.stdout?.(text);
21308
+ stdout(text2) {
21309
+ stdout.push(text2);
21310
+ sinks.stdout?.(text2);
21311
21311
  },
21312
- stderr(text) {
21313
- stderr.push(text);
21314
- sinks.stderr?.(text);
21312
+ stderr(text2) {
21313
+ stderr.push(text2);
21314
+ sinks.stderr?.(text2);
21315
21315
  }
21316
21316
  };
21317
21317
  return {
@@ -21829,10 +21829,10 @@ function stringWidthJs(input2) {
21829
21829
  function stringWidth(input2) {
21830
21830
  return globalThis.Bun?.stringWidth(input2, { countAnsiEscapeCodes: false }) ?? stringWidthJs(input2);
21831
21831
  }
21832
- function padEnd(text, width, fillChar = " ") {
21833
- const currentWidth = stringWidth(text);
21834
- if (currentWidth >= width) return text;
21835
- return text + fillChar.repeat(width - currentWidth);
21832
+ function padEnd(text2, width, fillChar = " ") {
21833
+ const currentWidth = stringWidth(text2);
21834
+ if (currentWidth >= width) return text2;
21835
+ return text2 + fillChar.repeat(width - currentWidth);
21836
21836
  }
21837
21837
  var modifierCodes = {
21838
21838
  /** Bold / increased intensity. */
@@ -22694,9 +22694,9 @@ var namedColorValues = {
22694
22694
  50
22695
22695
  ]
22696
22696
  };
22697
- function applyStyle(text, style2) {
22698
- if (text == null) return "";
22699
- let result = String(text);
22697
+ function applyStyle(text2, style2) {
22698
+ if (text2 == null) return "";
22699
+ let result = String(text2);
22700
22700
  if (result === "") return "";
22701
22701
  const { open: open7, close } = style2;
22702
22702
  if (result.includes(close)) result = result.replaceAll(close, close + open7);
@@ -22800,15 +22800,15 @@ function colorPair(kind, input2, depth) {
22800
22800
  close: kind === "fg" ? FG_CLOSE : BG_CLOSE
22801
22801
  };
22802
22802
  }
22803
- function paint(kind, text, input2, depth) {
22803
+ function paint(kind, text2, input2, depth) {
22804
22804
  const pair = colorPair(kind, input2, depth);
22805
- return depth === "none" ? text : applyStyle(text, pair);
22805
+ return depth === "none" ? text2 : applyStyle(text2, pair);
22806
22806
  }
22807
22807
  var OSC = "\x1B]";
22808
22808
  var ST = "\x1B\\";
22809
22809
  var HYPERLINK_CLOSE = `${OSC}8;;${ST}`;
22810
- function assertMatches(value, label, pattern, suffix = "") {
22811
- if (!pattern.test(value)) throw new TypeError(`Invalid ${label}: ${JSON.stringify(value)} must contain only printable ASCII characters${suffix}.`);
22810
+ function assertMatches(value, label3, pattern, suffix = "") {
22811
+ if (!pattern.test(value)) throw new TypeError(`Invalid ${label3}: ${JSON.stringify(value)} must contain only printable ASCII characters${suffix}.`);
22812
22812
  }
22813
22813
  function serializeParams(options) {
22814
22814
  const id2 = options?.id;
@@ -22825,8 +22825,8 @@ function linkCode(url2, options) {
22825
22825
  close: HYPERLINK_CLOSE
22826
22826
  };
22827
22827
  }
22828
- function link$1(text, url2, options) {
22829
- return applyStyle(text, linkCode(url2, options));
22828
+ function link$1(text2, url2, options) {
22829
+ return applyStyle(text2, linkCode(url2, options));
22830
22830
  }
22831
22831
  var dynamicColorKinds = ["fg", "bg"];
22832
22832
  function stepIsModifier(step) {
@@ -22850,9 +22850,9 @@ function colorStep(kind, input2) {
22850
22850
  ]
22851
22851
  } : step;
22852
22852
  }
22853
- function applyChain(text, steps, resolveCapabilities) {
22854
- if (text == null) return "";
22855
- let result = String(text);
22853
+ function applyChain(text2, steps, resolveCapabilities) {
22854
+ if (text2 == null) return "";
22855
+ let result = String(text2);
22856
22856
  if (result === "") return result;
22857
22857
  const capabilities = resolveCapabilities();
22858
22858
  const { modifiersEnabled, colorsEnabled } = capabilities;
@@ -22876,12 +22876,12 @@ function buildChainableStyleFactory(resolveCapabilities, runtime) {
22876
22876
  if (cached2) return cached2;
22877
22877
  const styleFn = ((first, ...rest) => {
22878
22878
  if (isTemplateStringsArray(first)) {
22879
- let text = "";
22879
+ let text2 = "";
22880
22880
  for (let i2 = 0; i2 < first.length; i2++) {
22881
- text += first[i2] ?? "";
22882
- if (i2 < rest.length) text += String(rest[i2]);
22881
+ text2 += first[i2] ?? "";
22882
+ if (i2 < rest.length) text2 += String(rest[i2]);
22883
22883
  }
22884
- return applyChain(text, steps, resolveCapabilities);
22884
+ return applyChain(text2, steps, resolveCapabilities);
22885
22885
  }
22886
22886
  return applyChain(first, steps, resolveCapabilities);
22887
22887
  });
@@ -22966,10 +22966,10 @@ function createStyleInstance(options, runtime) {
22966
22966
  get colorDepth() {
22967
22967
  return resolveCapabilities().colorDepth;
22968
22968
  },
22969
- link(text, url2, hyperlinkOptions) {
22970
- if (resolveCapabilities().modifiersEnabled) return link$1(text, url2, hyperlinkOptions);
22969
+ link(text2, url2, hyperlinkOptions) {
22970
+ if (resolveCapabilities().modifiersEnabled) return link$1(text2, url2, hyperlinkOptions);
22971
22971
  linkCode(url2, hyperlinkOptions);
22972
- return text;
22972
+ return text2;
22973
22973
  },
22974
22974
  ...Object.fromEntries(dynamicColorKinds.map((kind) => [kind, (...args) => {
22975
22975
  if (args.length === 1) return createChainableStyle([colorStep(kind, args[0])]);
@@ -23073,12 +23073,12 @@ function fishSingleQuote(value) {
23073
23073
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
23074
23074
  }
23075
23075
  function subcmdWordlist(node2) {
23076
- const words = [];
23076
+ const words2 = [];
23077
23077
  for (const sub of node2.subCommands) {
23078
- words.push(sub.name);
23079
- if (sub.aliases !== void 0) for (const alias of sub.aliases) words.push(alias);
23078
+ words2.push(sub.name);
23079
+ if (sub.aliases !== void 0) for (const alias of sub.aliases) words2.push(alias);
23080
23080
  }
23081
- return words.join(" ");
23081
+ return words2.join(" ");
23082
23082
  }
23083
23083
  function flagWordlist(node2) {
23084
23084
  return node2.flags.flatMap((flag) => flag.spellings).join(" ");
@@ -23168,12 +23168,12 @@ function collectArgChoiceCases(cmdPath, node2, out2) {
23168
23168
  for (const sub of node2.subCommands) collectArgChoiceCases(childPath(cmdPath, sub.name), sub, out2);
23169
23169
  }
23170
23170
  function valueFlagWordlist(node2) {
23171
- const words = [];
23171
+ const words2 = [];
23172
23172
  for (const flag of node2.flags) {
23173
23173
  if (!flag.takesValue) continue;
23174
- for (const spelling of flag.spellings) words.push(spelling);
23174
+ for (const spelling of flag.spellings) words2.push(spelling);
23175
23175
  }
23176
- return words.join(" ");
23176
+ return words2.join(" ");
23177
23177
  }
23178
23178
  function renderBash(spec, binName, version3, command = "completion") {
23179
23179
  const ident = toShellIdent(binName);
@@ -23896,8 +23896,8 @@ var FLAG_COLUMN_WIDTH = 28;
23896
23896
  var ARG_COLUMN_WIDTH = 18;
23897
23897
  var COMMAND_COLUMN_WIDTH = 10;
23898
23898
  var HELP = defineExtensionId("crust:help");
23899
- function formatArgText(text, required2) {
23900
- return required2 ? yellow(text) : dim(yellow(text));
23899
+ function formatArgText(text2, required2) {
23900
+ return required2 ? yellow(text2) : dim(yellow(text2));
23901
23901
  }
23902
23902
  function formatUsageSegment(segment) {
23903
23903
  switch (segment.kind) {
@@ -23913,7 +23913,7 @@ function formatUsageSegment(segment) {
23913
23913
  }
23914
23914
  function formatSection(title, width, rows) {
23915
23915
  if (rows.length === 0) return [];
23916
- return [bold(cyan(`${title}:`)), ...rows.map(([label, description]) => ` ${padEnd(label, width)} ${description}`.trimEnd())];
23916
+ return [bold(cyan(`${title}:`)), ...rows.map(([label3, description]) => ` ${padEnd(label3, width)} ${description}`.trimEnd())];
23917
23917
  }
23918
23918
  function formatCommandLabel(command) {
23919
23919
  const name2 = green(command.name);
@@ -24295,9 +24295,9 @@ 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 { readFile as readFile14, writeFile as writeFile10 } from "node:fs/promises";
24299
- import { resolve as resolve12 } from "node:path";
24300
- import { setTimeout as delay5 } from "node:timers/promises";
24298
+ import { readFile as readFile15, writeFile as writeFile12 } from "node:fs/promises";
24299
+ import { resolve as resolve14 } from "node:path";
24300
+ import { setTimeout as delay6 } from "node:timers/promises";
24301
24301
 
24302
24302
  // node_modules/fflate/esm/index.mjs
24303
24303
  import { createRequire } from "module";
@@ -25302,6 +25302,7 @@ var SPRITE_STYLES = [...GAME_SPRITE_STYLES, ...VIDEO_SPRITE_STYLES];
25302
25302
  // shared/credits.ts
25303
25303
  var UNITS_PER_CREDIT = 10;
25304
25304
  var toCredits = (units) => Math.round(units) / UNITS_PER_CREDIT;
25305
+ var toUnits = (credits) => Math.round(credits * UNITS_PER_CREDIT);
25305
25306
 
25306
25307
  // shared/sprites/types.ts
25307
25308
  var SPRITE_KINDS = ["character", "vehicle", "machine", "effect"];
@@ -25351,7 +25352,7 @@ var SPRITE_VIDEO_MODELS = [
25351
25352
  resolutions: ["480p", "768p"],
25352
25353
  modes: ["cost", "speed", "quality"],
25353
25354
  lastFrame: true,
25354
- usdPerSecond: { "480p": { cost: 0.01, speed: 0.02, quality: 0.04 }, "768p": { cost: 0.025, speed: 0.035, quality: 0.075 } },
25355
+ estimatedCreditsPerSecond: { "480p": { cost: 1, speed: 2, quality: 4 }, "768p": { cost: 2.5, speed: 3.5, quality: 7.5 } },
25355
25356
  seconds: { min: 5, max: 15 }
25356
25357
  },
25357
25358
  {
@@ -25362,7 +25363,7 @@ var SPRITE_VIDEO_MODELS = [
25362
25363
  resolutions: ["480p", "768p"],
25363
25364
  modes: ["cost"],
25364
25365
  lastFrame: false,
25365
- usdPerSecond: { "480p": { cost: 0.01 }, "768p": { cost: 0.015 } },
25366
+ estimatedCreditsPerSecond: { "480p": { cost: 1 }, "768p": { cost: 1.5 } },
25366
25367
  seconds: { min: 5, max: 15 }
25367
25368
  },
25368
25369
  {
@@ -25379,11 +25380,7 @@ var SPRITE_VIDEO_MODELS = [
25379
25380
  seed: true,
25380
25381
  promptExpansion: PROMPT_EXPANSION_MODES,
25381
25382
  audio: true,
25382
- // Regular rates, not the temporary promotion ending 2026-10-15; the same for every workflow,
25383
- // 2K extensions only. Extensions bill reference input beyond 4,096 tokens a request too
25384
- // ($0.02 per 1,000), which fal doesn't report back, so it isn't charged.
25385
- // https://fal.ai/models/minimax/h3-max/image-to-video, …/text-to-video, …/extend-video
25386
- usdPerSecond: { "480p": { quality: 0.05 }, "768p": { quality: 0.08 }, "1080p": { quality: 0.16 }, "2k": { quality: 0.32 } },
25383
+ estimatedCreditsPerSecond: { "480p": { quality: 5 }, "768p": { quality: 8 }, "1080p": { quality: 16 }, "2k": { quality: 32 } },
25387
25384
  seconds: { min: 1, max: 15 }
25388
25385
  },
25389
25386
  {
@@ -25400,9 +25397,7 @@ var SPRITE_VIDEO_MODELS = [
25400
25397
  seed: true,
25401
25398
  promptExpansion: PROMPT_EXPANSION_MODES,
25402
25399
  audio: true,
25403
- // Regular rates, not the temporary promotion ending 2026-10-15; extensions bill only the new footage.
25404
- // https://fal.ai/models/minimax/h3-max-turbo/image-to-video, …/text-to-video, …/extend-video
25405
- usdPerSecond: { "480p": { speed: 0.025 }, "768p": { speed: 0.04 }, "1080p": { speed: 0.08 }, "2k": { speed: 0.16 } },
25400
+ estimatedCreditsPerSecond: { "480p": { speed: 2.5 }, "768p": { speed: 4 }, "1080p": { speed: 8 }, "2k": { speed: 16 } },
25406
25401
  seconds: { min: 1, max: 15 }
25407
25402
  }
25408
25403
  ];
@@ -25414,10 +25409,10 @@ function spriteVideoModel(id2) {
25414
25409
  function videoResolutions(model, workflow = "image-to-video") {
25415
25410
  return workflow === "extend-video" ? model.extendResolutions ?? model.resolutions : model.resolutions;
25416
25411
  }
25417
- function spriteVideoCostUsd(model, p) {
25418
- const byMode = model.usdPerSecond[p.resolution] ?? model.usdPerSecond[model.resolutions[0]];
25412
+ function spriteVideoEstimate(model, p) {
25413
+ const byMode = model.estimatedCreditsPerSecond[p.resolution] ?? model.estimatedCreditsPerSecond[model.resolutions[0]];
25419
25414
  const perSecond = byMode[p.mode] ?? byMode[model.modes[0]] ?? 0;
25420
- return perSecond * Math.round(p.seconds);
25415
+ return Math.max(1, Math.ceil(perSecond * Math.round(p.seconds) * UNITS_PER_CREDIT));
25421
25416
  }
25422
25417
 
25423
25418
  // node_modules/zod/v4/classic/external.js
@@ -28943,7 +28938,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
28943
28938
  }
28944
28939
  return propValues;
28945
28940
  });
28946
- const isObject2 = isObject;
28941
+ const isObject3 = isObject;
28947
28942
  const catchall = def.catchall;
28948
28943
  let value;
28949
28944
  const memo2 = globalConfig.memoizer;
@@ -28951,7 +28946,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
28951
28946
  inst._zod.parse = (payload, ctx) => {
28952
28947
  value ?? (value = _normalized.value);
28953
28948
  const input2 = payload.value;
28954
- if (!isObject2(input2)) {
28949
+ if (!isObject3(input2)) {
28955
28950
  payload.issues.push({
28956
28951
  expected: "object",
28957
28952
  code: "invalid_type",
@@ -29087,7 +29082,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
29087
29082
  return doc.compile();
29088
29083
  };
29089
29084
  let fastpass;
29090
- const isObject2 = isObject;
29085
+ const isObject3 = isObject;
29091
29086
  const jit = !globalConfig.jitless;
29092
29087
  const allowsEval2 = allowsEval;
29093
29088
  const fastEnabled = jit && allowsEval2.value;
@@ -29096,7 +29091,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
29096
29091
  inst._zod.parse = (payload, ctx) => {
29097
29092
  value ?? (value = _normalized.value);
29098
29093
  const input2 = payload.value;
29099
- if (!isObject2(input2)) {
29094
+ if (!isObject3(input2)) {
29100
29095
  payload.issues.push({
29101
29096
  expected: "object",
29102
29097
  code: "invalid_type",
@@ -30446,7 +30441,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
30446
30441
  var NONE = 0;
30447
30442
  var ASSUMED = 1;
30448
30443
  var PROVEN = 2;
30449
- function isRecursive(inst, stack, resolve13) {
30444
+ function isRecursive(inst, stack, resolve15) {
30450
30445
  const cached2 = recursive.get(inst);
30451
30446
  if (cached2 !== void 0)
30452
30447
  return cached2 ? PROVEN : NONE;
@@ -30456,7 +30451,7 @@ function isRecursive(inst, stack, resolve13) {
30456
30451
  let result = NONE;
30457
30452
  const check2 = (child) => {
30458
30453
  if (result !== PROVEN && child?._zod) {
30459
- const answer = isRecursive(child, stack, resolve13);
30454
+ const answer = isRecursive(child, stack, resolve15);
30460
30455
  if (answer > result)
30461
30456
  result = answer;
30462
30457
  }
@@ -30467,7 +30462,7 @@ function isRecursive(inst, stack, resolve13) {
30467
30462
  const desc = Object.getOwnPropertyDescriptor(sh, key);
30468
30463
  if (spread && !desc.enumerable)
30469
30464
  continue;
30470
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve13) : NONE;
30465
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve15) : NONE;
30471
30466
  if (child > answer)
30472
30467
  answer = child;
30473
30468
  }
@@ -30531,7 +30526,7 @@ function isRecursive(inst, stack, resolve13) {
30531
30526
  break;
30532
30527
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
30533
30528
  case "lazy": {
30534
- const inner = def._cachedInner ?? (resolve13 ? inst._zod.innerType : void 0);
30529
+ const inner = def._cachedInner ?? (resolve15 ? inst._zod.innerType : void 0);
30535
30530
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
30536
30531
  break;
30537
30532
  }
@@ -34729,8 +34724,8 @@ function ko_default() {
34729
34724
  }
34730
34725
 
34731
34726
  // node_modules/zod/v4/locales/lt.js
34732
- var capitalizeFirstCharacter = (text) => {
34733
- return text.charAt(0).toUpperCase() + text.slice(1);
34727
+ var capitalizeFirstCharacter = (text2) => {
34728
+ return text2.charAt(0).toUpperCase() + text2.slice(1);
34734
34729
  };
34735
34730
  function getUnitTypeFromNumber(number4) {
34736
34731
  const abs = Math.abs(number4);
@@ -38600,9 +38595,9 @@ function codePointLengthVar(doc, ctx, accessor, inDoubt) {
38600
38595
  doc.write(`const ${v} = typeof ${accessor} === "string" && ${inDoubt} ? ${cpLen}(${accessor}) : ${accessor}.length;`);
38601
38596
  return v;
38602
38597
  }
38603
- function numericOperand(value, label) {
38598
+ function numericOperand(value, label3) {
38604
38599
  if (typeof value !== "number" || !Number.isFinite(value)) {
38605
- throw new ZodCompileUnsupportedError(`${label} bound of type ${typeof value}`);
38600
+ throw new ZodCompileUnsupportedError(`${label3} bound of type ${typeof value}`);
38606
38601
  }
38607
38602
  return `${value}`;
38608
38603
  }
@@ -41576,8 +41571,8 @@ var contributors = {
41576
41571
  function aggregateChecks(schema) {
41577
41572
  const agg = {};
41578
41573
  const def = schema._zod.def;
41579
- const list2 = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
41580
- for (const ch of list2)
41574
+ const list3 = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
41575
+ for (const ch of list3)
41581
41576
  contributors[ch._zod.def.check]?.(agg, ch._zod.def);
41582
41577
  const bag = schema._zod.bag;
41583
41578
  if (bag.minimum !== void 0)
@@ -45199,26 +45194,34 @@ function safeProjectPath(path) {
45199
45194
  }
45200
45195
 
45201
45196
  // cli/src/init.ts
45202
- import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile5 } from "node:fs/promises";
45203
- import { dirname as dirname4, resolve as resolve4 } from "node:path";
45204
- async function initializeSkill(directory = process.cwd()) {
45205
- const path = resolve4(directory, ".agents", "skills", "animaguru", "SKILL.md");
45206
- const content = await readFile3(new URL("../skills/animaguru/SKILL.md", import.meta.url), "utf8");
45197
+ import { mkdir as mkdir5, readFile as readFile3, readdir, writeFile as writeFile5 } from "node:fs/promises";
45198
+ import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
45199
+ async function refresh(path, content) {
45207
45200
  await mkdir5(dirname4(path), { recursive: true });
45208
45201
  try {
45209
45202
  await writeFile5(path, content, { flag: "wx" });
45210
- return { path, created: true };
45203
+ return true;
45211
45204
  } catch (error62) {
45212
45205
  if (error62.code !== "EEXIST") throw error62;
45213
45206
  if (await readFile3(path, "utf8") !== content) await writeFile5(path, content);
45214
- return { path, created: false };
45207
+ return false;
45208
+ }
45209
+ }
45210
+ async function initializeSkill(directory = process.cwd()) {
45211
+ const root = resolve4(directory, ".agents", "skills", "animaguru");
45212
+ const path = join5(root, "SKILL.md");
45213
+ const created = await refresh(path, await readFile3(new URL("../skills/animaguru/SKILL.md", import.meta.url), "utf8"));
45214
+ const references = new URL("../skills/animaguru/references/", import.meta.url);
45215
+ for (const file2 of (await readdir(references)).filter((name2) => name2.endsWith(".md")).sort()) {
45216
+ await refresh(join5(root, "references", file2), await readFile3(new URL(file2, references), "utf8"));
45215
45217
  }
45218
+ return { path, created };
45216
45219
  }
45217
45220
 
45218
45221
  // cli/src/create.ts
45219
45222
  import { spawn } from "node:child_process";
45220
- import { cp, mkdir as mkdir6, readFile as readFile4, readdir, access, writeFile as writeFile6, rename as rename3 } from "node:fs/promises";
45221
- import { basename as basename2, dirname as dirname5, delimiter, join as join5, resolve as resolve5 } from "node:path";
45223
+ import { cp, mkdir as mkdir6, readFile as readFile4, readdir as readdir2, access, writeFile as writeFile6, rename as rename3 } from "node:fs/promises";
45224
+ import { basename as basename2, dirname as dirname5, delimiter, join as join6, resolve as resolve5 } from "node:path";
45222
45225
  import { fileURLToPath } from "node:url";
45223
45226
 
45224
45227
  // shared/locales/en/animation-styles.json
@@ -46153,30 +46156,30 @@ async function createVideoProject(options, installer = installDependencies) {
46153
46156
  throw error62;
46154
46157
  }
46155
46158
  options.log?.(`Creating a video workspace in ${directory}\u2026`);
46156
- const templateRoot = join5(packageRoot, "templates/video");
46157
- for (const entry of await readdir(templateRoot)) {
46159
+ const templateRoot = join6(packageRoot, "templates/video");
46160
+ for (const entry of await readdir2(templateRoot)) {
46158
46161
  if (entry === "WORKSPACE-AGENTS.md") continue;
46159
- await cp(join5(templateRoot, entry), join5(directory, entry), { recursive: true, errorOnExist: true, force: false });
46162
+ await cp(join6(templateRoot, entry), join6(directory, entry), { recursive: true, errorOnExist: true, force: false });
46160
46163
  }
46161
- await rename3(join5(directory, "gitignore"), join5(directory, ".gitignore"));
46162
- await mkdir6(join5(directory, "public/assets"), { recursive: true });
46163
- await mkdir6(join5(directory, "production"), { recursive: true });
46164
- const packagePath = join5(directory, "package.json");
46164
+ await rename3(join6(directory, "gitignore"), join6(directory, ".gitignore"));
46165
+ await mkdir6(join6(directory, "public/assets"), { recursive: true });
46166
+ await mkdir6(join6(directory, "production"), { recursive: true });
46167
+ const packagePath = join6(directory, "package.json");
46165
46168
  const manifest = JSON.parse(await readFile4(packagePath, "utf8"));
46166
46169
  manifest.name = basename2(directory).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 100) || "animaguru-video";
46167
46170
  await writeFile6(packagePath, JSON.stringify(manifest, null, 2) + "\n");
46168
46171
  const skills = [.../* @__PURE__ */ new Set(["animaguru", "animaguru-video", "animaguru-brand-kit", ...VIDEO_PURPOSE_SKILLS, ...VIDEO_TEMPLATES.map((template) => template.skill)])];
46169
- const pixiSkillsRoot = join5(packageRoot, "vendor/pixijs-skills/skills");
46170
- const pixiSkills = (await readdir(pixiSkillsRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
46172
+ const pixiSkillsRoot = join6(packageRoot, "vendor/pixijs-skills/skills");
46173
+ const pixiSkills = (await readdir2(pixiSkillsRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
46171
46174
  for (const agent of [".agents", ".claude"]) {
46172
- const skillRoot = join5(directory, agent, "skills");
46175
+ const skillRoot = join6(directory, agent, "skills");
46173
46176
  await mkdir6(skillRoot, { recursive: true });
46174
- for (const skill of skills) await cp(join5(packageRoot, "skills", skill), join5(skillRoot, skill), { recursive: true });
46175
- for (const skill of pixiSkills) await cp(join5(pixiSkillsRoot, skill), join5(skillRoot, skill), { recursive: true });
46177
+ for (const skill of skills) await cp(join6(packageRoot, "skills", skill), join6(skillRoot, skill), { recursive: true });
46178
+ for (const skill of pixiSkills) await cp(join6(pixiSkillsRoot, skill), join6(skillRoot, skill), { recursive: true });
46176
46179
  }
46177
- await cp(join5(packageRoot, "vendor/pixijs-skills/LICENSE"), join5(directory, "PIXIJS-SKILLS-LICENSE.txt"));
46178
- await cp(join5(packageRoot, "vendor/pixijs-skills/provenance.json"), join5(directory, "production/pixijs-skills-provenance.json"));
46179
- await writeFile6(join5(directory, "animaguru.project.json"), JSON.stringify({
46180
+ await cp(join6(packageRoot, "vendor/pixijs-skills/LICENSE"), join6(directory, "PIXIJS-SKILLS-LICENSE.txt"));
46181
+ await cp(join6(packageRoot, "vendor/pixijs-skills/provenance.json"), join6(directory, "production/pixijs-skills-provenance.json"));
46182
+ await writeFile6(join6(directory, "animaguru.project.json"), JSON.stringify({
46180
46183
  schemaVersion: 3,
46181
46184
  cliVersion: package_default.version,
46182
46185
  category: null,
@@ -46188,7 +46191,7 @@ async function createVideoProject(options, installer = installDependencies) {
46188
46191
  interview: "pending",
46189
46192
  animaguruProjectId: null
46190
46193
  }, null, 2) + "\n");
46191
- await writeFile6(join5(directory, "animaguru.templates.json"), JSON.stringify(listTemplates(), null, 2) + "\n");
46194
+ await writeFile6(join6(directory, "animaguru.templates.json"), JSON.stringify(listTemplates(), null, 2) + "\n");
46192
46195
  if (options.install !== false) {
46193
46196
  options.log?.("Installing PixiJS, Vite, TypeScript, and the MP4 tools\u2026");
46194
46197
  try {
@@ -46217,24 +46220,24 @@ async function createWorkspace(options, installer = installDependencies) {
46217
46220
  } }, installer);
46218
46221
  const directory = result.path;
46219
46222
  const { rm: rm3 } = await import("node:fs/promises");
46220
- await rename3(join5(directory, "src"), join5(directory, "runtime"));
46221
- await mkdir6(join5(directory, "templates/animation/src"), { recursive: true });
46222
- await mkdir6(join5(directory, "templates/animation/shared/locales/en"), { recursive: true });
46223
+ await rename3(join6(directory, "src"), join6(directory, "runtime"));
46224
+ await mkdir6(join6(directory, "templates/animation/src"), { recursive: true });
46225
+ await mkdir6(join6(directory, "templates/animation/shared/locales/en"), { recursive: true });
46223
46226
  for (const file2 of ["film.ts", "film-resources.ts"]) {
46224
- const original = await readFile4(join5(directory, "runtime", file2), "utf8");
46225
- const rewritten = original.replace('"./player-types"', '"../../../runtime/player-types"').replace('"./timeline-model"', '"../../../runtime/timeline-model"').replace('"../shared/locales/en/timeline.json"', '"../../../shared/locales/en/timeline.json"');
46226
- await writeFile6(join5(directory, "templates/animation/src", file2), rewritten);
46227
- await rm3(join5(directory, "runtime", file2));
46228
- }
46229
- await rm3(join5(directory, "runtime/main.ts"));
46230
- await rename3(join5(directory, "film.config.json"), join5(directory, "templates/animation/film.config.json"));
46231
- await rename3(join5(directory, "shared/locales/en/film.json"), join5(directory, "templates/animation/shared/locales/en/film.json"));
46227
+ const original = await readFile4(join6(directory, "runtime", file2), "utf8");
46228
+ const rewritten = original.replace('"./player-types"', '"../../../runtime/player-types"').replace('"./timeline-model"', '"../../../runtime/timeline-model"').replace('"./kit"', '"../../../runtime/kit"').replace('"../shared/locales/en/timeline.json"', '"../../../shared/locales/en/timeline.json"');
46229
+ await writeFile6(join6(directory, "templates/animation/src", file2), rewritten);
46230
+ await rm3(join6(directory, "runtime", file2));
46231
+ }
46232
+ await rm3(join6(directory, "runtime/main.ts"));
46233
+ await rename3(join6(directory, "film.config.json"), join6(directory, "templates/animation/film.config.json"));
46234
+ await rename3(join6(directory, "shared/locales/en/film.json"), join6(directory, "templates/animation/shared/locales/en/film.json"));
46232
46235
  const { createHash: createHash7 } = await import("node:crypto");
46233
- await writeFile6(join5(directory, "templates/animation/starter-film.sha256"), createHash7("sha256").update(await readFile4(join5(directory, "templates/animation/src/film.ts"))).digest("hex") + "\n");
46234
- await rm3(join5(directory, "animaguru.project.json"));
46235
- await mkdir6(join5(directory, "animations"));
46236
- await mkdir6(join5(directory, "branding"));
46237
- await writeFile6(join5(directory, "branding/brand.json"), JSON.stringify({
46236
+ await writeFile6(join6(directory, "templates/animation/starter-film.sha256"), createHash7("sha256").update(await readFile4(join6(directory, "templates/animation/src/film.ts"))).digest("hex") + "\n");
46237
+ await rm3(join6(directory, "animaguru.project.json"));
46238
+ await mkdir6(join6(directory, "animations"));
46239
+ await mkdir6(join6(directory, "branding"));
46240
+ await writeFile6(join6(directory, "branding/brand.json"), JSON.stringify({
46238
46241
  name: "Your brand",
46239
46242
  tagline: "Your next story starts here",
46240
46243
  logo: null,
@@ -46242,18 +46245,18 @@ async function createWorkspace(options, installer = installDependencies) {
46242
46245
  fonts: { heading: { family: "Arial, sans-serif", file: null }, body: { family: "Arial, sans-serif", file: null } },
46243
46246
  assets: []
46244
46247
  }, null, 2) + "\n");
46245
- await writeFile6(join5(directory, "branding/README.md"), "# Shared branding\n\nThe starter brand.json contains placeholders. On the first creative request, the agent asks for your official website or brand guide unless you already supplied one. It researches the identity and records sources and usage notes in brand-guide.md. You can also provide logos, fonts and guides here or proceed without a website. Register reusable web assets in brand.json with workspace-relative paths, such as branding/logo.svg. All animations inherit this brand. Only registered web assets are included in exports; guides and other local documents remain in this workspace.\n");
46246
- await writeFile6(join5(directory, "animaguru.workspace.json"), JSON.stringify({ schemaVersion: 1, cliVersion: package_default.version, name: basename2(directory), animationsDirectory: "animations", branding: "branding/brand.json" }, null, 2) + "\n");
46247
- const pkg = JSON.parse(await readFile4(join5(directory, "package.json"), "utf8"));
46248
+ await writeFile6(join6(directory, "branding/README.md"), "# Shared branding\n\nThe starter brand.json contains placeholders. On the first creative request, the agent asks for your official website or brand guide unless you already supplied one. It researches the identity and records sources and usage notes in brand-guide.md. You can also provide logos, fonts and guides here or proceed without a website. Register reusable web assets in brand.json with workspace-relative paths, such as branding/logo.svg. All animations inherit this brand. Only registered web assets are included in exports; guides and other local documents remain in this workspace.\n");
46249
+ await writeFile6(join6(directory, "animaguru.workspace.json"), JSON.stringify({ schemaVersion: 1, cliVersion: package_default.version, name: basename2(directory), animationsDirectory: "animations", branding: "branding/brand.json" }, null, 2) + "\n");
46250
+ const pkg = JSON.parse(await readFile4(join6(directory, "package.json"), "utf8"));
46248
46251
  pkg.scripts.dev = "node scripts/dev.mjs";
46249
- await writeFile6(join5(directory, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
46250
- const tsconfig = JSON.parse(await readFile4(join5(directory, "tsconfig.json"), "utf8"));
46252
+ await writeFile6(join6(directory, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
46253
+ const tsconfig = JSON.parse(await readFile4(join6(directory, "tsconfig.json"), "utf8"));
46251
46254
  tsconfig.include = ["runtime", "animations/*/src"];
46252
- await writeFile6(join5(directory, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
46253
- await writeFile6(join5(directory, "AGENTS.md"), await readFile4(join5(packageRoot, "templates/video/WORKSPACE-AGENTS.md"), "utf8"));
46254
- await writeFile6(join5(directory, "CLAUDE.md"), "# AnimaGuru workspace\n\nRead AGENTS.md for the multi-animation workflow, shared branding and commands. Claude skills are in .claude/skills. For an incomplete shared kit, read .claude/skills/animaguru-brand-kit/SKILL.md and ask for the official website or brand guide if the user did not supply one. Select the animation folder before editing; reuse shared runtime/ and scripts/.\n");
46255
- await rm3(join5(directory, "WORKSPACE-AGENTS.md"), { force: true });
46256
- await writeFile6(join5(directory, "README.md"), "# Your AnimaGuru workspace\n\nOpen this root folder in Codex or Claude Code and describe a film. If you have an official website or brand guide, include it; otherwise the agent asks for it while setting up the shared branding/ kit. You can also provide local brand assets or proceed without a website. Create a film with animaguru create animation my-video.\n\nRun npm run dev for the workspace hub. Run npm run build -- --animation my-video, npm run export:html -- --animation my-video, or npm run export:mp4 -- --animation my-video. Player code, dependencies, skills and export tools are shared once; animation folders contain only their own production files.\n");
46255
+ await writeFile6(join6(directory, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
46256
+ await writeFile6(join6(directory, "AGENTS.md"), await readFile4(join6(packageRoot, "templates/video/WORKSPACE-AGENTS.md"), "utf8"));
46257
+ await writeFile6(join6(directory, "CLAUDE.md"), "# AnimaGuru workspace\n\nRead AGENTS.md for the multi-animation workflow, shared branding and commands. Claude skills are in .claude/skills. For an incomplete shared kit, read .claude/skills/animaguru-brand-kit/SKILL.md and ask for the official website or brand guide if the user did not supply one. Select the animation folder before editing; reuse shared runtime/ and scripts/.\n");
46258
+ await rm3(join6(directory, "WORKSPACE-AGENTS.md"), { force: true });
46259
+ await writeFile6(join6(directory, "README.md"), "# Your AnimaGuru workspace\n\nOpen this root folder in Codex or Claude Code and describe a film. If you have an official website or brand guide, include it; otherwise the agent asks for it while setting up the shared branding/ kit. You can also provide local brand assets or proceed without a website. Create a film with animaguru create animation my-video.\n\nRun npm run dev for the workspace hub. Run npm run build -- --animation my-video, npm run export:html -- --animation my-video, or npm run export:mp4 -- --animation my-video. Player code, dependencies, skills and export tools are shared once; animation folders contain only their own production files.\n");
46257
46260
  if (options.install !== false) {
46258
46261
  try {
46259
46262
  await installer(directory, options);
@@ -46269,8 +46272,8 @@ async function createWorkspace(options, installer = installDependencies) {
46269
46272
  skills: result.skills,
46270
46273
  agents: result.agents,
46271
46274
  installed: options.install !== false,
46272
- branding: join5(directory, "branding"),
46273
- animations: join5(directory, "animations"),
46275
+ branding: join6(directory, "branding"),
46276
+ animations: join6(directory, "animations"),
46274
46277
  nextSteps: ["Open this workspace in Codex or Claude Code and provide your website or brand guide; the agent asks if it is missing.", "Build the shared brand kit in branding/.", "Run animaguru create animation my-video.", "Run npm run dev for the animation hub."]
46275
46278
  };
46276
46279
  }
@@ -46279,7 +46282,7 @@ async function findWorkspace(start = process.cwd()) {
46279
46282
  let directory = await realpath2(resolve5(start));
46280
46283
  while (true) {
46281
46284
  try {
46282
- const info = JSON.parse(await readFile4(join5(directory, "animaguru.workspace.json"), "utf8"));
46285
+ const info = JSON.parse(await readFile4(join6(directory, "animaguru.workspace.json"), "utf8"));
46283
46286
  if (info.schemaVersion !== 1 || info.animationsDirectory !== "animations" || info.branding !== "branding/brand.json") throw new Error("Unsupported AnimaGuru workspace.");
46284
46287
  return directory;
46285
46288
  } catch (error62) {
@@ -46294,23 +46297,23 @@ async function createAnimation(options) {
46294
46297
  if (!/^[a-z0-9][a-z0-9-]{0,79}$/.test(options.name)) throw new Error("Choose a lowercase, hyphenated animation name, such as product-launch.");
46295
46298
  options.signal?.throwIfAborted();
46296
46299
  const root = await findWorkspace(options.workspace);
46297
- const directory = join5(root, "animations", options.name);
46300
+ const directory = join6(root, "animations", options.name);
46298
46301
  try {
46299
46302
  await mkdir6(directory);
46300
46303
  } catch (error62) {
46301
46304
  if (error62.code === "EEXIST") throw new Error(`Animation already exists: ${options.name}. Existing files were not changed.`);
46302
46305
  throw error62;
46303
46306
  }
46304
- for (const file2 of await readdir(join5(root, "templates/animation"))) {
46305
- if (file2 !== "starter-film.sha256") await cp(join5(root, "templates/animation", file2), join5(directory, file2), { recursive: true, errorOnExist: true, force: false });
46307
+ for (const file2 of await readdir2(join6(root, "templates/animation"))) {
46308
+ if (file2 !== "starter-film.sha256") await cp(join6(root, "templates/animation", file2), join6(directory, file2), { recursive: true, errorOnExist: true, force: false });
46306
46309
  }
46307
- const config2 = JSON.parse(await readFile4(join5(directory, "film.config.json"), "utf8"));
46310
+ const config2 = JSON.parse(await readFile4(join6(directory, "film.config.json"), "utf8"));
46308
46311
  config2.slug = options.name;
46309
46312
  config2.title = options.name.replaceAll("-", " ").replace(/^./, (value) => value.toUpperCase());
46310
- await writeFile6(join5(directory, "film.config.json"), JSON.stringify(config2, null, 2) + "\n");
46311
- await mkdir6(join5(directory, "public/assets"), { recursive: true });
46312
- await mkdir6(join5(directory, "production"), { recursive: true });
46313
- await writeFile6(join5(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");
46313
+ await writeFile6(join6(directory, "film.config.json"), JSON.stringify(config2, null, 2) + "\n");
46314
+ await mkdir6(join6(directory, "public/assets"), { recursive: true });
46315
+ await mkdir6(join6(directory, "production"), { recursive: true });
46316
+ 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");
46314
46317
  options.log?.(`Animation ready: ${directory}. It uses the workspace's branding, player and export tools.`);
46315
46318
  return {
46316
46319
  type: "animation",
@@ -46323,10 +46326,6 @@ async function createAnimation(options) {
46323
46326
  };
46324
46327
  }
46325
46328
 
46326
- // shared/games/ai.ts
46327
- var USD_PER_CREDIT = 1e-3;
46328
- var creditsFor = (usd) => Math.max(1, Math.ceil(usd / USD_PER_CREDIT));
46329
-
46330
46329
  // shared/assets.ts
46331
46330
  var ASSET_TYPES = ["image", "video", "music", "speech", "sfx"];
46332
46331
  var SPEECH_MODELS = [
@@ -46403,31 +46402,27 @@ var assetRequest = external_exports.discriminatedUnion("type", [
46403
46402
  }).transform((p) => ({ ...p, voice: p.voice || (isElevenLabsSpeech(p.model) ? DEFAULT_ELEVENLABS_VOICE : "Kore") })),
46404
46403
  external_exports.object({ ...base, type: external_exports.literal("sfx"), model: external_exports.literal("eleven_text_to_sound_v2").default("eleven_text_to_sound_v2"), seconds: external_exports.number().min(0.5).max(30).default(5), loop: external_exports.boolean().default(false), promptInfluence: external_exports.number().min(0).max(1).default(0.3) })
46405
46404
  ]);
46406
- function speechCostUsd(model, inputTokens, outputTokens, now = Date.now()) {
46407
- const promotion = now < Date.UTC(2027, 0, 1);
46408
- const inputRate = promotion ? 0.5 : 1;
46409
- const outputRate = (model === "gemini-3.8-flash-tts" ? 18 : 12) * (promotion ? 0.5 : 1);
46410
- return (Math.max(0, inputTokens) * inputRate + Math.max(0, outputTokens) * outputRate) / 1e6;
46411
- }
46412
- function elevenLabsSpeechCostUsd(model, characters, now = Date.now()) {
46413
- const promotion = now < Date.UTC(2026, 9, 13);
46414
- const rate = model === "eleven_v4_turbo" ? promotion ? 0.011 : 0.04 : promotion ? 0.022 : 0.08;
46415
- return Math.max(0, characters) * rate / 1e3;
46416
- }
46417
- var elevenLabsSfxCostUsd = (seconds2) => Math.max(0, seconds2) * 0.12 / 60;
46418
- var speechCharacters = (text) => Array.from(text).length;
46419
- function assetEstimate(p) {
46405
+ var speechCharacters = (text2) => Array.from(text2).length;
46406
+ function assetEstimate(p, now = Date.now()) {
46420
46407
  if (p.type === "image") return Math.ceil(130 * spriteImageModel(p.model).relCost);
46421
- if (p.type === "video") return creditsFor(spriteVideoCostUsd(spriteVideoModel(p.model), p));
46422
- if (p.type === "music") return creditsFor(0.08);
46423
- if (p.type === "sfx") return creditsFor(elevenLabsSfxCostUsd(p.seconds));
46424
- if (isElevenLabsSpeech(p.model)) return creditsFor(elevenLabsSpeechCostUsd(p.model, speechCharacters(p.prompt)));
46425
- return creditsFor(speechCostUsd(p.model, p.prompt.length + p.delivery.length, Math.ceil(p.prompt.length / 4) * 25));
46408
+ if (p.type === "video") return spriteVideoEstimate(spriteVideoModel(p.model), p);
46409
+ if (p.type === "music") return 80;
46410
+ const units = (credits) => Math.max(1, Math.ceil(credits * UNITS_PER_CREDIT));
46411
+ if (p.type === "sfx") return units(Math.max(0, p.seconds) * 0.2);
46412
+ if (isElevenLabsSpeech(p.model)) {
46413
+ const promotion2 = now < Date.UTC(2026, 9, 13);
46414
+ const perThousandCharacters = p.model === "eleven_v4_turbo" ? promotion2 ? 1.1 : 4 : promotion2 ? 2.2 : 8;
46415
+ return units(speechCharacters(p.prompt) * perThousandCharacters / 1e3);
46416
+ }
46417
+ const promotion = now < Date.UTC(2027, 0, 1);
46418
+ const inputPerThousand = promotion ? 0.05 : 0.1;
46419
+ const outputPerThousand = (p.model === "gemini-3.8-flash-tts" ? 1.8 : 1.2) * (promotion ? 0.5 : 1);
46420
+ return units(((p.prompt.length + p.delivery.length) * inputPerThousand + Math.ceil(p.prompt.length / 4) * 25 * outputPerThousand) / 1e3);
46426
46421
  }
46427
46422
 
46428
46423
  // cli/src/videos.ts
46429
46424
  import { open as open3, readFile as readFile7, stat as stat2 } from "node:fs/promises";
46430
- import { basename as basename4, join as join7, resolve as resolve8 } from "node:path";
46425
+ import { basename as basename4, join as join8, resolve as resolve8 } from "node:path";
46431
46426
  import { setTimeout as delay } from "node:timers/promises";
46432
46427
  import { spawn as spawn2 } from "node:child_process";
46433
46428
  import { createHash as createHash3 } from "node:crypto";
@@ -46484,13 +46479,13 @@ function seconds(value) {
46484
46479
  if (!match || Number(match[2]) > 59 || Number(match[3]) > 59) return NaN;
46485
46480
  return Number(match[1] ?? 0) * 3600 + Number(match[2]) * 60 + Number(match[3]) + Number(match[4]) / 1e3;
46486
46481
  }
46487
- var subRipText = (text) => text.replace(/<(?!\/?[ibu]>)[^<>]*>/gi, "").replace(/&(?!(?:[a-z][a-z\d]*|#\d+|#x[\da-f]+);)/gi, "&amp;").replace(/<(?!\/?[ibu]>)/gi, "&lt;");
46482
+ var subRipText = (text2) => text2.replace(/<(?!\/?[ibu]>)[^<>]*>/gi, "").replace(/&(?!(?:[a-z][a-z\d]*|#\d+|#x[\da-f]+);)/gi, "&amp;").replace(/<(?!\/?[ibu]>)/gi, "&lt;");
46488
46483
  function parseSubtitles(input2, duration3) {
46489
- const text = input2.replace(/^/, "").replace(/\r\n?/g, "\n");
46490
- if (text.includes("\0") || text.includes("\uFFFD")) throw new Error("Use a UTF-8 text subtitle file.");
46491
- const vtt = /^WEBVTT(?:[ \t][^\n]*)?(?:\n|$)/.test(text);
46484
+ const text2 = input2.replace(/^/, "").replace(/\r\n?/g, "\n");
46485
+ if (text2.includes("\0") || text2.includes("\uFFFD")) throw new Error("Use a UTF-8 text subtitle file.");
46486
+ const vtt = /^WEBVTT(?:[ \t][^\n]*)?(?:\n|$)/.test(text2);
46492
46487
  const cues = [];
46493
- for (const [index2, block] of text.split(/\n[ \t]*\n/).entries()) {
46488
+ for (const [index2, block] of text2.split(/\n[ \t]*\n/).entries()) {
46494
46489
  const lines = block.split("\n").filter((line) => line.trim());
46495
46490
  if (!lines.length || vtt && (index2 === 0 || /^(?:NOTE|STYLE|REGION)(?:[ \t]|$)/.test(lines[0]))) continue;
46496
46491
  const timing = lines.findIndex((line) => line.includes("-->"));
@@ -46536,9 +46531,9 @@ async function readSubtitleFile(file2, maxBytes) {
46536
46531
  }
46537
46532
  if (!info.isFile() || !/\.(?:srt|vtt)$/i.test(file2) || info.size < 1 || info.size > maxBytes) throw new Error(`Use a .srt or .vtt subtitle file up to ${maxBytes / 1024 / 1024} MiB, such as the one npm run export:mp4 writes beside the MP4.`);
46538
46533
  const content = await readFile5(file2);
46539
- const text = content.toString("utf8");
46540
- if (text.includes("\uFFFD") || !/\d\d:\d\d[,.]\d{3} --> /.test(text)) throw new Error("Use a UTF-8 .srt or .vtt subtitle file with timed captions.");
46541
- return { content, sha256: createHash2("sha256").update(content).digest("hex"), language: /^\uFEFF?WEBVTT[^\n]*\n(?:[^\n]+\n)*?Language:[ \t]*([^\s]+)/.exec(text)?.[1] };
46534
+ const text2 = content.toString("utf8");
46535
+ if (text2.includes("\uFFFD") || !/\d\d:\d\d[,.]\d{3} --> /.test(text2)) throw new Error("Use a UTF-8 .srt or .vtt subtitle file with timed captions.");
46536
+ return { content, sha256: createHash2("sha256").update(content).digest("hex"), language: /^\uFEFF?WEBVTT[^\n]*\n(?:[^\n]+\n)*?Language:[ \t]*([^\s]+)/.exec(text2)?.[1] };
46542
46537
  }
46543
46538
  async function subtitleFile(root, mp4, choice, extensions) {
46544
46539
  if (choice === "none") return null;
@@ -46620,8 +46615,8 @@ async function mp4Info(file2) {
46620
46615
  }
46621
46616
 
46622
46617
  // cli/src/local-project.ts
46623
- import { readFile as readFile6, readdir as readdir2 } from "node:fs/promises";
46624
- import { join as join6, relative, resolve as resolve7, sep } from "node:path";
46618
+ import { readFile as readFile6, readdir as readdir3 } from "node:fs/promises";
46619
+ import { join as join7, relative, resolve as resolve7, sep } from "node:path";
46625
46620
  async function localProject(directory, selected) {
46626
46621
  const root = resolve7(directory);
46627
46622
  let workspace;
@@ -46635,10 +46630,10 @@ async function localProject(directory, selected) {
46635
46630
  let animation = selected ?? (location[0] === "animations" ? location[1] : void 0);
46636
46631
  if (!animation) {
46637
46632
  const names = [];
46638
- for (const entry of await readdir2(join6(workspace, "animations"), { withFileTypes: true })) {
46633
+ for (const entry of await readdir3(join7(workspace, "animations"), { withFileTypes: true })) {
46639
46634
  if (!entry.isDirectory()) continue;
46640
46635
  try {
46641
- await readFile6(join6(workspace, "animations", entry.name, "animaguru.project.json"));
46636
+ await readFile6(join7(workspace, "animations", entry.name, "animaguru.project.json"));
46642
46637
  names.push(entry.name);
46643
46638
  } catch (error62) {
46644
46639
  if (error62.code !== "ENOENT") throw error62;
@@ -46648,8 +46643,8 @@ async function localProject(directory, selected) {
46648
46643
  animation = names[0];
46649
46644
  }
46650
46645
  if (!/^[a-z0-9][a-z0-9-]{0,79}$/.test(animation)) throw new Error("Use a lowercase, hyphenated animation name.");
46651
- const projectRoot = join6(workspace, "animations", animation);
46652
- await readFile6(join6(projectRoot, "animaguru.project.json"));
46646
+ const projectRoot = join7(workspace, "animations", animation);
46647
+ await readFile6(join7(projectRoot, "animaguru.project.json"));
46653
46648
  return { toolsRoot: workspace, projectRoot, animation };
46654
46649
  }
46655
46650
 
@@ -46659,7 +46654,7 @@ function sharingEmails(value) {
46659
46654
  return value ? value.split(",").map((email3) => email3.trim()).filter(Boolean) : [];
46660
46655
  }
46661
46656
  async function exportHtml(root, animation, signal, log) {
46662
- const script = join7(root, "scripts/export-html.mjs");
46657
+ const script = join8(root, "scripts/export-html.mjs");
46663
46658
  await stat2(script).catch(() => {
46664
46659
  throw new Error("Choose an AnimaGuru video project, or pass --file for an exported HTML5 ZIP or MP4.");
46665
46660
  });
@@ -46708,7 +46703,7 @@ async function submitVideo(client, options) {
46708
46703
  if (metadata.format !== "spriteguru-html5" || metadata.version !== 1) throw new Error("Use an AnimaGuru HTML5 export.");
46709
46704
  } else {
46710
46705
  try {
46711
- metadata = JSON.parse(await readFile7(join7(context.projectRoot, "film.config.json"), "utf8"));
46706
+ metadata = JSON.parse(await readFile7(join8(context.projectRoot, "film.config.json"), "utf8"));
46712
46707
  } catch {
46713
46708
  }
46714
46709
  const handle2 = await open3(file2, "r");
@@ -46810,9 +46805,17 @@ async function changeVideoSubtitles(client, id2, options) {
46810
46805
  }
46811
46806
 
46812
46807
  // cli/src/assets.ts
46813
- import { readFile as readFile8, writeFile as writeFile7 } from "node:fs/promises";
46814
- import { resolve as resolve9 } from "node:path";
46808
+ import { mkdir as mkdir7, readFile as readFile8, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
46809
+ import { dirname as dirname6, join as join9, resolve as resolve9 } from "node:path";
46810
+ import { setTimeout as delay2 } from "node:timers/promises";
46815
46811
  var extras = { image: ["aspect-ratio", "transparent"], video: ["workflow", "reference", "end-reference", "source", "soundtrack", "audio-references", "seconds", "resolution", "mode", "aspect-ratio", "prompt-expansion", "seed", "extend-output"], music: [], speech: ["voice", "delivery"], sfx: ["seconds", "loop", "prompt-influence"] };
46812
+ var list = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
46813
+ function accepted(type) {
46814
+ if (type === "music") return "Music accepts only --name, --prompt and --model; the model chooses the length, so fit it during the edit.";
46815
+ const options = extras[type];
46816
+ if (!options) return "";
46817
+ return `${type[0].toUpperCase()}${type.slice(1)} assets accept ${list(["--name", "--prompt", "--model", ...options.map((option) => `--${option}`)])}.`;
46818
+ }
46816
46819
  function parseAsset(input2) {
46817
46820
  const parsed = assetRequest.safeParse(input2);
46818
46821
  if (parsed.success) return parsed.data;
@@ -46821,7 +46824,7 @@ function parseAsset(input2) {
46821
46824
  function assetFromFlags(flags) {
46822
46825
  for (const name2 of Object.values(extras).flat()) {
46823
46826
  const value = flags[name2];
46824
- if (value !== void 0 && value !== false && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets.`);
46827
+ if (value !== void 0 && value !== false && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets. ${accepted(flags.type)}`.trim());
46825
46828
  }
46826
46829
  const base2 = { type: flags.type, name: flags.name, prompt: flags.prompt, model: flags.model };
46827
46830
  if (flags.type === "image") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], transparent: flags.transparent });
@@ -46853,27 +46856,201 @@ async function assetFromFile(file2, model) {
46853
46856
  if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) throw new Error("The asset file must contain a JSON object.");
46854
46857
  return parseAsset({ ...input2, ...model ? { model } : {} });
46855
46858
  }
46859
+ var MAX_BATCH = 50;
46860
+ var isObject2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
46861
+ var fileName = (name2) => name2.normalize("NFKD").replace(/[^\w.-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
46862
+ async function assetsFromBatchFile(file2, model) {
46863
+ const input2 = JSON.parse(await readFile8(file2, "utf8"));
46864
+ let defaults = {};
46865
+ let items;
46866
+ if (Array.isArray(input2)) items = input2;
46867
+ else if (isObject2(input2) && Array.isArray(input2.assets)) {
46868
+ if (input2.defaults !== void 0 && !isObject2(input2.defaults)) throw new Error("The batch file's defaults must be a JSON object.");
46869
+ defaults = input2.defaults ?? {};
46870
+ items = input2.assets;
46871
+ } else throw new Error('The batch file must contain a JSON array of asset requests, or {"defaults": {...}, "assets": [...]}.');
46872
+ if (!items.length) throw new Error("The batch file lists no assets.");
46873
+ if (items.length > MAX_BATCH) throw new Error(`A batch takes at most ${MAX_BATCH} assets; split the file.`);
46874
+ const errors = [];
46875
+ const requests = [];
46876
+ const names = /* @__PURE__ */ new Map();
46877
+ items.forEach((item, index2) => {
46878
+ const label3 = `#${index2 + 1}${isObject2(item) && typeof item.name === "string" ? ` (${item.name})` : ""}`;
46879
+ if (!isObject2(item)) {
46880
+ errors.push(`${label3}: expected a JSON object.`);
46881
+ return;
46882
+ }
46883
+ try {
46884
+ const request2 = parseAsset({ ...defaults, ...item, ...model ? { model } : {} });
46885
+ const key = (fileName(request2.name) || request2.name).toLowerCase();
46886
+ const first = names.get(key);
46887
+ if (first !== void 0) errors.push(`${label3}: the name repeats #${first + 1}; downloads need distinct names.`);
46888
+ else names.set(key, index2);
46889
+ requests.push(request2);
46890
+ } catch (error62) {
46891
+ errors.push(`${label3}: ${(error62 instanceof Error ? error62.message : String(error62)).replaceAll("\n", "; ")}`);
46892
+ }
46893
+ });
46894
+ if (errors.length) throw new Error(`Fix these batch items; nothing was submitted.
46895
+ ${errors.join("\n")}`);
46896
+ return requests;
46897
+ }
46856
46898
  async function submitAsset(client, project, body, options) {
46857
46899
  if (options["dry-run"]) return { dryRun: true, request: body, estimatedCredits: toCredits(assetEstimate(body)) };
46858
46900
  if (!options.yes) throw new Error("Pass --yes to authorize spending credits, or --dry-run to validate and estimate without generation.");
46859
46901
  return client.request(`/api/v1/sprites/${encodeURIComponent(project)}/assets`, { method: "POST", body });
46860
46902
  }
46861
- async function downloadAsset(client, project, assetId, output2) {
46862
- const library = await client.request(`/api/v1/sprites/${encodeURIComponent(project)}/assets`);
46863
- const asset = library.assets.find((a) => a.id === assetId);
46864
- if (!asset) throw new Error("Asset not found in this project. Run assets list to find its id.");
46903
+ var timeoutSeconds = (value) => {
46904
+ const seconds2 = value ?? 600;
46905
+ if (!Number.isFinite(seconds2) || seconds2 <= 0) throw new Error("Timeout must be positive.");
46906
+ return seconds2;
46907
+ };
46908
+ async function waitForJob(client, project, jobId, timeout = 600, signal) {
46909
+ const deadline = Date.now() + timeoutSeconds(timeout) * 1e3;
46910
+ while (Date.now() < deadline) {
46911
+ const { job } = await client.request(`/api/v1/sprites/${encodeURIComponent(project)}/jobs/${encodeURIComponent(jobId)}`);
46912
+ if (job.status === "failed") throw new Error(job.error ?? "Generation failed.");
46913
+ if (job.status === "done") return job;
46914
+ await delay2(3e3, void 0, { signal });
46915
+ }
46916
+ throw new Error("Timed out waiting for the job. It may still be running.");
46917
+ }
46918
+ async function waitForJobs(client, project, ids, timeout, signal) {
46919
+ const results = /* @__PURE__ */ new Map();
46920
+ const deadline = Date.now() + timeout * 1e3;
46921
+ let pending = [...ids];
46922
+ while (pending.length && Date.now() < deadline) {
46923
+ for (const id2 of pending) {
46924
+ const { job } = await client.request(`/api/v1/sprites/${encodeURIComponent(project)}/jobs/${encodeURIComponent(id2)}`);
46925
+ if (job.status === "done" || job.status === "failed") results.set(id2, job);
46926
+ }
46927
+ pending = pending.filter((id2) => !results.has(id2));
46928
+ if (pending.length) await delay2(3e3, void 0, { signal });
46929
+ }
46930
+ return { results, pending };
46931
+ }
46932
+ var MIME_EXTENSIONS = {
46933
+ "audio/wav": "wav",
46934
+ "audio/x-wav": "wav",
46935
+ "audio/wave": "wav",
46936
+ "audio/mpeg": "mp3",
46937
+ "audio/mp4": "m4a",
46938
+ "audio/ogg": "ogg",
46939
+ "image/png": "png",
46940
+ "image/jpeg": "jpg",
46941
+ "image/webp": "webp",
46942
+ "video/mp4": "mp4",
46943
+ "video/webm": "webm"
46944
+ };
46945
+ var extensionFor = (asset) => MIME_EXTENSIONS[asset.mimeType?.split(";")[0].trim().toLowerCase()] ?? /\.([a-z0-9]{1,5})$/i.exec(asset.file ?? "")?.[1]?.toLowerCase() ?? "bin";
46946
+ async function downloadTarget(output2, asset, folder = false) {
46947
+ const path = resolve9(output2);
46948
+ const isFolder = folder || /[\\/]$/.test(output2) || await stat3(path).then((info) => info.isDirectory(), () => false);
46949
+ if (!isFolder) {
46950
+ await mkdir7(dirname6(path), { recursive: true });
46951
+ return path;
46952
+ }
46953
+ await mkdir7(path, { recursive: true });
46954
+ return join9(path, `${fileName(asset.name) || asset.id}.${extensionFor(asset)}`);
46955
+ }
46956
+ async function saveAsset(client, library, asset, path) {
46865
46957
  if (!library.ownerId || !/^[a-f0-9]{64}$/.test(asset.file)) throw new Error("Invalid asset download metadata.");
46866
46958
  const response = await client.request(`/api/v1/blobs/${encodeURIComponent(library.ownerId)}/${asset.file}`, { raw: true });
46867
- const path = resolve9(output2);
46868
46959
  const bytes = new Uint8Array(await response.arrayBuffer());
46869
46960
  await writeFile7(path, bytes, { flag: "wx" });
46870
46961
  return { path, id: asset.id, type: asset.type, mimeType: asset.mimeType, size: bytes.byteLength };
46871
46962
  }
46963
+ var assetsPath = (project) => `/api/v1/sprites/${encodeURIComponent(project)}/assets`;
46964
+ var assetSummary = (asset) => ({ id: asset.id, name: asset.name, type: asset.type, mimeType: asset.mimeType });
46965
+ async function jobAsset(client, project, jobId, signal) {
46966
+ for (let attempt = 0; ; attempt++) {
46967
+ const library = await client.request(assetsPath(project));
46968
+ const asset = library.assets.find((item) => item.jobId === jobId);
46969
+ if (asset) return { library, asset };
46970
+ if (attempt) throw new Error(`Job ${jobId} finished, but its asset is not in the project yet. Run assets list, then assets download.`);
46971
+ await delay2(2e3, void 0, { signal });
46972
+ }
46973
+ }
46974
+ async function downloadAsset(client, project, assetId, output2) {
46975
+ const library = await client.request(assetsPath(project));
46976
+ const asset = library.assets.find((a) => a.id === assetId);
46977
+ if (!asset) throw new Error("Asset not found in this project. Run assets list to find its id.");
46978
+ return saveAsset(client, library, asset, resolve9(output2));
46979
+ }
46980
+ async function generateAsset(client, project, body, options, signal) {
46981
+ const waiting = !options["dry-run"] && Boolean(options.wait || options.download);
46982
+ const timeout = waiting ? timeoutSeconds(options.timeout) : 0;
46983
+ const submission = await submitAsset(client, project, body, options);
46984
+ if (!waiting) return submission;
46985
+ if (typeof submission.id !== "string") throw new Error("The server did not return a job id; run jobs list before submitting again.");
46986
+ const job = await waitForJob(client, project, submission.id, timeout, signal);
46987
+ if (!options.download) return { ...submission, job };
46988
+ const { library, asset } = await jobAsset(client, project, submission.id, signal);
46989
+ const saved = await saveAsset(client, library, asset, await downloadTarget(options.download, asset));
46990
+ return { ...submission, job, asset: assetSummary(asset), download: { path: saved.path, size: saved.size } };
46991
+ }
46992
+ var sumCredits = (amounts) => toCredits(amounts.reduce((total, credits) => total + (typeof credits === "number" ? toUnits(credits) : 0), 0));
46993
+ async function submitAssetBatch(client, project, requests, options, signal) {
46994
+ if (options["dry-run"]) {
46995
+ const items2 = requests.map((request2) => ({ name: request2.name, type: request2.type, model: request2.model, estimatedCredits: toCredits(assetEstimate(request2)) }));
46996
+ return { dryRun: true, items: items2, estimatedCredits: toCredits(requests.reduce((total2, request2) => total2 + assetEstimate(request2), 0)) };
46997
+ }
46998
+ if (!options.yes) throw new Error("Pass --yes to authorize spending credits, or --dry-run to validate and estimate without generation.");
46999
+ const waiting = Boolean(options.wait || options.download);
47000
+ const timeout = waiting ? timeoutSeconds(options.timeout) : 0;
47001
+ const items = [];
47002
+ for (const [index2, request2] of requests.entries()) {
47003
+ try {
47004
+ const submission = await submitAsset(client, project, request2, options);
47005
+ if (typeof submission.id !== "string") throw new Error("The server did not return a job id.");
47006
+ items.push({ name: request2.name, ...submission });
47007
+ } catch (error62) {
47008
+ const message = error62 instanceof Error ? error62.message : String(error62);
47009
+ return { items, estimatedCredits: sumCredits(items.map((item) => item.estimatedCredits)), error: `Item #${index2 + 1} (${request2.name}) was not submitted: ${message}`, notSubmitted: requests.slice(index2).map((item) => item.name) };
47010
+ }
47011
+ }
47012
+ const total = sumCredits(items.map((item) => item.estimatedCredits));
47013
+ if (!waiting) return { items, estimatedCredits: total };
47014
+ const { results, pending } = await waitForJobs(client, project, items.map((item) => item.id), timeout, signal);
47015
+ let library;
47016
+ for (const item of items) {
47017
+ const job = results.get(item.id);
47018
+ if (!job) {
47019
+ item.error = "Timed out waiting for the job. It may still be running.";
47020
+ continue;
47021
+ }
47022
+ item.job = job;
47023
+ if (job.status === "failed") {
47024
+ item.error = job.error ?? "Generation failed.";
47025
+ continue;
47026
+ }
47027
+ if (!options.download) continue;
47028
+ library ??= await client.request(assetsPath(project));
47029
+ let asset = library.assets.find((candidate) => candidate.jobId === item.id);
47030
+ if (!asset) {
47031
+ try {
47032
+ ({ library, asset } = await jobAsset(client, project, item.id, signal));
47033
+ } catch (error62) {
47034
+ item.error = error62 instanceof Error ? error62.message : String(error62);
47035
+ continue;
47036
+ }
47037
+ }
47038
+ item.asset = assetSummary(asset);
47039
+ try {
47040
+ const saved = await saveAsset(client, library, asset, await downloadTarget(options.download, asset, true));
47041
+ item.download = { path: saved.path, size: saved.size };
47042
+ } catch (error62) {
47043
+ item.error = error62 instanceof Error ? error62.message : String(error62);
47044
+ }
47045
+ }
47046
+ const failed = items.filter((item) => item.error);
47047
+ return { items, estimatedCredits: total, ...failed.length ? { error: `${failed.length} of ${items.length} items did not finish${pending.length ? " in time" : ""}: ${failed.map((item) => item.name).join(", ")}. The others are complete; do not resubmit them.` } : {} };
47048
+ }
46872
47049
 
46873
47050
  // cli/src/avatars.ts
46874
- import { readFile as readFile9, stat as stat3 } from "node:fs/promises";
47051
+ import { readFile as readFile9, stat as stat4 } from "node:fs/promises";
46875
47052
  import { extname } from "node:path";
46876
- import { setTimeout as delay2 } from "node:timers/promises";
47053
+ import { setTimeout as delay3 } from "node:timers/promises";
46877
47054
 
46878
47055
  // shared/avatars.ts
46879
47056
  var AVATAR_OWNERSHIPS = ["public", "private"];
@@ -46882,8 +47059,8 @@ var AVATAR_CREATE_TYPES = ["prompt", "photo", "digital_twin"];
46882
47059
  var AVATAR_ASPECT_RATIOS = ["auto", "16:9", "9:16", "1:1", "4:5", "5:4"];
46883
47060
  var LOOK_PACK_ASPECT_RATIOS = ["16:9", "9:16"];
46884
47061
  var AVATAR_LOOK_METHODS = ["look_pack", "template"];
46885
- var AVATAR_USD = { digital_twin: 2.13, photo: 1.32, prompt: 1.32 };
46886
- var AVATAR_LOOK_USD = 1.32;
47062
+ var AVATAR_CREDIT_UNITS = { digital_twin: 2130, photo: 1320, prompt: 1320 };
47063
+ var AVATAR_LOOK_CREDIT_UNITS = 1320;
46887
47064
  var LOOKS_PER_METHOD = { look_pack: 5, template: 2 };
46888
47065
  var AVATAR_LOOK_TEMPLATES = [
46889
47066
  { id: "5a8e6be843ee4321a014946bf62aa322", method: "look_pack", name: "Modern Corporate", variant: "female" },
@@ -46960,10 +47137,8 @@ var limit = external_exports.coerce.number().int().min(1).max(50).default(20);
46960
47137
  var token = external_exports.string().max(2048).optional();
46961
47138
  var avatarListQuery = external_exports.object({ ownership: external_exports.enum(AVATAR_OWNERSHIPS).default("public"), limit, token });
46962
47139
  var avatarLookListQuery = external_exports.object({ groupId: heygenId.optional(), avatarType: external_exports.enum(AVATAR_LOOK_TYPES).optional(), limit, token });
46963
- var avatarCreateUsd = (p) => AVATAR_USD[p.type];
46964
- var avatarLooksUsd = (method, looks = LOOKS_PER_METHOD[method]) => looks * AVATAR_LOOK_USD;
46965
- var avatarCreateEstimate = (p) => creditsFor(avatarCreateUsd(p));
46966
- var avatarLooksEstimate = (p) => creditsFor(avatarLooksUsd(p.method));
47140
+ var avatarCreateEstimate = (p) => AVATAR_CREDIT_UNITS[p.type];
47141
+ var avatarLooksEstimate = (p) => LOOKS_PER_METHOD[p.method] * AVATAR_LOOK_CREDIT_UNITS;
46967
47142
 
46968
47143
  // cli/src/avatars.ts
46969
47144
  var MEDIA_TYPES = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".mp4": "video/mp4", ".mov": "video/quicktime", ".webm": "video/webm" };
@@ -46979,7 +47154,7 @@ async function avatarFile2(value) {
46979
47154
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) throw new Error("Use an HTTPS URL, a project file SHA or a local file.");
46980
47155
  const mediaType = MEDIA_TYPES[extname(value).toLowerCase()];
46981
47156
  if (!mediaType) throw new Error("Use a PNG, JPEG or WebP image, or MP4, MOV or WebM footage.");
46982
- if ((await stat3(value)).size > AVATAR_INLINE_MAX_BYTES) throw new Error("Local files must be at most 8 MB. Use an HTTPS URL for larger footage.");
47157
+ if ((await stat4(value)).size > AVATAR_INLINE_MAX_BYTES) throw new Error("Local files must be at most 8 MB. Use an HTTPS URL for larger footage.");
46983
47158
  return { type: "base64", mediaType, data: (await readFile9(value)).toString("base64") };
46984
47159
  }
46985
47160
  async function avatarFromFlags(flags) {
@@ -47021,18 +47196,18 @@ async function waitForLook(client, project, lookId, timeout, signal, interval =
47021
47196
  if (look.status === "failed") throw new Error(look.error?.message ?? "HeyGen could not create this look.");
47022
47197
  if (look.status !== "processing") return { look };
47023
47198
  if (Date.now() + interval > deadline) throw new Error("Timed out waiting for the look. HeyGen may still be working on it.");
47024
- await delay2(interval, void 0, { signal });
47199
+ await delay3(interval, void 0, { signal });
47025
47200
  }
47026
47201
  }
47027
47202
 
47028
47203
  // cli/src/youtube-auth.ts
47029
47204
  import { createServer } from "node:http";
47030
47205
  import { randomBytes, createHash as createHash4, timingSafeEqual } from "node:crypto";
47031
- import { readFile as readFile11, stat as stat4 } from "node:fs/promises";
47206
+ import { readFile as readFile11, stat as stat5 } from "node:fs/promises";
47032
47207
 
47033
47208
  // cli/src/youtube-store.ts
47034
- import { chmod as chmod3, lstat, mkdir as mkdir7, open as open4, readFile as readFile10, readdir as readdir3, rename as rename4, unlink, writeFile as writeFile8 } from "node:fs/promises";
47035
- import { dirname as dirname6, join as join8 } from "node:path";
47209
+ import { chmod as chmod3, lstat, mkdir as mkdir8, open as open4, readFile as readFile10, readdir as readdir4, rename as rename4, unlink, writeFile as writeFile8 } from "node:fs/promises";
47210
+ import { dirname as dirname7, join as join10 } from "node:path";
47036
47211
  import { randomUUID as randomUUID2 } from "node:crypto";
47037
47212
  function cloudYouTube() {
47038
47213
  const project = process.env.ANIMAGURU_CLOUD_PROJECT;
@@ -47094,14 +47269,14 @@ var youtubeJob = external_exports.object({
47094
47269
  captions: youtubeCaptions.optional(),
47095
47270
  thumbnail: youtubeThumbnail.optional()
47096
47271
  }).strict();
47097
- var youtubeDirectory = () => join8(dirname6(credentialsPath()), "youtube");
47098
- var credentialFile = () => join8(youtubeDirectory(), "credentials.json");
47272
+ var youtubeDirectory = () => join10(dirname7(credentialsPath()), "youtube");
47273
+ var credentialFile = () => join10(youtubeDirectory(), "credentials.json");
47099
47274
  function jobFile(id2) {
47100
47275
  if (!external_exports.uuid().safeParse(id2).success) throw new Error("Use an upload ID returned by animaguru youtube uploads list.");
47101
- return join8(youtubeDirectory(), "uploads", `${id2}.json`);
47276
+ return join10(youtubeDirectory(), "uploads", `${id2}.json`);
47102
47277
  }
47103
47278
  async function privateDirectory(directory) {
47104
- await mkdir7(directory, { recursive: true, mode: 448 });
47279
+ await mkdir8(directory, { recursive: true, mode: 448 });
47105
47280
  const info = await lstat(directory);
47106
47281
  if (info.isSymbolicLink() || !info.isDirectory()) throw new Error("YouTube configuration must use a real directory.");
47107
47282
  await chmod3(directory, 448);
@@ -47118,7 +47293,7 @@ async function existingDirectory(directory) {
47118
47293
  }
47119
47294
  async function readPrivate(file2) {
47120
47295
  try {
47121
- if (!await existingDirectory(youtubeDirectory()) || !await existingDirectory(dirname6(file2))) return null;
47296
+ if (!await existingDirectory(youtubeDirectory()) || !await existingDirectory(dirname7(file2))) return null;
47122
47297
  const info = await lstat(file2);
47123
47298
  if (info.isSymbolicLink() || !info.isFile() || info.size > 65536) throw new Error("Invalid local YouTube state file.");
47124
47299
  await chmod3(file2, 384);
@@ -47130,7 +47305,7 @@ async function readPrivate(file2) {
47130
47305
  }
47131
47306
  async function writePrivate(file2, value) {
47132
47307
  await privateDirectory(youtubeDirectory());
47133
- await privateDirectory(dirname6(file2));
47308
+ await privateDirectory(dirname7(file2));
47134
47309
  const temporary = `${file2}.${randomUUID2()}.tmp`;
47135
47310
  try {
47136
47311
  await writeFile8(temporary, JSON.stringify(value) + "\n", { flag: "wx", mode: 384 });
@@ -47183,11 +47358,11 @@ async function localYouTubeJobs() {
47183
47358
  const result = await cloud.client.request(`${cloud.path}/uploads`);
47184
47359
  return result.jobs.map((job) => youtubeJob.parse(job));
47185
47360
  }
47186
- const directory = join8(youtubeDirectory(), "uploads");
47361
+ const directory = join10(youtubeDirectory(), "uploads");
47187
47362
  if (!await existingDirectory(directory)) return [];
47188
47363
  let files;
47189
47364
  try {
47190
- files = await readdir3(directory);
47365
+ files = await readdir4(directory);
47191
47366
  } catch (error62) {
47192
47367
  if (error62.code === "ENOENT") return [];
47193
47368
  throw error62;
@@ -47204,10 +47379,10 @@ async function clearYouTubeData() {
47204
47379
  await unlink(credentialFile()).catch((error62) => {
47205
47380
  if (error62.code !== "ENOENT") throw error62;
47206
47381
  });
47207
- if (!await existingDirectory(join8(youtubeDirectory(), "uploads"))) return;
47382
+ if (!await existingDirectory(join10(youtubeDirectory(), "uploads"))) return;
47208
47383
  let files;
47209
47384
  try {
47210
- files = await readdir3(join8(youtubeDirectory(), "uploads"));
47385
+ files = await readdir4(join10(youtubeDirectory(), "uploads"));
47211
47386
  } catch (error62) {
47212
47387
  if (error62.code === "ENOENT") return;
47213
47388
  throw error62;
@@ -47216,7 +47391,7 @@ async function clearYouTubeData() {
47216
47391
  }
47217
47392
  async function withYouTubeLock(operation) {
47218
47393
  await privateDirectory(youtubeDirectory());
47219
- const file2 = join8(youtubeDirectory(), "operation.lock");
47394
+ const file2 = join10(youtubeDirectory(), "operation.lock");
47220
47395
  const lock = await open4(file2, "wx", 384).catch((error62) => {
47221
47396
  if (error62.code === "EEXIST") throw new Error(`Another YouTube command is running. If a previous command was killed, verify it has stopped before removing ${file2}.`);
47222
47397
  throw error62;
@@ -47366,7 +47541,7 @@ async function youtubeLogin(options) {
47366
47541
  if (existing && options.captions && !canAddCaptions(existing)) throw new Error("A YouTube channel is already connected without caption permission. Run youtube auth logout --yes, then youtube auth login --captions.");
47367
47542
  if (existing) throw new Error("A YouTube channel is already connected. Run youtube auth logout --yes before switching channels.");
47368
47543
  const file2 = options["client-file"];
47369
- const info = await stat4(file2);
47544
+ const info = await stat5(file2);
47370
47545
  if (!info.isFile() || info.size > 65536) throw new Error("Use Google's downloaded Desktop app OAuth client JSON.");
47371
47546
  let installed;
47372
47547
  try {
@@ -47380,8 +47555,8 @@ async function youtubeLogin(options) {
47380
47555
  let receive;
47381
47556
  let fail;
47382
47557
  let used = false;
47383
- const callback = new Promise((resolve13, reject) => {
47384
- receive = resolve13;
47558
+ const callback = new Promise((resolve15, reject) => {
47559
+ receive = resolve15;
47385
47560
  fail = reject;
47386
47561
  });
47387
47562
  void callback.catch(() => {
@@ -47419,9 +47594,9 @@ async function youtubeLogin(options) {
47419
47594
  response.end("Authorization received. Return to your AnimaGuru terminal.");
47420
47595
  receive(code);
47421
47596
  });
47422
- await new Promise((resolve13, reject) => {
47597
+ await new Promise((resolve15, reject) => {
47423
47598
  server.once("error", reject);
47424
- server.listen(0, "127.0.0.1", resolve13);
47599
+ server.listen(0, "127.0.0.1", resolve15);
47425
47600
  });
47426
47601
  const address = server.address();
47427
47602
  if (!address || typeof address === "string") throw new Error("Cannot open the local YouTube authorization listener.");
@@ -47456,7 +47631,7 @@ async function youtubeLogin(options) {
47456
47631
  clearTimeout(timer);
47457
47632
  options.signal?.removeEventListener("abort", abort);
47458
47633
  server.closeAllConnections();
47459
- await new Promise((resolve13) => server.close(() => resolve13()));
47634
+ await new Promise((resolve15) => server.close(() => resolve15()));
47460
47635
  }
47461
47636
  });
47462
47637
  }
@@ -47487,19 +47662,19 @@ async function youtubeLogout(options) {
47487
47662
 
47488
47663
  // cli/src/youtube-upload.ts
47489
47664
  import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
47490
- import { open as open6, readFile as readFile13, stat as stat6 } from "node:fs/promises";
47491
- import { basename as basename5, join as join10, resolve as resolve11 } from "node:path";
47492
- import { setTimeout as delay4 } from "node:timers/promises";
47665
+ import { open as open6, readFile as readFile13, stat as stat7 } from "node:fs/promises";
47666
+ import { basename as basename5, join as join12, resolve as resolve11 } from "node:path";
47667
+ import { setTimeout as delay5 } from "node:timers/promises";
47493
47668
 
47494
47669
  // cli/src/cloud-sync.ts
47495
47670
  var import_isomorphic_git = __toESM(require_isomorphic_git(), 1);
47496
47671
  import * as fs from "node:fs";
47497
- import { chmod as chmod4, lstat as lstat2, mkdir as mkdir8, open as open5, readFile as readFile12, readdir as readdir4, realpath, rename as rename5, rm as rm2, stat as stat5, writeFile as writeFile9 } from "node:fs/promises";
47672
+ import { chmod as chmod4, lstat as lstat2, mkdir as mkdir9, open as open5, readFile as readFile12, readdir as readdir5, realpath, rename as rename5, rm as rm2, stat as stat6, writeFile as writeFile9 } from "node:fs/promises";
47498
47673
  import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
47499
- import { dirname as dirname7, join as join9, resolve as resolve10 } from "node:path";
47674
+ import { dirname as dirname8, join as join11, resolve as resolve10 } from "node:path";
47500
47675
  import { Readable } from "node:stream";
47501
47676
  import { pipeline } from "node:stream/promises";
47502
- import { setTimeout as delay3 } from "node:timers/promises";
47677
+ import { setTimeout as delay4 } from "node:timers/promises";
47503
47678
 
47504
47679
  // node_modules/isomorphic-git/http/web/index.js
47505
47680
  function fromValue(value) {
@@ -47671,8 +47846,8 @@ sha256 ${sha256}
47671
47846
  size ${size}
47672
47847
  `;
47673
47848
  var POINTER = /^animaguru-cloud-object v1\nsha256 ([a-f0-9]{64})\nsize (\d{1,16})\n$/;
47674
- function parseCloudPointer(text) {
47675
- const match = POINTER.exec(text);
47849
+ function parseCloudPointer(text2) {
47850
+ const match = POINTER.exec(text2);
47676
47851
  if (!match) return null;
47677
47852
  const size = Number(match[2]);
47678
47853
  return Number.isSafeInteger(size) && size > 0 && size <= CLOUD_OBJECT_MAX_BYTES ? { sha256: match[1], size } : null;
@@ -47712,20 +47887,20 @@ var BUILT_IN_IGNORES = [
47712
47887
  ];
47713
47888
  var builtIn = (0, import_ignore.default)().add(BUILT_IN_IGNORES);
47714
47889
  var exists = (path) => lstat2(path).then(() => true, () => false);
47715
- var list = (paths, limit2 = 200) => paths.length > limit2 ? [...paths.slice(0, limit2), `\u2026and ${paths.length - limit2} more`] : paths;
47890
+ var list2 = (paths, limit2 = 200) => paths.length > limit2 ? [...paths.slice(0, limit2), `\u2026and ${paths.length - limit2} more`] : paths;
47716
47891
  var short = (oid) => oid.slice(0, 12);
47717
47892
  var executable = (mode) => (mode & 73) !== 0;
47718
47893
  async function cloudRootFor(start) {
47719
47894
  let directory = resolve10(start);
47720
47895
  while (true) {
47721
- if (await exists(join9(directory, LINK_FILE)) || await exists(join9(directory, "animaguru.workspace.json"))) return directory;
47896
+ if (await exists(join11(directory, LINK_FILE)) || await exists(join11(directory, "animaguru.workspace.json"))) return directory;
47722
47897
  try {
47723
- const project = JSON.parse(await readFile12(join9(directory, "animaguru.project.json"), "utf8"));
47898
+ const project = JSON.parse(await readFile12(join11(directory, "animaguru.project.json"), "utf8"));
47724
47899
  if (!project.workspace) return directory;
47725
47900
  } catch (error62) {
47726
47901
  if (error62.code !== "ENOENT" && !(error62 instanceof SyntaxError)) throw error62;
47727
47902
  }
47728
- const parent = dirname7(directory);
47903
+ const parent = dirname8(directory);
47729
47904
  if (parent === directory) throw new Error("Run this inside an AnimaGuru video workspace or project, or pass --dir. Create one with animaguru create workspace NAME.");
47730
47905
  directory = parent;
47731
47906
  }
@@ -47739,14 +47914,14 @@ async function readJson2(path) {
47739
47914
  }
47740
47915
  }
47741
47916
  async function writeJson2(path, value) {
47742
- await mkdir8(dirname7(path), { recursive: true });
47917
+ await mkdir9(dirname8(path), { recursive: true });
47743
47918
  const temp = `${path}.${randomUUID3()}.tmp`;
47744
47919
  await writeFile9(temp, JSON.stringify(value, null, 2) + "\n", { mode: 384 });
47745
47920
  await rename5(temp, path);
47746
47921
  }
47747
47922
  async function withLock(root, run) {
47748
- const path = join9(root, SYNC_DIR, "lock");
47749
- await mkdir8(dirname7(path), { recursive: true });
47923
+ const path = join11(root, SYNC_DIR, "lock");
47924
+ await mkdir9(dirname8(path), { recursive: true });
47750
47925
  for (let attempt = 0; ; attempt++) {
47751
47926
  try {
47752
47927
  await writeFile9(path, JSON.stringify({ pid: process.pid, at: Date.now() }), { flag: "wx" });
@@ -47774,27 +47949,27 @@ async function withLock(root, run) {
47774
47949
  }
47775
47950
  async function openContext(dir, options, url2) {
47776
47951
  const root = await cloudRootFor(dir);
47777
- const link2 = await readJson2(join9(root, LINK_FILE));
47952
+ const link2 = await readJson2(join11(root, LINK_FILE));
47778
47953
  if (!link2) throw new Error("This folder is not linked to a cloud project. Run animaguru cloud link, or animaguru cloud clone ID.");
47779
47954
  if (link2.schemaVersion !== 1 || !cloudProjectId.safeParse(link2.projectId).success) throw new Error(`Unsupported cloud link in ${LINK_FILE}. Run animaguru cloud unlink and link again.`);
47780
- const state = await readJson2(join9(root, STATE_FILE)) ?? { schemaVersion: 1, base: null, files: {} };
47781
- return { root, gitdir: join9(root, GIT_DIR), link: link2, state, client: new Client(url2 ?? link2.origin, options.signal), options };
47955
+ const state = await readJson2(join11(root, STATE_FILE)) ?? { schemaVersion: 1, base: null, files: {} };
47956
+ return { root, gitdir: join11(root, GIT_DIR), link: link2, state, client: new Client(url2 ?? link2.origin, options.signal), options };
47782
47957
  }
47783
47958
  async function cloudLink(dir) {
47784
- const link2 = await readJson2(join9(await cloudRootFor(dir), LINK_FILE));
47959
+ const link2 = await readJson2(join11(await cloudRootFor(dir), LINK_FILE));
47785
47960
  if (!link2) throw new Error("This folder is not linked to a cloud project. Pass a cloud project ID.");
47786
47961
  return link2;
47787
47962
  }
47788
- var saveState = (context) => writeJson2(join9(context.root, STATE_FILE), context.state);
47963
+ var saveState = (context) => writeJson2(join11(context.root, STATE_FILE), context.state);
47789
47964
  async function scanFiles(root) {
47790
47965
  const files = /* @__PURE__ */ new Map();
47791
47966
  const skipped = [];
47792
47967
  const tooLarge = [];
47793
47968
  async function walk(directory, prefix, rules) {
47794
- const entries = (await readdir4(directory, { withFileTypes: true })).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
47969
+ const entries = (await readdir5(directory, { withFileTypes: true })).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
47795
47970
  const scoped = [...rules];
47796
47971
  for (const name2 of [".gitignore", ".animaguruignore"]) {
47797
- if (entries.some((entry) => entry.name === name2 && entry.isFile())) scoped.push({ base: prefix, rules: (0, import_ignore.default)().add(await readFile12(join9(directory, name2), "utf8")) });
47972
+ if (entries.some((entry) => entry.name === name2 && entry.isFile())) scoped.push({ base: prefix, rules: (0, import_ignore.default)().add(await readFile12(join11(directory, name2), "utf8")) });
47798
47973
  }
47799
47974
  for (const entry of entries) {
47800
47975
  const path = prefix ? `${prefix}/${entry.name}` : entry.name;
@@ -47805,7 +47980,7 @@ async function scanFiles(root) {
47805
47980
  continue;
47806
47981
  }
47807
47982
  if (entry.isDirectory()) {
47808
- await walk(join9(directory, entry.name), path, scoped);
47983
+ await walk(join11(directory, entry.name), path, scoped);
47809
47984
  continue;
47810
47985
  }
47811
47986
  if (!entry.isFile()) continue;
@@ -47816,7 +47991,7 @@ async function scanFiles(root) {
47816
47991
  skipped.push(`${path} (unsupported name)`);
47817
47992
  continue;
47818
47993
  }
47819
- const info = await stat5(join9(directory, entry.name));
47994
+ const info = await stat6(join11(directory, entry.name));
47820
47995
  if (info.size > CLOUD_OBJECT_MAX_BYTES) {
47821
47996
  skipped.push(`${path} (larger than ${CLOUD_OBJECT_MAX_BYTES / 1024 ** 3} GB)`);
47822
47997
  continue;
@@ -47825,14 +48000,14 @@ async function scanFiles(root) {
47825
48000
  tooLarge.push(safe);
47826
48001
  continue;
47827
48002
  }
47828
- files.set(safe, { path: safe, absolute: join9(directory, entry.name), size: info.size, mtimeMs: info.mtimeMs, mode: executable(info.mode) ? "100755" : "100644" });
48003
+ files.set(safe, { path: safe, absolute: join11(directory, entry.name), size: info.size, mtimeMs: info.mtimeMs, mode: executable(info.mode) ? "100755" : "100644" });
47829
48004
  if (files.size > CLOUD_MAX_FILES) throw new Error(`Cloud sync supports up to ${CLOUD_MAX_FILES} files. Add generated folders to .animaguruignore.`);
47830
48005
  }
47831
48006
  }
47832
48007
  await walk(root, "", []);
47833
48008
  return { files, skipped, tooLarge };
47834
48009
  }
47835
- var tooLargeError = (paths) => new Error(`Work files over ${CLOUD_GIT_FILE_MAX_BYTES / 1024 / 1024} MB cannot be versioned in Git: ${list(paths, 20).join(", ")}. Add them to .animaguruignore or move them out of the folder; images, video, audio and ZIP files of any size are stored separately.`);
48010
+ var tooLargeError = (paths) => new Error(`Work files over ${CLOUD_GIT_FILE_MAX_BYTES / 1024 / 1024} MB cannot be versioned in Git: ${list2(paths, 20).join(", ")}. Add them to .animaguruignore or move them out of the folder; images, video, audio and ZIP files of any size are stored separately.`);
47836
48011
  function guardTooLarge(tooLarge, paths) {
47837
48012
  const blocked = paths.filter((path) => tooLarge.includes(path));
47838
48013
  if (blocked.length) throw tooLargeError(blocked);
@@ -47921,14 +48096,14 @@ ${entries.join(",\n")}
47921
48096
  }}
47922
48097
  `;
47923
48098
  }
47924
- async function token2(context, access2) {
47925
- const result = await context.client.request(`/api/v1/cloud/${context.link.projectId}/token`, { method: "POST", body: { access: access2 } });
48099
+ async function token2(context, access3) {
48100
+ const result = await context.client.request(`/api/v1/cloud/${context.link.projectId}/token`, { method: "POST", body: { access: access3 } });
47926
48101
  const remote = new URL(result.remote);
47927
48102
  if (remote.protocol !== "https:" && !(remote.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(remote.hostname))) throw new Error("The server returned an unsafe cloud remote.");
47928
48103
  return { ...result, onAuth: () => ({ username: "x", password: result.token.split("?expires=")[0] }) };
47929
48104
  }
47930
48105
  async function ensureRepo(gitdir) {
47931
- if (await exists(join9(gitdir, "HEAD"))) return;
48106
+ if (await exists(join11(gitdir, "HEAD"))) return;
47932
48107
  await import_isomorphic_git.default.init({ fs, gitdir, bare: true, defaultBranch: CLOUD_BRANCH });
47933
48108
  await import_isomorphic_git.default.setConfig({ fs, gitdir, path: "remote.origin.fetch", value: `+refs/heads/${CLOUD_BRANCH}:refs/remotes/origin/${CLOUD_BRANCH}` });
47934
48109
  }
@@ -47984,7 +48159,7 @@ async function stageCloudVideo(options) {
47984
48159
  const root = await realpath(context.root);
47985
48160
  const file2 = await realpath(options.file);
47986
48161
  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.");
47987
- const info = await stat5(file2);
48162
+ const info = await stat6(file2);
47988
48163
  if (!info.isFile() || info.size !== options.size) throw new Error("The MP4 changed before staging.");
47989
48164
  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);
47990
48165
  }
@@ -47994,7 +48169,7 @@ async function retry(context, run) {
47994
48169
  return await run();
47995
48170
  } catch (error62) {
47996
48171
  if (attempt >= 2 || context.options.signal?.aborted || error62 instanceof ServiceError && error62.status < 500 && error62.status !== 429) throw error62;
47997
- await delay3(1e3 * (attempt + 1), void 0, { signal: context.options.signal });
48172
+ await delay4(1e3 * (attempt + 1), void 0, { signal: context.options.signal });
47998
48173
  }
47999
48174
  }
48000
48175
  }
@@ -48003,12 +48178,12 @@ async function target(root, path) {
48003
48178
  if (builtIn.ignores(path)) throw new Error(`Refusing to write ${path}: cloud sync never writes ignored or secret files.`);
48004
48179
  let current = root;
48005
48180
  for (const part of parts.slice(0, -1)) {
48006
- current = join9(current, part);
48181
+ current = join11(current, part);
48007
48182
  const info2 = await lstat2(current).catch(() => null);
48008
- if (!info2) await mkdir8(current);
48183
+ if (!info2) await mkdir9(current);
48009
48184
  else if (info2.isSymbolicLink() || !info2.isDirectory()) throw new Error(`Cannot write ${path}: ${part} is not a folder.`);
48010
48185
  }
48011
- const file2 = join9(current, parts.at(-1));
48186
+ const file2 = join11(current, parts.at(-1));
48012
48187
  const info = await lstat2(file2).catch(() => null);
48013
48188
  if (info && !info.isFile()) throw new Error(`Cannot replace ${path}: it is a link or folder.`);
48014
48189
  return file2;
@@ -48034,7 +48209,7 @@ async function materialize(context, path, entry) {
48034
48209
  } else await writeFile9(temp, blob2, { mode: 420 });
48035
48210
  await chmod4(temp, entry.mode === "100755" ? 493 : 420);
48036
48211
  await rename5(temp, file2);
48037
- const info = await stat5(file2);
48212
+ const info = await stat6(file2);
48038
48213
  return { ...entry, size: info.size, mtimeMs: info.mtimeMs, ...pointer ? { sha256: pointer.sha256 } : {} };
48039
48214
  } catch (error62) {
48040
48215
  await rm2(temp, { force: true });
@@ -48042,10 +48217,10 @@ async function materialize(context, path, entry) {
48042
48217
  }
48043
48218
  }
48044
48219
  async function backup(context, folder, path) {
48045
- const source = join9(context.root, path);
48220
+ const source = join11(context.root, path);
48046
48221
  if (!await exists(source)) return;
48047
- const destination = join9(context.root, SYNC_DIR, "backups", folder, path);
48048
- await mkdir8(dirname7(destination), { recursive: true });
48222
+ const destination = join11(context.root, SYNC_DIR, "backups", folder, path);
48223
+ await mkdir9(dirname8(destination), { recursive: true });
48049
48224
  await fs.promises.copyFile(source, destination);
48050
48225
  }
48051
48226
  async function remove(context, path) {
@@ -48065,23 +48240,23 @@ async function apply(context, local, writes, deletes) {
48065
48240
  }
48066
48241
  async function linkCloud(client, options) {
48067
48242
  const root = await cloudRootFor(options.dir);
48068
- if (await exists(join9(root, LINK_FILE))) throw new Error(`This folder is already linked. Run animaguru cloud status, or animaguru cloud unlink first.`);
48243
+ if (await exists(join11(root, LINK_FILE))) throw new Error(`This folder is already linked. Run animaguru cloud status, or animaguru cloud unlink first.`);
48069
48244
  const project = options.id ? (await client.request(`/api/v1/cloud/${encodeURIComponent(options.id)}`)).project : (await client.request("/api/v1/cloud", { method: "POST", body: { workspace: options.workspace, name: options.name ?? root.split(/[\\/]/).pop() } })).project;
48070
- await writeJson2(join9(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
48245
+ await writeJson2(join11(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
48071
48246
  await keepOutOfGit(root);
48072
48247
  return { project, path: root, nextSteps: project.head ? ["Run animaguru cloud pull to combine the cloud versions with this folder."] : ['Run animaguru cloud push -m "First version" to save the first version.'] };
48073
48248
  }
48074
48249
  async function keepOutOfGit(root) {
48075
- const path = join9(root, ".gitignore");
48076
- const text = await readFile12(path, "utf8").catch(() => null);
48077
- if (text !== null && !/^\/?\.animaguru\/(?:sync\/?)?$/m.test(text)) await writeFile9(path, `${text}${text.endsWith("\n") || !text ? "" : "\n"}.animaguru/sync/
48250
+ const path = join11(root, ".gitignore");
48251
+ const text2 = await readFile12(path, "utf8").catch(() => null);
48252
+ if (text2 !== null && !/^\/?\.animaguru\/(?:sync\/?)?$/m.test(text2)) await writeFile9(path, `${text2}${text2.endsWith("\n") || !text2 ? "" : "\n"}.animaguru/sync/
48078
48253
  `);
48079
48254
  }
48080
48255
  async function unlinkCloud(options) {
48081
48256
  const root = await cloudRootFor(options.dir);
48082
- if (!await exists(join9(root, LINK_FILE))) throw new Error("This folder is not linked to a cloud project.");
48257
+ if (!await exists(join11(root, LINK_FILE))) throw new Error("This folder is not linked to a cloud project.");
48083
48258
  await withLock(root, async () => {
48084
- for (const name2 of ["link.json", "state.json", "repo.git"]) await rm2(join9(root, SYNC_DIR, name2), { recursive: true, force: true });
48259
+ for (const name2 of ["link.json", "state.json", "repo.git"]) await rm2(join11(root, SYNC_DIR, name2), { recursive: true, force: true });
48085
48260
  });
48086
48261
  return { unlinked: true, path: root, note: "The cloud project and its versions were not changed." };
48087
48262
  }
@@ -48103,10 +48278,10 @@ async function cloudStatus(options) {
48103
48278
  project: { id: context.link.projectId, name: context.link.name },
48104
48279
  path: context.root,
48105
48280
  version: context.state.base,
48106
- changes: { count: diff.count, added: list(diff.added), modified: list(diff.modified), deleted: list(diff.deleted) },
48281
+ changes: { count: diff.count, added: list2(diff.added), modified: list2(diff.modified), deleted: list2(diff.deleted) },
48107
48282
  cloud,
48108
- skipped: list(skipped),
48109
- ...tooLarge.length ? { tooLarge: list(tooLarge), problem: tooLargeError(tooLarge).message } : {},
48283
+ skipped: list2(skipped),
48284
+ ...tooLarge.length ? { tooLarge: list2(tooLarge), problem: tooLargeError(tooLarge).message } : {},
48110
48285
  next: cloud?.newer ? "Run animaguru cloud pull to get the newer cloud version." : tooLarge.length ? "Add the work files over 32 MB to .animaguruignore or move them, then push." : diff.count ? 'Run animaguru cloud push -m "What changed" to save a version.' : "Everything is saved."
48111
48286
  };
48112
48287
  });
@@ -48131,13 +48306,13 @@ async function pushCloud(options) {
48131
48306
  if (!local.size) throw new Error("There are no files to save.");
48132
48307
  for (const [path, entry] of local) {
48133
48308
  if (base2.get(path)?.oid === entry.oid) continue;
48134
- const bytes = entry.sha256 ? new TextEncoder().encode(cloudPointer(entry.sha256, entry.size)) : await readFile12(join9(context.root, path));
48309
+ const bytes = entry.sha256 ? new TextEncoder().encode(cloudPointer(entry.sha256, entry.size)) : await readFile12(join11(context.root, path));
48135
48310
  if (await import_isomorphic_git.default.writeBlob({ fs, gitdir: context.gitdir, blob: bytes }) !== entry.oid) throw new Error(`${path} changed while saving. Run the push again.`);
48136
48311
  }
48137
- const uploaded = await uploadObjects(context, local, (path) => join9(context.root, path));
48312
+ const uploaded = await uploadObjects(context, local, (path) => join11(context.root, path));
48138
48313
  for (const [path, entry] of local) {
48139
48314
  if (!entry.sha256 || base2.get(path)?.oid === entry.oid) continue;
48140
- const info = await stat5(join9(context.root, path));
48315
+ const info = await stat6(join11(context.root, path));
48141
48316
  if (info.size !== entry.size || info.mtimeMs !== entry.mtimeMs) throw new Error(`${path} changed while saving. Run the push again.`);
48142
48317
  }
48143
48318
  const tree = await writeTree(context.gitdir, local, manifestText(local));
@@ -48162,7 +48337,7 @@ async function pushCloud(options) {
48162
48337
  remember(context, local);
48163
48338
  await saveState(context);
48164
48339
  const recorded = await context.client.request(`/api/v1/cloud/${context.link.projectId}/versions`, { method: "POST", body: { version: commit } });
48165
- return { saved: true, version: commit, message, changes: { added: diff.added.length, modified: diff.modified.length, deleted: diff.deleted.length }, uploadedMedia: uploaded, files: recorded.version.files, bytes: recorded.version.bytes, skipped: list(skipped) };
48340
+ return { saved: true, version: commit, message, changes: { added: diff.added.length, modified: diff.modified.length, deleted: diff.deleted.length }, uploadedMedia: uploaded, files: recorded.version.files, bytes: recorded.version.bytes, skipped: list2(skipped) };
48166
48341
  });
48167
48342
  }
48168
48343
  function defaultMessage(diff) {
@@ -48194,7 +48369,7 @@ async function pullCloud(options) {
48194
48369
  else deletes.push(path);
48195
48370
  }
48196
48371
  guardTooLarge(tooLarge, [...conflicts, ...writes.map(([path]) => path), ...deletes]);
48197
- if (conflicts.length) throw Object.assign(new Error(`These files changed both here and in the cloud: ${list(conflicts, 20).join(", ")}. Run animaguru cloud pull --prefer local to keep yours (the next push replaces the cloud copies), or --prefer cloud to take the cloud's (yours are backed up in ${SYNC_DIR}/backups).`), { conflicts });
48372
+ if (conflicts.length) throw Object.assign(new Error(`These files changed both here and in the cloud: ${list2(conflicts, 20).join(", ")}. Run animaguru cloud pull --prefer local to keep yours (the next push replaces the cloud copies), or --prefer cloud to take the cloud's (yours are backed up in ${SYNC_DIR}/backups).`), { conflicts });
48198
48373
  const folder = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
48199
48374
  let backedUp = 0;
48200
48375
  for (const path of [...writes.map(([path2]) => path2), ...deletes]) if (!same(local.get(path), base2.get(path)) && local.has(path)) {
@@ -48212,9 +48387,9 @@ async function pullCloud(options) {
48212
48387
  async function cloneCloud(client, options) {
48213
48388
  const { project } = await client.request(`/api/v1/cloud/${encodeURIComponent(options.id)}`);
48214
48389
  const root = resolve10(options.dir ?? (project.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || project.id));
48215
- if (await exists(root) && (await readdir4(root)).length) throw new Error(`Destination is not empty: ${root}. Choose a new folder; existing files were not changed.`);
48216
- await mkdir8(root, { recursive: true });
48217
- await writeJson2(join9(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
48390
+ if (await exists(root) && (await readdir5(root)).length) throw new Error(`Destination is not empty: ${root}. Choose a new folder; existing files were not changed.`);
48391
+ await mkdir9(root, { recursive: true });
48392
+ await writeJson2(join11(root, LINK_FILE), { schemaVersion: 1, origin: client.origin, projectId: project.id, name: project.name, workspace: project.workspaceId });
48218
48393
  const pulled = await pullCloud({ ...options, dir: root });
48219
48394
  return { project, path: root, version: pulled.version, files: "written" in pulled ? pulled.written : 0, nextSteps: ["Run npm install in the folder before previewing or exporting."] };
48220
48395
  }
@@ -48242,7 +48417,7 @@ async function restoreCloud(options) {
48242
48417
  if (selected.length && !writes.length && !deletes.length && ![...wanted.keys()].some(inScope)) throw new Error(`None of ${selected.join(", ")} is in version ${short(version3)}.`);
48243
48418
  guardTooLarge(tooLarge, writes.map(([path]) => path));
48244
48419
  const unsaved = [...writes.map(([path]) => path), ...deletes].filter((path) => local.has(path) && !same(local.get(path), base2.get(path)));
48245
- if (unsaved.length && !options.yes) throw new Error(`Restoring replaces unsaved changes in ${list(unsaved, 20).join(", ")}. Push them first, or pass --yes to replace them (copies are kept in ${SYNC_DIR}/backups).`);
48420
+ if (unsaved.length && !options.yes) throw new Error(`Restoring replaces unsaved changes in ${list2(unsaved, 20).join(", ")}. Push them first, or pass --yes to replace them (copies are kept in ${SYNC_DIR}/backups).`);
48246
48421
  const folder = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
48247
48422
  for (const path of unsaved) await backup(context, folder, path);
48248
48423
  await apply(context, local, writes, deletes);
@@ -48303,7 +48478,7 @@ async function planCaptions(root, mp4, options, fallbackLanguage) {
48303
48478
  async function readThumbnail(file2) {
48304
48479
  let info;
48305
48480
  try {
48306
- info = await stat6(file2);
48481
+ info = await stat7(file2);
48307
48482
  } catch {
48308
48483
  throw new Error(`Cannot read the thumbnail ${file2}.`);
48309
48484
  }
@@ -48319,7 +48494,7 @@ async function planThumbnail(root, mp4, choice = "auto") {
48319
48494
  if (!file2) {
48320
48495
  for (const extension of [".jpg", ".jpeg", ".png"]) {
48321
48496
  const candidate = mp4.replace(/\.mp4$/i, extension);
48322
- if (await stat6(candidate).then((info) => info.isFile(), () => false)) {
48497
+ if (await stat7(candidate).then((info) => info.isFile(), () => false)) {
48323
48498
  file2 = candidate;
48324
48499
  break;
48325
48500
  }
@@ -48345,7 +48520,7 @@ async function addThumbnail(credentials, job, options) {
48345
48520
  if (!(error62 instanceof YouTubeError)) throw error62;
48346
48521
  if (error62.reason === "forbidden") throw new Error("YouTube did not allow a custom thumbnail. Verify the channel at https://www.youtube.com/verify, then resume.");
48347
48522
  if (options.signal?.aborted || !error62.retryable || attempts >= 2) throw error62;
48348
- await delay4(1e3 * 2 ** attempts, void 0, { signal: options.signal });
48523
+ await delay5(1e3 * 2 ** attempts, void 0, { signal: options.signal });
48349
48524
  }
48350
48525
  }
48351
48526
  thumbnail.status = "uploaded";
@@ -48417,7 +48592,7 @@ async function addCaptions(credentials, job, options) {
48417
48592
  break;
48418
48593
  }
48419
48594
  if (options.signal?.aborted || !error62.retryable || attempts >= 2) throw error62;
48420
- await delay4(1e3 * 2 ** attempts++, void 0, { signal: options.signal });
48595
+ await delay5(1e3 * 2 ** attempts++, void 0, { signal: options.signal });
48421
48596
  }
48422
48597
  }
48423
48598
  captions.name = names[index2];
@@ -48489,7 +48664,7 @@ async function transfer(credentials, job, source, options) {
48489
48664
  } catch (error62) {
48490
48665
  if (options.signal?.aborted || !(error62 instanceof YouTubeError) || !error62.retryable || attempts >= 3) throw error62;
48491
48666
  options.log?.("YouTube transfer interrupted. Checking the saved upload before retrying\u2026");
48492
- await delay4(1e3 * 2 ** attempts++, void 0, { signal: options.signal });
48667
+ await delay5(1e3 * 2 ** attempts++, void 0, { signal: options.signal });
48493
48668
  }
48494
48669
  }
48495
48670
  } catch (error62) {
@@ -48508,7 +48683,7 @@ async function uploadYouTube(options) {
48508
48683
  const context = await localProject(root, options.animation);
48509
48684
  let config2 = {};
48510
48685
  try {
48511
- config2 = JSON.parse(await readFile13(join10(context.projectRoot, "film.config.json"), "utf8"));
48686
+ config2 = JSON.parse(await readFile13(join12(context.projectRoot, "film.config.json"), "utf8"));
48512
48687
  } catch {
48513
48688
  }
48514
48689
  const receipt = await exportReceipt(file2);
@@ -48588,12 +48763,224 @@ async function resumeYouTube(id2, options) {
48588
48763
  }
48589
48764
  var listYouTubeUploads = () => withYouTubeLock(async () => ({ uploads: (await localYouTubeJobs()).map(youtubeJobSummary) }));
48590
48765
 
48766
+ // cli/src/motion.ts
48767
+ import { access as access2, mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
48768
+ import { dirname as dirname9, join as join13, relative as relative2, resolve as resolve12, sep as sep2 } from "node:path";
48769
+
48770
+ // shared/motion-library.ts
48771
+ var MOTION_CATEGORIES = [
48772
+ { id: "kinetic-typography", label: "Kinetic Typography", description: "Type-led motion: phrase choreography, word slams, masked line reveals, word swaps, tracking and emphasis changes." },
48773
+ { id: "application-ui", label: "Application UI", description: "Mobile and web app interface motion: screen transitions, gestures, microinteractions, loading states, navigation and feedback." },
48774
+ { id: "logo-reveal", label: "Logo & Brand Reveal", description: "Logo builds, brand stings, monogram assembly and end-of-film brand marks." },
48775
+ { id: "titles-lower-thirds", label: "Titles & Lower Thirds", description: "Title cards, name straps, chapter headers, broadcast graphics and callout labels." },
48776
+ { id: "transitions", label: "Scene Transitions", description: "Wipes, masks, morphs, whip pans, shape and match cuts between scenes." },
48777
+ { id: "data-visualization", label: "Data Visualization", description: "Animated charts, counters, maps of numbers, comparisons and dashboards that explain data." },
48778
+ { id: "diagrams-explainers", label: "Diagrams & Explainers", description: "Process flows, system diagrams, step sequences, formulas and annotated illustrations." },
48779
+ { id: "product-showcase", label: "Product Showcase", description: "Product reveals, feature callouts, turntables, exploded views and packshots." },
48780
+ { id: "icons-micro-illustration", label: "Icons & Micro-illustrations", description: "Animated icons, pictograms, spot illustrations, stickers and small loops." },
48781
+ { id: "character-mascot", label: "Character & Mascot", description: "Character rigs, mascots, cutout puppets, expressions, walk and idle cycles." },
48782
+ { id: "backgrounds-loops", label: "Backgrounds & Ambient Loops", description: "Seamless backdrops, gradients, grids, patterns and ambient motion beds." },
48783
+ { id: "particles-effects", label: "Particles & Effects", description: "Confetti, sparks, smoke, light leaks, glows, trails and procedural FX." },
48784
+ { id: "social-short-form", label: "Social & Short-form", description: "Vertical hooks, captions-first layouts, stickers, polls, progress bars and CTAs for feeds." },
48785
+ { id: "maps-geography", label: "Maps & Geography", description: "Route lines, location pins, zooms, globe spins and regional comparisons." },
48786
+ { id: "abstract-shapes", label: "Abstract Shapes & Geometric Motion", description: "Shape choreography, morphs, loops, patterns and rhythm-driven geometry." },
48787
+ { id: "end-cards-cta", label: "End Cards & Calls to Action", description: "Closing frames, subscribe/download prompts, offer cards and QR or URL reveals." }
48788
+ ];
48789
+ var MOTION_CATEGORY_IDS = MOTION_CATEGORIES.map((category) => category.id);
48790
+ var WORKSPACE_EXTRA_DEPTH = "../../../";
48791
+ var label = external_exports.string().trim().toLowerCase().regex(/^[a-z0-9][a-z0-9+.-]{0,39}$/, "Labels are lowercase words or hyphenated terms.");
48792
+ var labelList = external_exports.union([external_exports.array(label).max(8), external_exports.string().max(400).transform((value) => value.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean))]).pipe(external_exports.array(label).max(8));
48793
+ var motionSearchQuery = external_exports.object({
48794
+ query: external_exports.string().trim().max(500).default(""),
48795
+ category: external_exports.enum(MOTION_CATEGORY_IDS).optional(),
48796
+ /** Every label must be present on a result. */
48797
+ labels: labelList.optional(),
48798
+ limit: external_exports.coerce.number().int().min(1).max(20).default(5),
48799
+ /** Include each result's scene source; otherwise fetch it with get. */
48800
+ include_code: external_exports.union([external_exports.boolean(), external_exports.enum(["true", "false", "1", "0"]).transform((value) => value === "true" || value === "1")]).optional()
48801
+ });
48802
+ var motionExampleId = external_exports.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(80);
48803
+ function motionCodeForWorkspace(code) {
48804
+ return code.replace(/from "((?:\.\.\/)+)kit"/g, (_, up) => `from "${up}${WORKSPACE_EXTRA_DEPTH}runtime/kit"`);
48805
+ }
48806
+
48807
+ // cli/src/motion.ts
48808
+ async function searchMotion(client, query, flags) {
48809
+ const params = new URLSearchParams();
48810
+ if (query?.trim()) params.set("q", query.trim());
48811
+ if (flags.category) params.set("category", flags.category);
48812
+ if (flags.labels) params.set("labels", flags.labels);
48813
+ if (flags.limit) params.set("limit", String(flags.limit));
48814
+ if (flags.code) params.set("include_code", "true");
48815
+ return client.request(`/api/v1/motion-library/search?${params}`);
48816
+ }
48817
+ var exists2 = (path) => access2(path).then(() => true, () => false);
48818
+ async function workspaceRoot(start) {
48819
+ for (let directory = start; ; directory = dirname9(directory)) {
48820
+ if (await exists2(join13(directory, "animaguru.workspace.json"))) return directory;
48821
+ if (dirname9(directory) === directory) return null;
48822
+ }
48823
+ }
48824
+ async function writeMotionExample(example, directory, { force = false } = {}) {
48825
+ const target2 = resolve12(directory);
48826
+ const workspace = await workspaceRoot(target2);
48827
+ const inAnimation = Boolean(workspace && relative2(workspace, target2).split(sep2)[0] === "animations");
48828
+ const files = example.files.map((file2) => ({ path: join13(target2, safeProjectPath(file2.path)), code: inAnimation ? motionCodeForWorkspace(file2.code) : file2.code }));
48829
+ if (!force) {
48830
+ const clashes = [];
48831
+ for (const [index2, file2] of files.entries()) if (index2 === 0 && await exists2(file2.path)) clashes.push(file2.path);
48832
+ if (clashes.length) throw new Error(`Already exists: ${clashes.join(", ")}. Pass --force to replace it.`);
48833
+ }
48834
+ const written = [], kept = [];
48835
+ for (const [index2, file2] of files.entries()) {
48836
+ if (!force && index2 > 0 && await exists2(file2.path)) {
48837
+ kept.push(file2.path);
48838
+ continue;
48839
+ }
48840
+ await mkdir10(dirname9(file2.path), { recursive: true });
48841
+ await writeFile10(file2.path, file2.code);
48842
+ written.push(file2.path);
48843
+ }
48844
+ return { id: example.id, written, kept, kitImports: inAnimation ? "workspace (runtime/kit)" : "standalone (src/kit)", usage: example.usage };
48845
+ }
48846
+
48847
+ // cli/src/library.ts
48848
+ import { mkdir as mkdir11, readFile as readFile14, writeFile as writeFile11 } from "node:fs/promises";
48849
+ import { dirname as dirname10, join as join14, resolve as resolve13 } from "node:path";
48850
+
48851
+ // shared/asset-library.ts
48852
+ var LIBRARY_ASSET_TYPES = ["sprite", "image", "video", "music", "speech", "sfx"];
48853
+ var slug = external_exports.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Use lowercase words joined by hyphens.").max(80);
48854
+ var label2 = external_exports.string().trim().toLowerCase().regex(/^[a-z0-9][a-z0-9+.-]{0,39}$/, "Labels are lowercase words or hyphenated terms.");
48855
+ var labelList2 = external_exports.union([external_exports.array(label2).max(8), external_exports.string().max(400).transform((value) => value.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean))]).pipe(external_exports.array(label2).max(8));
48856
+ var librarySearchQuery = external_exports.object({
48857
+ query: external_exports.string().trim().max(500).default(""),
48858
+ type: external_exports.enum(LIBRARY_ASSET_TYPES).optional(),
48859
+ /** Every label must be present on a result. */
48860
+ labels: labelList2.optional(),
48861
+ limit: external_exports.coerce.number().int().min(1).max(30).default(10)
48862
+ });
48863
+ var libraryImportBody = external_exports.object({
48864
+ projectId: external_exports.string().regex(/^prj_[A-Za-z0-9]{8,40}$/, "Choose a project."),
48865
+ /** Name in the project; defaults to the library title. */
48866
+ name: external_exports.string().trim().min(1).max(80).optional()
48867
+ });
48868
+ var text = (max2) => external_exports.string().trim().min(1).max(max2);
48869
+ var keywordList = external_exports.array(external_exports.string().trim().min(1).max(60)).max(24);
48870
+ var detailsInput = external_exports.object({
48871
+ width: external_exports.number().int().positive().max(16384),
48872
+ height: external_exports.number().int().positive().max(16384),
48873
+ aspectRatio: external_exports.string().max(10),
48874
+ transparent: external_exports.boolean(),
48875
+ seconds: external_exports.number().positive().max(3600),
48876
+ resolution: external_exports.string().max(10),
48877
+ audio: external_exports.boolean(),
48878
+ loop: external_exports.boolean(),
48879
+ transcript: external_exports.string().max(4e3),
48880
+ voice: external_exports.string().max(80),
48881
+ language: external_exports.string().max(40),
48882
+ bpm: external_exports.number().int().min(20).max(300),
48883
+ mood: external_exports.string().max(120)
48884
+ }).partial();
48885
+ var metadataFields = {
48886
+ title: text(80),
48887
+ summary: text(200),
48888
+ description: text(2e3),
48889
+ labels: external_exports.array(label2).min(1).max(8),
48890
+ keywords: keywordList.default([]),
48891
+ /** Facts the server cannot read from the file, such as tempo or mood; they override what it measured. */
48892
+ details: detailsInput.default({})
48893
+ };
48894
+ var libraryPublishBody = external_exports.object({
48895
+ /** Defaults to the title as a slug. */
48896
+ id: slug.optional(),
48897
+ projectId: external_exports.string().regex(/^prj_[A-Za-z0-9]{8,40}$/),
48898
+ source: external_exports.discriminatedUnion("kind", [
48899
+ external_exports.object({ kind: external_exports.literal("asset"), assetId: external_exports.string().uuid() }),
48900
+ external_exports.object({ kind: external_exports.literal("sprite"), character: slug })
48901
+ ]),
48902
+ /** Replace an existing entry with the same id. */
48903
+ replace: external_exports.boolean().default(false),
48904
+ ...metadataFields
48905
+ });
48906
+ var libraryUpdateBody = external_exports.object({ ...metadataFields, keywords: keywordList, details: detailsInput }).partial().refine((value) => Object.keys(value).length > 0, "Change at least one field.");
48907
+
48908
+ // cli/src/library.ts
48909
+ var libraryPath = (id2) => `/api/v1/asset-library/${encodeURIComponent(id2)}`;
48910
+ var commaList = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean);
48911
+ function searchLibrary(client, query, flags) {
48912
+ const params = new URLSearchParams();
48913
+ if (query?.trim()) params.set("q", query.trim());
48914
+ if (flags.type) params.set("type", flags.type);
48915
+ if (flags.labels) params.set("labels", flags.labels);
48916
+ if (flags.limit) params.set("limit", String(flags.limit));
48917
+ return client.request(`/api/v1/asset-library/search?${params}`);
48918
+ }
48919
+ var getLibraryAsset = (client, id2) => client.request(libraryPath(id2));
48920
+ async function downloadLibraryAsset(client, id2, output2, { force = false } = {}) {
48921
+ const asset = await getLibraryAsset(client, id2);
48922
+ const root = resolve13(output2, asset.type === "sprite" ? safeProjectPath(asset.id) : ".");
48923
+ const written = [];
48924
+ for (const file2 of asset.files) {
48925
+ const path = join14(root, safeProjectPath(file2.path));
48926
+ const response = await client.request(`${libraryPath(asset.id)}/files/${file2.path.split("/").map(encodeURIComponent).join("/")}?download=1`, { raw: true, timeout: 3e5 });
48927
+ const bytes = new Uint8Array(await response.arrayBuffer());
48928
+ await mkdir11(dirname10(path), { recursive: true });
48929
+ await writeFile11(path, bytes, { flag: force ? "w" : "wx" }).catch((error62) => {
48930
+ throw error62.code === "EEXIST" ? new Error(`Already exists: ${path}. Pass --force to replace it.`) : error62;
48931
+ });
48932
+ written.push({ path, size: bytes.byteLength, mimeType: file2.mimeType });
48933
+ }
48934
+ return { id: asset.id, type: asset.type, files: written, ...asset.type === "sprite" ? { animations: asset.details.animations?.map(({ action, sheet, data, frames, fps, loop }) => ({ action, sheet: join14(root, sheet), data: join14(root, data), frames, fps, loop })) } : {} };
48935
+ }
48936
+ var importLibraryAsset = (client, id2, project, name2) => client.request(`${libraryPath(id2)}/import`, { method: "POST", body: { projectId: project, ...name2 ? { name: name2 } : {} } });
48937
+ async function words(flags) {
48938
+ const input2 = flags.file ? JSON.parse(await readFile14(flags.file, "utf8")) : {};
48939
+ if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) throw new Error("The file must contain a JSON object.");
48940
+ return {
48941
+ ...input2,
48942
+ ...flags.title ? { title: flags.title } : {},
48943
+ ...flags.summary ? { summary: flags.summary } : {},
48944
+ ...flags.description ? { description: flags.description } : {},
48945
+ ...flags.labels ? { labels: commaList(flags.labels) } : {},
48946
+ ...flags.keywords ? { keywords: commaList(flags.keywords) } : {},
48947
+ ...flags.details ? { details: JSON.parse(flags.details) } : {}
48948
+ };
48949
+ }
48950
+ var checked = (parsed) => {
48951
+ if (parsed.success) return parsed.data;
48952
+ throw new Error(parsed.error.issues.map((issue2) => `${issue2.path.length ? `${issue2.path.join(".")}: ` : ""}${issue2.message}`).join("\n"));
48953
+ };
48954
+ async function publishLibraryAsset(client, flags) {
48955
+ if (Boolean(flags.asset) === Boolean(flags.character)) throw new Error("Pass --asset ASSET_ID or --character SLUG.");
48956
+ const source = flags.asset ? { kind: "asset", assetId: flags.asset } : { kind: "sprite", character: flags.character };
48957
+ const body = checked(libraryPublishBody.safeParse({ ...await words(flags), projectId: flags.project, source, ...flags.id ? { id: flags.id } : {}, ...flags.replace ? { replace: true } : {} }));
48958
+ return client.request("/api/v1/asset-library", { method: "POST", body, timeout: 12e4 });
48959
+ }
48960
+ async function updateLibraryAsset(client, id2, flags) {
48961
+ return client.request(libraryPath(id2), { method: "PATCH", body: checked(libraryUpdateBody.safeParse(await words(flags))), timeout: 12e4 });
48962
+ }
48963
+
48591
48964
  // cli/src/commands.ts
48592
48965
  var assetModelIds = [...SPRITE_IMAGE_MODEL_IDS, ...SPRITE_VIDEO_MODEL_IDS, ...MUSIC_MODELS.map((m) => m.id), ...SPEECH_MODELS.map((m) => m.id), ...SFX_MODELS.map((m) => m.id)];
48593
48966
  var assetAuthorizationFlags = [
48594
48967
  { name: "yes", type: "boolean", description: "Authorize spending credits" },
48595
48968
  { name: "dry-run", type: "boolean", description: "Validate and estimate locally without submitting a paid job" }
48596
48969
  ];
48970
+ var assetWaitFlags = [
48971
+ { name: "wait", type: "boolean", description: "Wait until the job finishes; fail if generation fails" },
48972
+ { name: "timeout", type: "number", default: 600, description: "With --wait or --download: maximum seconds to wait" }
48973
+ ];
48974
+ var catalogSections = {
48975
+ sprites: ["styles", "kinds", "actions", "imageModels", "videoModels"],
48976
+ image: ["assetTypes", "imageModels"],
48977
+ video: ["assetTypes", "videoModels", "videoProfiles"],
48978
+ music: ["assetTypes", "musicModels"],
48979
+ speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices"],
48980
+ sfx: ["assetTypes", "sfxModels"],
48981
+ avatars: ["avatarTypes", "avatarLookTypes"]
48982
+ };
48983
+ var catalog = () => ({ styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, imageModels: SPRITE_IMAGE_MODEL_IDS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
48597
48984
  var modelFlags = [
48598
48985
  { name: "image-model", type: "string", choices: SPRITE_IMAGE_MODEL_IDS, description: "Image model override for this operation" },
48599
48986
  { name: "video-model", type: "string", choices: SPRITE_VIDEO_MODEL_IDS, description: "Video model override for this operation" }
@@ -48603,8 +48990,18 @@ var selectedModels = (flags) => ({
48603
48990
  ...flags["video-model"] ? { videoModel: flags["video-model"] } : {}
48604
48991
  });
48605
48992
  var id = { name: "id", type: "string", required: true, description: "Project ID" };
48993
+ var urlFlag = { name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" };
48994
+ var libraryWordFlags = [
48995
+ { name: "file", type: "string", description: "JSON with title, summary, description, labels, keywords and details; flags override it" },
48996
+ { name: "title", type: "string" },
48997
+ { name: "summary", type: "string", description: "One sentence for cards" },
48998
+ { name: "description", type: "string", description: "What it looks or sounds like and when to use it (searched by meaning)" },
48999
+ { name: "labels", type: "string", description: "Comma-separated facets, e.g. pixel-art,character" },
49000
+ { name: "keywords", type: "string", description: "Comma-separated synonyms people may search for" },
49001
+ { name: "details", type: "string", description: 'JSON facts the server cannot measure, e.g. {"bpm":110,"mood":"uplifting"}' }
49002
+ ];
48606
49003
  var out = (stdout, data) => stdout(JSON.stringify(data));
48607
- var actions = (text) => text ? text.split(",").map((s) => s.trim()).filter(Boolean) : [];
49004
+ var actions = (text2) => text2 ? text2.split(",").map((s) => s.trim()).filter(Boolean) : [];
48608
49005
  var projectPath = (project) => `/api/v1/sprites/${encodeURIComponent(project)}`;
48609
49006
  var workspaceQuery = async (client) => {
48610
49007
  const selected = await selectedWorkspace(client.origin);
@@ -48613,17 +49010,17 @@ var workspaceQuery = async (client) => {
48613
49010
  async function openBrowser(url2) {
48614
49011
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32" : "xdg-open";
48615
49012
  const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url2] : [url2];
48616
- await new Promise((resolve13) => {
49013
+ await new Promise((resolve15) => {
48617
49014
  const child = spawn3(command, args, { stdio: "ignore", detached: true });
48618
- child.once("error", () => resolve13());
49015
+ child.once("error", () => resolve15());
48619
49016
  child.once("spawn", () => {
48620
49017
  child.unref();
48621
- resolve13();
49018
+ resolve15();
48622
49019
  });
48623
49020
  });
48624
49021
  }
48625
49022
  function createCli() {
48626
- return new Crust("animaguru", { description: "Sprite, asset and HeyGen avatar generation, video workspaces, video sharing, and direct local YouTube uploads. Successful commands output JSON. Paid jobs and uploads require --yes.", version: package_default.version }).command("youtube", (youtube) => youtube.command("auth", (auth) => auth.add(defineCommand("login", { description: "Connect a YouTube channel through Google; credentials stay on this computer" }, (command) => command.flags(
49023
+ return new Crust("animaguru", { description: "Sprite, asset and HeyGen avatar generation, the motion and asset libraries, video workspaces, video sharing, and direct local YouTube uploads. Successful commands output JSON. Paid jobs and uploads require --yes.", version: package_default.version }).command("youtube", (youtube) => youtube.command("auth", (auth) => auth.add(defineCommand("login", { description: "Connect a YouTube channel through Google; credentials stay on this computer" }, (command) => command.flags(
48627
49024
  { name: "client-file", type: "string", required: true, env: { name: "ANIMAGURU_YOUTUBE_CLIENT_FILE" }, description: "Google Desktop app OAuth client JSON" },
48628
49025
  { name: "browser", type: "boolean", default: true, description: "Open the system browser; --no-browser prints the URL" },
48629
49026
  { name: "timeout", type: "number", default: 300, description: "Authorization timeout in seconds (1\u2013600)" },
@@ -48701,7 +49098,7 @@ Confirm code: ${device.user_code}`);
48701
49098
  const expiresAt = Date.now() + device.expires_in * 1e3;
48702
49099
  let interval = device.interval * 1e3;
48703
49100
  while (Date.now() < expiresAt) {
48704
- await delay5(interval, void 0, { signal });
49101
+ await delay6(interval, void 0, { signal });
48705
49102
  try {
48706
49103
  const session = await client.request("/api/auth/device/token", { method: "POST", authenticated: false, body: { client_id: CLI_CLIENT_ID, device_code: device.device_code, grant_type: "urn:ietf:params:oauth:grant-type:device_code" } });
48707
49104
  const credentials = await readCredentials();
@@ -48742,7 +49139,40 @@ Confirm code: ${device.user_code}`);
48742
49139
  })))).add(defineCommand("credits", { description: "Show the selected workspace's remaining credit balance" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
48743
49140
  const client = new Client(flags.url, signal);
48744
49141
  out(stdout, await client.request(`/api/v1/credits${await workspaceQuery(client)}`));
48745
- }))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings, speech voices and avatar types" }, (command) => command.action(({ stdout }) => out(stdout, { styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, imageModels: SPRITE_IMAGE_MODEL_IDS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES })))).command("projects", (projects) => projects.add(defineCommand("list", { description: "List projects in the selected workspace" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
49142
+ }))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings, speech voices and avatar types" }, (command) => command.flags({ name: "type", type: "string", choices: Object.keys(catalogSections), description: "Only one part: sprites, image, video, music, speech, sfx or avatars" }).action(({ flags, stdout }) => {
49143
+ const full = catalog();
49144
+ const section = flags.type;
49145
+ out(stdout, section ? Object.fromEntries(catalogSections[section].map((key) => [key, full[key]])) : full);
49146
+ }))).command("motion", (motion) => motion.add(defineCommand("search", { description: "Search the motion library: PixiJS example scenes (kinetic typography, app UI, \u2026) by natural language and keywords" }, (command) => command.args({ name: "query", type: "string", variadic: true, description: "What the motion should look like, e.g. word slam on a beat, swipe to delete" }).flags(
49147
+ { name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" },
49148
+ { name: "category", type: "string", choices: MOTION_CATEGORY_IDS, description: "Only this category (see motion categories)" },
49149
+ { name: "labels", type: "string", description: "Comma-separated labels every result must have, e.g. mobile,dark" },
49150
+ { name: "limit", type: "number", default: 5, description: "Results, 1\u201320" },
49151
+ { name: "code", type: "boolean", description: "Include each result's scene source" }
49152
+ ).action(async ({ args, flags, stdout, signal }) => out(stdout, await searchMotion(new Client(flags.url, signal), (args.query ?? []).join(" "), flags))))).add(defineCommand("get", { description: "Get a motion example's beats, options and code; --write installs its files into a scenes folder" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Example id from motion search" }).flags(
49153
+ { name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" },
49154
+ { name: "write", type: "string", description: "Folder to write the scene into, e.g. src/scenes or animations/NAME/src/scenes; kit imports are adjusted for workspaces" },
49155
+ { name: "force", type: "boolean", description: "With --write: replace existing files" }
49156
+ ).action(async ({ args, flags, stdout, signal }) => {
49157
+ const example = await new Client(flags.url, signal).request(`/api/v1/motion-library/${encodeURIComponent(args.id)}`);
49158
+ out(stdout, flags.write ? await writeMotionExample(example, flags.write, { force: flags.force }) : example);
49159
+ }))).add(defineCommand("categories", { description: "List motion library categories and their example counts" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request("/api/v1/motion-library/categories")))))).command("library", (library) => library.add(defineCommand("search", { description: "Search the asset library (Pro and Team plans): ready-made sprites, images, videos, music, speech and sound effects, by natural language and keywords" }, (command) => command.args({ name: "query", type: "string", variadic: true, description: "What you need, e.g. whoosh transition, upbeat piano background, pixel knight" }).flags(
49160
+ urlFlag,
49161
+ { name: "type", type: "string", choices: LIBRARY_ASSET_TYPES, description: "Only this type" },
49162
+ { name: "labels", type: "string", description: "Comma-separated labels every result must have, e.g. loop,transparent" },
49163
+ { name: "limit", type: "number", default: 10, description: "Results, 1\u201330" }
49164
+ ).action(async ({ args, flags, stdout, signal }) => out(stdout, await searchLibrary(new Client(flags.url, signal), (args.query ?? []).join(" "), flags))))).add(defineCommand("get", { description: "Get a library asset's description, details (length, size, transcript, sprite frames) and files" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Asset id from library search" }).flags(urlFlag).action(async ({ args, flags, stdout, signal }) => out(stdout, await getLibraryAsset(new Client(flags.url, signal), args.id))))).add(defineCommand("download", { description: "Save a library asset's files into a folder: media as ID.EXT, sprites as ID/ with sheets and frame data" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Asset id from library search" }).flags(urlFlag, { name: "output", type: "string", required: true, description: "Folder to save into" }, { name: "force", type: "boolean", description: "Replace existing files" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await downloadLibraryAsset(new Client(flags.url, signal), args.id, flags.output, { force: flags.force }))))).add(defineCommand("import", { description: "Copy a library asset into a project (no credits): media become saved assets, sprites become characters" }, (command) => command.args({ name: "id", type: "string", required: true, description: "Asset id from library search" }).flags(urlFlag, { name: "project", type: "string", required: true, description: "Project ID" }, { name: "name", type: "string", description: "Name in the project; defaults to the library title" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await importLibraryAsset(new Client(flags.url, signal), args.id, flags.project, flags.name))))).add(defineCommand("types", { description: "List asset library types, how many assets each has, and whether this account can use the library" }, (command) => command.flags(urlFlag).action(async ({ flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request("/api/v1/asset-library/types"))))).add(defineCommand("publish", { description: "Staff: publish a saved asset or an animated character from a project into the library" }, (command) => command.flags(
49165
+ urlFlag,
49166
+ { name: "project", type: "string", required: true, description: "Project ID" },
49167
+ { name: "asset", type: "string", description: "Saved asset id (assets list)" },
49168
+ { name: "character", type: "string", description: "Character slug (projects get); it must be animated" },
49169
+ { name: "id", type: "string", description: "Library id; defaults to the title as a slug" },
49170
+ { name: "replace", type: "boolean", description: "Replace an entry with the same id" },
49171
+ ...libraryWordFlags
49172
+ ).action(async ({ flags, stdout, signal }) => out(stdout, await publishLibraryAsset(new Client(flags.url, signal), flags))))).add(defineCommand("update", { description: "Staff: change a library asset's title, summary, description, labels, keywords or details" }, (command) => command.args({ name: "id", type: "string", required: true }).flags(urlFlag, ...libraryWordFlags).action(async ({ args, flags, stdout, signal }) => out(stdout, await updateLibraryAsset(new Client(flags.url, signal), args.id, flags))))).add(defineCommand("remove", { description: "Staff: remove an asset from the library; projects that imported it keep their copies. Requires --yes" }, (command) => command.args({ name: "id", type: "string", required: true }).flags(urlFlag, { name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
49173
+ if (!flags.yes) throw new Error("Pass --yes to remove this library asset.");
49174
+ out(stdout, await new Client(flags.url, signal).request(`/api/v1/asset-library/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
49175
+ })))).command("projects", (projects) => projects.add(defineCommand("list", { description: "List projects in the selected workspace" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
48746
49176
  const client = new Client(flags.url, signal);
48747
49177
  out(stdout, await client.request(`/api/v1/projects${await workspaceQuery(client)}`));
48748
49178
  }))).add(defineCommand("create", { description: "Create an empty sprite project; generate artwork with jobs submit" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).flags(...modelFlags).flags({ name: "name", type: "string", required: true }).action(async ({ flags, stdout, signal }) => {
@@ -48775,8 +49205,26 @@ Confirm code: ${device.user_code}`);
48775
49205
  { name: "delivery", type: "string", description: "Gemini speech delivery instructions; ElevenLabs uses audio tags in the transcript" },
48776
49206
  { name: "loop", type: "boolean", description: "SFX: create a seamless loop" },
48777
49207
  { name: "prompt-influence", type: "number", description: "SFX: prompt adherence, 0\u20131 (default 0.3)" },
48778
- ...assetAuthorizationFlags
48779
- ).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitAsset(new Client(flags.url, signal), args.id, assetFromFlags(flags), flags))))).add(defineCommand("submit", { description: "Submit a validated JSON asset file; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "file", type: "string", required: true, description: "JSON asset request" }, { name: "model", type: "string", choices: assetModelIds, description: "Override the model in the file" }, ...assetAuthorizationFlags).action(async ({ args, flags, stdout, signal }) => out(stdout, await submitAsset(new Client(flags.url, signal), args.id, await assetFromFile(flags.file, flags.model), flags))))).add(defineCommand("download", { description: "Download a saved asset by id; refuses to overwrite" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "asset", type: "string", required: true, description: "Asset id from assets list" }).flags({ name: "output", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await downloadAsset(new Client(flags.url, signal), args.id, args.asset, flags.output)))))).command("avatars", (avatars) => avatars.add(defineCommand("list", { description: "List HeyGen avatar characters: the public catalog, or --ownership private for this project's own" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "ownership", type: "string", choices: AVATAR_OWNERSHIPS, default: "public" }, { name: "limit", type: "number", default: 20, description: "Avatars per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}?${new URLSearchParams({ ownership: flags.ownership, limit: String(flags.limit), ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("looks", { description: "List an avatar's looks with --group, or HeyGen's public looks; a look ID is what HeyGen renders with" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string", description: "Avatar group ID: one of this project's or a public one" }, { name: "avatar-type", type: "string", choices: AVATAR_LOOK_TYPES }, { name: "limit", type: "number", default: 20, description: "Looks per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/looks?${new URLSearchParams({ limit: String(flags.limit), ...flags.group ? { groupId: flags.group } : {}, ...flags["avatar-type"] ? { avatarType: flags["avatar-type"] } : {}, ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("get", { description: "Show one avatar group (--group) or look (--look), with status and consent" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string" }, { name: "look", type: "string" }).action(async ({ args, flags, stdout, signal }) => {
49208
+ ...assetAuthorizationFlags,
49209
+ ...assetWaitFlags,
49210
+ { name: "download", type: "string", description: "Wait, then save the result to this file, or into this folder (existing, or ending in /) as NAME.EXT; never overwrites" }
49211
+ ).action(async ({ args, flags, stdout, signal }) => out(stdout, await generateAsset(new Client(flags.url, signal), args.id, assetFromFlags(flags), flags, signal))))).add(defineCommand("submit", { description: "Submit a validated JSON asset file; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
49212
+ { name: "file", type: "string", required: true, description: "JSON asset request" },
49213
+ { name: "model", type: "string", choices: assetModelIds, description: "Override the model in the file" },
49214
+ ...assetAuthorizationFlags,
49215
+ ...assetWaitFlags,
49216
+ { name: "download", type: "string", description: "Wait, then save the result to this file, or into this folder (existing, or ending in /) as NAME.EXT; never overwrites" }
49217
+ ).action(async ({ args, flags, stdout, signal }) => out(stdout, await generateAsset(new Client(flags.url, signal), args.id, await assetFromFile(flags.file, flags.model), flags, signal))))).add(defineCommand("batch", { description: "Submit several asset requests from one JSON file (a list, or {defaults, assets}); validates all first; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
49218
+ { name: "file", type: "string", required: true, description: 'JSON list of asset requests, or {"defaults": {...}, "assets": [...]}' },
49219
+ { name: "model", type: "string", choices: assetModelIds, description: "Override every item's model" },
49220
+ ...assetAuthorizationFlags,
49221
+ ...assetWaitFlags,
49222
+ { name: "download", type: "string", description: "Wait, then save every result into this folder as NAME.EXT; never overwrites" }
49223
+ ).action(async ({ args, flags, stdout, signal }) => {
49224
+ const result = await submitAssetBatch(new Client(flags.url, signal), args.id, await assetsFromBatchFile(flags.file, flags.model), flags, signal);
49225
+ out(stdout, result);
49226
+ if (result.error) throw new Error(result.error);
49227
+ }))).add(defineCommand("download", { description: "Download a saved asset by id; refuses to overwrite" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id, { name: "asset", type: "string", required: true, description: "Asset id from assets list" }).flags({ name: "output", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await downloadAsset(new Client(flags.url, signal), args.id, args.asset, flags.output)))))).command("avatars", (avatars) => avatars.add(defineCommand("list", { description: "List HeyGen avatar characters: the public catalog, or --ownership private for this project's own" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "ownership", type: "string", choices: AVATAR_OWNERSHIPS, default: "public" }, { name: "limit", type: "number", default: 20, description: "Avatars per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}?${new URLSearchParams({ ownership: flags.ownership, limit: String(flags.limit), ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("looks", { description: "List an avatar's looks with --group, or HeyGen's public looks; a look ID is what HeyGen renders with" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string", description: "Avatar group ID: one of this project's or a public one" }, { name: "avatar-type", type: "string", choices: AVATAR_LOOK_TYPES }, { name: "limit", type: "number", default: 20, description: "Looks per page, 1\u201350" }, { name: "token", type: "string", description: "nextToken from the previous page" }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${avatarsPath(args.id)}/looks?${new URLSearchParams({ limit: String(flags.limit), ...flags.group ? { groupId: flags.group } : {}, ...flags["avatar-type"] ? { avatarType: flags["avatar-type"] } : {}, ...flags.token ? { token: flags.token } : {} })}`))))).add(defineCommand("get", { description: "Show one avatar group (--group) or look (--look), with status and consent" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags({ name: "group", type: "string" }, { name: "look", type: "string" }).action(async ({ args, flags, stdout, signal }) => {
48780
49228
  if (Boolean(flags.group) === Boolean(flags.look)) throw new Error("Pass --group or --look.");
48781
49229
  out(stdout, await new Client(flags.url, signal).request(flags.look ? `${avatarsPath(args.id)}/looks/${encodeURIComponent(flags.look)}` : `${avatarsPath(args.id)}/${encodeURIComponent(flags.group)}`));
48782
49230
  }))).add(defineCommand("templates", { description: "List HeyGen Look Packs and look templates with their female and male IDs" }, (command) => command.action(({ stdout }) => out(stdout, { templates: AVATAR_LOOK_TEMPLATES })))).add(defineCommand("create", { description: "Create a HeyGen avatar from a prompt, a photo or footage (digital_twin); --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
@@ -48802,23 +49250,9 @@ Confirm code: ${device.user_code}`);
48802
49250
  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" }));
48803
49251
  })))).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 }) => {
48804
49252
  if (!flags.yes) throw new Error("Pass --yes to authorize spending credits.");
48805
- const body = spriteJobBody.parse({ ...JSON.parse(await readFile14(flags.file, "utf8")), ...selectedModels(flags) });
49253
+ const body = spriteJobBody.parse({ ...JSON.parse(await readFile15(flags.file, "utf8")), ...selectedModels(flags) });
48806
49254
  out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/jobs`, { method: "POST", body }));
48807
- }))).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 }) => {
48808
- if (!Number.isFinite(flags.timeout) || flags.timeout <= 0) throw new Error("Timeout must be positive.");
48809
- const client = new Client(flags.url, signal);
48810
- const deadline = Date.now() + flags.timeout * 1e3;
48811
- while (Date.now() < deadline) {
48812
- const { job } = await client.request(`${projectPath(args.id)}/jobs/${encodeURIComponent(args.job)}`);
48813
- if (job.status === "failed") throw new Error(job.error ?? "Generation failed.");
48814
- if (job.status === "done") {
48815
- out(stdout, { job });
48816
- return;
48817
- }
48818
- await delay5(3e3, void 0, { signal });
48819
- }
48820
- throw new Error("Timed out waiting for the job. It may still be running.");
48821
- })))).add(defineCommand("models", { description: "Set default image and/or video models 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[0], aliases: ["model"] }, modelFlags[1]).action(async ({ args, flags, stdout, signal }) => {
49255
+ }))).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 default image and/or video models 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[0], aliases: ["model"] }, modelFlags[1]).action(async ({ args, flags, stdout, signal }) => {
48822
49256
  const body = selectedModels(flags);
48823
49257
  if (!Object.keys(body).length) throw new Error("Pass --image-model or --video-model.");
48824
49258
  out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/models`, { method: "PUT", body }));
@@ -48831,7 +49265,7 @@ Confirm code: ${device.user_code}`);
48831
49265
  const extension = flags.file.split(".").at(-1)?.toLowerCase();
48832
49266
  const type = extension === "png" ? "image/png" : extension === "jpg" || extension === "jpeg" ? "image/jpeg" : extension === "webp" ? "image/webp" : void 0;
48833
49267
  if (!type) throw new Error("Use a PNG, JPEG or WebP image.");
48834
- const bytes = await readFile14(flags.file);
49268
+ const bytes = await readFile15(flags.file);
48835
49269
  if (bytes.length > 10 * 1024 * 1024) throw new Error("Image must be at most 10 MB.");
48836
49270
  const form = new FormData();
48837
49271
  form.set("image", new Blob([bytes], { type }), `reference.${extension}`);
@@ -48849,8 +49283,8 @@ Confirm code: ${device.user_code}`);
48849
49283
  const response = await client.request(`/api/v1/blobs/${encodeURIComponent(manifest.ownerId)}/${file2.sha}`, { raw: true });
48850
49284
  entries[path2] = new Uint8Array(await response.arrayBuffer());
48851
49285
  }
48852
- const path = resolve12(flags.output);
48853
- await writeFile10(path, zipSync(entries, { level: 0 }), { flag: "wx" });
49286
+ const path = resolve14(flags.output);
49287
+ await writeFile12(path, zipSync(entries, { level: 0 }), { flag: "wx" });
48854
49288
  out(stdout, { path, files: manifest.files.length });
48855
49289
  })))).extend(version(package_default.version, { format: "plain" })).extend(help()).extend(completion());
48856
49290
  }