@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
@@ -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.ZodOptional<z.ZodNumber>;
35
- token_budget: z.ZodOptional<z.ZodNumber>;
34
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
35
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
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<{
@@ -51,7 +51,8 @@ declare const CCv3DataSchema: z.ZodObject<{
51
51
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
52
52
  z.ZodEnum<[
53
53
  "before_char",
54
- "after_char"
54
+ "after_char",
55
+ "in_chat"
55
56
  ]>,
56
57
  z.ZodNumber,
57
58
  z.ZodLiteral<"">
@@ -94,7 +95,8 @@ declare const CCv3DataSchema: z.ZodObject<{
94
95
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
95
96
  z.ZodEnum<[
96
97
  "before_char",
97
- "after_char"
98
+ "after_char",
99
+ "in_chat"
98
100
  ]>,
99
101
  z.ZodNumber,
100
102
  z.ZodLiteral<"">
@@ -137,7 +139,8 @@ declare const CCv3DataSchema: z.ZodObject<{
137
139
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
138
140
  z.ZodEnum<[
139
141
  "before_char",
140
- "after_char"
142
+ "after_char",
143
+ "in_chat"
141
144
  ]>,
142
145
  z.ZodNumber,
143
146
  z.ZodLiteral<"">
@@ -182,7 +185,8 @@ declare const CCv3DataSchema: z.ZodObject<{
182
185
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
183
186
  z.ZodEnum<[
184
187
  "before_char",
185
- "after_char"
188
+ "after_char",
189
+ "in_chat"
186
190
  ]>,
187
191
  z.ZodNumber,
188
192
  z.ZodLiteral<"">
@@ -233,7 +237,8 @@ declare const CCv3DataSchema: z.ZodObject<{
233
237
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
234
238
  z.ZodEnum<[
235
239
  "before_char",
236
- "after_char"
240
+ "after_char",
241
+ "in_chat"
237
242
  ]>,
238
243
  z.ZodNumber,
239
244
  z.ZodLiteral<"">
@@ -263,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
263
268
  }, z.ZodTypeAny, "passthrough">[];
264
269
  name?: string | undefined;
265
270
  description?: string | undefined;
266
- scan_depth?: number | undefined;
267
- token_budget?: number | undefined;
271
+ scan_depth?: unknown;
272
+ token_budget?: unknown;
268
273
  recursive_scanning?: boolean | undefined;
269
274
  extensions?: Record<string, unknown> | undefined;
270
275
  }>>>;
271
276
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
272
277
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
273
- type: z.ZodEnum<[
278
+ type: z.ZodEffects<z.ZodEnum<[
274
279
  "icon",
275
280
  "background",
276
281
  "emotion",
@@ -279,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
279
284
  "video",
280
285
  "custom",
281
286
  "x-risu-asset"
282
- ]>;
287
+ ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
283
288
  uri: z.ZodString;
284
289
  name: z.ZodString;
285
290
  ext: z.ZodString;
@@ -290,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
290
295
  ext: string;
291
296
  }, {
292
297
  name: string;
293
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
294
298
  uri: string;
295
299
  ext: string;
300
+ type?: unknown;
296
301
  }>, "many">>;
297
302
  nickname: z.ZodOptional<z.ZodString>;
298
303
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
299
304
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
300
- creation_date: z.ZodOptional<z.ZodNumber>;
301
- modification_date: z.ZodOptional<z.ZodNumber>;
305
+ creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
306
+ modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
302
307
  }, "strip", z.ZodTypeAny, {
303
308
  name: string;
304
309
  description: string;
@@ -332,7 +337,8 @@ declare const CCv3DataSchema: z.ZodObject<{
332
337
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
333
338
  z.ZodEnum<[
334
339
  "before_char",
335
- "after_char"
340
+ "after_char",
341
+ "in_chat"
336
342
  ]>,
337
343
  z.ZodNumber,
338
344
  z.ZodLiteral<"">
@@ -407,7 +413,8 @@ declare const CCv3DataSchema: z.ZodObject<{
407
413
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
408
414
  z.ZodEnum<[
409
415
  "before_char",
410
- "after_char"
416
+ "after_char",
417
+ "in_chat"
411
418
  ]>,
412
419
  z.ZodNumber,
413
420
  z.ZodLiteral<"">
@@ -437,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
437
444
  }, z.ZodTypeAny, "passthrough">[];
438
445
  name?: string | undefined;
439
446
  description?: string | undefined;
440
- scan_depth?: number | undefined;
441
- token_budget?: number | undefined;
447
+ scan_depth?: unknown;
448
+ token_budget?: unknown;
442
449
  recursive_scanning?: boolean | undefined;
443
450
  extensions?: Record<string, unknown> | undefined;
444
451
  } | null | undefined;
@@ -448,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
448
455
  group_only_greetings?: string[] | undefined;
449
456
  assets?: {
450
457
  name: string;
451
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
452
458
  uri: string;
453
459
  ext: string;
460
+ type?: unknown;
454
461
  }[] | undefined;
455
462
  nickname?: string | undefined;
456
463
  creator_notes_multilingual?: Record<string, string> | undefined;
457
464
  source?: string[] | undefined;
458
- creation_date?: number | undefined;
459
- modification_date?: number | undefined;
465
+ creation_date?: unknown;
466
+ modification_date?: unknown;
460
467
  }>;
461
468
  }, "strip", z.ZodTypeAny, {
462
469
  data: {
@@ -492,7 +499,8 @@ declare const CCv3DataSchema: z.ZodObject<{
492
499
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
493
500
  z.ZodEnum<[
494
501
  "before_char",
495
- "after_char"
502
+ "after_char",
503
+ "in_chat"
496
504
  ]>,
497
505
  z.ZodNumber,
498
506
  z.ZodLiteral<"">
@@ -571,7 +579,8 @@ declare const CCv3DataSchema: z.ZodObject<{
571
579
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
572
580
  z.ZodEnum<[
573
581
  "before_char",
574
- "after_char"
582
+ "after_char",
583
+ "in_chat"
575
584
  ]>,
576
585
  z.ZodNumber,
577
586
  z.ZodLiteral<"">
@@ -601,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
601
610
  }, z.ZodTypeAny, "passthrough">[];
602
611
  name?: string | undefined;
603
612
  description?: string | undefined;
604
- scan_depth?: number | undefined;
605
- token_budget?: number | undefined;
613
+ scan_depth?: unknown;
614
+ token_budget?: unknown;
606
615
  recursive_scanning?: boolean | undefined;
607
616
  extensions?: Record<string, unknown> | undefined;
608
617
  } | null | undefined;
@@ -612,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
612
621
  group_only_greetings?: string[] | undefined;
613
622
  assets?: {
614
623
  name: string;
615
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
616
624
  uri: string;
617
625
  ext: string;
626
+ type?: unknown;
618
627
  }[] | undefined;
619
628
  nickname?: string | undefined;
620
629
  creator_notes_multilingual?: Record<string, string> | undefined;
621
630
  source?: string[] | undefined;
622
- creation_date?: number | undefined;
623
- modification_date?: number | undefined;
631
+ creation_date?: unknown;
632
+ modification_date?: unknown;
624
633
  };
625
634
  spec: "chara_card_v3";
626
635
  spec_version: "3.0";
@@ -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.ZodOptional<z.ZodNumber>;
35
- token_budget: z.ZodOptional<z.ZodNumber>;
34
+ scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
35
+ token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
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<{
@@ -51,7 +51,8 @@ declare const CCv3DataSchema: z.ZodObject<{
51
51
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
52
52
  z.ZodEnum<[
53
53
  "before_char",
54
- "after_char"
54
+ "after_char",
55
+ "in_chat"
55
56
  ]>,
56
57
  z.ZodNumber,
57
58
  z.ZodLiteral<"">
@@ -94,7 +95,8 @@ declare const CCv3DataSchema: z.ZodObject<{
94
95
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
95
96
  z.ZodEnum<[
96
97
  "before_char",
97
- "after_char"
98
+ "after_char",
99
+ "in_chat"
98
100
  ]>,
99
101
  z.ZodNumber,
100
102
  z.ZodLiteral<"">
@@ -137,7 +139,8 @@ declare const CCv3DataSchema: z.ZodObject<{
137
139
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
138
140
  z.ZodEnum<[
139
141
  "before_char",
140
- "after_char"
142
+ "after_char",
143
+ "in_chat"
141
144
  ]>,
142
145
  z.ZodNumber,
143
146
  z.ZodLiteral<"">
@@ -182,7 +185,8 @@ declare const CCv3DataSchema: z.ZodObject<{
182
185
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
183
186
  z.ZodEnum<[
184
187
  "before_char",
185
- "after_char"
188
+ "after_char",
189
+ "in_chat"
186
190
  ]>,
187
191
  z.ZodNumber,
188
192
  z.ZodLiteral<"">
@@ -233,7 +237,8 @@ declare const CCv3DataSchema: z.ZodObject<{
233
237
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
234
238
  z.ZodEnum<[
235
239
  "before_char",
236
- "after_char"
240
+ "after_char",
241
+ "in_chat"
237
242
  ]>,
238
243
  z.ZodNumber,
239
244
  z.ZodLiteral<"">
@@ -263,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
263
268
  }, z.ZodTypeAny, "passthrough">[];
264
269
  name?: string | undefined;
265
270
  description?: string | undefined;
266
- scan_depth?: number | undefined;
267
- token_budget?: number | undefined;
271
+ scan_depth?: unknown;
272
+ token_budget?: unknown;
268
273
  recursive_scanning?: boolean | undefined;
269
274
  extensions?: Record<string, unknown> | undefined;
270
275
  }>>>;
271
276
  extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
272
277
  assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
273
- type: z.ZodEnum<[
278
+ type: z.ZodEffects<z.ZodEnum<[
274
279
  "icon",
275
280
  "background",
276
281
  "emotion",
@@ -279,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
279
284
  "video",
280
285
  "custom",
281
286
  "x-risu-asset"
282
- ]>;
287
+ ]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
283
288
  uri: z.ZodString;
284
289
  name: z.ZodString;
285
290
  ext: z.ZodString;
@@ -290,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
290
295
  ext: string;
291
296
  }, {
292
297
  name: string;
293
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
294
298
  uri: string;
295
299
  ext: string;
300
+ type?: unknown;
296
301
  }>, "many">>;
297
302
  nickname: z.ZodOptional<z.ZodString>;
298
303
  creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
299
304
  source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
300
- creation_date: z.ZodOptional<z.ZodNumber>;
301
- modification_date: z.ZodOptional<z.ZodNumber>;
305
+ creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
306
+ modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
302
307
  }, "strip", z.ZodTypeAny, {
303
308
  name: string;
304
309
  description: string;
@@ -332,7 +337,8 @@ declare const CCv3DataSchema: z.ZodObject<{
332
337
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
333
338
  z.ZodEnum<[
334
339
  "before_char",
335
- "after_char"
340
+ "after_char",
341
+ "in_chat"
336
342
  ]>,
337
343
  z.ZodNumber,
338
344
  z.ZodLiteral<"">
@@ -407,7 +413,8 @@ declare const CCv3DataSchema: z.ZodObject<{
407
413
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
408
414
  z.ZodEnum<[
409
415
  "before_char",
410
- "after_char"
416
+ "after_char",
417
+ "in_chat"
411
418
  ]>,
412
419
  z.ZodNumber,
413
420
  z.ZodLiteral<"">
@@ -437,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
437
444
  }, z.ZodTypeAny, "passthrough">[];
438
445
  name?: string | undefined;
439
446
  description?: string | undefined;
440
- scan_depth?: number | undefined;
441
- token_budget?: number | undefined;
447
+ scan_depth?: unknown;
448
+ token_budget?: unknown;
442
449
  recursive_scanning?: boolean | undefined;
443
450
  extensions?: Record<string, unknown> | undefined;
444
451
  } | null | undefined;
@@ -448,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
448
455
  group_only_greetings?: string[] | undefined;
449
456
  assets?: {
450
457
  name: string;
451
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
452
458
  uri: string;
453
459
  ext: string;
460
+ type?: unknown;
454
461
  }[] | undefined;
455
462
  nickname?: string | undefined;
456
463
  creator_notes_multilingual?: Record<string, string> | undefined;
457
464
  source?: string[] | undefined;
458
- creation_date?: number | undefined;
459
- modification_date?: number | undefined;
465
+ creation_date?: unknown;
466
+ modification_date?: unknown;
460
467
  }>;
461
468
  }, "strip", z.ZodTypeAny, {
462
469
  data: {
@@ -492,7 +499,8 @@ declare const CCv3DataSchema: z.ZodObject<{
492
499
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
493
500
  z.ZodEnum<[
494
501
  "before_char",
495
- "after_char"
502
+ "after_char",
503
+ "in_chat"
496
504
  ]>,
497
505
  z.ZodNumber,
498
506
  z.ZodLiteral<"">
@@ -571,7 +579,8 @@ declare const CCv3DataSchema: z.ZodObject<{
571
579
  position: z.ZodOptional<z.ZodNullable<z.ZodUnion<[
572
580
  z.ZodEnum<[
573
581
  "before_char",
574
- "after_char"
582
+ "after_char",
583
+ "in_chat"
575
584
  ]>,
576
585
  z.ZodNumber,
577
586
  z.ZodLiteral<"">
@@ -601,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
601
610
  }, z.ZodTypeAny, "passthrough">[];
602
611
  name?: string | undefined;
603
612
  description?: string | undefined;
604
- scan_depth?: number | undefined;
605
- token_budget?: number | undefined;
613
+ scan_depth?: unknown;
614
+ token_budget?: unknown;
606
615
  recursive_scanning?: boolean | undefined;
607
616
  extensions?: Record<string, unknown> | undefined;
608
617
  } | null | undefined;
@@ -612,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
612
621
  group_only_greetings?: string[] | undefined;
613
622
  assets?: {
614
623
  name: string;
615
- type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
616
624
  uri: string;
617
625
  ext: string;
626
+ type?: unknown;
618
627
  }[] | undefined;
619
628
  nickname?: string | undefined;
620
629
  creator_notes_multilingual?: Record<string, string> | undefined;
621
630
  source?: string[] | undefined;
622
- creation_date?: number | undefined;
623
- modification_date?: number | undefined;
631
+ creation_date?: unknown;
632
+ modification_date?: unknown;
624
633
  };
625
634
  spec: "chara_card_v3";
626
635
  spec_version: "3.0";
package/dist/exporter.js CHANGED
@@ -184,6 +184,58 @@ import { z } from "zod";
184
184
  import { z as z2 } from "zod";
185
185
  import { z as z3 } from "zod";
186
186
  import "zod";
187
+ function preprocessTimestamp(val) {
188
+ if (val === null || val === void 0) return void 0;
189
+ let num;
190
+ if (typeof val === "number") {
191
+ num = val;
192
+ } else if (typeof val === "string") {
193
+ const trimmed = val.trim();
194
+ if (!trimmed) return void 0;
195
+ const parsed = Number(trimmed);
196
+ if (!isNaN(parsed)) {
197
+ num = parsed;
198
+ } else {
199
+ const date = new Date(trimmed);
200
+ if (isNaN(date.getTime())) return void 0;
201
+ num = Math.floor(date.getTime() / 1e3);
202
+ }
203
+ } else {
204
+ return void 0;
205
+ }
206
+ if (num > 1e10) {
207
+ num = Math.floor(num / 1e3);
208
+ }
209
+ if (num < 0) return void 0;
210
+ return num;
211
+ }
212
+ function preprocessNumeric(val) {
213
+ if (val === null || val === void 0) return void 0;
214
+ if (typeof val === "number") {
215
+ return isNaN(val) ? void 0 : val;
216
+ }
217
+ if (typeof val === "string") {
218
+ const trimmed = val.trim();
219
+ if (!trimmed) return void 0;
220
+ const parsed = Number(trimmed);
221
+ return isNaN(parsed) ? void 0 : parsed;
222
+ }
223
+ return void 0;
224
+ }
225
+ var KNOWN_ASSET_TYPES = /* @__PURE__ */ new Set([
226
+ "icon",
227
+ "background",
228
+ "emotion",
229
+ "user_icon",
230
+ "sound",
231
+ "video",
232
+ "custom",
233
+ "x-risu-asset"
234
+ ]);
235
+ function preprocessAssetType(val) {
236
+ if (typeof val !== "string") return "custom";
237
+ return KNOWN_ASSET_TYPES.has(val) ? val : "custom";
238
+ }
187
239
  var ISO8601Schema = z.string().datetime();
188
240
  var UUIDSchema = z.string().uuid();
189
241
  var SpecSchema = z.enum(["v2", "v3"]);
@@ -206,16 +258,19 @@ var SourceFormatSchema = z.enum([
206
258
  // VoxPkg format
207
259
  ]);
208
260
  var OriginalShapeSchema = z.enum(["wrapped", "unwrapped", "legacy"]);
209
- var AssetTypeSchema = z.enum([
210
- "icon",
211
- "background",
212
- "emotion",
213
- "user_icon",
214
- "sound",
215
- "video",
216
- "custom",
217
- "x-risu-asset"
218
- ]);
261
+ var AssetTypeSchema = z.preprocess(
262
+ preprocessAssetType,
263
+ z.enum([
264
+ "icon",
265
+ "background",
266
+ "emotion",
267
+ "user_icon",
268
+ "sound",
269
+ "video",
270
+ "custom",
271
+ "x-risu-asset"
272
+ ])
273
+ );
219
274
  var AssetDescriptorSchema = z.object({
220
275
  type: AssetTypeSchema,
221
276
  uri: z.string(),
@@ -244,13 +299,13 @@ var CCv2LorebookEntrySchema = z2.object({
244
299
  selective: z2.boolean().nullable().optional(),
245
300
  secondary_keys: z2.array(z2.string()).nullable().optional(),
246
301
  constant: z2.boolean().nullable().optional(),
247
- position: z2.union([z2.enum(["before_char", "after_char"]), z2.number().int(), z2.literal("")]).nullable().optional()
302
+ position: z2.union([z2.enum(["before_char", "after_char", "in_chat"]), z2.number().int(), z2.literal("")]).nullable().optional()
248
303
  }).passthrough();
249
304
  var CCv2CharacterBookSchema = z2.object({
250
305
  name: z2.string().optional(),
251
306
  description: z2.string().optional(),
252
- scan_depth: z2.number().int().nonnegative().optional(),
253
- token_budget: z2.number().int().nonnegative().optional(),
307
+ scan_depth: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
308
+ token_budget: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
254
309
  recursive_scanning: z2.boolean().optional(),
255
310
  extensions: z2.record(z2.unknown()).optional(),
256
311
  entries: z2.array(CCv2LorebookEntrySchema)
@@ -297,7 +352,7 @@ var CCv3LorebookEntrySchema = z3.object({
297
352
  selective: z3.boolean().nullable().optional(),
298
353
  secondary_keys: z3.array(z3.string()).nullable().optional(),
299
354
  constant: z3.boolean().nullable().optional(),
300
- position: z3.union([z3.enum(["before_char", "after_char"]), z3.number().int(), z3.literal("")]).nullable().optional(),
355
+ position: z3.union([z3.enum(["before_char", "after_char", "in_chat"]), z3.number().int(), z3.literal("")]).nullable().optional(),
301
356
  extensions: z3.record(z3.unknown()).optional(),
302
357
  // v3 specific - also lenient with types since SillyTavern uses numbers for enums
303
358
  automation_id: z3.string().optional(),
@@ -313,8 +368,8 @@ var CCv3LorebookEntrySchema = z3.object({
313
368
  var CCv3CharacterBookSchema = z3.object({
314
369
  name: z3.string().optional(),
315
370
  description: z3.string().optional(),
316
- scan_depth: z3.number().int().nonnegative().optional(),
317
- token_budget: z3.number().int().nonnegative().optional(),
371
+ scan_depth: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
372
+ token_budget: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
318
373
  recursive_scanning: z3.boolean().optional(),
319
374
  extensions: z3.record(z3.unknown()).optional(),
320
375
  entries: z3.array(CCv3LorebookEntrySchema)
@@ -346,10 +401,9 @@ var CCv3DataInnerSchema = z3.object({
346
401
  nickname: z3.string().optional(),
347
402
  creator_notes_multilingual: z3.record(z3.string()).optional(),
348
403
  source: z3.array(z3.string()).optional(),
349
- creation_date: z3.number().int().nonnegative().optional(),
350
- // Unix timestamp in seconds
351
- modification_date: z3.number().int().nonnegative().optional()
352
- // Unix timestamp in seconds
404
+ // Unix timestamps - preprocess to handle ISO strings, numeric strings, milliseconds
405
+ creation_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional()),
406
+ modification_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional())
353
407
  });
354
408
  var CCv3DataSchema = z3.object({
355
409
  spec: z3.literal("chara_card_v3"),
@@ -514,36 +568,6 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
514
568
  "data",
515
569
  "unknown"
516
570
  ]);
517
- var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
518
- // Images
519
- "png",
520
- "jpg",
521
- "jpeg",
522
- "webp",
523
- "gif",
524
- "avif",
525
- "svg",
526
- "bmp",
527
- "ico",
528
- // Audio
529
- "mp3",
530
- "wav",
531
- "ogg",
532
- "flac",
533
- "m4a",
534
- "aac",
535
- "opus",
536
- // Video
537
- "mp4",
538
- "webm",
539
- "avi",
540
- "mov",
541
- "mkv",
542
- // Data
543
- "json",
544
- "txt",
545
- "bin"
546
- ]);
547
571
  function getCharxCategory(mimetype) {
548
572
  if (mimetype.startsWith("image/")) return "images";
549
573
  if (mimetype.startsWith("audio/")) return "audio";
@@ -559,11 +583,20 @@ function sanitizeAssetType(type) {
559
583
  return sanitized || "custom";
560
584
  }
561
585
  function sanitizeExtension(ext) {
562
- const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
563
- if (SAFE_EXTENSIONS.has(normalized)) {
564
- return normalized;
586
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
587
+ if (!normalized) {
588
+ throw new Error("Invalid asset extension: empty extension");
589
+ }
590
+ if (normalized.length > 64) {
591
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
592
+ }
593
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
594
+ throw new Error("Invalid asset extension: path separators are not allowed");
565
595
  }
566
- return "bin";
596
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
597
+ throw new Error(`Invalid asset extension: "${ext}"`);
598
+ }
599
+ return normalized;
567
600
  }
568
601
  function sanitizeName(name, ext) {
569
602
  let safeName = name;
@@ -7014,6 +7047,22 @@ function sanitizeName2(name, ext) {
7014
7047
  if (!safeName) safeName = "asset";
7015
7048
  return safeName;
7016
7049
  }
7050
+ function sanitizeExtension2(ext) {
7051
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
7052
+ if (!normalized) {
7053
+ throw new Error("Invalid asset extension: empty extension");
7054
+ }
7055
+ if (normalized.length > 64) {
7056
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
7057
+ }
7058
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
7059
+ throw new Error("Invalid asset extension: path separators are not allowed");
7060
+ }
7061
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
7062
+ throw new Error(`Invalid asset extension: "${ext}"`);
7063
+ }
7064
+ return normalized;
7065
+ }
7017
7066
  function writeVoxta(card, assets, options = {}) {
7018
7067
  const { compressionLevel = 6, includePackageJson = false } = options;
7019
7068
  const cardData = card.data;
@@ -7102,8 +7151,9 @@ function writeVoxta(card, assets, options = {}) {
7102
7151
  let assetCount = 0;
7103
7152
  let mainThumbnail;
7104
7153
  for (const asset of assets) {
7105
- const safeName = sanitizeName2(asset.name, asset.ext);
7106
- const finalFilename = `${safeName}.${asset.ext}`;
7154
+ const safeExt = sanitizeExtension2(asset.ext);
7155
+ const safeName = sanitizeName2(asset.name, safeExt);
7156
+ const finalFilename = `${safeName}.${safeExt}`;
7107
7157
  let voxtaPath = "";
7108
7158
  const tags = asset.tags || [];
7109
7159
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);