@character-foundry/character-foundry 0.1.5 → 0.1.6

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 (61) 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/index.cjs +122 -18
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +123 -19
  28. package/dist/index.js.map +1 -1
  29. package/dist/loader.cjs +42 -14
  30. package/dist/loader.cjs.map +1 -1
  31. package/dist/loader.js +43 -15
  32. package/dist/loader.js.map +1 -1
  33. package/dist/lorebook.cjs +1 -0
  34. package/dist/lorebook.cjs.map +1 -1
  35. package/dist/lorebook.js +1 -0
  36. package/dist/lorebook.js.map +1 -1
  37. package/dist/media.cjs +1 -0
  38. package/dist/media.cjs.map +1 -1
  39. package/dist/media.js +1 -0
  40. package/dist/media.js.map +1 -1
  41. package/dist/normalizer.cjs +1 -0
  42. package/dist/normalizer.cjs.map +1 -1
  43. package/dist/normalizer.d.cts +1 -0
  44. package/dist/normalizer.d.ts +1 -0
  45. package/dist/normalizer.js +1 -0
  46. package/dist/normalizer.js.map +1 -1
  47. package/dist/png.cjs +19 -0
  48. package/dist/png.cjs.map +1 -1
  49. package/dist/png.js +19 -0
  50. package/dist/png.js.map +1 -1
  51. package/dist/schemas.cjs +80 -0
  52. package/dist/schemas.cjs.map +1 -1
  53. package/dist/schemas.d.cts +30 -0
  54. package/dist/schemas.d.ts +30 -0
  55. package/dist/schemas.js +80 -0
  56. package/dist/schemas.js.map +1 -1
  57. package/dist/voxta.cjs +14 -102
  58. package/dist/voxta.cjs.map +1 -1
  59. package/dist/voxta.js +15 -103
  60. package/dist/voxta.js.map +1 -1
  61. package/package.json +4 -4
package/dist/charx.js CHANGED
@@ -6,6 +6,7 @@ function toString(data) {
6
6
  return new TextDecoder().decode(data);
7
7
  }
8
8
  var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
9
+ var LARGE_BUFFER_THRESHOLD = 1024 * 1024;
9
10
  function decode(base64) {
10
11
  if (isNode) {
11
12
  return new Uint8Array(Buffer.from(base64, "base64"));
@@ -802,12 +803,69 @@ async function readCharXAsync(data, options = {}) {
802
803
  assets: fetchedAssets
803
804
  };
804
805
  }
806
+ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
807
+ "icon",
808
+ "user_icon",
809
+ "emotion",
810
+ "background",
811
+ "sound",
812
+ "video",
813
+ "custom",
814
+ "x-risu-asset",
815
+ "data",
816
+ "unknown"
817
+ ]);
818
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
819
+ // Images
820
+ "png",
821
+ "jpg",
822
+ "jpeg",
823
+ "webp",
824
+ "gif",
825
+ "avif",
826
+ "svg",
827
+ "bmp",
828
+ "ico",
829
+ // Audio
830
+ "mp3",
831
+ "wav",
832
+ "ogg",
833
+ "flac",
834
+ "m4a",
835
+ "aac",
836
+ "opus",
837
+ // Video
838
+ "mp4",
839
+ "webm",
840
+ "avi",
841
+ "mov",
842
+ "mkv",
843
+ // Data
844
+ "json",
845
+ "txt",
846
+ "bin"
847
+ ]);
805
848
  function getCharxCategory(mimetype) {
806
849
  if (mimetype.startsWith("image/")) return "images";
807
850
  if (mimetype.startsWith("audio/")) return "audio";
808
851
  if (mimetype.startsWith("video/")) return "video";
809
852
  return "other";
810
853
  }
854
+ function sanitizeAssetType(type) {
855
+ const normalized = type.toLowerCase().replace(/[^a-z0-9-_]/g, "-");
856
+ if (SAFE_ASSET_TYPES.has(normalized)) {
857
+ return normalized;
858
+ }
859
+ const sanitized = normalized.replace(/[^a-z0-9]/g, "");
860
+ return sanitized || "custom";
861
+ }
862
+ function sanitizeExtension(ext) {
863
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
864
+ if (SAFE_EXTENSIONS.has(normalized)) {
865
+ return normalized;
866
+ }
867
+ return "bin";
868
+ }
811
869
  function sanitizeName(name, ext) {
812
870
  let safeName = name;
813
871
  if (safeName.toLowerCase().endsWith(`.${ext.toLowerCase()}`)) {
@@ -841,10 +899,12 @@ Import this file into SillyTavern, RisuAI, or other compatible applications.
841
899
  let assetCount = 0;
842
900
  for (let i = 0; i < assets.length; i++) {
843
901
  const asset = assets[i];
844
- const mimetype = getMimeTypeFromExt(asset.ext);
902
+ const safeType = sanitizeAssetType(asset.type);
903
+ const safeExt = sanitizeExtension(asset.ext);
904
+ const mimetype = getMimeTypeFromExt(safeExt);
845
905
  const category = getCharxCategory(mimetype);
846
- const safeName = sanitizeName(asset.name, asset.ext);
847
- const assetPath = `assets/${asset.type}/${category}/${safeName}.${asset.ext}`;
906
+ const safeName = sanitizeName(asset.name, safeExt);
907
+ const assetPath = `assets/${safeType}/${category}/${safeName}.${safeExt}`;
848
908
  zipEntries[assetPath] = [asset.data, { level: compressionLevel }];
849
909
  assetCount++;
850
910
  if (emitXMeta && mimetype.startsWith("image/")) {
@@ -865,16 +925,18 @@ Import this file into SillyTavern, RisuAI, or other compatible applications.
865
925
  };
866
926
  }
867
927
  function transformAssetUris(card, assets) {
868
- const transformed = JSON.parse(JSON.stringify(card));
928
+ const transformed = typeof structuredClone === "function" ? structuredClone(card) : JSON.parse(JSON.stringify(card));
869
929
  transformed.data.assets = assets.map((asset) => {
870
- const mimetype = getMimeTypeFromExt(asset.ext);
930
+ const safeType = sanitizeAssetType(asset.type);
931
+ const safeExt = sanitizeExtension(asset.ext);
932
+ const mimetype = getMimeTypeFromExt(safeExt);
871
933
  const category = getCharxCategory(mimetype);
872
- const safeName = sanitizeName(asset.name, asset.ext);
934
+ const safeName = sanitizeName(asset.name, safeExt);
873
935
  return {
874
936
  type: asset.type,
875
- uri: `embeded://assets/${asset.type}/${category}/${safeName}.${asset.ext}`,
937
+ uri: `embeded://assets/${safeType}/${category}/${safeName}.${safeExt}`,
876
938
  name: safeName,
877
- ext: asset.ext
939
+ ext: safeExt
878
940
  };
879
941
  });
880
942
  return transformed;