@character-foundry/character-foundry 0.4.2 → 0.4.3-dev.1766019473

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 (57) hide show
  1. package/dist/charx.cjs +15 -36
  2. package/dist/charx.cjs.map +1 -1
  3. package/dist/charx.d.cts +18 -9
  4. package/dist/charx.d.ts +18 -9
  5. package/dist/charx.js +15 -36
  6. package/dist/charx.js.map +1 -1
  7. package/dist/exporter.cjs +34 -38
  8. package/dist/exporter.cjs.map +1 -1
  9. package/dist/exporter.d.cts +18 -9
  10. package/dist/exporter.d.ts +18 -9
  11. package/dist/exporter.js +34 -38
  12. package/dist/exporter.js.map +1 -1
  13. package/dist/federation.cjs +104 -36
  14. package/dist/federation.cjs.map +1 -1
  15. package/dist/federation.d.cts +53 -9
  16. package/dist/federation.d.ts +53 -9
  17. package/dist/federation.js +104 -36
  18. package/dist/federation.js.map +1 -1
  19. package/dist/index.cjs +34 -38
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +42 -21
  22. package/dist/index.d.ts +42 -21
  23. package/dist/index.js +34 -38
  24. package/dist/index.js.map +1 -1
  25. package/dist/loader.cjs +101 -15
  26. package/dist/loader.cjs.map +1 -1
  27. package/dist/loader.d.cts +42 -14
  28. package/dist/loader.d.ts +42 -14
  29. package/dist/loader.js +101 -15
  30. package/dist/loader.js.map +1 -1
  31. package/dist/lorebook.d.cts +34 -17
  32. package/dist/lorebook.d.ts +34 -17
  33. package/dist/normalizer.cjs +2 -2
  34. package/dist/normalizer.cjs.map +1 -1
  35. package/dist/normalizer.d.cts +60 -30
  36. package/dist/normalizer.d.ts +60 -30
  37. package/dist/normalizer.js +2 -2
  38. package/dist/normalizer.js.map +1 -1
  39. package/dist/png.cjs +2 -2
  40. package/dist/png.cjs.map +1 -1
  41. package/dist/png.d.cts +32 -16
  42. package/dist/png.d.ts +32 -16
  43. package/dist/png.js +2 -2
  44. package/dist/png.js.map +1 -1
  45. package/dist/schemas.cjs +7 -7
  46. package/dist/schemas.cjs.map +1 -1
  47. package/dist/schemas.d.cts +96 -48
  48. package/dist/schemas.d.ts +96 -48
  49. package/dist/schemas.js +7 -7
  50. package/dist/schemas.js.map +1 -1
  51. package/dist/voxta.cjs +21 -4
  52. package/dist/voxta.cjs.map +1 -1
  53. package/dist/voxta.d.cts +28 -14
  54. package/dist/voxta.d.ts +28 -14
  55. package/dist/voxta.js +21 -4
  56. package/dist/voxta.js.map +1 -1
  57. package/package.json +6 -6
package/dist/exporter.cjs CHANGED
@@ -276,7 +276,7 @@ var CCv2LorebookEntrySchema = import_zod2.z.object({
276
276
  selective: import_zod2.z.boolean().nullable().optional(),
277
277
  secondary_keys: import_zod2.z.array(import_zod2.z.string()).nullable().optional(),
278
278
  constant: import_zod2.z.boolean().nullable().optional(),
279
- position: import_zod2.z.union([import_zod2.z.enum(["before_char", "after_char"]), import_zod2.z.number().int(), import_zod2.z.literal("")]).nullable().optional()
279
+ position: import_zod2.z.union([import_zod2.z.enum(["before_char", "after_char", "in_chat"]), import_zod2.z.number().int(), import_zod2.z.literal("")]).nullable().optional()
280
280
  }).passthrough();
281
281
  var CCv2CharacterBookSchema = import_zod2.z.object({
282
282
  name: import_zod2.z.string().optional(),
@@ -329,7 +329,7 @@ var CCv3LorebookEntrySchema = import_zod3.z.object({
329
329
  selective: import_zod3.z.boolean().nullable().optional(),
330
330
  secondary_keys: import_zod3.z.array(import_zod3.z.string()).nullable().optional(),
331
331
  constant: import_zod3.z.boolean().nullable().optional(),
332
- position: import_zod3.z.union([import_zod3.z.enum(["before_char", "after_char"]), import_zod3.z.number().int(), import_zod3.z.literal("")]).nullable().optional(),
332
+ position: import_zod3.z.union([import_zod3.z.enum(["before_char", "after_char", "in_chat"]), import_zod3.z.number().int(), import_zod3.z.literal("")]).nullable().optional(),
333
333
  extensions: import_zod3.z.record(import_zod3.z.unknown()).optional(),
334
334
  // v3 specific - also lenient with types since SillyTavern uses numbers for enums
335
335
  automation_id: import_zod3.z.string().optional(),
@@ -546,36 +546,6 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
546
546
  "data",
547
547
  "unknown"
548
548
  ]);
549
- var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
550
- // Images
551
- "png",
552
- "jpg",
553
- "jpeg",
554
- "webp",
555
- "gif",
556
- "avif",
557
- "svg",
558
- "bmp",
559
- "ico",
560
- // Audio
561
- "mp3",
562
- "wav",
563
- "ogg",
564
- "flac",
565
- "m4a",
566
- "aac",
567
- "opus",
568
- // Video
569
- "mp4",
570
- "webm",
571
- "avi",
572
- "mov",
573
- "mkv",
574
- // Data
575
- "json",
576
- "txt",
577
- "bin"
578
- ]);
579
549
  function getCharxCategory(mimetype) {
580
550
  if (mimetype.startsWith("image/")) return "images";
581
551
  if (mimetype.startsWith("audio/")) return "audio";
@@ -591,11 +561,20 @@ function sanitizeAssetType(type) {
591
561
  return sanitized || "custom";
592
562
  }
593
563
  function sanitizeExtension(ext) {
594
- const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
595
- if (SAFE_EXTENSIONS.has(normalized)) {
596
- return normalized;
564
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
565
+ if (!normalized) {
566
+ throw new Error("Invalid asset extension: empty extension");
567
+ }
568
+ if (normalized.length > 64) {
569
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
570
+ }
571
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
572
+ throw new Error("Invalid asset extension: path separators are not allowed");
573
+ }
574
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
575
+ throw new Error(`Invalid asset extension: "${ext}"`);
597
576
  }
598
- return "bin";
577
+ return normalized;
599
578
  }
600
579
  function sanitizeName(name, ext) {
601
580
  let safeName = name;
@@ -7046,6 +7025,22 @@ function sanitizeName2(name, ext) {
7046
7025
  if (!safeName) safeName = "asset";
7047
7026
  return safeName;
7048
7027
  }
7028
+ function sanitizeExtension2(ext) {
7029
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
7030
+ if (!normalized) {
7031
+ throw new Error("Invalid asset extension: empty extension");
7032
+ }
7033
+ if (normalized.length > 64) {
7034
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
7035
+ }
7036
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
7037
+ throw new Error("Invalid asset extension: path separators are not allowed");
7038
+ }
7039
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
7040
+ throw new Error(`Invalid asset extension: "${ext}"`);
7041
+ }
7042
+ return normalized;
7043
+ }
7049
7044
  function writeVoxta(card, assets, options = {}) {
7050
7045
  const { compressionLevel = 6, includePackageJson = false } = options;
7051
7046
  const cardData = card.data;
@@ -7134,8 +7129,9 @@ function writeVoxta(card, assets, options = {}) {
7134
7129
  let assetCount = 0;
7135
7130
  let mainThumbnail;
7136
7131
  for (const asset of assets) {
7137
- const safeName = sanitizeName2(asset.name, asset.ext);
7138
- const finalFilename = `${safeName}.${asset.ext}`;
7132
+ const safeExt = sanitizeExtension2(asset.ext);
7133
+ const safeName = sanitizeName2(asset.name, safeExt);
7134
+ const finalFilename = `${safeName}.${safeExt}`;
7139
7135
  let voxtaPath = "";
7140
7136
  const tags = asset.tags || [];
7141
7137
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);