@character-foundry/character-foundry 0.4.3 → 0.5.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 (63) hide show
  1. package/dist/app-framework.cjs +12 -3
  2. package/dist/app-framework.cjs.map +1 -1
  3. package/dist/app-framework.d.cts +9 -1
  4. package/dist/app-framework.d.ts +9 -1
  5. package/dist/app-framework.js +12 -3
  6. package/dist/app-framework.js.map +1 -1
  7. package/dist/charx.cjs +85 -52
  8. package/dist/charx.cjs.map +1 -1
  9. package/dist/charx.d.cts +22 -22
  10. package/dist/charx.d.ts +22 -22
  11. package/dist/charx.js +85 -52
  12. package/dist/charx.js.map +1 -1
  13. package/dist/exporter.cjs +104 -54
  14. package/dist/exporter.cjs.map +1 -1
  15. package/dist/exporter.d.cts +19 -19
  16. package/dist/exporter.d.ts +19 -19
  17. package/dist/exporter.js +104 -54
  18. package/dist/exporter.js.map +1 -1
  19. package/dist/federation.cjs +104 -36
  20. package/dist/federation.cjs.map +1 -1
  21. package/dist/federation.d.cts +54 -19
  22. package/dist/federation.d.ts +54 -19
  23. package/dist/federation.js +104 -36
  24. package/dist/federation.js.map +1 -1
  25. package/dist/index.cjs +104 -54
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +29 -29
  28. package/dist/index.d.ts +29 -29
  29. package/dist/index.js +104 -54
  30. package/dist/index.js.map +1 -1
  31. package/dist/loader.cjs +171 -31
  32. package/dist/loader.cjs.map +1 -1
  33. package/dist/loader.d.cts +37 -23
  34. package/dist/loader.d.ts +37 -23
  35. package/dist/loader.js +171 -31
  36. package/dist/loader.js.map +1 -1
  37. package/dist/lorebook.d.cts +23 -23
  38. package/dist/lorebook.d.ts +23 -23
  39. package/dist/normalizer.cjs +72 -18
  40. package/dist/normalizer.cjs.map +1 -1
  41. package/dist/normalizer.d.cts +37 -37
  42. package/dist/normalizer.d.ts +37 -37
  43. package/dist/normalizer.js +72 -18
  44. package/dist/normalizer.js.map +1 -1
  45. package/dist/png.cjs +72 -18
  46. package/dist/png.cjs.map +1 -1
  47. package/dist/png.d.cts +25 -25
  48. package/dist/png.d.ts +25 -25
  49. package/dist/png.js +72 -18
  50. package/dist/png.js.map +1 -1
  51. package/dist/schemas.cjs +80 -23
  52. package/dist/schemas.cjs.map +1 -1
  53. package/dist/schemas.d.cts +85 -67
  54. package/dist/schemas.d.ts +85 -67
  55. package/dist/schemas.js +80 -23
  56. package/dist/schemas.js.map +1 -1
  57. package/dist/voxta.cjs +91 -20
  58. package/dist/voxta.cjs.map +1 -1
  59. package/dist/voxta.d.cts +23 -23
  60. package/dist/voxta.d.ts +23 -23
  61. package/dist/voxta.js +91 -20
  62. package/dist/voxta.js.map +1 -1
  63. package/package.json +24 -24
package/dist/index.d.cts CHANGED
@@ -13,8 +13,8 @@ export type BinaryData = Uint8Array;
13
13
  declare const CCv3CharacterBookSchema: z.ZodObject<{
14
14
  name: z.ZodOptional<z.ZodString>;
15
15
  description: z.ZodOptional<z.ZodString>;
16
- scan_depth: z.ZodOptional<z.ZodNumber>;
17
- token_budget: z.ZodOptional<z.ZodNumber>;
16
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
17
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
18
18
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
19
19
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
20
  entries: z.ZodArray<z.ZodObject<{
@@ -250,8 +250,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
250
250
  }, z.ZodTypeAny, "passthrough">[];
251
251
  name?: string | undefined;
252
252
  description?: string | undefined;
253
- scan_depth?: number | undefined;
254
- token_budget?: number | undefined;
253
+ scan_depth?: unknown;
254
+ token_budget?: unknown;
255
255
  recursive_scanning?: boolean | undefined;
256
256
  extensions?: Record<string, unknown> | undefined;
257
257
  }>;
@@ -276,8 +276,8 @@ declare const CCv3DataSchema: z.ZodObject<{
276
276
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
277
277
  name: z.ZodOptional<z.ZodString>;
278
278
  description: z.ZodOptional<z.ZodString>;
279
- scan_depth: z.ZodOptional<z.ZodNumber>;
280
- token_budget: z.ZodOptional<z.ZodNumber>;
279
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
280
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
281
281
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
282
282
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
283
283
  entries: z.ZodArray<z.ZodObject<{
@@ -513,14 +513,14 @@ declare const CCv3DataSchema: z.ZodObject<{
513
513
  }, z.ZodTypeAny, "passthrough">[];
514
514
  name?: string | undefined;
515
515
  description?: string | undefined;
516
- scan_depth?: number | undefined;
517
- token_budget?: number | undefined;
516
+ scan_depth?: unknown;
517
+ token_budget?: unknown;
518
518
  recursive_scanning?: boolean | undefined;
519
519
  extensions?: Record<string, unknown> | undefined;
520
520
  }>>>;
521
521
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
522
522
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
523
- type: z.ZodEnum<[
523
+ type: z.ZodEffects<z.ZodEnum<[
524
524
  "icon",
525
525
  "background",
526
526
  "emotion",
@@ -529,7 +529,7 @@ declare const CCv3DataSchema: z.ZodObject<{
529
529
  "video",
530
530
  "custom",
531
531
  "x-risu-asset"
532
- ]>;
532
+ ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
533
533
  uri: z.ZodString;
534
534
  name: z.ZodString;
535
535
  ext: z.ZodString;
@@ -540,15 +540,15 @@ declare const CCv3DataSchema: z.ZodObject<{
540
540
  ext: string;
541
541
  }, {
542
542
  name: string;
543
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
544
543
  uri: string;
545
544
  ext: string;
545
+ type?: unknown;
546
546
  }>, "many">>;
547
547
  nickname: z.ZodOptional<z.ZodString>;
548
548
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
549
549
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
550
- creation_date: z.ZodOptional<z.ZodNumber>;
551
- modification_date: z.ZodOptional<z.ZodNumber>;
550
+ creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
551
+ modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
552
552
  }, "strip", z.ZodTypeAny, {
553
553
  name: string;
554
554
  description: string;
@@ -689,8 +689,8 @@ declare const CCv3DataSchema: z.ZodObject<{
689
689
  }, z.ZodTypeAny, "passthrough">[];
690
690
  name?: string | undefined;
691
691
  description?: string | undefined;
692
- scan_depth?: number | undefined;
693
- token_budget?: number | undefined;
692
+ scan_depth?: unknown;
693
+ token_budget?: unknown;
694
694
  recursive_scanning?: boolean | undefined;
695
695
  extensions?: Record<string, unknown> | undefined;
696
696
  } | null | undefined;
@@ -700,15 +700,15 @@ declare const CCv3DataSchema: z.ZodObject<{
700
700
  group_only_greetings?: string[] | undefined;
701
701
  assets?: {
702
702
  name: string;
703
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
704
703
  uri: string;
705
704
  ext: string;
705
+ type?: unknown;
706
706
  }[] | undefined;
707
707
  nickname?: string | undefined;
708
708
  creator_notes_multilingual?: Record<string, string> | undefined;
709
709
  source?: string[] | undefined;
710
- creation_date?: number | undefined;
711
- modification_date?: number | undefined;
710
+ creation_date?: unknown;
711
+ modification_date?: unknown;
712
712
  }>;
713
713
  }, "strip", z.ZodTypeAny, {
714
714
  data: {
@@ -855,8 +855,8 @@ declare const CCv3DataSchema: z.ZodObject<{
855
855
  }, z.ZodTypeAny, "passthrough">[];
856
856
  name?: string | undefined;
857
857
  description?: string | undefined;
858
- scan_depth?: number | undefined;
859
- token_budget?: number | undefined;
858
+ scan_depth?: unknown;
859
+ token_budget?: unknown;
860
860
  recursive_scanning?: boolean | undefined;
861
861
  extensions?: Record<string, unknown> | undefined;
862
862
  } | null | undefined;
@@ -866,15 +866,15 @@ declare const CCv3DataSchema: z.ZodObject<{
866
866
  group_only_greetings?: string[] | undefined;
867
867
  assets?: {
868
868
  name: string;
869
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
870
869
  uri: string;
871
870
  ext: string;
871
+ type?: unknown;
872
872
  }[] | undefined;
873
873
  nickname?: string | undefined;
874
874
  creator_notes_multilingual?: Record<string, string> | undefined;
875
875
  source?: string[] | undefined;
876
- creation_date?: number | undefined;
877
- modification_date?: number | undefined;
876
+ creation_date?: unknown;
877
+ modification_date?: unknown;
878
878
  };
879
879
  spec: "chara_card_v3";
880
880
  spec_version: "3.0";
@@ -923,8 +923,8 @@ declare const CCv2DataSchema: z.ZodObject<{
923
923
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
924
924
  name: z.ZodOptional<z.ZodString>;
925
925
  description: z.ZodOptional<z.ZodString>;
926
- scan_depth: z.ZodOptional<z.ZodNumber>;
927
- token_budget: z.ZodOptional<z.ZodNumber>;
926
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
927
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
928
928
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
929
929
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
930
930
  entries: z.ZodArray<z.ZodObject<{
@@ -1055,8 +1055,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1055
1055
  }, z.ZodTypeAny, "passthrough">[];
1056
1056
  name?: string | undefined;
1057
1057
  description?: string | undefined;
1058
- scan_depth?: number | undefined;
1059
- token_budget?: number | undefined;
1058
+ scan_depth?: unknown;
1059
+ token_budget?: unknown;
1060
1060
  recursive_scanning?: boolean | undefined;
1061
1061
  extensions?: Record<string, unknown> | undefined;
1062
1062
  }>>>;
@@ -1150,8 +1150,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1150
1150
  }, z.ZodTypeAny, "passthrough">[];
1151
1151
  name?: string | undefined;
1152
1152
  description?: string | undefined;
1153
- scan_depth?: number | undefined;
1154
- token_budget?: number | undefined;
1153
+ scan_depth?: unknown;
1154
+ token_budget?: unknown;
1155
1155
  recursive_scanning?: boolean | undefined;
1156
1156
  extensions?: Record<string, unknown> | undefined;
1157
1157
  } | null | undefined;
package/dist/index.d.ts CHANGED
@@ -13,8 +13,8 @@ export type BinaryData = Uint8Array;
13
13
  declare const CCv3CharacterBookSchema: z.ZodObject<{
14
14
  name: z.ZodOptional<z.ZodString>;
15
15
  description: z.ZodOptional<z.ZodString>;
16
- scan_depth: z.ZodOptional<z.ZodNumber>;
17
- token_budget: z.ZodOptional<z.ZodNumber>;
16
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
17
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
18
18
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
19
19
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
20
  entries: z.ZodArray<z.ZodObject<{
@@ -250,8 +250,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
250
250
  }, z.ZodTypeAny, "passthrough">[];
251
251
  name?: string | undefined;
252
252
  description?: string | undefined;
253
- scan_depth?: number | undefined;
254
- token_budget?: number | undefined;
253
+ scan_depth?: unknown;
254
+ token_budget?: unknown;
255
255
  recursive_scanning?: boolean | undefined;
256
256
  extensions?: Record<string, unknown> | undefined;
257
257
  }>;
@@ -276,8 +276,8 @@ declare const CCv3DataSchema: z.ZodObject<{
276
276
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
277
277
  name: z.ZodOptional<z.ZodString>;
278
278
  description: z.ZodOptional<z.ZodString>;
279
- scan_depth: z.ZodOptional<z.ZodNumber>;
280
- token_budget: z.ZodOptional<z.ZodNumber>;
279
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
280
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
281
281
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
282
282
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
283
283
  entries: z.ZodArray<z.ZodObject<{
@@ -513,14 +513,14 @@ declare const CCv3DataSchema: z.ZodObject<{
513
513
  }, z.ZodTypeAny, "passthrough">[];
514
514
  name?: string | undefined;
515
515
  description?: string | undefined;
516
- scan_depth?: number | undefined;
517
- token_budget?: number | undefined;
516
+ scan_depth?: unknown;
517
+ token_budget?: unknown;
518
518
  recursive_scanning?: boolean | undefined;
519
519
  extensions?: Record<string, unknown> | undefined;
520
520
  }>>>;
521
521
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
522
522
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
523
- type: z.ZodEnum<[
523
+ type: z.ZodEffects<z.ZodEnum<[
524
524
  "icon",
525
525
  "background",
526
526
  "emotion",
@@ -529,7 +529,7 @@ declare const CCv3DataSchema: z.ZodObject<{
529
529
  "video",
530
530
  "custom",
531
531
  "x-risu-asset"
532
- ]>;
532
+ ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
533
533
  uri: z.ZodString;
534
534
  name: z.ZodString;
535
535
  ext: z.ZodString;
@@ -540,15 +540,15 @@ declare const CCv3DataSchema: z.ZodObject<{
540
540
  ext: string;
541
541
  }, {
542
542
  name: string;
543
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
544
543
  uri: string;
545
544
  ext: string;
545
+ type?: unknown;
546
546
  }>, "many">>;
547
547
  nickname: z.ZodOptional<z.ZodString>;
548
548
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
549
549
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
550
- creation_date: z.ZodOptional<z.ZodNumber>;
551
- modification_date: z.ZodOptional<z.ZodNumber>;
550
+ creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
551
+ modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
552
552
  }, "strip", z.ZodTypeAny, {
553
553
  name: string;
554
554
  description: string;
@@ -689,8 +689,8 @@ declare const CCv3DataSchema: z.ZodObject<{
689
689
  }, z.ZodTypeAny, "passthrough">[];
690
690
  name?: string | undefined;
691
691
  description?: string | undefined;
692
- scan_depth?: number | undefined;
693
- token_budget?: number | undefined;
692
+ scan_depth?: unknown;
693
+ token_budget?: unknown;
694
694
  recursive_scanning?: boolean | undefined;
695
695
  extensions?: Record<string, unknown> | undefined;
696
696
  } | null | undefined;
@@ -700,15 +700,15 @@ declare const CCv3DataSchema: z.ZodObject<{
700
700
  group_only_greetings?: string[] | undefined;
701
701
  assets?: {
702
702
  name: string;
703
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
704
703
  uri: string;
705
704
  ext: string;
705
+ type?: unknown;
706
706
  }[] | undefined;
707
707
  nickname?: string | undefined;
708
708
  creator_notes_multilingual?: Record<string, string> | undefined;
709
709
  source?: string[] | undefined;
710
- creation_date?: number | undefined;
711
- modification_date?: number | undefined;
710
+ creation_date?: unknown;
711
+ modification_date?: unknown;
712
712
  }>;
713
713
  }, "strip", z.ZodTypeAny, {
714
714
  data: {
@@ -855,8 +855,8 @@ declare const CCv3DataSchema: z.ZodObject<{
855
855
  }, z.ZodTypeAny, "passthrough">[];
856
856
  name?: string | undefined;
857
857
  description?: string | undefined;
858
- scan_depth?: number | undefined;
859
- token_budget?: number | undefined;
858
+ scan_depth?: unknown;
859
+ token_budget?: unknown;
860
860
  recursive_scanning?: boolean | undefined;
861
861
  extensions?: Record<string, unknown> | undefined;
862
862
  } | null | undefined;
@@ -866,15 +866,15 @@ declare const CCv3DataSchema: z.ZodObject<{
866
866
  group_only_greetings?: string[] | undefined;
867
867
  assets?: {
868
868
  name: string;
869
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
870
869
  uri: string;
871
870
  ext: string;
871
+ type?: unknown;
872
872
  }[] | undefined;
873
873
  nickname?: string | undefined;
874
874
  creator_notes_multilingual?: Record<string, string> | undefined;
875
875
  source?: string[] | undefined;
876
- creation_date?: number | undefined;
877
- modification_date?: number | undefined;
876
+ creation_date?: unknown;
877
+ modification_date?: unknown;
878
878
  };
879
879
  spec: "chara_card_v3";
880
880
  spec_version: "3.0";
@@ -923,8 +923,8 @@ declare const CCv2DataSchema: z.ZodObject<{
923
923
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
924
924
  name: z.ZodOptional<z.ZodString>;
925
925
  description: z.ZodOptional<z.ZodString>;
926
- scan_depth: z.ZodOptional<z.ZodNumber>;
927
- token_budget: z.ZodOptional<z.ZodNumber>;
926
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
927
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
928
928
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
929
929
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
930
930
  entries: z.ZodArray<z.ZodObject<{
@@ -1055,8 +1055,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1055
1055
  }, z.ZodTypeAny, "passthrough">[];
1056
1056
  name?: string | undefined;
1057
1057
  description?: string | undefined;
1058
- scan_depth?: number | undefined;
1059
- token_budget?: number | undefined;
1058
+ scan_depth?: unknown;
1059
+ token_budget?: unknown;
1060
1060
  recursive_scanning?: boolean | undefined;
1061
1061
  extensions?: Record<string, unknown> | undefined;
1062
1062
  }>>>;
@@ -1150,8 +1150,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1150
1150
  }, z.ZodTypeAny, "passthrough">[];
1151
1151
  name?: string | undefined;
1152
1152
  description?: string | undefined;
1153
- scan_depth?: number | undefined;
1154
- token_budget?: number | undefined;
1153
+ scan_depth?: unknown;
1154
+ token_budget?: unknown;
1155
1155
  recursive_scanning?: boolean | undefined;
1156
1156
  extensions?: Record<string, unknown> | undefined;
1157
1157
  } | null | undefined;
package/dist/index.js CHANGED
@@ -536,6 +536,58 @@ import { z } from "zod";
536
536
  import { z as z2 } from "zod";
537
537
  import { z as z3 } from "zod";
538
538
  import "zod";
539
+ function preprocessTimestamp(val) {
540
+ if (val === null || val === void 0) return void 0;
541
+ let num;
542
+ if (typeof val === "number") {
543
+ num = val;
544
+ } else if (typeof val === "string") {
545
+ const trimmed = val.trim();
546
+ if (!trimmed) return void 0;
547
+ const parsed = Number(trimmed);
548
+ if (!isNaN(parsed)) {
549
+ num = parsed;
550
+ } else {
551
+ const date = new Date(trimmed);
552
+ if (isNaN(date.getTime())) return void 0;
553
+ num = Math.floor(date.getTime() / 1e3);
554
+ }
555
+ } else {
556
+ return void 0;
557
+ }
558
+ if (num > 1e10) {
559
+ num = Math.floor(num / 1e3);
560
+ }
561
+ if (num < 0) return void 0;
562
+ return num;
563
+ }
564
+ function preprocessNumeric(val) {
565
+ if (val === null || val === void 0) return void 0;
566
+ if (typeof val === "number") {
567
+ return isNaN(val) ? void 0 : val;
568
+ }
569
+ if (typeof val === "string") {
570
+ const trimmed = val.trim();
571
+ if (!trimmed) return void 0;
572
+ const parsed = Number(trimmed);
573
+ return isNaN(parsed) ? void 0 : parsed;
574
+ }
575
+ return void 0;
576
+ }
577
+ var KNOWN_ASSET_TYPES = /* @__PURE__ */ new Set([
578
+ "icon",
579
+ "background",
580
+ "emotion",
581
+ "user_icon",
582
+ "sound",
583
+ "video",
584
+ "custom",
585
+ "x-risu-asset"
586
+ ]);
587
+ function preprocessAssetType(val) {
588
+ if (typeof val !== "string") return "custom";
589
+ return KNOWN_ASSET_TYPES.has(val) ? val : "custom";
590
+ }
539
591
  var ISO8601Schema = z.string().datetime();
540
592
  var UUIDSchema = z.string().uuid();
541
593
  var SpecSchema = z.enum(["v2", "v3"]);
@@ -558,16 +610,19 @@ var SourceFormatSchema = z.enum([
558
610
  // VoxPkg format
559
611
  ]);
560
612
  var OriginalShapeSchema = z.enum(["wrapped", "unwrapped", "legacy"]);
561
- var AssetTypeSchema = z.enum([
562
- "icon",
563
- "background",
564
- "emotion",
565
- "user_icon",
566
- "sound",
567
- "video",
568
- "custom",
569
- "x-risu-asset"
570
- ]);
613
+ var AssetTypeSchema = z.preprocess(
614
+ preprocessAssetType,
615
+ z.enum([
616
+ "icon",
617
+ "background",
618
+ "emotion",
619
+ "user_icon",
620
+ "sound",
621
+ "video",
622
+ "custom",
623
+ "x-risu-asset"
624
+ ])
625
+ );
571
626
  var AssetDescriptorSchema = z.object({
572
627
  type: AssetTypeSchema,
573
628
  uri: z.string(),
@@ -601,8 +656,8 @@ var CCv2LorebookEntrySchema = z2.object({
601
656
  var CCv2CharacterBookSchema = z2.object({
602
657
  name: z2.string().optional(),
603
658
  description: z2.string().optional(),
604
- scan_depth: z2.number().int().nonnegative().optional(),
605
- token_budget: z2.number().int().nonnegative().optional(),
659
+ scan_depth: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
660
+ token_budget: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
606
661
  recursive_scanning: z2.boolean().optional(),
607
662
  extensions: z2.record(z2.unknown()).optional(),
608
663
  entries: z2.array(CCv2LorebookEntrySchema)
@@ -676,8 +731,8 @@ var CCv3LorebookEntrySchema = z3.object({
676
731
  var CCv3CharacterBookSchema = z3.object({
677
732
  name: z3.string().optional(),
678
733
  description: z3.string().optional(),
679
- scan_depth: z3.number().int().nonnegative().optional(),
680
- token_budget: z3.number().int().nonnegative().optional(),
734
+ scan_depth: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
735
+ token_budget: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
681
736
  recursive_scanning: z3.boolean().optional(),
682
737
  extensions: z3.record(z3.unknown()).optional(),
683
738
  entries: z3.array(CCv3LorebookEntrySchema)
@@ -709,10 +764,9 @@ var CCv3DataInnerSchema = z3.object({
709
764
  nickname: z3.string().optional(),
710
765
  creator_notes_multilingual: z3.record(z3.string()).optional(),
711
766
  source: z3.array(z3.string()).optional(),
712
- creation_date: z3.number().int().nonnegative().optional(),
713
- // Unix timestamp in seconds
714
- modification_date: z3.number().int().nonnegative().optional()
715
- // Unix timestamp in seconds
767
+ // Unix timestamps - preprocess to handle ISO strings, numeric strings, milliseconds
768
+ creation_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional()),
769
+ modification_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional())
716
770
  });
717
771
  var CCv3DataSchema = z3.object({
718
772
  spec: z3.literal("chara_card_v3"),
@@ -1339,36 +1393,6 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
1339
1393
  "data",
1340
1394
  "unknown"
1341
1395
  ]);
1342
- var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
1343
- // Images
1344
- "png",
1345
- "jpg",
1346
- "jpeg",
1347
- "webp",
1348
- "gif",
1349
- "avif",
1350
- "svg",
1351
- "bmp",
1352
- "ico",
1353
- // Audio
1354
- "mp3",
1355
- "wav",
1356
- "ogg",
1357
- "flac",
1358
- "m4a",
1359
- "aac",
1360
- "opus",
1361
- // Video
1362
- "mp4",
1363
- "webm",
1364
- "avi",
1365
- "mov",
1366
- "mkv",
1367
- // Data
1368
- "json",
1369
- "txt",
1370
- "bin"
1371
- ]);
1372
1396
  function getCharxCategory(mimetype) {
1373
1397
  if (mimetype.startsWith("image/")) return "images";
1374
1398
  if (mimetype.startsWith("audio/")) return "audio";
@@ -1384,11 +1408,20 @@ function sanitizeAssetType(type) {
1384
1408
  return sanitized || "custom";
1385
1409
  }
1386
1410
  function sanitizeExtension(ext) {
1387
- const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
1388
- if (SAFE_EXTENSIONS.has(normalized)) {
1389
- return normalized;
1411
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
1412
+ if (!normalized) {
1413
+ throw new Error("Invalid asset extension: empty extension");
1414
+ }
1415
+ if (normalized.length > 64) {
1416
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
1417
+ }
1418
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
1419
+ throw new Error("Invalid asset extension: path separators are not allowed");
1390
1420
  }
1391
- return "bin";
1421
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
1422
+ throw new Error(`Invalid asset extension: "${ext}"`);
1423
+ }
1424
+ return normalized;
1392
1425
  }
1393
1426
  function sanitizeName(name, ext) {
1394
1427
  let safeName = name;
@@ -8170,6 +8203,22 @@ function sanitizeName2(name, ext) {
8170
8203
  if (!safeName) safeName = "asset";
8171
8204
  return safeName;
8172
8205
  }
8206
+ function sanitizeExtension2(ext) {
8207
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
8208
+ if (!normalized) {
8209
+ throw new Error("Invalid asset extension: empty extension");
8210
+ }
8211
+ if (normalized.length > 64) {
8212
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
8213
+ }
8214
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
8215
+ throw new Error("Invalid asset extension: path separators are not allowed");
8216
+ }
8217
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
8218
+ throw new Error(`Invalid asset extension: "${ext}"`);
8219
+ }
8220
+ return normalized;
8221
+ }
8173
8222
  function writeVoxta(card, assets, options = {}) {
8174
8223
  const { compressionLevel = 6, includePackageJson = false } = options;
8175
8224
  const cardData = card.data;
@@ -8258,8 +8307,9 @@ function writeVoxta(card, assets, options = {}) {
8258
8307
  let assetCount = 0;
8259
8308
  let mainThumbnail;
8260
8309
  for (const asset of assets) {
8261
- const safeName = sanitizeName2(asset.name, asset.ext);
8262
- const finalFilename = `${safeName}.${asset.ext}`;
8310
+ const safeExt = sanitizeExtension2(asset.ext);
8311
+ const safeName = sanitizeName2(asset.name, safeExt);
8312
+ const finalFilename = `${safeName}.${safeExt}`;
8263
8313
  let voxtaPath = "";
8264
8314
  const tags = asset.tags || [];
8265
8315
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);