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

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 +15 -36
  2. package/dist/charx.cjs.map +1 -1
  3. package/dist/charx.d.cts +18 -9
  4. package/dist/charx.d.ts +18 -9
  5. package/dist/charx.js +15 -36
  6. package/dist/charx.js.map +1 -1
  7. package/dist/exporter.cjs +34 -38
  8. package/dist/exporter.cjs.map +1 -1
  9. package/dist/exporter.d.cts +18 -9
  10. package/dist/exporter.d.ts +18 -9
  11. package/dist/exporter.js +34 -38
  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 +53 -9
  16. package/dist/federation.d.ts +53 -9
  17. package/dist/federation.js +104 -36
  18. package/dist/federation.js.map +1 -1
  19. package/dist/index.cjs +34 -38
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +42 -21
  22. package/dist/index.d.ts +42 -21
  23. package/dist/index.js +34 -38
  24. package/dist/index.js.map +1 -1
  25. package/dist/loader.cjs +101 -15
  26. package/dist/loader.cjs.map +1 -1
  27. package/dist/loader.d.cts +42 -14
  28. package/dist/loader.d.ts +42 -14
  29. package/dist/loader.js +101 -15
  30. package/dist/loader.js.map +1 -1
  31. package/dist/lorebook.d.cts +34 -17
  32. package/dist/lorebook.d.ts +34 -17
  33. package/dist/normalizer.cjs +2 -2
  34. package/dist/normalizer.cjs.map +1 -1
  35. package/dist/normalizer.d.cts +60 -30
  36. package/dist/normalizer.d.ts +60 -30
  37. package/dist/normalizer.js +2 -2
  38. package/dist/normalizer.js.map +1 -1
  39. package/dist/png.cjs +2 -2
  40. package/dist/png.cjs.map +1 -1
  41. package/dist/png.d.cts +32 -16
  42. package/dist/png.d.ts +32 -16
  43. package/dist/png.js +2 -2
  44. package/dist/png.js.map +1 -1
  45. package/dist/schemas.cjs +7 -7
  46. package/dist/schemas.cjs.map +1 -1
  47. package/dist/schemas.d.cts +96 -48
  48. package/dist/schemas.d.ts +96 -48
  49. package/dist/schemas.js +7 -7
  50. package/dist/schemas.js.map +1 -1
  51. package/dist/voxta.cjs +21 -4
  52. package/dist/voxta.cjs.map +1 -1
  53. package/dist/voxta.d.cts +28 -14
  54. package/dist/voxta.d.ts +28 -14
  55. package/dist/voxta.js +21 -4
  56. package/dist/voxta.js.map +1 -1
  57. package/package.json +6 -6
package/dist/index.d.cts CHANGED
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
package/dist/index.d.ts CHANGED
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
@@ -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<"">
package/dist/index.js CHANGED
@@ -596,7 +596,7 @@ var CCv2LorebookEntrySchema = z2.object({
596
596
  selective: z2.boolean().nullable().optional(),
597
597
  secondary_keys: z2.array(z2.string()).nullable().optional(),
598
598
  constant: z2.boolean().nullable().optional(),
599
- position: z2.union([z2.enum(["before_char", "after_char"]), z2.number().int(), z2.literal("")]).nullable().optional()
599
+ position: z2.union([z2.enum(["before_char", "after_char", "in_chat"]), z2.number().int(), z2.literal("")]).nullable().optional()
600
600
  }).passthrough();
601
601
  var CCv2CharacterBookSchema = z2.object({
602
602
  name: z2.string().optional(),
@@ -660,7 +660,7 @@ var CCv3LorebookEntrySchema = z3.object({
660
660
  selective: z3.boolean().nullable().optional(),
661
661
  secondary_keys: z3.array(z3.string()).nullable().optional(),
662
662
  constant: z3.boolean().nullable().optional(),
663
- position: z3.union([z3.enum(["before_char", "after_char"]), z3.number().int(), z3.literal("")]).nullable().optional(),
663
+ position: z3.union([z3.enum(["before_char", "after_char", "in_chat"]), z3.number().int(), z3.literal("")]).nullable().optional(),
664
664
  extensions: z3.record(z3.unknown()).optional(),
665
665
  // v3 specific - also lenient with types since SillyTavern uses numbers for enums
666
666
  automation_id: z3.string().optional(),
@@ -1339,36 +1339,6 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
1339
1339
  "data",
1340
1340
  "unknown"
1341
1341
  ]);
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
1342
  function getCharxCategory(mimetype) {
1373
1343
  if (mimetype.startsWith("image/")) return "images";
1374
1344
  if (mimetype.startsWith("audio/")) return "audio";
@@ -1384,11 +1354,20 @@ function sanitizeAssetType(type) {
1384
1354
  return sanitized || "custom";
1385
1355
  }
1386
1356
  function sanitizeExtension(ext) {
1387
- const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
1388
- if (SAFE_EXTENSIONS.has(normalized)) {
1389
- return normalized;
1357
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
1358
+ if (!normalized) {
1359
+ throw new Error("Invalid asset extension: empty extension");
1360
+ }
1361
+ if (normalized.length > 64) {
1362
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
1363
+ }
1364
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
1365
+ throw new Error("Invalid asset extension: path separators are not allowed");
1366
+ }
1367
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
1368
+ throw new Error(`Invalid asset extension: "${ext}"`);
1390
1369
  }
1391
- return "bin";
1370
+ return normalized;
1392
1371
  }
1393
1372
  function sanitizeName(name, ext) {
1394
1373
  let safeName = name;
@@ -8170,6 +8149,22 @@ function sanitizeName2(name, ext) {
8170
8149
  if (!safeName) safeName = "asset";
8171
8150
  return safeName;
8172
8151
  }
8152
+ function sanitizeExtension2(ext) {
8153
+ const normalized = ext.trim().replace(/^\./, "").toLowerCase();
8154
+ if (!normalized) {
8155
+ throw new Error("Invalid asset extension: empty extension");
8156
+ }
8157
+ if (normalized.length > 64) {
8158
+ throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
8159
+ }
8160
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
8161
+ throw new Error("Invalid asset extension: path separators are not allowed");
8162
+ }
8163
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
8164
+ throw new Error(`Invalid asset extension: "${ext}"`);
8165
+ }
8166
+ return normalized;
8167
+ }
8173
8168
  function writeVoxta(card, assets, options = {}) {
8174
8169
  const { compressionLevel = 6, includePackageJson = false } = options;
8175
8170
  const cardData = card.data;
@@ -8258,8 +8253,9 @@ function writeVoxta(card, assets, options = {}) {
8258
8253
  let assetCount = 0;
8259
8254
  let mainThumbnail;
8260
8255
  for (const asset of assets) {
8261
- const safeName = sanitizeName2(asset.name, asset.ext);
8262
- const finalFilename = `${safeName}.${asset.ext}`;
8256
+ const safeExt = sanitizeExtension2(asset.ext);
8257
+ const safeName = sanitizeName2(asset.name, safeExt);
8258
+ const finalFilename = `${safeName}.${safeExt}`;
8263
8259
  let voxtaPath = "";
8264
8260
  const tags = asset.tags || [];
8265
8261
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);