@character-foundry/character-foundry 0.4.3-dev.1766103111 → 0.4.3

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 +52 -85
  2. package/dist/charx.cjs.map +1 -1
  3. package/dist/charx.d.cts +22 -22
  4. package/dist/charx.d.ts +22 -22
  5. package/dist/charx.js +52 -85
  6. package/dist/charx.js.map +1 -1
  7. package/dist/exporter.cjs +54 -104
  8. package/dist/exporter.cjs.map +1 -1
  9. package/dist/exporter.d.cts +19 -19
  10. package/dist/exporter.d.ts +19 -19
  11. package/dist/exporter.js +54 -104
  12. package/dist/exporter.js.map +1 -1
  13. package/dist/federation.cjs +36 -104
  14. package/dist/federation.cjs.map +1 -1
  15. package/dist/federation.d.cts +19 -54
  16. package/dist/federation.d.ts +19 -54
  17. package/dist/federation.js +36 -104
  18. package/dist/federation.js.map +1 -1
  19. package/dist/index.cjs +54 -104
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +29 -29
  22. package/dist/index.d.ts +29 -29
  23. package/dist/index.js +54 -104
  24. package/dist/index.js.map +1 -1
  25. package/dist/loader.cjs +31 -171
  26. package/dist/loader.cjs.map +1 -1
  27. package/dist/loader.d.cts +23 -37
  28. package/dist/loader.d.ts +23 -37
  29. package/dist/loader.js +31 -171
  30. package/dist/loader.js.map +1 -1
  31. package/dist/lorebook.d.cts +23 -23
  32. package/dist/lorebook.d.ts +23 -23
  33. package/dist/normalizer.cjs +18 -72
  34. package/dist/normalizer.cjs.map +1 -1
  35. package/dist/normalizer.d.cts +37 -37
  36. package/dist/normalizer.d.ts +37 -37
  37. package/dist/normalizer.js +18 -72
  38. package/dist/normalizer.js.map +1 -1
  39. package/dist/png.cjs +18 -72
  40. package/dist/png.cjs.map +1 -1
  41. package/dist/png.d.cts +25 -25
  42. package/dist/png.d.ts +25 -25
  43. package/dist/png.js +18 -72
  44. package/dist/png.js.map +1 -1
  45. package/dist/schemas.cjs +23 -80
  46. package/dist/schemas.cjs.map +1 -1
  47. package/dist/schemas.d.cts +67 -85
  48. package/dist/schemas.d.ts +67 -85
  49. package/dist/schemas.js +23 -80
  50. package/dist/schemas.js.map +1 -1
  51. package/dist/voxta.cjs +20 -91
  52. package/dist/voxta.cjs.map +1 -1
  53. package/dist/voxta.d.cts +23 -23
  54. package/dist/voxta.d.ts +23 -23
  55. package/dist/voxta.js +20 -91
  56. package/dist/voxta.js.map +1 -1
  57. package/package.json +5 -5
package/dist/charx.d.cts CHANGED
@@ -31,8 +31,8 @@ declare const CCv3DataSchema: z.ZodObject<{
31
31
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
32
32
  name: z.ZodOptional<z.ZodString>;
33
33
  description: z.ZodOptional<z.ZodString>;
34
- scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
35
- token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
34
+ scan_depth: z.ZodOptional<z.ZodNumber>;
35
+ token_budget: z.ZodOptional<z.ZodNumber>;
36
36
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
37
37
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
38
38
  entries: z.ZodArray<z.ZodObject<{
@@ -268,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
268
268
  }, z.ZodTypeAny, "passthrough">[];
269
269
  name?: string | undefined;
270
270
  description?: string | undefined;
271
- scan_depth?: unknown;
272
- token_budget?: unknown;
271
+ scan_depth?: number | undefined;
272
+ token_budget?: number | undefined;
273
273
  recursive_scanning?: boolean | undefined;
274
274
  extensions?: Record<string, unknown> | undefined;
275
275
  }>>>;
276
276
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
277
277
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
278
- type: z.ZodEffects<z.ZodEnum<[
278
+ type: z.ZodEnum<[
279
279
  "icon",
280
280
  "background",
281
281
  "emotion",
@@ -284,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
284
284
  "video",
285
285
  "custom",
286
286
  "x-risu-asset"
287
- ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
287
+ ]>;
288
288
  uri: z.ZodString;
289
289
  name: z.ZodString;
290
290
  ext: z.ZodString;
@@ -295,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
295
295
  ext: string;
296
296
  }, {
297
297
  name: string;
298
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
298
299
  uri: string;
299
300
  ext: string;
300
- type?: unknown;
301
301
  }>, "many">>;
302
302
  nickname: z.ZodOptional<z.ZodString>;
303
303
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
304
304
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
305
- creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
306
- modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
305
+ creation_date: z.ZodOptional<z.ZodNumber>;
306
+ modification_date: z.ZodOptional<z.ZodNumber>;
307
307
  }, "strip", z.ZodTypeAny, {
308
308
  name: string;
309
309
  description: string;
@@ -444,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
444
444
  }, z.ZodTypeAny, "passthrough">[];
445
445
  name?: string | undefined;
446
446
  description?: string | undefined;
447
- scan_depth?: unknown;
448
- token_budget?: unknown;
447
+ scan_depth?: number | undefined;
448
+ token_budget?: number | undefined;
449
449
  recursive_scanning?: boolean | undefined;
450
450
  extensions?: Record<string, unknown> | undefined;
451
451
  } | null | undefined;
@@ -455,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
455
455
  group_only_greetings?: string[] | undefined;
456
456
  assets?: {
457
457
  name: string;
458
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
458
459
  uri: string;
459
460
  ext: string;
460
- type?: unknown;
461
461
  }[] | undefined;
462
462
  nickname?: string | undefined;
463
463
  creator_notes_multilingual?: Record<string, string> | undefined;
464
464
  source?: string[] | undefined;
465
- creation_date?: unknown;
466
- modification_date?: unknown;
465
+ creation_date?: number | undefined;
466
+ modification_date?: number | undefined;
467
467
  }>;
468
468
  }, "strip", z.ZodTypeAny, {
469
469
  data: {
@@ -610,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
610
610
  }, z.ZodTypeAny, "passthrough">[];
611
611
  name?: string | undefined;
612
612
  description?: string | undefined;
613
- scan_depth?: unknown;
614
- token_budget?: unknown;
613
+ scan_depth?: number | undefined;
614
+ token_budget?: number | undefined;
615
615
  recursive_scanning?: boolean | undefined;
616
616
  extensions?: Record<string, unknown> | undefined;
617
617
  } | null | undefined;
@@ -621,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
621
621
  group_only_greetings?: string[] | undefined;
622
622
  assets?: {
623
623
  name: string;
624
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
624
625
  uri: string;
625
626
  ext: string;
626
- type?: unknown;
627
627
  }[] | undefined;
628
628
  nickname?: string | undefined;
629
629
  creator_notes_multilingual?: Record<string, string> | undefined;
630
630
  source?: string[] | undefined;
631
- creation_date?: unknown;
632
- modification_date?: unknown;
631
+ creation_date?: number | undefined;
632
+ modification_date?: number | undefined;
633
633
  };
634
634
  spec: "chara_card_v3";
635
635
  spec_version: "3.0";
@@ -639,7 +639,7 @@ declare const CCv3DataSchema: z.ZodObject<{
639
639
  */
640
640
  export type CCv3Data = z.infer<typeof CCv3DataSchema>;
641
641
  declare const AssetDescriptorSchema: z.ZodObject<{
642
- type: z.ZodEffects<z.ZodEnum<[
642
+ type: z.ZodEnum<[
643
643
  "icon",
644
644
  "background",
645
645
  "emotion",
@@ -648,7 +648,7 @@ declare const AssetDescriptorSchema: z.ZodObject<{
648
648
  "video",
649
649
  "custom",
650
650
  "x-risu-asset"
651
- ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
651
+ ]>;
652
652
  uri: z.ZodString;
653
653
  name: z.ZodString;
654
654
  ext: z.ZodString;
@@ -659,9 +659,9 @@ declare const AssetDescriptorSchema: z.ZodObject<{
659
659
  ext: string;
660
660
  }, {
661
661
  name: string;
662
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
662
663
  uri: string;
663
664
  ext: string;
664
- type?: unknown;
665
665
  }>;
666
666
  /**
667
667
  * Asset descriptor (v3 spec)
package/dist/charx.d.ts CHANGED
@@ -31,8 +31,8 @@ declare const CCv3DataSchema: z.ZodObject<{
31
31
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
32
32
  name: z.ZodOptional<z.ZodString>;
33
33
  description: z.ZodOptional<z.ZodString>;
34
- scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
35
- token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
34
+ scan_depth: z.ZodOptional<z.ZodNumber>;
35
+ token_budget: z.ZodOptional<z.ZodNumber>;
36
36
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
37
37
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
38
38
  entries: z.ZodArray<z.ZodObject<{
@@ -268,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
268
268
  }, z.ZodTypeAny, "passthrough">[];
269
269
  name?: string | undefined;
270
270
  description?: string | undefined;
271
- scan_depth?: unknown;
272
- token_budget?: unknown;
271
+ scan_depth?: number | undefined;
272
+ token_budget?: number | undefined;
273
273
  recursive_scanning?: boolean | undefined;
274
274
  extensions?: Record<string, unknown> | undefined;
275
275
  }>>>;
276
276
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
277
277
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
278
- type: z.ZodEffects<z.ZodEnum<[
278
+ type: z.ZodEnum<[
279
279
  "icon",
280
280
  "background",
281
281
  "emotion",
@@ -284,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
284
284
  "video",
285
285
  "custom",
286
286
  "x-risu-asset"
287
- ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
287
+ ]>;
288
288
  uri: z.ZodString;
289
289
  name: z.ZodString;
290
290
  ext: z.ZodString;
@@ -295,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
295
295
  ext: string;
296
296
  }, {
297
297
  name: string;
298
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
298
299
  uri: string;
299
300
  ext: string;
300
- type?: unknown;
301
301
  }>, "many">>;
302
302
  nickname: z.ZodOptional<z.ZodString>;
303
303
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
304
304
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
305
- creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
306
- modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
305
+ creation_date: z.ZodOptional<z.ZodNumber>;
306
+ modification_date: z.ZodOptional<z.ZodNumber>;
307
307
  }, "strip", z.ZodTypeAny, {
308
308
  name: string;
309
309
  description: string;
@@ -444,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
444
444
  }, z.ZodTypeAny, "passthrough">[];
445
445
  name?: string | undefined;
446
446
  description?: string | undefined;
447
- scan_depth?: unknown;
448
- token_budget?: unknown;
447
+ scan_depth?: number | undefined;
448
+ token_budget?: number | undefined;
449
449
  recursive_scanning?: boolean | undefined;
450
450
  extensions?: Record<string, unknown> | undefined;
451
451
  } | null | undefined;
@@ -455,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
455
455
  group_only_greetings?: string[] | undefined;
456
456
  assets?: {
457
457
  name: string;
458
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
458
459
  uri: string;
459
460
  ext: string;
460
- type?: unknown;
461
461
  }[] | undefined;
462
462
  nickname?: string | undefined;
463
463
  creator_notes_multilingual?: Record<string, string> | undefined;
464
464
  source?: string[] | undefined;
465
- creation_date?: unknown;
466
- modification_date?: unknown;
465
+ creation_date?: number | undefined;
466
+ modification_date?: number | undefined;
467
467
  }>;
468
468
  }, "strip", z.ZodTypeAny, {
469
469
  data: {
@@ -610,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
610
610
  }, z.ZodTypeAny, "passthrough">[];
611
611
  name?: string | undefined;
612
612
  description?: string | undefined;
613
- scan_depth?: unknown;
614
- token_budget?: unknown;
613
+ scan_depth?: number | undefined;
614
+ token_budget?: number | undefined;
615
615
  recursive_scanning?: boolean | undefined;
616
616
  extensions?: Record<string, unknown> | undefined;
617
617
  } | null | undefined;
@@ -621,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
621
621
  group_only_greetings?: string[] | undefined;
622
622
  assets?: {
623
623
  name: string;
624
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
624
625
  uri: string;
625
626
  ext: string;
626
- type?: unknown;
627
627
  }[] | undefined;
628
628
  nickname?: string | undefined;
629
629
  creator_notes_multilingual?: Record<string, string> | undefined;
630
630
  source?: string[] | undefined;
631
- creation_date?: unknown;
632
- modification_date?: unknown;
631
+ creation_date?: number | undefined;
632
+ modification_date?: number | undefined;
633
633
  };
634
634
  spec: "chara_card_v3";
635
635
  spec_version: "3.0";
@@ -639,7 +639,7 @@ declare const CCv3DataSchema: z.ZodObject<{
639
639
  */
640
640
  export type CCv3Data = z.infer<typeof CCv3DataSchema>;
641
641
  declare const AssetDescriptorSchema: z.ZodObject<{
642
- type: z.ZodEffects<z.ZodEnum<[
642
+ type: z.ZodEnum<[
643
643
  "icon",
644
644
  "background",
645
645
  "emotion",
@@ -648,7 +648,7 @@ declare const AssetDescriptorSchema: z.ZodObject<{
648
648
  "video",
649
649
  "custom",
650
650
  "x-risu-asset"
651
- ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
651
+ ]>;
652
652
  uri: z.ZodString;
653
653
  name: z.ZodString;
654
654
  ext: z.ZodString;
@@ -659,9 +659,9 @@ declare const AssetDescriptorSchema: z.ZodObject<{
659
659
  ext: string;
660
660
  }, {
661
661
  name: string;
662
+ type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
662
663
  uri: string;
663
664
  ext: string;
664
- type?: unknown;
665
665
  }>;
666
666
  /**
667
667
  * Asset descriptor (v3 spec)
package/dist/charx.js CHANGED
@@ -408,58 +408,6 @@ import { z } from "zod";
408
408
  import { z as z2 } from "zod";
409
409
  import { z as z3 } from "zod";
410
410
  import "zod";
411
- function preprocessTimestamp(val) {
412
- if (val === null || val === void 0) return void 0;
413
- let num;
414
- if (typeof val === "number") {
415
- num = val;
416
- } else if (typeof val === "string") {
417
- const trimmed = val.trim();
418
- if (!trimmed) return void 0;
419
- const parsed = Number(trimmed);
420
- if (!isNaN(parsed)) {
421
- num = parsed;
422
- } else {
423
- const date = new Date(trimmed);
424
- if (isNaN(date.getTime())) return void 0;
425
- num = Math.floor(date.getTime() / 1e3);
426
- }
427
- } else {
428
- return void 0;
429
- }
430
- if (num > 1e10) {
431
- num = Math.floor(num / 1e3);
432
- }
433
- if (num < 0) return void 0;
434
- return num;
435
- }
436
- function preprocessNumeric(val) {
437
- if (val === null || val === void 0) return void 0;
438
- if (typeof val === "number") {
439
- return isNaN(val) ? void 0 : val;
440
- }
441
- if (typeof val === "string") {
442
- const trimmed = val.trim();
443
- if (!trimmed) return void 0;
444
- const parsed = Number(trimmed);
445
- return isNaN(parsed) ? void 0 : parsed;
446
- }
447
- return void 0;
448
- }
449
- var KNOWN_ASSET_TYPES = /* @__PURE__ */ new Set([
450
- "icon",
451
- "background",
452
- "emotion",
453
- "user_icon",
454
- "sound",
455
- "video",
456
- "custom",
457
- "x-risu-asset"
458
- ]);
459
- function preprocessAssetType(val) {
460
- if (typeof val !== "string") return "custom";
461
- return KNOWN_ASSET_TYPES.has(val) ? val : "custom";
462
- }
463
411
  var ISO8601Schema = z.string().datetime();
464
412
  var UUIDSchema = z.string().uuid();
465
413
  var SpecSchema = z.enum(["v2", "v3"]);
@@ -482,19 +430,16 @@ var SourceFormatSchema = z.enum([
482
430
  // VoxPkg format
483
431
  ]);
484
432
  var OriginalShapeSchema = z.enum(["wrapped", "unwrapped", "legacy"]);
485
- var AssetTypeSchema = z.preprocess(
486
- preprocessAssetType,
487
- z.enum([
488
- "icon",
489
- "background",
490
- "emotion",
491
- "user_icon",
492
- "sound",
493
- "video",
494
- "custom",
495
- "x-risu-asset"
496
- ])
497
- );
433
+ var AssetTypeSchema = z.enum([
434
+ "icon",
435
+ "background",
436
+ "emotion",
437
+ "user_icon",
438
+ "sound",
439
+ "video",
440
+ "custom",
441
+ "x-risu-asset"
442
+ ]);
498
443
  var AssetDescriptorSchema = z.object({
499
444
  type: AssetTypeSchema,
500
445
  uri: z.string(),
@@ -528,8 +473,8 @@ var CCv2LorebookEntrySchema = z2.object({
528
473
  var CCv2CharacterBookSchema = z2.object({
529
474
  name: z2.string().optional(),
530
475
  description: z2.string().optional(),
531
- scan_depth: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
532
- token_budget: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
476
+ scan_depth: z2.number().int().nonnegative().optional(),
477
+ token_budget: z2.number().int().nonnegative().optional(),
533
478
  recursive_scanning: z2.boolean().optional(),
534
479
  extensions: z2.record(z2.unknown()).optional(),
535
480
  entries: z2.array(CCv2LorebookEntrySchema)
@@ -592,8 +537,8 @@ var CCv3LorebookEntrySchema = z3.object({
592
537
  var CCv3CharacterBookSchema = z3.object({
593
538
  name: z3.string().optional(),
594
539
  description: z3.string().optional(),
595
- scan_depth: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
596
- token_budget: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
540
+ scan_depth: z3.number().int().nonnegative().optional(),
541
+ token_budget: z3.number().int().nonnegative().optional(),
597
542
  recursive_scanning: z3.boolean().optional(),
598
543
  extensions: z3.record(z3.unknown()).optional(),
599
544
  entries: z3.array(CCv3LorebookEntrySchema)
@@ -625,9 +570,10 @@ var CCv3DataInnerSchema = z3.object({
625
570
  nickname: z3.string().optional(),
626
571
  creator_notes_multilingual: z3.record(z3.string()).optional(),
627
572
  source: z3.array(z3.string()).optional(),
628
- // Unix timestamps - preprocess to handle ISO strings, numeric strings, milliseconds
629
- creation_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional()),
630
- modification_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional())
573
+ creation_date: z3.number().int().nonnegative().optional(),
574
+ // Unix timestamp in seconds
575
+ modification_date: z3.number().int().nonnegative().optional()
576
+ // Unix timestamp in seconds
631
577
  });
632
578
  var CCv3DataSchema = z3.object({
633
579
  spec: z3.literal("chara_card_v3"),
@@ -890,6 +836,36 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
890
836
  "data",
891
837
  "unknown"
892
838
  ]);
839
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
840
+ // Images
841
+ "png",
842
+ "jpg",
843
+ "jpeg",
844
+ "webp",
845
+ "gif",
846
+ "avif",
847
+ "svg",
848
+ "bmp",
849
+ "ico",
850
+ // Audio
851
+ "mp3",
852
+ "wav",
853
+ "ogg",
854
+ "flac",
855
+ "m4a",
856
+ "aac",
857
+ "opus",
858
+ // Video
859
+ "mp4",
860
+ "webm",
861
+ "avi",
862
+ "mov",
863
+ "mkv",
864
+ // Data
865
+ "json",
866
+ "txt",
867
+ "bin"
868
+ ]);
893
869
  function getCharxCategory(mimetype) {
894
870
  if (mimetype.startsWith("image/")) return "images";
895
871
  if (mimetype.startsWith("audio/")) return "audio";
@@ -905,20 +881,11 @@ function sanitizeAssetType(type) {
905
881
  return sanitized || "custom";
906
882
  }
907
883
  function sanitizeExtension(ext) {
908
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
909
- if (!normalized) {
910
- throw new Error("Invalid asset extension: empty extension");
911
- }
912
- if (normalized.length > 64) {
913
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
914
- }
915
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
916
- throw new Error("Invalid asset extension: path separators are not allowed");
917
- }
918
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
919
- throw new Error(`Invalid asset extension: "${ext}"`);
884
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
885
+ if (SAFE_EXTENSIONS.has(normalized)) {
886
+ return normalized;
920
887
  }
921
- return normalized;
888
+ return "bin";
922
889
  }
923
890
  function sanitizeName(name, ext) {
924
891
  let safeName = name;