@character-foundry/character-foundry 0.4.1 → 0.4.2-dev.1765997746
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 +17 -38
- package/dist/charx.cjs.map +1 -1
- package/dist/charx.d.cts +27 -18
- package/dist/charx.d.ts +27 -18
- package/dist/charx.js +17 -38
- package/dist/charx.js.map +1 -1
- package/dist/exporter.cjs +36 -40
- package/dist/exporter.cjs.map +1 -1
- package/dist/exporter.d.cts +27 -18
- package/dist/exporter.d.ts +27 -18
- package/dist/exporter.js +36 -40
- 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 +62 -18
- package/dist/federation.d.ts +62 -18
- package/dist/federation.js +104 -36
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +36 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -42
- package/dist/index.d.ts +63 -42
- package/dist/index.js +36 -40
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +103 -17
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.d.cts +56 -28
- package/dist/loader.d.ts +56 -28
- package/dist/loader.js +103 -17
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.d.cts +51 -34
- package/dist/lorebook.d.ts +51 -34
- package/dist/normalizer.cjs +4 -4
- package/dist/normalizer.cjs.map +1 -1
- package/dist/normalizer.d.cts +90 -60
- package/dist/normalizer.d.ts +90 -60
- package/dist/normalizer.js +4 -4
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +4 -4
- package/dist/png.cjs.map +1 -1
- package/dist/png.d.cts +48 -32
- package/dist/png.d.ts +48 -32
- package/dist/png.js +4 -4
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +9 -9
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +144 -96
- package/dist/schemas.d.ts +144 -96
- package/dist/schemas.js +9 -9
- package/dist/schemas.js.map +1 -1
- package/dist/voxta.cjs +23 -6
- package/dist/voxta.cjs.map +1 -1
- package/dist/voxta.d.cts +42 -28
- package/dist/voxta.d.ts +42 -28
- package/dist/voxta.js +23 -6
- package/dist/voxta.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -609,7 +609,7 @@ var CCv2LorebookEntrySchema = import_zod2.z.object({
|
|
|
609
609
|
content: import_zod2.z.string(),
|
|
610
610
|
enabled: import_zod2.z.boolean().default(true),
|
|
611
611
|
// Default to enabled if missing
|
|
612
|
-
insertion_order: import_zod2.z.
|
|
612
|
+
insertion_order: import_zod2.z.preprocess((v) => v ?? 0, import_zod2.z.number().int()),
|
|
613
613
|
// Optional fields - be lenient with nulls since wild data has them
|
|
614
614
|
extensions: import_zod2.z.record(import_zod2.z.unknown()).optional(),
|
|
615
615
|
case_sensitive: import_zod2.z.boolean().nullable().optional(),
|
|
@@ -620,7 +620,7 @@ var CCv2LorebookEntrySchema = import_zod2.z.object({
|
|
|
620
620
|
selective: import_zod2.z.boolean().nullable().optional(),
|
|
621
621
|
secondary_keys: import_zod2.z.array(import_zod2.z.string()).nullable().optional(),
|
|
622
622
|
constant: import_zod2.z.boolean().nullable().optional(),
|
|
623
|
-
position: import_zod2.z.union([import_zod2.z.enum(["before_char", "after_char"]), import_zod2.z.number().int(), import_zod2.z.literal("")]).nullable().optional()
|
|
623
|
+
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()
|
|
624
624
|
}).passthrough();
|
|
625
625
|
var CCv2CharacterBookSchema = import_zod2.z.object({
|
|
626
626
|
name: import_zod2.z.string().optional(),
|
|
@@ -674,7 +674,7 @@ var CCv3LorebookEntrySchema = import_zod3.z.object({
|
|
|
674
674
|
content: import_zod3.z.string(),
|
|
675
675
|
enabled: import_zod3.z.boolean().default(true),
|
|
676
676
|
// Default to enabled if missing
|
|
677
|
-
insertion_order: import_zod3.z.
|
|
677
|
+
insertion_order: import_zod3.z.preprocess((v) => v ?? 0, import_zod3.z.number().int()),
|
|
678
678
|
// Optional fields - be lenient with nulls since wild data has them
|
|
679
679
|
case_sensitive: import_zod3.z.boolean().nullable().optional(),
|
|
680
680
|
name: import_zod3.z.string().optional(),
|
|
@@ -684,7 +684,7 @@ var CCv3LorebookEntrySchema = import_zod3.z.object({
|
|
|
684
684
|
selective: import_zod3.z.boolean().nullable().optional(),
|
|
685
685
|
secondary_keys: import_zod3.z.array(import_zod3.z.string()).nullable().optional(),
|
|
686
686
|
constant: import_zod3.z.boolean().nullable().optional(),
|
|
687
|
-
position: import_zod3.z.union([import_zod3.z.enum(["before_char", "after_char"]), import_zod3.z.number().int(), import_zod3.z.literal("")]).nullable().optional(),
|
|
687
|
+
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(),
|
|
688
688
|
extensions: import_zod3.z.record(import_zod3.z.unknown()).optional(),
|
|
689
689
|
// v3 specific - also lenient with types since SillyTavern uses numbers for enums
|
|
690
690
|
automation_id: import_zod3.z.string().optional(),
|
|
@@ -1363,36 +1363,6 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
|
|
|
1363
1363
|
"data",
|
|
1364
1364
|
"unknown"
|
|
1365
1365
|
]);
|
|
1366
|
-
var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1367
|
-
// Images
|
|
1368
|
-
"png",
|
|
1369
|
-
"jpg",
|
|
1370
|
-
"jpeg",
|
|
1371
|
-
"webp",
|
|
1372
|
-
"gif",
|
|
1373
|
-
"avif",
|
|
1374
|
-
"svg",
|
|
1375
|
-
"bmp",
|
|
1376
|
-
"ico",
|
|
1377
|
-
// Audio
|
|
1378
|
-
"mp3",
|
|
1379
|
-
"wav",
|
|
1380
|
-
"ogg",
|
|
1381
|
-
"flac",
|
|
1382
|
-
"m4a",
|
|
1383
|
-
"aac",
|
|
1384
|
-
"opus",
|
|
1385
|
-
// Video
|
|
1386
|
-
"mp4",
|
|
1387
|
-
"webm",
|
|
1388
|
-
"avi",
|
|
1389
|
-
"mov",
|
|
1390
|
-
"mkv",
|
|
1391
|
-
// Data
|
|
1392
|
-
"json",
|
|
1393
|
-
"txt",
|
|
1394
|
-
"bin"
|
|
1395
|
-
]);
|
|
1396
1366
|
function getCharxCategory(mimetype) {
|
|
1397
1367
|
if (mimetype.startsWith("image/")) return "images";
|
|
1398
1368
|
if (mimetype.startsWith("audio/")) return "audio";
|
|
@@ -1408,11 +1378,20 @@ function sanitizeAssetType(type) {
|
|
|
1408
1378
|
return sanitized || "custom";
|
|
1409
1379
|
}
|
|
1410
1380
|
function sanitizeExtension(ext) {
|
|
1411
|
-
const normalized = ext.replace(/^\./, "").toLowerCase()
|
|
1412
|
-
if (
|
|
1413
|
-
|
|
1381
|
+
const normalized = ext.trim().replace(/^\./, "").toLowerCase();
|
|
1382
|
+
if (!normalized) {
|
|
1383
|
+
throw new Error("Invalid asset extension: empty extension");
|
|
1384
|
+
}
|
|
1385
|
+
if (normalized.length > 64) {
|
|
1386
|
+
throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
|
|
1387
|
+
}
|
|
1388
|
+
if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
|
|
1389
|
+
throw new Error("Invalid asset extension: path separators are not allowed");
|
|
1390
|
+
}
|
|
1391
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
|
|
1392
|
+
throw new Error(`Invalid asset extension: "${ext}"`);
|
|
1414
1393
|
}
|
|
1415
|
-
return
|
|
1394
|
+
return normalized;
|
|
1416
1395
|
}
|
|
1417
1396
|
function sanitizeName(name, ext) {
|
|
1418
1397
|
let safeName = name;
|
|
@@ -8194,6 +8173,22 @@ function sanitizeName2(name, ext) {
|
|
|
8194
8173
|
if (!safeName) safeName = "asset";
|
|
8195
8174
|
return safeName;
|
|
8196
8175
|
}
|
|
8176
|
+
function sanitizeExtension2(ext) {
|
|
8177
|
+
const normalized = ext.trim().replace(/^\./, "").toLowerCase();
|
|
8178
|
+
if (!normalized) {
|
|
8179
|
+
throw new Error("Invalid asset extension: empty extension");
|
|
8180
|
+
}
|
|
8181
|
+
if (normalized.length > 64) {
|
|
8182
|
+
throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
|
|
8183
|
+
}
|
|
8184
|
+
if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
|
|
8185
|
+
throw new Error("Invalid asset extension: path separators are not allowed");
|
|
8186
|
+
}
|
|
8187
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
|
|
8188
|
+
throw new Error(`Invalid asset extension: "${ext}"`);
|
|
8189
|
+
}
|
|
8190
|
+
return normalized;
|
|
8191
|
+
}
|
|
8197
8192
|
function writeVoxta(card, assets, options = {}) {
|
|
8198
8193
|
const { compressionLevel = 6, includePackageJson = false } = options;
|
|
8199
8194
|
const cardData = card.data;
|
|
@@ -8282,8 +8277,9 @@ function writeVoxta(card, assets, options = {}) {
|
|
|
8282
8277
|
let assetCount = 0;
|
|
8283
8278
|
let mainThumbnail;
|
|
8284
8279
|
for (const asset of assets) {
|
|
8285
|
-
const
|
|
8286
|
-
const
|
|
8280
|
+
const safeExt = sanitizeExtension2(asset.ext);
|
|
8281
|
+
const safeName = sanitizeName2(asset.name, safeExt);
|
|
8282
|
+
const finalFilename = `${safeName}.${safeExt}`;
|
|
8287
8283
|
let voxtaPath = "";
|
|
8288
8284
|
const tags = asset.tags || [];
|
|
8289
8285
|
const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);
|