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

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 +87 -54
  2. package/dist/charx.cjs.map +1 -1
  3. package/dist/charx.d.cts +40 -31
  4. package/dist/charx.d.ts +40 -31
  5. package/dist/charx.js +87 -54
  6. package/dist/charx.js.map +1 -1
  7. package/dist/exporter.cjs +106 -56
  8. package/dist/exporter.cjs.map +1 -1
  9. package/dist/exporter.d.cts +37 -28
  10. package/dist/exporter.d.ts +37 -28
  11. package/dist/exporter.js +106 -56
  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 +72 -28
  16. package/dist/federation.d.ts +72 -28
  17. package/dist/federation.js +104 -36
  18. package/dist/federation.js.map +1 -1
  19. package/dist/index.cjs +106 -56
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +71 -50
  22. package/dist/index.d.ts +71 -50
  23. package/dist/index.js +106 -56
  24. package/dist/index.js.map +1 -1
  25. package/dist/loader.cjs +173 -33
  26. package/dist/loader.cjs.map +1 -1
  27. package/dist/loader.d.cts +65 -37
  28. package/dist/loader.d.ts +65 -37
  29. package/dist/loader.js +173 -33
  30. package/dist/loader.js.map +1 -1
  31. package/dist/lorebook.d.cts +57 -40
  32. package/dist/lorebook.d.ts +57 -40
  33. package/dist/normalizer.cjs +74 -20
  34. package/dist/normalizer.cjs.map +1 -1
  35. package/dist/normalizer.d.cts +97 -67
  36. package/dist/normalizer.d.ts +97 -67
  37. package/dist/normalizer.js +74 -20
  38. package/dist/normalizer.js.map +1 -1
  39. package/dist/png.cjs +74 -20
  40. package/dist/png.cjs.map +1 -1
  41. package/dist/png.d.cts +57 -41
  42. package/dist/png.d.ts +57 -41
  43. package/dist/png.js +74 -20
  44. package/dist/png.js.map +1 -1
  45. package/dist/schemas.cjs +82 -25
  46. package/dist/schemas.cjs.map +1 -1
  47. package/dist/schemas.d.cts +181 -115
  48. package/dist/schemas.d.ts +181 -115
  49. package/dist/schemas.js +82 -25
  50. package/dist/schemas.js.map +1 -1
  51. package/dist/voxta.cjs +93 -22
  52. package/dist/voxta.cjs.map +1 -1
  53. package/dist/voxta.d.cts +51 -37
  54. package/dist/voxta.d.ts +51 -37
  55. package/dist/voxta.js +93 -22
  56. package/dist/voxta.js.map +1 -1
  57. package/package.json +5 -5
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<{
@@ -33,7 +33,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
33
33
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
34
34
  z.ZodEnum<[
35
35
  "before_char",
36
- "after_char"
36
+ "after_char",
37
+ "in_chat"
37
38
  ]>,
38
39
  z.ZodNumber,
39
40
  z.ZodLiteral<"">
@@ -76,7 +77,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
76
77
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
77
78
  z.ZodEnum<[
78
79
  "before_char",
79
- "after_char"
80
+ "after_char",
81
+ "in_chat"
80
82
  ]>,
81
83
  z.ZodNumber,
82
84
  z.ZodLiteral<"">
@@ -119,7 +121,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
119
121
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
120
122
  z.ZodEnum<[
121
123
  "before_char",
122
- "after_char"
124
+ "after_char",
125
+ "in_chat"
123
126
  ]>,
124
127
  z.ZodNumber,
125
128
  z.ZodLiteral<"">
@@ -164,7 +167,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
164
167
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
165
168
  z.ZodEnum<[
166
169
  "before_char",
167
- "after_char"
170
+ "after_char",
171
+ "in_chat"
168
172
  ]>,
169
173
  z.ZodNumber,
170
174
  z.ZodLiteral<"">
@@ -215,7 +219,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
215
219
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
216
220
  z.ZodEnum<[
217
221
  "before_char",
218
- "after_char"
222
+ "after_char",
223
+ "in_chat"
219
224
  ]>,
220
225
  z.ZodNumber,
221
226
  z.ZodLiteral<"">
@@ -245,8 +250,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
245
250
  }, z.ZodTypeAny, "passthrough">[];
246
251
  name?: string | undefined;
247
252
  description?: string | undefined;
248
- scan_depth?: number | undefined;
249
- token_budget?: number | undefined;
253
+ scan_depth?: unknown;
254
+ token_budget?: unknown;
250
255
  recursive_scanning?: boolean | undefined;
251
256
  extensions?: Record<string, unknown> | undefined;
252
257
  }>;
@@ -271,8 +276,8 @@ declare const CCv3DataSchema: z.ZodObject<{
271
276
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
272
277
  name: z.ZodOptional<z.ZodString>;
273
278
  description: z.ZodOptional<z.ZodString>;
274
- scan_depth: z.ZodOptional<z.ZodNumber>;
275
- 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>;
276
281
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
277
282
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
278
283
  entries: z.ZodArray<z.ZodObject<{
@@ -291,7 +296,8 @@ declare const CCv3DataSchema: z.ZodObject<{
291
296
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
292
297
  z.ZodEnum<[
293
298
  "before_char",
294
- "after_char"
299
+ "after_char",
300
+ "in_chat"
295
301
  ]>,
296
302
  z.ZodNumber,
297
303
  z.ZodLiteral<"">
@@ -334,7 +340,8 @@ declare const CCv3DataSchema: z.ZodObject<{
334
340
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
335
341
  z.ZodEnum<[
336
342
  "before_char",
337
- "after_char"
343
+ "after_char",
344
+ "in_chat"
338
345
  ]>,
339
346
  z.ZodNumber,
340
347
  z.ZodLiteral<"">
@@ -377,7 +384,8 @@ declare const CCv3DataSchema: z.ZodObject<{
377
384
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
378
385
  z.ZodEnum<[
379
386
  "before_char",
380
- "after_char"
387
+ "after_char",
388
+ "in_chat"
381
389
  ]>,
382
390
  z.ZodNumber,
383
391
  z.ZodLiteral<"">
@@ -422,7 +430,8 @@ declare const CCv3DataSchema: z.ZodObject<{
422
430
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
423
431
  z.ZodEnum<[
424
432
  "before_char",
425
- "after_char"
433
+ "after_char",
434
+ "in_chat"
426
435
  ]>,
427
436
  z.ZodNumber,
428
437
  z.ZodLiteral<"">
@@ -473,7 +482,8 @@ declare const CCv3DataSchema: z.ZodObject<{
473
482
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
474
483
  z.ZodEnum<[
475
484
  "before_char",
476
- "after_char"
485
+ "after_char",
486
+ "in_chat"
477
487
  ]>,
478
488
  z.ZodNumber,
479
489
  z.ZodLiteral<"">
@@ -503,14 +513,14 @@ declare const CCv3DataSchema: z.ZodObject<{
503
513
  }, z.ZodTypeAny, "passthrough">[];
504
514
  name?: string | undefined;
505
515
  description?: string | undefined;
506
- scan_depth?: number | undefined;
507
- token_budget?: number | undefined;
516
+ scan_depth?: unknown;
517
+ token_budget?: unknown;
508
518
  recursive_scanning?: boolean | undefined;
509
519
  extensions?: Record<string, unknown> | undefined;
510
520
  }>>>;
511
521
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
512
522
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
513
- type: z.ZodEnum<[
523
+ type: z.ZodEffects<z.ZodEnum<[
514
524
  "icon",
515
525
  "background",
516
526
  "emotion",
@@ -519,7 +529,7 @@ declare const CCv3DataSchema: z.ZodObject<{
519
529
  "video",
520
530
  "custom",
521
531
  "x-risu-asset"
522
- ]>;
532
+ ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
523
533
  uri: z.ZodString;
524
534
  name: z.ZodString;
525
535
  ext: z.ZodString;
@@ -530,15 +540,15 @@ declare const CCv3DataSchema: z.ZodObject<{
530
540
  ext: string;
531
541
  }, {
532
542
  name: string;
533
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
534
543
  uri: string;
535
544
  ext: string;
545
+ type?: unknown;
536
546
  }>, "many">>;
537
547
  nickname: z.ZodOptional<z.ZodString>;
538
548
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
539
549
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
540
- creation_date: z.ZodOptional<z.ZodNumber>;
541
- 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>;
542
552
  }, "strip", z.ZodTypeAny, {
543
553
  name: string;
544
554
  description: string;
@@ -572,7 +582,8 @@ declare const CCv3DataSchema: z.ZodObject<{
572
582
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
573
583
  z.ZodEnum<[
574
584
  "before_char",
575
- "after_char"
585
+ "after_char",
586
+ "in_chat"
576
587
  ]>,
577
588
  z.ZodNumber,
578
589
  z.ZodLiteral<"">
@@ -647,7 +658,8 @@ declare const CCv3DataSchema: z.ZodObject<{
647
658
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
648
659
  z.ZodEnum<[
649
660
  "before_char",
650
- "after_char"
661
+ "after_char",
662
+ "in_chat"
651
663
  ]>,
652
664
  z.ZodNumber,
653
665
  z.ZodLiteral<"">
@@ -677,8 +689,8 @@ declare const CCv3DataSchema: z.ZodObject<{
677
689
  }, z.ZodTypeAny, "passthrough">[];
678
690
  name?: string | undefined;
679
691
  description?: string | undefined;
680
- scan_depth?: number | undefined;
681
- token_budget?: number | undefined;
692
+ scan_depth?: unknown;
693
+ token_budget?: unknown;
682
694
  recursive_scanning?: boolean | undefined;
683
695
  extensions?: Record<string, unknown> | undefined;
684
696
  } | null | undefined;
@@ -688,15 +700,15 @@ declare const CCv3DataSchema: z.ZodObject<{
688
700
  group_only_greetings?: string[] | undefined;
689
701
  assets?: {
690
702
  name: string;
691
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
692
703
  uri: string;
693
704
  ext: string;
705
+ type?: unknown;
694
706
  }[] | undefined;
695
707
  nickname?: string | undefined;
696
708
  creator_notes_multilingual?: Record<string, string> | undefined;
697
709
  source?: string[] | undefined;
698
- creation_date?: number | undefined;
699
- modification_date?: number | undefined;
710
+ creation_date?: unknown;
711
+ modification_date?: unknown;
700
712
  }>;
701
713
  }, "strip", z.ZodTypeAny, {
702
714
  data: {
@@ -732,7 +744,8 @@ declare const CCv3DataSchema: z.ZodObject<{
732
744
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
733
745
  z.ZodEnum<[
734
746
  "before_char",
735
- "after_char"
747
+ "after_char",
748
+ "in_chat"
736
749
  ]>,
737
750
  z.ZodNumber,
738
751
  z.ZodLiteral<"">
@@ -811,7 +824,8 @@ declare const CCv3DataSchema: z.ZodObject<{
811
824
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
812
825
  z.ZodEnum<[
813
826
  "before_char",
814
- "after_char"
827
+ "after_char",
828
+ "in_chat"
815
829
  ]>,
816
830
  z.ZodNumber,
817
831
  z.ZodLiteral<"">
@@ -841,8 +855,8 @@ declare const CCv3DataSchema: z.ZodObject<{
841
855
  }, z.ZodTypeAny, "passthrough">[];
842
856
  name?: string | undefined;
843
857
  description?: string | undefined;
844
- scan_depth?: number | undefined;
845
- token_budget?: number | undefined;
858
+ scan_depth?: unknown;
859
+ token_budget?: unknown;
846
860
  recursive_scanning?: boolean | undefined;
847
861
  extensions?: Record<string, unknown> | undefined;
848
862
  } | null | undefined;
@@ -852,15 +866,15 @@ declare const CCv3DataSchema: z.ZodObject<{
852
866
  group_only_greetings?: string[] | undefined;
853
867
  assets?: {
854
868
  name: string;
855
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
856
869
  uri: string;
857
870
  ext: string;
871
+ type?: unknown;
858
872
  }[] | undefined;
859
873
  nickname?: string | undefined;
860
874
  creator_notes_multilingual?: Record<string, string> | undefined;
861
875
  source?: string[] | undefined;
862
- creation_date?: number | undefined;
863
- modification_date?: number | undefined;
876
+ creation_date?: unknown;
877
+ modification_date?: unknown;
864
878
  };
865
879
  spec: "chara_card_v3";
866
880
  spec_version: "3.0";
@@ -909,8 +923,8 @@ declare const CCv2DataSchema: z.ZodObject<{
909
923
  character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
910
924
  name: z.ZodOptional<z.ZodString>;
911
925
  description: z.ZodOptional<z.ZodString>;
912
- scan_depth: z.ZodOptional<z.ZodNumber>;
913
- 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>;
914
928
  recursive_scanning: z.ZodOptional<z.ZodBoolean>;
915
929
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
916
930
  entries: z.ZodArray<z.ZodObject<{
@@ -930,7 +944,8 @@ declare const CCv2DataSchema: z.ZodObject<{
930
944
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
931
945
  z.ZodEnum<[
932
946
  "before_char",
933
- "after_char"
947
+ "after_char",
948
+ "in_chat"
934
949
  ]>,
935
950
  z.ZodNumber,
936
951
  z.ZodLiteral<"">
@@ -952,7 +967,8 @@ declare const CCv2DataSchema: z.ZodObject<{
952
967
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
953
968
  z.ZodEnum<[
954
969
  "before_char",
955
- "after_char"
970
+ "after_char",
971
+ "in_chat"
956
972
  ]>,
957
973
  z.ZodNumber,
958
974
  z.ZodLiteral<"">
@@ -974,7 +990,8 @@ declare const CCv2DataSchema: z.ZodObject<{
974
990
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
975
991
  z.ZodEnum<[
976
992
  "before_char",
977
- "after_char"
993
+ "after_char",
994
+ "in_chat"
978
995
  ]>,
979
996
  z.ZodNumber,
980
997
  z.ZodLiteral<"">
@@ -998,7 +1015,8 @@ declare const CCv2DataSchema: z.ZodObject<{
998
1015
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
999
1016
  z.ZodEnum<[
1000
1017
  "before_char",
1001
- "after_char"
1018
+ "after_char",
1019
+ "in_chat"
1002
1020
  ]>,
1003
1021
  z.ZodNumber,
1004
1022
  z.ZodLiteral<"">
@@ -1028,7 +1046,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1028
1046
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
1029
1047
  z.ZodEnum<[
1030
1048
  "before_char",
1031
- "after_char"
1049
+ "after_char",
1050
+ "in_chat"
1032
1051
  ]>,
1033
1052
  z.ZodNumber,
1034
1053
  z.ZodLiteral<"">
@@ -1036,8 +1055,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1036
1055
  }, z.ZodTypeAny, "passthrough">[];
1037
1056
  name?: string | undefined;
1038
1057
  description?: string | undefined;
1039
- scan_depth?: number | undefined;
1040
- token_budget?: number | undefined;
1058
+ scan_depth?: unknown;
1059
+ token_budget?: unknown;
1041
1060
  recursive_scanning?: boolean | undefined;
1042
1061
  extensions?: Record<string, unknown> | undefined;
1043
1062
  }>>>;
@@ -1075,7 +1094,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1075
1094
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
1076
1095
  z.ZodEnum<[
1077
1096
  "before_char",
1078
- "after_char"
1097
+ "after_char",
1098
+ "in_chat"
1079
1099
  ]>,
1080
1100
  z.ZodNumber,
1081
1101
  z.ZodLiteral<"">
@@ -1121,7 +1141,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1121
1141
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
1122
1142
  z.ZodEnum<[
1123
1143
  "before_char",
1124
- "after_char"
1144
+ "after_char",
1145
+ "in_chat"
1125
1146
  ]>,
1126
1147
  z.ZodNumber,
1127
1148
  z.ZodLiteral<"">
@@ -1129,8 +1150,8 @@ declare const CCv2DataSchema: z.ZodObject<{
1129
1150
  }, z.ZodTypeAny, "passthrough">[];
1130
1151
  name?: string | undefined;
1131
1152
  description?: string | undefined;
1132
- scan_depth?: number | undefined;
1133
- token_budget?: number | undefined;
1153
+ scan_depth?: unknown;
1154
+ token_budget?: unknown;
1134
1155
  recursive_scanning?: boolean | undefined;
1135
1156
  extensions?: Record<string, unknown> | undefined;
1136
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(),
@@ -596,13 +651,13 @@ var CCv2LorebookEntrySchema = z2.object({
596
651
  selective: z2.boolean().nullable().optional(),
597
652
  secondary_keys: z2.array(z2.string()).nullable().optional(),
598
653
  constant: z2.boolean().nullable().optional(),
599
- position: z2.union([z2.enum(["before_char", "after_char"]), z2.number().int(), z2.literal("")]).nullable().optional()
654
+ position: z2.union([z2.enum(["before_char", "after_char", "in_chat"]), z2.number().int(), z2.literal("")]).nullable().optional()
600
655
  }).passthrough();
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)
@@ -660,7 +715,7 @@ var CCv3LorebookEntrySchema = z3.object({
660
715
  selective: z3.boolean().nullable().optional(),
661
716
  secondary_keys: z3.array(z3.string()).nullable().optional(),
662
717
  constant: z3.boolean().nullable().optional(),
663
- position: z3.union([z3.enum(["before_char", "after_char"]), z3.number().int(), z3.literal("")]).nullable().optional(),
718
+ position: z3.union([z3.enum(["before_char", "after_char", "in_chat"]), z3.number().int(), z3.literal("")]).nullable().optional(),
664
719
  extensions: z3.record(z3.unknown()).optional(),
665
720
  // v3 specific - also lenient with types since SillyTavern uses numbers for enums
666
721
  automation_id: z3.string().optional(),
@@ -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);