@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.
- package/dist/charx.cjs +87 -54
- package/dist/charx.cjs.map +1 -1
- package/dist/charx.d.cts +40 -31
- package/dist/charx.d.ts +40 -31
- package/dist/charx.js +87 -54
- package/dist/charx.js.map +1 -1
- package/dist/exporter.cjs +106 -56
- package/dist/exporter.cjs.map +1 -1
- package/dist/exporter.d.cts +37 -28
- package/dist/exporter.d.ts +37 -28
- package/dist/exporter.js +106 -56
- 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 +72 -28
- package/dist/federation.d.ts +72 -28
- package/dist/federation.js +104 -36
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +106 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -50
- package/dist/index.d.ts +71 -50
- package/dist/index.js +106 -56
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +173 -33
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.d.cts +65 -37
- package/dist/loader.d.ts +65 -37
- package/dist/loader.js +173 -33
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.d.cts +57 -40
- package/dist/lorebook.d.ts +57 -40
- package/dist/normalizer.cjs +74 -20
- package/dist/normalizer.cjs.map +1 -1
- package/dist/normalizer.d.cts +97 -67
- package/dist/normalizer.d.ts +97 -67
- package/dist/normalizer.js +74 -20
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +74 -20
- package/dist/png.cjs.map +1 -1
- package/dist/png.d.cts +57 -41
- package/dist/png.d.ts +57 -41
- package/dist/png.js +74 -20
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +82 -25
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +181 -115
- package/dist/schemas.d.ts +181 -115
- package/dist/schemas.js +82 -25
- package/dist/schemas.js.map +1 -1
- package/dist/voxta.cjs +93 -22
- package/dist/voxta.cjs.map +1 -1
- package/dist/voxta.d.cts +51 -37
- package/dist/voxta.d.ts +51 -37
- package/dist/voxta.js +93 -22
- package/dist/voxta.js.map +1 -1
- package/package.json +5 -5
package/dist/voxta.cjs
CHANGED
|
@@ -6613,6 +6613,58 @@ var import_zod = require("zod");
|
|
|
6613
6613
|
var import_zod2 = require("zod");
|
|
6614
6614
|
var import_zod3 = require("zod");
|
|
6615
6615
|
var import_zod4 = require("zod");
|
|
6616
|
+
function preprocessTimestamp(val) {
|
|
6617
|
+
if (val === null || val === void 0) return void 0;
|
|
6618
|
+
let num;
|
|
6619
|
+
if (typeof val === "number") {
|
|
6620
|
+
num = val;
|
|
6621
|
+
} else if (typeof val === "string") {
|
|
6622
|
+
const trimmed = val.trim();
|
|
6623
|
+
if (!trimmed) return void 0;
|
|
6624
|
+
const parsed = Number(trimmed);
|
|
6625
|
+
if (!isNaN(parsed)) {
|
|
6626
|
+
num = parsed;
|
|
6627
|
+
} else {
|
|
6628
|
+
const date = new Date(trimmed);
|
|
6629
|
+
if (isNaN(date.getTime())) return void 0;
|
|
6630
|
+
num = Math.floor(date.getTime() / 1e3);
|
|
6631
|
+
}
|
|
6632
|
+
} else {
|
|
6633
|
+
return void 0;
|
|
6634
|
+
}
|
|
6635
|
+
if (num > 1e10) {
|
|
6636
|
+
num = Math.floor(num / 1e3);
|
|
6637
|
+
}
|
|
6638
|
+
if (num < 0) return void 0;
|
|
6639
|
+
return num;
|
|
6640
|
+
}
|
|
6641
|
+
function preprocessNumeric(val) {
|
|
6642
|
+
if (val === null || val === void 0) return void 0;
|
|
6643
|
+
if (typeof val === "number") {
|
|
6644
|
+
return isNaN(val) ? void 0 : val;
|
|
6645
|
+
}
|
|
6646
|
+
if (typeof val === "string") {
|
|
6647
|
+
const trimmed = val.trim();
|
|
6648
|
+
if (!trimmed) return void 0;
|
|
6649
|
+
const parsed = Number(trimmed);
|
|
6650
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
6651
|
+
}
|
|
6652
|
+
return void 0;
|
|
6653
|
+
}
|
|
6654
|
+
var KNOWN_ASSET_TYPES = /* @__PURE__ */ new Set([
|
|
6655
|
+
"icon",
|
|
6656
|
+
"background",
|
|
6657
|
+
"emotion",
|
|
6658
|
+
"user_icon",
|
|
6659
|
+
"sound",
|
|
6660
|
+
"video",
|
|
6661
|
+
"custom",
|
|
6662
|
+
"x-risu-asset"
|
|
6663
|
+
]);
|
|
6664
|
+
function preprocessAssetType(val) {
|
|
6665
|
+
if (typeof val !== "string") return "custom";
|
|
6666
|
+
return KNOWN_ASSET_TYPES.has(val) ? val : "custom";
|
|
6667
|
+
}
|
|
6616
6668
|
var ISO8601Schema = import_zod.z.string().datetime();
|
|
6617
6669
|
var UUIDSchema = import_zod.z.string().uuid();
|
|
6618
6670
|
var SpecSchema = import_zod.z.enum(["v2", "v3"]);
|
|
@@ -6635,16 +6687,19 @@ var SourceFormatSchema = import_zod.z.enum([
|
|
|
6635
6687
|
// VoxPkg format
|
|
6636
6688
|
]);
|
|
6637
6689
|
var OriginalShapeSchema = import_zod.z.enum(["wrapped", "unwrapped", "legacy"]);
|
|
6638
|
-
var AssetTypeSchema = import_zod.z.
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6690
|
+
var AssetTypeSchema = import_zod.z.preprocess(
|
|
6691
|
+
preprocessAssetType,
|
|
6692
|
+
import_zod.z.enum([
|
|
6693
|
+
"icon",
|
|
6694
|
+
"background",
|
|
6695
|
+
"emotion",
|
|
6696
|
+
"user_icon",
|
|
6697
|
+
"sound",
|
|
6698
|
+
"video",
|
|
6699
|
+
"custom",
|
|
6700
|
+
"x-risu-asset"
|
|
6701
|
+
])
|
|
6702
|
+
);
|
|
6648
6703
|
var AssetDescriptorSchema = import_zod.z.object({
|
|
6649
6704
|
type: AssetTypeSchema,
|
|
6650
6705
|
uri: import_zod.z.string(),
|
|
@@ -6673,13 +6728,13 @@ var CCv2LorebookEntrySchema = import_zod2.z.object({
|
|
|
6673
6728
|
selective: import_zod2.z.boolean().nullable().optional(),
|
|
6674
6729
|
secondary_keys: import_zod2.z.array(import_zod2.z.string()).nullable().optional(),
|
|
6675
6730
|
constant: import_zod2.z.boolean().nullable().optional(),
|
|
6676
|
-
position: import_zod2.z.union([import_zod2.z.enum(["before_char", "after_char"]), import_zod2.z.number().int(), import_zod2.z.literal("")]).nullable().optional()
|
|
6731
|
+
position: import_zod2.z.union([import_zod2.z.enum(["before_char", "after_char", "in_chat"]), import_zod2.z.number().int(), import_zod2.z.literal("")]).nullable().optional()
|
|
6677
6732
|
}).passthrough();
|
|
6678
6733
|
var CCv2CharacterBookSchema = import_zod2.z.object({
|
|
6679
6734
|
name: import_zod2.z.string().optional(),
|
|
6680
6735
|
description: import_zod2.z.string().optional(),
|
|
6681
|
-
scan_depth: import_zod2.z.number().int().nonnegative().optional(),
|
|
6682
|
-
token_budget: import_zod2.z.number().int().nonnegative().optional(),
|
|
6736
|
+
scan_depth: import_zod2.z.preprocess(preprocessNumeric, import_zod2.z.number().int().nonnegative().optional()),
|
|
6737
|
+
token_budget: import_zod2.z.preprocess(preprocessNumeric, import_zod2.z.number().int().nonnegative().optional()),
|
|
6683
6738
|
recursive_scanning: import_zod2.z.boolean().optional(),
|
|
6684
6739
|
extensions: import_zod2.z.record(import_zod2.z.unknown()).optional(),
|
|
6685
6740
|
entries: import_zod2.z.array(CCv2LorebookEntrySchema)
|
|
@@ -6726,7 +6781,7 @@ var CCv3LorebookEntrySchema = import_zod3.z.object({
|
|
|
6726
6781
|
selective: import_zod3.z.boolean().nullable().optional(),
|
|
6727
6782
|
secondary_keys: import_zod3.z.array(import_zod3.z.string()).nullable().optional(),
|
|
6728
6783
|
constant: import_zod3.z.boolean().nullable().optional(),
|
|
6729
|
-
position: import_zod3.z.union([import_zod3.z.enum(["before_char", "after_char"]), import_zod3.z.number().int(), import_zod3.z.literal("")]).nullable().optional(),
|
|
6784
|
+
position: import_zod3.z.union([import_zod3.z.enum(["before_char", "after_char", "in_chat"]), import_zod3.z.number().int(), import_zod3.z.literal("")]).nullable().optional(),
|
|
6730
6785
|
extensions: import_zod3.z.record(import_zod3.z.unknown()).optional(),
|
|
6731
6786
|
// v3 specific - also lenient with types since SillyTavern uses numbers for enums
|
|
6732
6787
|
automation_id: import_zod3.z.string().optional(),
|
|
@@ -6742,8 +6797,8 @@ var CCv3LorebookEntrySchema = import_zod3.z.object({
|
|
|
6742
6797
|
var CCv3CharacterBookSchema = import_zod3.z.object({
|
|
6743
6798
|
name: import_zod3.z.string().optional(),
|
|
6744
6799
|
description: import_zod3.z.string().optional(),
|
|
6745
|
-
scan_depth: import_zod3.z.number().int().nonnegative().optional(),
|
|
6746
|
-
token_budget: import_zod3.z.number().int().nonnegative().optional(),
|
|
6800
|
+
scan_depth: import_zod3.z.preprocess(preprocessNumeric, import_zod3.z.number().int().nonnegative().optional()),
|
|
6801
|
+
token_budget: import_zod3.z.preprocess(preprocessNumeric, import_zod3.z.number().int().nonnegative().optional()),
|
|
6747
6802
|
recursive_scanning: import_zod3.z.boolean().optional(),
|
|
6748
6803
|
extensions: import_zod3.z.record(import_zod3.z.unknown()).optional(),
|
|
6749
6804
|
entries: import_zod3.z.array(CCv3LorebookEntrySchema)
|
|
@@ -6775,10 +6830,9 @@ var CCv3DataInnerSchema = import_zod3.z.object({
|
|
|
6775
6830
|
nickname: import_zod3.z.string().optional(),
|
|
6776
6831
|
creator_notes_multilingual: import_zod3.z.record(import_zod3.z.string()).optional(),
|
|
6777
6832
|
source: import_zod3.z.array(import_zod3.z.string()).optional(),
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
modification_date: import_zod3.z.number().int().nonnegative().optional()
|
|
6781
|
-
// Unix timestamp in seconds
|
|
6833
|
+
// Unix timestamps - preprocess to handle ISO strings, numeric strings, milliseconds
|
|
6834
|
+
creation_date: import_zod3.z.preprocess(preprocessTimestamp, import_zod3.z.number().int().nonnegative().optional()),
|
|
6835
|
+
modification_date: import_zod3.z.preprocess(preprocessTimestamp, import_zod3.z.number().int().nonnegative().optional())
|
|
6782
6836
|
});
|
|
6783
6837
|
var CCv3DataSchema = import_zod3.z.object({
|
|
6784
6838
|
spec: import_zod3.z.literal("chara_card_v3"),
|
|
@@ -7252,6 +7306,22 @@ function sanitizeName(name, ext) {
|
|
|
7252
7306
|
if (!safeName) safeName = "asset";
|
|
7253
7307
|
return safeName;
|
|
7254
7308
|
}
|
|
7309
|
+
function sanitizeExtension(ext) {
|
|
7310
|
+
const normalized = ext.trim().replace(/^\./, "").toLowerCase();
|
|
7311
|
+
if (!normalized) {
|
|
7312
|
+
throw new Error("Invalid asset extension: empty extension");
|
|
7313
|
+
}
|
|
7314
|
+
if (normalized.length > 64) {
|
|
7315
|
+
throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
|
|
7316
|
+
}
|
|
7317
|
+
if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
|
|
7318
|
+
throw new Error("Invalid asset extension: path separators are not allowed");
|
|
7319
|
+
}
|
|
7320
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
|
|
7321
|
+
throw new Error(`Invalid asset extension: "${ext}"`);
|
|
7322
|
+
}
|
|
7323
|
+
return normalized;
|
|
7324
|
+
}
|
|
7255
7325
|
function writeVoxta(card, assets, options = {}) {
|
|
7256
7326
|
const { compressionLevel = 6, includePackageJson = false } = options;
|
|
7257
7327
|
const cardData = card.data;
|
|
@@ -7340,8 +7410,9 @@ function writeVoxta(card, assets, options = {}) {
|
|
|
7340
7410
|
let assetCount = 0;
|
|
7341
7411
|
let mainThumbnail;
|
|
7342
7412
|
for (const asset of assets) {
|
|
7343
|
-
const
|
|
7344
|
-
const
|
|
7413
|
+
const safeExt = sanitizeExtension(asset.ext);
|
|
7414
|
+
const safeName = sanitizeName(asset.name, safeExt);
|
|
7415
|
+
const finalFilename = `${safeName}.${safeExt}`;
|
|
7345
7416
|
let voxtaPath = "";
|
|
7346
7417
|
const tags = asset.tags || [];
|
|
7347
7418
|
const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);
|