@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.
- package/dist/app-framework.cjs +12 -3
- package/dist/app-framework.cjs.map +1 -1
- package/dist/app-framework.d.cts +9 -1
- package/dist/app-framework.d.ts +9 -1
- package/dist/app-framework.js +12 -3
- package/dist/app-framework.js.map +1 -1
- package/dist/charx.cjs +85 -52
- package/dist/charx.cjs.map +1 -1
- package/dist/charx.d.cts +22 -22
- package/dist/charx.d.ts +22 -22
- package/dist/charx.js +85 -52
- package/dist/charx.js.map +1 -1
- package/dist/exporter.cjs +104 -54
- package/dist/exporter.cjs.map +1 -1
- package/dist/exporter.d.cts +19 -19
- package/dist/exporter.d.ts +19 -19
- package/dist/exporter.js +104 -54
- package/dist/exporter.js.map +1 -1
- package/dist/federation.cjs +104 -36
- package/dist/federation.cjs.map +1 -1
- package/dist/federation.d.cts +54 -19
- package/dist/federation.d.ts +54 -19
- package/dist/federation.js +104 -36
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +104 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -29
- package/dist/index.d.ts +29 -29
- package/dist/index.js +104 -54
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +171 -31
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.d.cts +37 -23
- package/dist/loader.d.ts +37 -23
- package/dist/loader.js +171 -31
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.d.cts +23 -23
- package/dist/lorebook.d.ts +23 -23
- package/dist/normalizer.cjs +72 -18
- package/dist/normalizer.cjs.map +1 -1
- package/dist/normalizer.d.cts +37 -37
- package/dist/normalizer.d.ts +37 -37
- package/dist/normalizer.js +72 -18
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +72 -18
- package/dist/png.cjs.map +1 -1
- package/dist/png.d.cts +25 -25
- package/dist/png.d.ts +25 -25
- package/dist/png.js +72 -18
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +80 -23
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +85 -67
- package/dist/schemas.d.ts +85 -67
- package/dist/schemas.js +80 -23
- package/dist/schemas.js.map +1 -1
- package/dist/voxta.cjs +91 -20
- package/dist/voxta.cjs.map +1 -1
- package/dist/voxta.d.cts +23 -23
- package/dist/voxta.d.ts +23 -23
- package/dist/voxta.js +91 -20
- package/dist/voxta.js.map +1 -1
- package/package.json +24 -24
package/dist/exporter.d.cts
CHANGED
|
@@ -31,8 +31,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
31
31
|
character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
32
32
|
name: z.ZodOptional<z.ZodString>;
|
|
33
33
|
description: z.ZodOptional<z.ZodString>;
|
|
34
|
-
scan_depth: z.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<{
|
|
@@ -268,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
268
268
|
}, z.ZodTypeAny, "passthrough">[];
|
|
269
269
|
name?: string | undefined;
|
|
270
270
|
description?: string | undefined;
|
|
271
|
-
scan_depth?:
|
|
272
|
-
token_budget?:
|
|
271
|
+
scan_depth?: unknown;
|
|
272
|
+
token_budget?: unknown;
|
|
273
273
|
recursive_scanning?: boolean | undefined;
|
|
274
274
|
extensions?: Record<string, unknown> | undefined;
|
|
275
275
|
}>>>;
|
|
276
276
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
277
277
|
assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
278
|
-
type: z.ZodEnum<[
|
|
278
|
+
type: z.ZodEffects<z.ZodEnum<[
|
|
279
279
|
"icon",
|
|
280
280
|
"background",
|
|
281
281
|
"emotion",
|
|
@@ -284,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
284
284
|
"video",
|
|
285
285
|
"custom",
|
|
286
286
|
"x-risu-asset"
|
|
287
|
-
]>;
|
|
287
|
+
]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
|
|
288
288
|
uri: z.ZodString;
|
|
289
289
|
name: z.ZodString;
|
|
290
290
|
ext: z.ZodString;
|
|
@@ -295,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
295
295
|
ext: string;
|
|
296
296
|
}, {
|
|
297
297
|
name: string;
|
|
298
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
299
298
|
uri: string;
|
|
300
299
|
ext: string;
|
|
300
|
+
type?: unknown;
|
|
301
301
|
}>, "many">>;
|
|
302
302
|
nickname: z.ZodOptional<z.ZodString>;
|
|
303
303
|
creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
304
304
|
source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
305
|
-
creation_date: z.ZodOptional<z.ZodNumber>;
|
|
306
|
-
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>;
|
|
307
307
|
}, "strip", z.ZodTypeAny, {
|
|
308
308
|
name: string;
|
|
309
309
|
description: string;
|
|
@@ -444,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
444
444
|
}, z.ZodTypeAny, "passthrough">[];
|
|
445
445
|
name?: string | undefined;
|
|
446
446
|
description?: string | undefined;
|
|
447
|
-
scan_depth?:
|
|
448
|
-
token_budget?:
|
|
447
|
+
scan_depth?: unknown;
|
|
448
|
+
token_budget?: unknown;
|
|
449
449
|
recursive_scanning?: boolean | undefined;
|
|
450
450
|
extensions?: Record<string, unknown> | undefined;
|
|
451
451
|
} | null | undefined;
|
|
@@ -455,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
455
455
|
group_only_greetings?: string[] | undefined;
|
|
456
456
|
assets?: {
|
|
457
457
|
name: string;
|
|
458
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
459
458
|
uri: string;
|
|
460
459
|
ext: string;
|
|
460
|
+
type?: unknown;
|
|
461
461
|
}[] | undefined;
|
|
462
462
|
nickname?: string | undefined;
|
|
463
463
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
464
464
|
source?: string[] | undefined;
|
|
465
|
-
creation_date?:
|
|
466
|
-
modification_date?:
|
|
465
|
+
creation_date?: unknown;
|
|
466
|
+
modification_date?: unknown;
|
|
467
467
|
}>;
|
|
468
468
|
}, "strip", z.ZodTypeAny, {
|
|
469
469
|
data: {
|
|
@@ -610,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
610
610
|
}, z.ZodTypeAny, "passthrough">[];
|
|
611
611
|
name?: string | undefined;
|
|
612
612
|
description?: string | undefined;
|
|
613
|
-
scan_depth?:
|
|
614
|
-
token_budget?:
|
|
613
|
+
scan_depth?: unknown;
|
|
614
|
+
token_budget?: unknown;
|
|
615
615
|
recursive_scanning?: boolean | undefined;
|
|
616
616
|
extensions?: Record<string, unknown> | undefined;
|
|
617
617
|
} | null | undefined;
|
|
@@ -621,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
621
621
|
group_only_greetings?: string[] | undefined;
|
|
622
622
|
assets?: {
|
|
623
623
|
name: string;
|
|
624
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
625
624
|
uri: string;
|
|
626
625
|
ext: string;
|
|
626
|
+
type?: unknown;
|
|
627
627
|
}[] | undefined;
|
|
628
628
|
nickname?: string | undefined;
|
|
629
629
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
630
630
|
source?: string[] | undefined;
|
|
631
|
-
creation_date?:
|
|
632
|
-
modification_date?:
|
|
631
|
+
creation_date?: unknown;
|
|
632
|
+
modification_date?: unknown;
|
|
633
633
|
};
|
|
634
634
|
spec: "chara_card_v3";
|
|
635
635
|
spec_version: "3.0";
|
package/dist/exporter.d.ts
CHANGED
|
@@ -31,8 +31,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
31
31
|
character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
32
32
|
name: z.ZodOptional<z.ZodString>;
|
|
33
33
|
description: z.ZodOptional<z.ZodString>;
|
|
34
|
-
scan_depth: z.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<{
|
|
@@ -268,14 +268,14 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
268
268
|
}, z.ZodTypeAny, "passthrough">[];
|
|
269
269
|
name?: string | undefined;
|
|
270
270
|
description?: string | undefined;
|
|
271
|
-
scan_depth?:
|
|
272
|
-
token_budget?:
|
|
271
|
+
scan_depth?: unknown;
|
|
272
|
+
token_budget?: unknown;
|
|
273
273
|
recursive_scanning?: boolean | undefined;
|
|
274
274
|
extensions?: Record<string, unknown> | undefined;
|
|
275
275
|
}>>>;
|
|
276
276
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
277
277
|
assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
278
|
-
type: z.ZodEnum<[
|
|
278
|
+
type: z.ZodEffects<z.ZodEnum<[
|
|
279
279
|
"icon",
|
|
280
280
|
"background",
|
|
281
281
|
"emotion",
|
|
@@ -284,7 +284,7 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
284
284
|
"video",
|
|
285
285
|
"custom",
|
|
286
286
|
"x-risu-asset"
|
|
287
|
-
]>;
|
|
287
|
+
]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
|
|
288
288
|
uri: z.ZodString;
|
|
289
289
|
name: z.ZodString;
|
|
290
290
|
ext: z.ZodString;
|
|
@@ -295,15 +295,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
295
295
|
ext: string;
|
|
296
296
|
}, {
|
|
297
297
|
name: string;
|
|
298
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
299
298
|
uri: string;
|
|
300
299
|
ext: string;
|
|
300
|
+
type?: unknown;
|
|
301
301
|
}>, "many">>;
|
|
302
302
|
nickname: z.ZodOptional<z.ZodString>;
|
|
303
303
|
creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
304
304
|
source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
305
|
-
creation_date: z.ZodOptional<z.ZodNumber>;
|
|
306
|
-
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>;
|
|
307
307
|
}, "strip", z.ZodTypeAny, {
|
|
308
308
|
name: string;
|
|
309
309
|
description: string;
|
|
@@ -444,8 +444,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
444
444
|
}, z.ZodTypeAny, "passthrough">[];
|
|
445
445
|
name?: string | undefined;
|
|
446
446
|
description?: string | undefined;
|
|
447
|
-
scan_depth?:
|
|
448
|
-
token_budget?:
|
|
447
|
+
scan_depth?: unknown;
|
|
448
|
+
token_budget?: unknown;
|
|
449
449
|
recursive_scanning?: boolean | undefined;
|
|
450
450
|
extensions?: Record<string, unknown> | undefined;
|
|
451
451
|
} | null | undefined;
|
|
@@ -455,15 +455,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
455
455
|
group_only_greetings?: string[] | undefined;
|
|
456
456
|
assets?: {
|
|
457
457
|
name: string;
|
|
458
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
459
458
|
uri: string;
|
|
460
459
|
ext: string;
|
|
460
|
+
type?: unknown;
|
|
461
461
|
}[] | undefined;
|
|
462
462
|
nickname?: string | undefined;
|
|
463
463
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
464
464
|
source?: string[] | undefined;
|
|
465
|
-
creation_date?:
|
|
466
|
-
modification_date?:
|
|
465
|
+
creation_date?: unknown;
|
|
466
|
+
modification_date?: unknown;
|
|
467
467
|
}>;
|
|
468
468
|
}, "strip", z.ZodTypeAny, {
|
|
469
469
|
data: {
|
|
@@ -610,8 +610,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
610
610
|
}, z.ZodTypeAny, "passthrough">[];
|
|
611
611
|
name?: string | undefined;
|
|
612
612
|
description?: string | undefined;
|
|
613
|
-
scan_depth?:
|
|
614
|
-
token_budget?:
|
|
613
|
+
scan_depth?: unknown;
|
|
614
|
+
token_budget?: unknown;
|
|
615
615
|
recursive_scanning?: boolean | undefined;
|
|
616
616
|
extensions?: Record<string, unknown> | undefined;
|
|
617
617
|
} | null | undefined;
|
|
@@ -621,15 +621,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
621
621
|
group_only_greetings?: string[] | undefined;
|
|
622
622
|
assets?: {
|
|
623
623
|
name: string;
|
|
624
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
625
624
|
uri: string;
|
|
626
625
|
ext: string;
|
|
626
|
+
type?: unknown;
|
|
627
627
|
}[] | undefined;
|
|
628
628
|
nickname?: string | undefined;
|
|
629
629
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
630
630
|
source?: string[] | undefined;
|
|
631
|
-
creation_date?:
|
|
632
|
-
modification_date?:
|
|
631
|
+
creation_date?: unknown;
|
|
632
|
+
modification_date?: unknown;
|
|
633
633
|
};
|
|
634
634
|
spec: "chara_card_v3";
|
|
635
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.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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(),
|
|
@@ -249,8 +304,8 @@ var CCv2LorebookEntrySchema = z2.object({
|
|
|
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)
|
|
@@ -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
|
-
|
|
350
|
-
|
|
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()
|
|
563
|
-
if (
|
|
564
|
-
|
|
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
|
-
|
|
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
|
|
7106
|
-
const
|
|
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);
|