@character-foundry/character-foundry 0.1.3 → 0.1.6
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/README.md +70 -0
- package/dist/app-framework.cjs +1859 -0
- package/dist/app-framework.cjs.map +1 -0
- package/dist/app-framework.d.cts +896 -0
- package/dist/app-framework.d.ts +896 -2
- package/dist/app-framework.js +1835 -1
- package/dist/app-framework.js.map +1 -1
- package/dist/charx.cjs +979 -0
- package/dist/charx.cjs.map +1 -0
- package/dist/charx.d.cts +640 -0
- package/dist/charx.d.ts +640 -2
- package/dist/charx.js +955 -1
- package/dist/charx.js.map +1 -1
- package/dist/core.cjs +755 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +404 -0
- package/dist/core.d.ts +404 -2
- package/dist/core.js +731 -1
- package/dist/core.js.map +1 -1
- package/dist/exporter.cjs +7619 -0
- package/dist/exporter.cjs.map +1 -0
- package/dist/exporter.d.cts +681 -0
- package/dist/exporter.d.ts +681 -2
- package/dist/exporter.js +7602 -1
- package/dist/exporter.js.map +1 -1
- package/dist/federation.cjs +3916 -0
- package/dist/federation.cjs.map +1 -0
- package/dist/federation.d.cts +2951 -0
- package/dist/federation.d.ts +2951 -2
- package/dist/federation.js +3892 -1
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +9213 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1119 -0
- package/dist/index.d.ts +1113 -20
- package/dist/index.js +9196 -26
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +8951 -0
- package/dist/loader.cjs.map +1 -0
- package/dist/loader.d.cts +1037 -0
- package/dist/loader.d.ts +1037 -2
- package/dist/loader.js +8934 -1
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.cjs +866 -0
- package/dist/lorebook.cjs.map +1 -0
- package/dist/lorebook.d.cts +1008 -0
- package/dist/lorebook.d.ts +1008 -2
- package/dist/lorebook.js +842 -1
- package/dist/lorebook.js.map +1 -1
- package/dist/media.cjs +6661 -0
- package/dist/media.cjs.map +1 -0
- package/dist/media.d.cts +87 -0
- package/dist/media.d.ts +87 -2
- package/dist/media.js +6644 -1
- package/dist/media.js.map +1 -1
- package/dist/normalizer.cjs +503 -0
- package/dist/normalizer.cjs.map +1 -0
- package/dist/normalizer.d.cts +1217 -0
- package/dist/normalizer.d.ts +1217 -2
- package/dist/normalizer.js +479 -1
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +797 -0
- package/dist/png.cjs.map +1 -0
- package/dist/png.d.cts +786 -0
- package/dist/png.d.ts +786 -2
- package/dist/png.js +773 -1
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +879 -0
- package/dist/schemas.cjs.map +1 -0
- package/dist/schemas.d.cts +2208 -0
- package/dist/schemas.d.ts +2208 -2
- package/dist/schemas.js +855 -1
- package/dist/schemas.js.map +1 -1
- package/dist/tokenizers.cjs +153 -0
- package/dist/tokenizers.cjs.map +1 -0
- package/dist/tokenizers.d.cts +155 -0
- package/dist/tokenizers.d.ts +155 -2
- package/dist/tokenizers.js +129 -1
- package/dist/tokenizers.js.map +1 -1
- package/dist/voxta.cjs +7907 -0
- package/dist/voxta.cjs.map +1 -0
- package/dist/voxta.d.cts +1349 -0
- package/dist/voxta.d.ts +1349 -2
- package/dist/voxta.js +7890 -1
- package/dist/voxta.js.map +1 -1
- package/package.json +177 -45
- package/dist/app-framework.d.ts.map +0 -1
- package/dist/charx.d.ts.map +0 -1
- package/dist/core.d.ts.map +0 -1
- package/dist/exporter.d.ts.map +0 -1
- package/dist/federation.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/loader.d.ts.map +0 -1
- package/dist/lorebook.d.ts.map +0 -1
- package/dist/media.d.ts.map +0 -1
- package/dist/normalizer.d.ts.map +0 -1
- package/dist/png.d.ts.map +0 -1
- package/dist/schemas.d.ts.map +0 -1
- package/dist/tokenizers.d.ts.map +0 -1
- package/dist/voxta.d.ts.map +0 -1
package/dist/schemas.js
CHANGED
|
@@ -1,2 +1,856 @@
|
|
|
1
|
-
|
|
1
|
+
// ../schemas/dist/index.js
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { z as z2 } from "zod";
|
|
4
|
+
import { z as z3 } from "zod";
|
|
5
|
+
import "zod";
|
|
6
|
+
var ISO8601Schema = z.string().datetime();
|
|
7
|
+
var UUIDSchema = z.string().uuid();
|
|
8
|
+
var SpecSchema = z.enum(["v2", "v3"]);
|
|
9
|
+
var SourceFormatSchema = z.enum([
|
|
10
|
+
"png_v2",
|
|
11
|
+
// PNG with 'chara' chunk (v2)
|
|
12
|
+
"png_v3",
|
|
13
|
+
// PNG with 'ccv3' chunk (v3)
|
|
14
|
+
"json_v2",
|
|
15
|
+
// Raw JSON v2
|
|
16
|
+
"json_v3",
|
|
17
|
+
// Raw JSON v3
|
|
18
|
+
"charx",
|
|
19
|
+
// ZIP with card.json (v3 spec)
|
|
20
|
+
"charx_risu",
|
|
21
|
+
// ZIP with card.json + module.risum
|
|
22
|
+
"charx_jpeg",
|
|
23
|
+
// JPEG with appended ZIP (read-only)
|
|
24
|
+
"voxta"
|
|
25
|
+
// VoxPkg format
|
|
26
|
+
]);
|
|
27
|
+
var OriginalShapeSchema = z.enum(["wrapped", "unwrapped", "legacy"]);
|
|
28
|
+
var AssetTypeSchema = z.enum([
|
|
29
|
+
"icon",
|
|
30
|
+
"background",
|
|
31
|
+
"emotion",
|
|
32
|
+
"user_icon",
|
|
33
|
+
"sound",
|
|
34
|
+
"video",
|
|
35
|
+
"custom",
|
|
36
|
+
"x-risu-asset"
|
|
37
|
+
]);
|
|
38
|
+
var AssetDescriptorSchema = z.object({
|
|
39
|
+
type: AssetTypeSchema,
|
|
40
|
+
uri: z.string(),
|
|
41
|
+
name: z.string(),
|
|
42
|
+
ext: z.string()
|
|
43
|
+
});
|
|
44
|
+
var ExtractedAssetSchema = z.object({
|
|
45
|
+
descriptor: AssetDescriptorSchema,
|
|
46
|
+
data: z.instanceof(Uint8Array),
|
|
47
|
+
mimeType: z.string()
|
|
48
|
+
});
|
|
49
|
+
var CCv2LorebookEntrySchema = z2.object({
|
|
50
|
+
keys: z2.array(z2.string()),
|
|
51
|
+
content: z2.string(),
|
|
52
|
+
enabled: z2.boolean(),
|
|
53
|
+
insertion_order: z2.number().int(),
|
|
54
|
+
// Optional fields
|
|
55
|
+
extensions: z2.record(z2.unknown()).optional(),
|
|
56
|
+
case_sensitive: z2.boolean().optional(),
|
|
57
|
+
name: z2.string().optional(),
|
|
58
|
+
priority: z2.number().int().optional(),
|
|
59
|
+
id: z2.number().int().optional(),
|
|
60
|
+
comment: z2.string().optional(),
|
|
61
|
+
selective: z2.boolean().optional(),
|
|
62
|
+
secondary_keys: z2.array(z2.string()).optional(),
|
|
63
|
+
constant: z2.boolean().optional(),
|
|
64
|
+
position: z2.enum(["before_char", "after_char"]).optional()
|
|
65
|
+
});
|
|
66
|
+
var CCv2CharacterBookSchema = z2.object({
|
|
67
|
+
name: z2.string().optional(),
|
|
68
|
+
description: z2.string().optional(),
|
|
69
|
+
scan_depth: z2.number().int().nonnegative().optional(),
|
|
70
|
+
token_budget: z2.number().int().nonnegative().optional(),
|
|
71
|
+
recursive_scanning: z2.boolean().optional(),
|
|
72
|
+
extensions: z2.record(z2.unknown()).optional(),
|
|
73
|
+
entries: z2.array(CCv2LorebookEntrySchema)
|
|
74
|
+
});
|
|
75
|
+
var CCv2DataSchema = z2.object({
|
|
76
|
+
// Core fields - use .default('') to handle missing fields in malformed cards
|
|
77
|
+
name: z2.string().default(""),
|
|
78
|
+
description: z2.string().default(""),
|
|
79
|
+
personality: z2.string().nullable().default(""),
|
|
80
|
+
// Can be null in wild (141 cards)
|
|
81
|
+
scenario: z2.string().default(""),
|
|
82
|
+
first_mes: z2.string().default(""),
|
|
83
|
+
mes_example: z2.string().nullable().default(""),
|
|
84
|
+
// Can be null in wild (186 cards)
|
|
85
|
+
// Optional fields
|
|
86
|
+
creator_notes: z2.string().optional(),
|
|
87
|
+
system_prompt: z2.string().optional(),
|
|
88
|
+
post_history_instructions: z2.string().optional(),
|
|
89
|
+
alternate_greetings: z2.array(z2.string()).optional(),
|
|
90
|
+
character_book: CCv2CharacterBookSchema.optional().nullable(),
|
|
91
|
+
tags: z2.array(z2.string()).optional(),
|
|
92
|
+
creator: z2.string().optional(),
|
|
93
|
+
character_version: z2.string().optional(),
|
|
94
|
+
extensions: z2.record(z2.unknown()).optional()
|
|
95
|
+
});
|
|
96
|
+
var CCv2WrappedSchema = z2.object({
|
|
97
|
+
spec: z2.literal("chara_card_v2"),
|
|
98
|
+
spec_version: z2.literal("2.0"),
|
|
99
|
+
data: CCv2DataSchema
|
|
100
|
+
});
|
|
101
|
+
function isWrappedV2(data) {
|
|
102
|
+
return CCv2WrappedSchema.safeParse(data).success;
|
|
103
|
+
}
|
|
104
|
+
function isV2CardData(data) {
|
|
105
|
+
return CCv2WrappedSchema.safeParse(data).success || CCv2DataSchema.safeParse(data).success;
|
|
106
|
+
}
|
|
107
|
+
function parseWrappedV2(data) {
|
|
108
|
+
return CCv2WrappedSchema.parse(data);
|
|
109
|
+
}
|
|
110
|
+
function parseV2Data(data) {
|
|
111
|
+
return CCv2DataSchema.parse(data);
|
|
112
|
+
}
|
|
113
|
+
function looksLikeWrappedV2(data) {
|
|
114
|
+
if (!data || typeof data !== "object") return false;
|
|
115
|
+
const obj = data;
|
|
116
|
+
return obj.spec === "chara_card_v2" && obj.data !== null && typeof obj.data === "object";
|
|
117
|
+
}
|
|
118
|
+
function getV2Data(card) {
|
|
119
|
+
if (looksLikeWrappedV2(card)) {
|
|
120
|
+
return card.data;
|
|
121
|
+
}
|
|
122
|
+
return card;
|
|
123
|
+
}
|
|
124
|
+
var CCv3LorebookEntrySchema = z3.object({
|
|
125
|
+
keys: z3.array(z3.string()),
|
|
126
|
+
content: z3.string(),
|
|
127
|
+
enabled: z3.boolean(),
|
|
128
|
+
insertion_order: z3.number().int(),
|
|
129
|
+
// Optional fields
|
|
130
|
+
case_sensitive: z3.boolean().optional(),
|
|
131
|
+
name: z3.string().optional(),
|
|
132
|
+
priority: z3.number().int().optional(),
|
|
133
|
+
id: z3.number().int().optional(),
|
|
134
|
+
comment: z3.string().optional(),
|
|
135
|
+
selective: z3.boolean().optional(),
|
|
136
|
+
secondary_keys: z3.array(z3.string()).optional(),
|
|
137
|
+
constant: z3.boolean().optional(),
|
|
138
|
+
position: z3.enum(["before_char", "after_char"]).optional(),
|
|
139
|
+
extensions: z3.record(z3.unknown()).optional(),
|
|
140
|
+
// v3 specific
|
|
141
|
+
automation_id: z3.string().optional(),
|
|
142
|
+
role: z3.enum(["system", "user", "assistant"]).optional(),
|
|
143
|
+
group: z3.string().optional(),
|
|
144
|
+
scan_frequency: z3.number().int().nonnegative().optional(),
|
|
145
|
+
probability: z3.number().min(0).max(1).optional(),
|
|
146
|
+
use_regex: z3.boolean().optional(),
|
|
147
|
+
depth: z3.number().int().nonnegative().optional(),
|
|
148
|
+
selective_logic: z3.enum(["AND", "NOT"]).optional()
|
|
149
|
+
});
|
|
150
|
+
var CCv3CharacterBookSchema = z3.object({
|
|
151
|
+
name: z3.string().optional(),
|
|
152
|
+
description: z3.string().optional(),
|
|
153
|
+
scan_depth: z3.number().int().nonnegative().optional(),
|
|
154
|
+
token_budget: z3.number().int().nonnegative().optional(),
|
|
155
|
+
recursive_scanning: z3.boolean().optional(),
|
|
156
|
+
extensions: z3.record(z3.unknown()).optional(),
|
|
157
|
+
entries: z3.array(CCv3LorebookEntrySchema)
|
|
158
|
+
});
|
|
159
|
+
var CCv3DataInnerSchema = z3.object({
|
|
160
|
+
// Core fields - use .default('') to handle missing fields in malformed cards
|
|
161
|
+
name: z3.string().default(""),
|
|
162
|
+
description: z3.string().default(""),
|
|
163
|
+
personality: z3.string().nullable().default(""),
|
|
164
|
+
// Can be null in wild (141 cards)
|
|
165
|
+
scenario: z3.string().default(""),
|
|
166
|
+
first_mes: z3.string().default(""),
|
|
167
|
+
mes_example: z3.string().nullable().default(""),
|
|
168
|
+
// Can be null in wild (186 cards)
|
|
169
|
+
// "Required" per spec but often missing in wild - use defaults for leniency
|
|
170
|
+
creator: z3.string().default(""),
|
|
171
|
+
character_version: z3.string().default(""),
|
|
172
|
+
tags: z3.array(z3.string()).default([]),
|
|
173
|
+
group_only_greetings: z3.array(z3.string()).default([]),
|
|
174
|
+
// Optional fields
|
|
175
|
+
creator_notes: z3.string().optional(),
|
|
176
|
+
system_prompt: z3.string().optional(),
|
|
177
|
+
post_history_instructions: z3.string().optional(),
|
|
178
|
+
alternate_greetings: z3.array(z3.string()).optional(),
|
|
179
|
+
character_book: CCv3CharacterBookSchema.optional().nullable(),
|
|
180
|
+
extensions: z3.record(z3.unknown()).optional(),
|
|
181
|
+
// v3 specific
|
|
182
|
+
assets: z3.array(AssetDescriptorSchema).optional(),
|
|
183
|
+
nickname: z3.string().optional(),
|
|
184
|
+
creator_notes_multilingual: z3.record(z3.string()).optional(),
|
|
185
|
+
source: z3.array(z3.string()).optional(),
|
|
186
|
+
creation_date: z3.number().int().nonnegative().optional(),
|
|
187
|
+
// Unix timestamp in seconds
|
|
188
|
+
modification_date: z3.number().int().nonnegative().optional()
|
|
189
|
+
// Unix timestamp in seconds
|
|
190
|
+
});
|
|
191
|
+
var CCv3DataSchema = z3.object({
|
|
192
|
+
spec: z3.literal("chara_card_v3"),
|
|
193
|
+
spec_version: z3.literal("3.0"),
|
|
194
|
+
data: CCv3DataInnerSchema
|
|
195
|
+
});
|
|
196
|
+
function isV3Card(data) {
|
|
197
|
+
return CCv3DataSchema.safeParse(data).success;
|
|
198
|
+
}
|
|
199
|
+
function parseV3Card(data) {
|
|
200
|
+
return CCv3DataSchema.parse(data);
|
|
201
|
+
}
|
|
202
|
+
function parseV3DataInner(data) {
|
|
203
|
+
return CCv3DataInnerSchema.parse(data);
|
|
204
|
+
}
|
|
205
|
+
function getV3Data(card) {
|
|
206
|
+
return card.data;
|
|
207
|
+
}
|
|
208
|
+
function looksLikeV3Card(data) {
|
|
209
|
+
if (!data || typeof data !== "object") return false;
|
|
210
|
+
const obj = data;
|
|
211
|
+
return obj.spec === "chara_card_v3" && obj.data !== null && typeof obj.data === "object";
|
|
212
|
+
}
|
|
213
|
+
function hasRisuExtensions(extensions) {
|
|
214
|
+
if (!extensions) return false;
|
|
215
|
+
return "risuai" in extensions || "risu" in extensions;
|
|
216
|
+
}
|
|
217
|
+
function hasRisuScripts(extensions) {
|
|
218
|
+
if (!extensions) return false;
|
|
219
|
+
const risu = extensions.risuai;
|
|
220
|
+
if (!risu) return false;
|
|
221
|
+
return !!risu.triggerscript || !!risu.customScripts;
|
|
222
|
+
}
|
|
223
|
+
function hasDepthPrompt(extensions) {
|
|
224
|
+
if (!extensions) return false;
|
|
225
|
+
if ("depth_prompt" in extensions && extensions.depth_prompt) return true;
|
|
226
|
+
const risu = extensions.risuai;
|
|
227
|
+
return !!risu?.depth_prompt;
|
|
228
|
+
}
|
|
229
|
+
function createEmptyNormalizedCard() {
|
|
230
|
+
return {
|
|
231
|
+
name: "",
|
|
232
|
+
description: "",
|
|
233
|
+
personality: "",
|
|
234
|
+
scenario: "",
|
|
235
|
+
firstMes: "",
|
|
236
|
+
mesExample: "",
|
|
237
|
+
alternateGreetings: [],
|
|
238
|
+
groupOnlyGreetings: [],
|
|
239
|
+
tags: [],
|
|
240
|
+
extensions: {}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function createEmptyFeatures() {
|
|
244
|
+
return {
|
|
245
|
+
hasAlternateGreetings: false,
|
|
246
|
+
alternateGreetingsCount: 0,
|
|
247
|
+
totalGreetingsCount: 1,
|
|
248
|
+
// first_mes always counts as 1
|
|
249
|
+
hasLorebook: false,
|
|
250
|
+
lorebookEntriesCount: 0,
|
|
251
|
+
hasEmbeddedImages: false,
|
|
252
|
+
embeddedImagesCount: 0,
|
|
253
|
+
hasGallery: false,
|
|
254
|
+
hasRisuExtensions: false,
|
|
255
|
+
hasRisuScripts: false,
|
|
256
|
+
hasDepthPrompt: false,
|
|
257
|
+
hasVoxtaAppearance: false,
|
|
258
|
+
tokens: {
|
|
259
|
+
description: 0,
|
|
260
|
+
personality: 0,
|
|
261
|
+
scenario: 0,
|
|
262
|
+
firstMes: 0,
|
|
263
|
+
mesExample: 0,
|
|
264
|
+
systemPrompt: 0,
|
|
265
|
+
total: 0
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function deriveFeatures(card) {
|
|
270
|
+
const isV3 = "assets" in card;
|
|
271
|
+
const altGreetings = card.alternate_greetings ?? [];
|
|
272
|
+
const hasAlternateGreetings = altGreetings.length > 0;
|
|
273
|
+
const alternateGreetingsCount = altGreetings.length;
|
|
274
|
+
const totalGreetingsCount = 1 + alternateGreetingsCount;
|
|
275
|
+
const characterBook = card.character_book;
|
|
276
|
+
const hasLorebook2 = !!characterBook && characterBook.entries.length > 0;
|
|
277
|
+
const lorebookEntriesCount = characterBook?.entries.length ?? 0;
|
|
278
|
+
const assets = isV3 ? card.assets ?? [] : [];
|
|
279
|
+
const imageAssetTypes = ["icon", "background", "emotion", "custom"];
|
|
280
|
+
const imageAssets = assets.filter(
|
|
281
|
+
(a) => imageAssetTypes.includes(a.type) || ["png", "jpg", "jpeg", "webp", "gif"].includes(a.ext.toLowerCase())
|
|
282
|
+
);
|
|
283
|
+
const hasGallery = imageAssets.length > 0;
|
|
284
|
+
const embeddedImageCount = countEmbeddedImages(card);
|
|
285
|
+
const hasEmbeddedImages = embeddedImageCount > 0;
|
|
286
|
+
const extensions = card.extensions ?? {};
|
|
287
|
+
const hasRisu = hasRisuExtensions(extensions);
|
|
288
|
+
const hasScripts = hasRisuScripts(extensions);
|
|
289
|
+
const hasDepth = hasDepthPrompt(extensions);
|
|
290
|
+
const hasVoxta = checkVoxtaAppearance(extensions);
|
|
291
|
+
const tokens = {
|
|
292
|
+
description: 0,
|
|
293
|
+
personality: 0,
|
|
294
|
+
scenario: 0,
|
|
295
|
+
firstMes: 0,
|
|
296
|
+
mesExample: 0,
|
|
297
|
+
systemPrompt: 0,
|
|
298
|
+
total: 0
|
|
299
|
+
};
|
|
300
|
+
return {
|
|
301
|
+
hasAlternateGreetings,
|
|
302
|
+
alternateGreetingsCount,
|
|
303
|
+
totalGreetingsCount,
|
|
304
|
+
hasLorebook: hasLorebook2,
|
|
305
|
+
lorebookEntriesCount,
|
|
306
|
+
hasEmbeddedImages,
|
|
307
|
+
embeddedImagesCount: embeddedImageCount,
|
|
308
|
+
hasGallery,
|
|
309
|
+
hasRisuExtensions: hasRisu,
|
|
310
|
+
hasRisuScripts: hasScripts,
|
|
311
|
+
hasDepthPrompt: hasDepth,
|
|
312
|
+
hasVoxtaAppearance: hasVoxta,
|
|
313
|
+
tokens
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function countEmbeddedImages(card) {
|
|
317
|
+
const textFields = [
|
|
318
|
+
card.description,
|
|
319
|
+
card.personality,
|
|
320
|
+
card.scenario,
|
|
321
|
+
card.first_mes,
|
|
322
|
+
card.mes_example,
|
|
323
|
+
card.creator_notes,
|
|
324
|
+
card.system_prompt,
|
|
325
|
+
card.post_history_instructions,
|
|
326
|
+
...card.alternate_greetings ?? []
|
|
327
|
+
].filter((field) => typeof field === "string");
|
|
328
|
+
if ("group_only_greetings" in card) {
|
|
329
|
+
textFields.push(...card.group_only_greetings ?? []);
|
|
330
|
+
}
|
|
331
|
+
let count = 0;
|
|
332
|
+
const dataUrlPattern = /data:image\/[^;]+;base64,/g;
|
|
333
|
+
for (const text of textFields) {
|
|
334
|
+
const matches = text.match(dataUrlPattern);
|
|
335
|
+
if (matches) {
|
|
336
|
+
count += matches.length;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return count;
|
|
340
|
+
}
|
|
341
|
+
function checkVoxtaAppearance(extensions) {
|
|
342
|
+
if (!extensions.voxta) return false;
|
|
343
|
+
const voxta = extensions.voxta;
|
|
344
|
+
return !!voxta.appearance;
|
|
345
|
+
}
|
|
346
|
+
var V3_ONLY_FIELDS = ["group_only_greetings", "creation_date", "modification_date", "assets"];
|
|
347
|
+
function detectSpec(data) {
|
|
348
|
+
return detectSpecDetailed(data).spec;
|
|
349
|
+
}
|
|
350
|
+
function detectSpecDetailed(data) {
|
|
351
|
+
const result = {
|
|
352
|
+
spec: null,
|
|
353
|
+
confidence: "low",
|
|
354
|
+
indicators: [],
|
|
355
|
+
warnings: []
|
|
356
|
+
};
|
|
357
|
+
if (!data || typeof data !== "object") {
|
|
358
|
+
result.indicators.push("Input is not an object");
|
|
359
|
+
return result;
|
|
360
|
+
}
|
|
361
|
+
const obj = data;
|
|
362
|
+
const dataObj = obj.data && typeof obj.data === "object" ? obj.data : null;
|
|
363
|
+
if (obj.spec === "chara_card_v3") {
|
|
364
|
+
result.spec = "v3";
|
|
365
|
+
result.confidence = "high";
|
|
366
|
+
result.indicators.push('spec field is "chara_card_v3"');
|
|
367
|
+
if (obj.spec_version && obj.spec_version !== "3.0") {
|
|
368
|
+
result.warnings.push(`spec_version "${obj.spec_version}" inconsistent with v3 spec`);
|
|
369
|
+
}
|
|
370
|
+
return result;
|
|
371
|
+
}
|
|
372
|
+
if (obj.spec === "chara_card_v2") {
|
|
373
|
+
result.spec = "v2";
|
|
374
|
+
result.confidence = "high";
|
|
375
|
+
result.indicators.push('spec field is "chara_card_v2"');
|
|
376
|
+
if (dataObj) {
|
|
377
|
+
for (const field of V3_ONLY_FIELDS) {
|
|
378
|
+
if (field in dataObj) {
|
|
379
|
+
result.warnings.push(`V3-only field "${field}" found in V2 card`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (obj.spec_version && obj.spec_version !== "2.0") {
|
|
384
|
+
result.warnings.push(`spec_version "${obj.spec_version}" inconsistent with v2 spec`);
|
|
385
|
+
}
|
|
386
|
+
return result;
|
|
387
|
+
}
|
|
388
|
+
if (typeof obj.spec_version === "string") {
|
|
389
|
+
if (obj.spec_version.startsWith("3")) {
|
|
390
|
+
result.spec = "v3";
|
|
391
|
+
result.confidence = "high";
|
|
392
|
+
result.indicators.push(`spec_version "${obj.spec_version}" starts with "3"`);
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
395
|
+
if (obj.spec_version.startsWith("2")) {
|
|
396
|
+
result.spec = "v2";
|
|
397
|
+
result.confidence = "high";
|
|
398
|
+
result.indicators.push(`spec_version "${obj.spec_version}" starts with "2"`);
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (obj.spec_version === 2 || obj.spec_version === 2) {
|
|
403
|
+
result.spec = "v2";
|
|
404
|
+
result.confidence = "high";
|
|
405
|
+
result.indicators.push(`spec_version is numeric ${obj.spec_version}`);
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
if (dataObj) {
|
|
409
|
+
const v3Fields = [];
|
|
410
|
+
for (const field of V3_ONLY_FIELDS) {
|
|
411
|
+
if (field in dataObj) {
|
|
412
|
+
v3Fields.push(field);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (v3Fields.length > 0) {
|
|
416
|
+
result.spec = "v3";
|
|
417
|
+
result.confidence = "medium";
|
|
418
|
+
result.indicators.push(`Has V3-only fields: ${v3Fields.join(", ")}`);
|
|
419
|
+
return result;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const rootV3Fields = [];
|
|
423
|
+
for (const field of V3_ONLY_FIELDS) {
|
|
424
|
+
if (field in obj) {
|
|
425
|
+
rootV3Fields.push(field);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (rootV3Fields.length > 0) {
|
|
429
|
+
result.spec = "v3";
|
|
430
|
+
result.confidence = "medium";
|
|
431
|
+
result.indicators.push(`Has V3-only fields at root: ${rootV3Fields.join(", ")}`);
|
|
432
|
+
result.warnings.push("V3 fields found at root level instead of data object");
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
if (obj.spec && dataObj) {
|
|
436
|
+
const dataName = dataObj.name;
|
|
437
|
+
if (dataName && typeof dataName === "string") {
|
|
438
|
+
if (typeof obj.spec === "string") {
|
|
439
|
+
if (obj.spec.includes("v3") || obj.spec.includes("3")) {
|
|
440
|
+
result.spec = "v3";
|
|
441
|
+
result.confidence = "medium";
|
|
442
|
+
result.indicators.push(`spec field "${obj.spec}" contains "v3" or "3"`);
|
|
443
|
+
return result;
|
|
444
|
+
}
|
|
445
|
+
if (obj.spec.includes("v2") || obj.spec.includes("2")) {
|
|
446
|
+
result.spec = "v2";
|
|
447
|
+
result.confidence = "medium";
|
|
448
|
+
result.indicators.push(`spec field "${obj.spec}" contains "v2" or "2"`);
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
result.spec = "v3";
|
|
453
|
+
result.confidence = "medium";
|
|
454
|
+
result.indicators.push("Has wrapped format with spec and data.name");
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
if (obj.name && typeof obj.name === "string") {
|
|
459
|
+
if ("description" in obj || "personality" in obj || "scenario" in obj) {
|
|
460
|
+
result.spec = "v2";
|
|
461
|
+
result.confidence = "medium";
|
|
462
|
+
result.indicators.push("Unwrapped format with name, description/personality/scenario");
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (dataObj && typeof dataObj.name === "string") {
|
|
467
|
+
if ("description" in dataObj || "personality" in dataObj) {
|
|
468
|
+
result.spec = "v2";
|
|
469
|
+
result.confidence = "low";
|
|
470
|
+
result.indicators.push("Has data object with name and card fields, but no spec");
|
|
471
|
+
result.warnings.push("Missing spec field");
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
result.indicators.push("No card structure detected");
|
|
476
|
+
return result;
|
|
477
|
+
}
|
|
478
|
+
function hasLorebook(data) {
|
|
479
|
+
if (!data || typeof data !== "object") return false;
|
|
480
|
+
const obj = data;
|
|
481
|
+
const wrapped = obj.data;
|
|
482
|
+
if (wrapped?.character_book) {
|
|
483
|
+
const book = wrapped.character_book;
|
|
484
|
+
if (Array.isArray(book.entries) && book.entries.length > 0) return true;
|
|
485
|
+
}
|
|
486
|
+
if (obj.character_book) {
|
|
487
|
+
const book = obj.character_book;
|
|
488
|
+
if (Array.isArray(book.entries) && book.entries.length > 0) return true;
|
|
489
|
+
}
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
function looksLikeCard(data) {
|
|
493
|
+
if (!data || typeof data !== "object") return false;
|
|
494
|
+
const obj = data;
|
|
495
|
+
if (obj.spec === "chara_card_v2" || obj.spec === "chara_card_v3") {
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
if (obj.data && typeof obj.data === "object") {
|
|
499
|
+
const dataObj = obj.data;
|
|
500
|
+
if (typeof dataObj.name === "string" && dataObj.name.length > 0) {
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (typeof obj.name === "string" && obj.name.length > 0) {
|
|
505
|
+
if ("description" in obj || "personality" in obj || "first_mes" in obj) {
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
var POSITION_MAP = {
|
|
512
|
+
0: "before_char",
|
|
513
|
+
1: "after_char"
|
|
514
|
+
};
|
|
515
|
+
var V3_ONLY_ENTRY_FIELDS = [
|
|
516
|
+
"probability",
|
|
517
|
+
"depth",
|
|
518
|
+
"group",
|
|
519
|
+
"scan_frequency",
|
|
520
|
+
"use_regex",
|
|
521
|
+
"selective_logic",
|
|
522
|
+
"role",
|
|
523
|
+
"automation_id"
|
|
524
|
+
];
|
|
525
|
+
var V2_REQUIRED_DEFAULTS = {
|
|
526
|
+
name: "",
|
|
527
|
+
description: "",
|
|
528
|
+
personality: "",
|
|
529
|
+
scenario: "",
|
|
530
|
+
first_mes: "",
|
|
531
|
+
mes_example: ""
|
|
532
|
+
};
|
|
533
|
+
var V3_REQUIRED_DEFAULTS = {
|
|
534
|
+
name: "",
|
|
535
|
+
description: "",
|
|
536
|
+
personality: "",
|
|
537
|
+
scenario: "",
|
|
538
|
+
first_mes: "",
|
|
539
|
+
mes_example: "",
|
|
540
|
+
creator: "",
|
|
541
|
+
character_version: "1.0",
|
|
542
|
+
tags: [],
|
|
543
|
+
group_only_greetings: []
|
|
544
|
+
};
|
|
545
|
+
var DATA_FIELDS = [
|
|
546
|
+
"name",
|
|
547
|
+
"description",
|
|
548
|
+
"personality",
|
|
549
|
+
"scenario",
|
|
550
|
+
"first_mes",
|
|
551
|
+
"mes_example",
|
|
552
|
+
"creator_notes",
|
|
553
|
+
"system_prompt",
|
|
554
|
+
"post_history_instructions",
|
|
555
|
+
"alternate_greetings",
|
|
556
|
+
"character_book",
|
|
557
|
+
"tags",
|
|
558
|
+
"creator",
|
|
559
|
+
"character_version",
|
|
560
|
+
"extensions",
|
|
561
|
+
"assets",
|
|
562
|
+
"nickname",
|
|
563
|
+
"creator_notes_multilingual",
|
|
564
|
+
"source",
|
|
565
|
+
"creation_date",
|
|
566
|
+
"modification_date",
|
|
567
|
+
"group_only_greetings"
|
|
568
|
+
];
|
|
569
|
+
function deepClone(obj) {
|
|
570
|
+
if (obj === null || obj === void 0) {
|
|
571
|
+
return obj;
|
|
572
|
+
}
|
|
573
|
+
if (Array.isArray(obj)) {
|
|
574
|
+
return obj.map((item) => deepClone(item));
|
|
575
|
+
}
|
|
576
|
+
if (typeof obj === "object") {
|
|
577
|
+
const result = {};
|
|
578
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
579
|
+
result[key] = deepClone(value);
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
return obj;
|
|
584
|
+
}
|
|
585
|
+
function isMilliseconds(timestamp) {
|
|
586
|
+
return timestamp > 1e10;
|
|
587
|
+
}
|
|
588
|
+
var CardNormalizer = {
|
|
589
|
+
/**
|
|
590
|
+
* Normalize card data to valid schema format.
|
|
591
|
+
*
|
|
592
|
+
* Handles:
|
|
593
|
+
* - Fixing spec/spec_version values
|
|
594
|
+
* - Moving misplaced fields to correct locations
|
|
595
|
+
* - Adding missing required fields with defaults
|
|
596
|
+
* - Handling hybrid formats (fields at root AND in data object)
|
|
597
|
+
*
|
|
598
|
+
* @param data - Raw card data (potentially malformed)
|
|
599
|
+
* @param spec - Target spec version
|
|
600
|
+
* @returns Normalized card data (does not mutate input)
|
|
601
|
+
*/
|
|
602
|
+
normalize(data, spec) {
|
|
603
|
+
if (!data || typeof data !== "object") {
|
|
604
|
+
if (spec === "v3") {
|
|
605
|
+
return {
|
|
606
|
+
spec: "chara_card_v3",
|
|
607
|
+
spec_version: "3.0",
|
|
608
|
+
data: { ...V3_REQUIRED_DEFAULTS }
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
spec: "chara_card_v2",
|
|
613
|
+
spec_version: "2.0",
|
|
614
|
+
data: { ...V2_REQUIRED_DEFAULTS }
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
const obj = data;
|
|
618
|
+
const result = {};
|
|
619
|
+
const existingData = obj.data && typeof obj.data === "object" ? obj.data : {};
|
|
620
|
+
const mergedData = {};
|
|
621
|
+
for (const [key, value] of Object.entries(existingData)) {
|
|
622
|
+
mergedData[key] = deepClone(value);
|
|
623
|
+
}
|
|
624
|
+
for (const field of DATA_FIELDS) {
|
|
625
|
+
if (field in obj && !(field in mergedData)) {
|
|
626
|
+
mergedData[field] = deepClone(obj[field]);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (mergedData.character_book === null) {
|
|
630
|
+
delete mergedData.character_book;
|
|
631
|
+
}
|
|
632
|
+
if (mergedData.character_book && typeof mergedData.character_book === "object") {
|
|
633
|
+
mergedData.character_book = this.normalizeCharacterBook(
|
|
634
|
+
mergedData.character_book,
|
|
635
|
+
spec
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
const defaults = spec === "v3" ? V3_REQUIRED_DEFAULTS : V2_REQUIRED_DEFAULTS;
|
|
639
|
+
for (const [key, defaultValue] of Object.entries(defaults)) {
|
|
640
|
+
if (!(key in mergedData) || mergedData[key] === void 0) {
|
|
641
|
+
mergedData[key] = Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (mergedData.tags && !Array.isArray(mergedData.tags)) {
|
|
645
|
+
mergedData.tags = [];
|
|
646
|
+
}
|
|
647
|
+
if (mergedData.alternate_greetings && !Array.isArray(mergedData.alternate_greetings)) {
|
|
648
|
+
mergedData.alternate_greetings = [];
|
|
649
|
+
}
|
|
650
|
+
if (spec === "v3") {
|
|
651
|
+
if (mergedData.group_only_greetings && !Array.isArray(mergedData.group_only_greetings)) {
|
|
652
|
+
mergedData.group_only_greetings = [];
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
if (spec === "v3") {
|
|
656
|
+
result.spec = "chara_card_v3";
|
|
657
|
+
result.spec_version = "3.0";
|
|
658
|
+
result.data = this.fixTimestampsInner(mergedData);
|
|
659
|
+
} else {
|
|
660
|
+
result.spec = "chara_card_v2";
|
|
661
|
+
result.spec_version = "2.0";
|
|
662
|
+
result.data = mergedData;
|
|
663
|
+
}
|
|
664
|
+
return result;
|
|
665
|
+
},
|
|
666
|
+
/**
|
|
667
|
+
* Normalize a character book (lorebook).
|
|
668
|
+
*
|
|
669
|
+
* Handles:
|
|
670
|
+
* - Ensuring required fields exist
|
|
671
|
+
* - Converting numeric position values to string enums
|
|
672
|
+
* - Moving V3-only fields to extensions for V2 compatibility
|
|
673
|
+
*
|
|
674
|
+
* @param book - Raw character book data
|
|
675
|
+
* @param spec - Target spec version
|
|
676
|
+
* @returns Normalized character book
|
|
677
|
+
*/
|
|
678
|
+
normalizeCharacterBook(book, spec) {
|
|
679
|
+
const result = {};
|
|
680
|
+
if (book.name !== void 0) result.name = book.name;
|
|
681
|
+
if (book.description !== void 0) result.description = book.description;
|
|
682
|
+
if (book.scan_depth !== void 0) result.scan_depth = book.scan_depth;
|
|
683
|
+
if (book.token_budget !== void 0) result.token_budget = book.token_budget;
|
|
684
|
+
if (book.recursive_scanning !== void 0)
|
|
685
|
+
result.recursive_scanning = book.recursive_scanning;
|
|
686
|
+
if (book.extensions !== void 0) result.extensions = deepClone(book.extensions);
|
|
687
|
+
const entries = Array.isArray(book.entries) ? book.entries : [];
|
|
688
|
+
result.entries = entries.map(
|
|
689
|
+
(entry) => this.normalizeEntry(entry, spec)
|
|
690
|
+
);
|
|
691
|
+
return result;
|
|
692
|
+
},
|
|
693
|
+
/**
|
|
694
|
+
* Normalize a single lorebook entry.
|
|
695
|
+
*
|
|
696
|
+
* Handles:
|
|
697
|
+
* - Converting numeric position to string enum
|
|
698
|
+
* - Moving V3-only fields to extensions for V2
|
|
699
|
+
* - Ensuring required fields exist
|
|
700
|
+
*
|
|
701
|
+
* @param entry - Raw entry data
|
|
702
|
+
* @param spec - Target spec version
|
|
703
|
+
* @returns Normalized entry
|
|
704
|
+
*/
|
|
705
|
+
normalizeEntry(entry, spec) {
|
|
706
|
+
const result = {};
|
|
707
|
+
result.keys = Array.isArray(entry.keys) ? [...entry.keys] : [];
|
|
708
|
+
result.content = typeof entry.content === "string" ? entry.content : "";
|
|
709
|
+
result.enabled = entry.enabled !== false;
|
|
710
|
+
result.insertion_order = typeof entry.insertion_order === "number" ? entry.insertion_order : 0;
|
|
711
|
+
if (spec === "v2") {
|
|
712
|
+
result.extensions = entry.extensions && typeof entry.extensions === "object" ? deepClone(entry.extensions) : {};
|
|
713
|
+
}
|
|
714
|
+
if (entry.case_sensitive !== void 0) result.case_sensitive = entry.case_sensitive;
|
|
715
|
+
if (entry.name !== void 0) result.name = entry.name;
|
|
716
|
+
if (entry.priority !== void 0) result.priority = entry.priority;
|
|
717
|
+
if (entry.id !== void 0) result.id = entry.id;
|
|
718
|
+
if (entry.comment !== void 0) result.comment = entry.comment;
|
|
719
|
+
if (entry.selective !== void 0) result.selective = entry.selective;
|
|
720
|
+
if (entry.secondary_keys !== void 0) {
|
|
721
|
+
result.secondary_keys = Array.isArray(entry.secondary_keys) ? [...entry.secondary_keys] : [];
|
|
722
|
+
}
|
|
723
|
+
if (entry.constant !== void 0) result.constant = entry.constant;
|
|
724
|
+
if (entry.position !== void 0) {
|
|
725
|
+
if (typeof entry.position === "number") {
|
|
726
|
+
result.position = POSITION_MAP[entry.position] || "before_char";
|
|
727
|
+
} else if (entry.position === "before_char" || entry.position === "after_char") {
|
|
728
|
+
result.position = entry.position;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (spec === "v3") {
|
|
732
|
+
if (entry.extensions !== void 0) result.extensions = deepClone(entry.extensions);
|
|
733
|
+
for (const field of V3_ONLY_ENTRY_FIELDS) {
|
|
734
|
+
if (entry[field] !== void 0) {
|
|
735
|
+
result[field] = entry[field];
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
} else {
|
|
739
|
+
const ext = result.extensions || {};
|
|
740
|
+
for (const field of V3_ONLY_ENTRY_FIELDS) {
|
|
741
|
+
if (entry[field] !== void 0) {
|
|
742
|
+
ext[field] = entry[field];
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
result.extensions = ext;
|
|
746
|
+
}
|
|
747
|
+
return result;
|
|
748
|
+
},
|
|
749
|
+
/**
|
|
750
|
+
* Fix CharacterTavern timestamp format (milliseconds -> seconds).
|
|
751
|
+
*
|
|
752
|
+
* CCv3 spec requires timestamps in seconds (Unix epoch).
|
|
753
|
+
* CharacterTavern exports timestamps in milliseconds.
|
|
754
|
+
*
|
|
755
|
+
* @param data - V3 card data
|
|
756
|
+
* @returns Card data with fixed timestamps (does not mutate input)
|
|
757
|
+
*/
|
|
758
|
+
fixTimestamps(data) {
|
|
759
|
+
const result = deepClone(data);
|
|
760
|
+
result.data = this.fixTimestampsInner(
|
|
761
|
+
result.data
|
|
762
|
+
);
|
|
763
|
+
return result;
|
|
764
|
+
},
|
|
765
|
+
/**
|
|
766
|
+
* Internal: fix timestamps in data object
|
|
767
|
+
*/
|
|
768
|
+
fixTimestampsInner(data) {
|
|
769
|
+
const result = { ...data };
|
|
770
|
+
if (typeof result.creation_date === "number" && isMilliseconds(result.creation_date)) {
|
|
771
|
+
result.creation_date = Math.floor(result.creation_date / 1e3);
|
|
772
|
+
}
|
|
773
|
+
if (typeof result.modification_date === "number" && isMilliseconds(result.modification_date)) {
|
|
774
|
+
result.modification_date = Math.floor(result.modification_date / 1e3);
|
|
775
|
+
}
|
|
776
|
+
return result;
|
|
777
|
+
},
|
|
778
|
+
/**
|
|
779
|
+
* Auto-detect spec and normalize.
|
|
780
|
+
*
|
|
781
|
+
* @param data - Raw card data
|
|
782
|
+
* @returns Normalized card data, or null if not a valid card
|
|
783
|
+
*/
|
|
784
|
+
autoNormalize(data) {
|
|
785
|
+
const spec = detectSpec(data);
|
|
786
|
+
if (!spec) return null;
|
|
787
|
+
const targetSpec = spec === "v3" ? "v3" : "v2";
|
|
788
|
+
return this.normalize(data, targetSpec);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
function zodErrorToMessage(zodError, context) {
|
|
792
|
+
const messages = zodError.errors.map((err) => {
|
|
793
|
+
const path = err.path.length > 0 ? `${err.path.join(".")}: ` : "";
|
|
794
|
+
return `${path}${err.message}`;
|
|
795
|
+
});
|
|
796
|
+
const message = messages.join("; ");
|
|
797
|
+
return context ? `${context} - ${message}` : message;
|
|
798
|
+
}
|
|
799
|
+
function getFirstErrorField(zodError) {
|
|
800
|
+
return zodError.errors[0]?.path[0]?.toString();
|
|
801
|
+
}
|
|
802
|
+
function safeParse(schema, data) {
|
|
803
|
+
const result = schema.safeParse(data);
|
|
804
|
+
if (result.success) {
|
|
805
|
+
return { success: true, data: result.data };
|
|
806
|
+
}
|
|
807
|
+
return {
|
|
808
|
+
success: false,
|
|
809
|
+
error: zodErrorToMessage(result.error),
|
|
810
|
+
field: getFirstErrorField(result.error)
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
export {
|
|
814
|
+
AssetDescriptorSchema,
|
|
815
|
+
AssetTypeSchema,
|
|
816
|
+
CCv2CharacterBookSchema,
|
|
817
|
+
CCv2DataSchema,
|
|
818
|
+
CCv2LorebookEntrySchema,
|
|
819
|
+
CCv2WrappedSchema,
|
|
820
|
+
CCv3CharacterBookSchema,
|
|
821
|
+
CCv3DataInnerSchema,
|
|
822
|
+
CCv3DataSchema,
|
|
823
|
+
CCv3LorebookEntrySchema,
|
|
824
|
+
CardNormalizer,
|
|
825
|
+
ExtractedAssetSchema,
|
|
826
|
+
ISO8601Schema,
|
|
827
|
+
OriginalShapeSchema,
|
|
828
|
+
SourceFormatSchema,
|
|
829
|
+
SpecSchema,
|
|
830
|
+
UUIDSchema,
|
|
831
|
+
createEmptyFeatures,
|
|
832
|
+
createEmptyNormalizedCard,
|
|
833
|
+
deriveFeatures,
|
|
834
|
+
detectSpec,
|
|
835
|
+
detectSpecDetailed,
|
|
836
|
+
getFirstErrorField,
|
|
837
|
+
getV2Data,
|
|
838
|
+
getV3Data,
|
|
839
|
+
hasDepthPrompt,
|
|
840
|
+
hasLorebook,
|
|
841
|
+
hasRisuExtensions,
|
|
842
|
+
hasRisuScripts,
|
|
843
|
+
isV2CardData,
|
|
844
|
+
isV3Card,
|
|
845
|
+
isWrappedV2,
|
|
846
|
+
looksLikeCard,
|
|
847
|
+
looksLikeV3Card,
|
|
848
|
+
looksLikeWrappedV2,
|
|
849
|
+
parseV2Data,
|
|
850
|
+
parseV3Card,
|
|
851
|
+
parseV3DataInner,
|
|
852
|
+
parseWrappedV2,
|
|
853
|
+
safeParse,
|
|
854
|
+
zodErrorToMessage
|
|
855
|
+
};
|
|
2
856
|
//# sourceMappingURL=schemas.js.map
|