@character-foundry/character-foundry 0.1.5 → 0.1.7

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 (67) hide show
  1. package/dist/app-framework.cjs +143 -26
  2. package/dist/app-framework.cjs.map +1 -1
  3. package/dist/app-framework.d.cts +16 -1
  4. package/dist/app-framework.d.ts +16 -1
  5. package/dist/app-framework.js +151 -34
  6. package/dist/app-framework.js.map +1 -1
  7. package/dist/charx.cjs +70 -8
  8. package/dist/charx.cjs.map +1 -1
  9. package/dist/charx.js +70 -8
  10. package/dist/charx.js.map +1 -1
  11. package/dist/core.cjs +93 -6
  12. package/dist/core.cjs.map +1 -1
  13. package/dist/core.d.cts +42 -1
  14. package/dist/core.d.ts +42 -1
  15. package/dist/core.js +93 -6
  16. package/dist/core.js.map +1 -1
  17. package/dist/exporter.cjs +88 -8
  18. package/dist/exporter.cjs.map +1 -1
  19. package/dist/exporter.js +89 -9
  20. package/dist/exporter.js.map +1 -1
  21. package/dist/federation.cjs +1 -0
  22. package/dist/federation.cjs.map +1 -1
  23. package/dist/federation.js +1 -0
  24. package/dist/federation.js.map +1 -1
  25. package/dist/image-utils.cjs +249 -0
  26. package/dist/image-utils.cjs.map +1 -0
  27. package/dist/image-utils.d.cts +136 -0
  28. package/dist/image-utils.d.ts +136 -0
  29. package/dist/image-utils.js +226 -0
  30. package/dist/image-utils.js.map +1 -0
  31. package/dist/index.cjs +122 -18
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +123 -19
  34. package/dist/index.js.map +1 -1
  35. package/dist/loader.cjs +42 -14
  36. package/dist/loader.cjs.map +1 -1
  37. package/dist/loader.js +43 -15
  38. package/dist/loader.js.map +1 -1
  39. package/dist/lorebook.cjs +1 -0
  40. package/dist/lorebook.cjs.map +1 -1
  41. package/dist/lorebook.js +1 -0
  42. package/dist/lorebook.js.map +1 -1
  43. package/dist/media.cjs +1 -0
  44. package/dist/media.cjs.map +1 -1
  45. package/dist/media.js +1 -0
  46. package/dist/media.js.map +1 -1
  47. package/dist/normalizer.cjs +1 -0
  48. package/dist/normalizer.cjs.map +1 -1
  49. package/dist/normalizer.d.cts +1 -0
  50. package/dist/normalizer.d.ts +1 -0
  51. package/dist/normalizer.js +1 -0
  52. package/dist/normalizer.js.map +1 -1
  53. package/dist/png.cjs +19 -0
  54. package/dist/png.cjs.map +1 -1
  55. package/dist/png.js +19 -0
  56. package/dist/png.js.map +1 -1
  57. package/dist/schemas.cjs +80 -0
  58. package/dist/schemas.cjs.map +1 -1
  59. package/dist/schemas.d.cts +30 -0
  60. package/dist/schemas.d.ts +30 -0
  61. package/dist/schemas.js +80 -0
  62. package/dist/schemas.js.map +1 -1
  63. package/dist/voxta.cjs +14 -102
  64. package/dist/voxta.cjs.map +1 -1
  65. package/dist/voxta.js +15 -103
  66. package/dist/voxta.js.map +1 -1
  67. package/package.json +16 -5
package/dist/exporter.js CHANGED
@@ -49,10 +49,14 @@ function alloc(size) {
49
49
  return new Uint8Array(size);
50
50
  }
51
51
  var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
52
+ var LARGE_BUFFER_THRESHOLD = 1024 * 1024;
52
53
  function encode(data) {
53
54
  if (isNode) {
54
55
  return Buffer.from(data).toString("base64");
55
56
  }
57
+ if (data.length > LARGE_BUFFER_THRESHOLD) {
58
+ return encodeChunked(data);
59
+ }
56
60
  let binary = "";
57
61
  for (let i = 0; i < data.length; i++) {
58
62
  binary += String.fromCharCode(data[i]);
@@ -60,6 +64,21 @@ function encode(data) {
60
64
  return btoa(binary);
61
65
  }
62
66
  var ENCODE_CHUNK_SIZE = 64 * 1024;
67
+ function encodeChunked(data) {
68
+ if (isNode) {
69
+ return Buffer.from(data).toString("base64");
70
+ }
71
+ const chunks = [];
72
+ for (let i = 0; i < data.length; i += ENCODE_CHUNK_SIZE) {
73
+ const chunk = data.subarray(i, Math.min(i + ENCODE_CHUNK_SIZE, data.length));
74
+ let binary = "";
75
+ for (let j = 0; j < chunk.length; j++) {
76
+ binary += String.fromCharCode(chunk[j]);
77
+ }
78
+ chunks.push(binary);
79
+ }
80
+ return btoa(chunks.join(""));
81
+ }
63
82
  var FOUNDRY_ERROR_MARKER = /* @__PURE__ */ Symbol.for("@character-foundry/core:FoundryError");
64
83
  var FoundryError = class extends Error {
65
84
  constructor(message, code) {
@@ -478,12 +497,69 @@ var DEFAULT_OPTIONS = {
478
497
  preserveXMeta: true,
479
498
  preserveModuleRisum: true
480
499
  };
500
+ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
501
+ "icon",
502
+ "user_icon",
503
+ "emotion",
504
+ "background",
505
+ "sound",
506
+ "video",
507
+ "custom",
508
+ "x-risu-asset",
509
+ "data",
510
+ "unknown"
511
+ ]);
512
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
513
+ // Images
514
+ "png",
515
+ "jpg",
516
+ "jpeg",
517
+ "webp",
518
+ "gif",
519
+ "avif",
520
+ "svg",
521
+ "bmp",
522
+ "ico",
523
+ // Audio
524
+ "mp3",
525
+ "wav",
526
+ "ogg",
527
+ "flac",
528
+ "m4a",
529
+ "aac",
530
+ "opus",
531
+ // Video
532
+ "mp4",
533
+ "webm",
534
+ "avi",
535
+ "mov",
536
+ "mkv",
537
+ // Data
538
+ "json",
539
+ "txt",
540
+ "bin"
541
+ ]);
481
542
  function getCharxCategory(mimetype) {
482
543
  if (mimetype.startsWith("image/")) return "images";
483
544
  if (mimetype.startsWith("audio/")) return "audio";
484
545
  if (mimetype.startsWith("video/")) return "video";
485
546
  return "other";
486
547
  }
548
+ function sanitizeAssetType(type) {
549
+ const normalized = type.toLowerCase().replace(/[^a-z0-9-_]/g, "-");
550
+ if (SAFE_ASSET_TYPES.has(normalized)) {
551
+ return normalized;
552
+ }
553
+ const sanitized = normalized.replace(/[^a-z0-9]/g, "");
554
+ return sanitized || "custom";
555
+ }
556
+ function sanitizeExtension(ext) {
557
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
558
+ if (SAFE_EXTENSIONS.has(normalized)) {
559
+ return normalized;
560
+ }
561
+ return "bin";
562
+ }
487
563
  function sanitizeName(name, ext) {
488
564
  let safeName = name;
489
565
  if (safeName.toLowerCase().endsWith(`.${ext.toLowerCase()}`)) {
@@ -517,10 +593,12 @@ Import this file into SillyTavern, RisuAI, or other compatible applications.
517
593
  let assetCount = 0;
518
594
  for (let i = 0; i < assets.length; i++) {
519
595
  const asset = assets[i];
520
- const mimetype = getMimeTypeFromExt(asset.ext);
596
+ const safeType = sanitizeAssetType(asset.type);
597
+ const safeExt = sanitizeExtension(asset.ext);
598
+ const mimetype = getMimeTypeFromExt(safeExt);
521
599
  const category = getCharxCategory(mimetype);
522
- const safeName = sanitizeName(asset.name, asset.ext);
523
- const assetPath = `assets/${asset.type}/${category}/${safeName}.${asset.ext}`;
600
+ const safeName = sanitizeName(asset.name, safeExt);
601
+ const assetPath = `assets/${safeType}/${category}/${safeName}.${safeExt}`;
524
602
  zipEntries[assetPath] = [asset.data, { level: compressionLevel }];
525
603
  assetCount++;
526
604
  if (emitXMeta && mimetype.startsWith("image/")) {
@@ -541,16 +619,18 @@ Import this file into SillyTavern, RisuAI, or other compatible applications.
541
619
  };
542
620
  }
543
621
  function transformAssetUris(card, assets) {
544
- const transformed = JSON.parse(JSON.stringify(card));
622
+ const transformed = typeof structuredClone === "function" ? structuredClone(card) : JSON.parse(JSON.stringify(card));
545
623
  transformed.data.assets = assets.map((asset) => {
546
- const mimetype = getMimeTypeFromExt(asset.ext);
624
+ const safeType = sanitizeAssetType(asset.type);
625
+ const safeExt = sanitizeExtension(asset.ext);
626
+ const mimetype = getMimeTypeFromExt(safeExt);
547
627
  const category = getCharxCategory(mimetype);
548
- const safeName = sanitizeName(asset.name, asset.ext);
628
+ const safeName = sanitizeName(asset.name, safeExt);
549
629
  return {
550
630
  type: asset.type,
551
- uri: `embeded://assets/${asset.type}/${category}/${safeName}.${asset.ext}`,
631
+ uri: `embeded://assets/${safeType}/${category}/${safeName}.${safeExt}`,
552
632
  name: safeName,
553
- ext: asset.ext
633
+ ext: safeExt
554
634
  };
555
635
  });
556
636
  return transformed;
@@ -6877,7 +6957,7 @@ function getExtension(format) {
6877
6957
  }
6878
6958
 
6879
6959
  // ../voxta/dist/index.js
6880
- import { unzipSync, zipSync as zipSync22 } from "fflate";
6960
+ import { zipSync as zipSync22 } from "fflate";
6881
6961
  var DEFAULT_OPTIONS2 = {
6882
6962
  maxFileSize: 50 * 1024 * 1024,
6883
6963
  // 50MB