@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.
- package/dist/charx.cjs +15 -36
- package/dist/charx.cjs.map +1 -1
- package/dist/charx.d.cts +18 -9
- package/dist/charx.d.ts +18 -9
- package/dist/charx.js +15 -36
- package/dist/charx.js.map +1 -1
- package/dist/exporter.cjs +34 -38
- package/dist/exporter.cjs.map +1 -1
- package/dist/exporter.d.cts +18 -9
- package/dist/exporter.d.ts +18 -9
- package/dist/exporter.js +34 -38
- 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 +53 -9
- package/dist/federation.d.ts +53 -9
- package/dist/federation.js +104 -36
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +34 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -21
- package/dist/index.d.ts +42 -21
- package/dist/index.js +34 -38
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +101 -15
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.d.cts +42 -14
- package/dist/loader.d.ts +42 -14
- package/dist/loader.js +101 -15
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.d.cts +34 -17
- package/dist/lorebook.d.ts +34 -17
- package/dist/normalizer.cjs +2 -2
- package/dist/normalizer.cjs.map +1 -1
- package/dist/normalizer.d.cts +60 -30
- package/dist/normalizer.d.ts +60 -30
- package/dist/normalizer.js +2 -2
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +2 -2
- package/dist/png.cjs.map +1 -1
- package/dist/png.d.cts +32 -16
- package/dist/png.d.ts +32 -16
- package/dist/png.js +2 -2
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +7 -7
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +96 -48
- package/dist/schemas.d.ts +96 -48
- package/dist/schemas.js +7 -7
- package/dist/schemas.js.map +1 -1
- package/dist/voxta.cjs +21 -4
- package/dist/voxta.cjs.map +1 -1
- package/dist/voxta.d.cts +28 -14
- package/dist/voxta.d.ts +28 -14
- package/dist/voxta.js +21 -4
- package/dist/voxta.js.map +1 -1
- package/package.json +6 -6
package/dist/loader.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<"">
|
|
@@ -1180,6 +1194,13 @@ export interface AuthoritativeMetadata {
|
|
|
1180
1194
|
tokens: TokenCounts;
|
|
1181
1195
|
/** Content hash computed server-side */
|
|
1182
1196
|
contentHash: string;
|
|
1197
|
+
/**
|
|
1198
|
+
* Content hash v2 computed server-side.
|
|
1199
|
+
*
|
|
1200
|
+
* @remarks
|
|
1201
|
+
* v1 is preserved for backwards compatibility. Prefer v2 for new storage/deduplication.
|
|
1202
|
+
*/
|
|
1203
|
+
contentHashV2?: string;
|
|
1183
1204
|
/** Whether the card has a lorebook */
|
|
1184
1205
|
hasLorebook: boolean;
|
|
1185
1206
|
/** Number of lorebook entries */
|
|
@@ -1279,6 +1300,13 @@ export declare function validateClientMetadata(clientMetadata: ClientMetadata, p
|
|
|
1279
1300
|
* @returns SHA-256 hash of canonical content
|
|
1280
1301
|
*/
|
|
1281
1302
|
export declare function computeContentHash(card: CCv3Data): Promise<string>;
|
|
1303
|
+
/**
|
|
1304
|
+
* Compute content hash v2 for a card (standalone utility)
|
|
1305
|
+
*
|
|
1306
|
+
* @param card - CCv3 card data
|
|
1307
|
+
* @returns SHA-256 hash of canonical content v2
|
|
1308
|
+
*/
|
|
1309
|
+
export declare function computeContentHashV2(card: CCv3Data): Promise<string>;
|
|
1282
1310
|
/**
|
|
1283
1311
|
* Options for synchronous metadata validation
|
|
1284
1312
|
*/
|
package/dist/loader.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<"">
|
|
@@ -1180,6 +1194,13 @@ export interface AuthoritativeMetadata {
|
|
|
1180
1194
|
tokens: TokenCounts;
|
|
1181
1195
|
/** Content hash computed server-side */
|
|
1182
1196
|
contentHash: string;
|
|
1197
|
+
/**
|
|
1198
|
+
* Content hash v2 computed server-side.
|
|
1199
|
+
*
|
|
1200
|
+
* @remarks
|
|
1201
|
+
* v1 is preserved for backwards compatibility. Prefer v2 for new storage/deduplication.
|
|
1202
|
+
*/
|
|
1203
|
+
contentHashV2?: string;
|
|
1183
1204
|
/** Whether the card has a lorebook */
|
|
1184
1205
|
hasLorebook: boolean;
|
|
1185
1206
|
/** Number of lorebook entries */
|
|
@@ -1279,6 +1300,13 @@ export declare function validateClientMetadata(clientMetadata: ClientMetadata, p
|
|
|
1279
1300
|
* @returns SHA-256 hash of canonical content
|
|
1280
1301
|
*/
|
|
1281
1302
|
export declare function computeContentHash(card: CCv3Data): Promise<string>;
|
|
1303
|
+
/**
|
|
1304
|
+
* Compute content hash v2 for a card (standalone utility)
|
|
1305
|
+
*
|
|
1306
|
+
* @param card - CCv3 card data
|
|
1307
|
+
* @returns SHA-256 hash of canonical content v2
|
|
1308
|
+
*/
|
|
1309
|
+
export declare function computeContentHashV2(card: CCv3Data): Promise<string>;
|
|
1282
1310
|
/**
|
|
1283
1311
|
* Options for synchronous metadata validation
|
|
1284
1312
|
*/
|
package/dist/loader.js
CHANGED
|
@@ -473,7 +473,7 @@ var CCv2LorebookEntrySchema = z2.object({
|
|
|
473
473
|
selective: z2.boolean().nullable().optional(),
|
|
474
474
|
secondary_keys: z2.array(z2.string()).nullable().optional(),
|
|
475
475
|
constant: z2.boolean().nullable().optional(),
|
|
476
|
-
position: z2.union([z2.enum(["before_char", "after_char"]), z2.number().int(), z2.literal("")]).nullable().optional()
|
|
476
|
+
position: z2.union([z2.enum(["before_char", "after_char", "in_chat"]), z2.number().int(), z2.literal("")]).nullable().optional()
|
|
477
477
|
}).passthrough();
|
|
478
478
|
var CCv2CharacterBookSchema = z2.object({
|
|
479
479
|
name: z2.string().optional(),
|
|
@@ -537,7 +537,7 @@ var CCv3LorebookEntrySchema = z3.object({
|
|
|
537
537
|
selective: z3.boolean().nullable().optional(),
|
|
538
538
|
secondary_keys: z3.array(z3.string()).nullable().optional(),
|
|
539
539
|
constant: z3.boolean().nullable().optional(),
|
|
540
|
-
position: z3.union([z3.enum(["before_char", "after_char"]), z3.number().int(), z3.literal("")]).nullable().optional(),
|
|
540
|
+
position: z3.union([z3.enum(["before_char", "after_char", "in_chat"]), z3.number().int(), z3.literal("")]).nullable().optional(),
|
|
541
541
|
extensions: z3.record(z3.unknown()).optional(),
|
|
542
542
|
// v3 specific - also lenient with types since SillyTavern uses numbers for enums
|
|
543
543
|
automation_id: z3.string().optional(),
|
|
@@ -8697,7 +8697,7 @@ function defaultTokenCounter(_card) {
|
|
|
8697
8697
|
total: 0
|
|
8698
8698
|
};
|
|
8699
8699
|
}
|
|
8700
|
-
function
|
|
8700
|
+
function getCanonicalContentV1(card) {
|
|
8701
8701
|
const normalized = {
|
|
8702
8702
|
name: card.data.name,
|
|
8703
8703
|
description: card.data.description || "",
|
|
@@ -8719,6 +8719,69 @@ function getCanonicalContent(card) {
|
|
|
8719
8719
|
};
|
|
8720
8720
|
return JSON.stringify(normalized, Object.keys(normalized).sort());
|
|
8721
8721
|
}
|
|
8722
|
+
function stableStringify(value) {
|
|
8723
|
+
if (value === null) return "null";
|
|
8724
|
+
switch (typeof value) {
|
|
8725
|
+
case "string":
|
|
8726
|
+
return JSON.stringify(value);
|
|
8727
|
+
case "number":
|
|
8728
|
+
return Number.isFinite(value) ? String(value) : "null";
|
|
8729
|
+
case "boolean":
|
|
8730
|
+
return value ? "true" : "false";
|
|
8731
|
+
case "bigint":
|
|
8732
|
+
return JSON.stringify(value.toString());
|
|
8733
|
+
case "undefined":
|
|
8734
|
+
case "function":
|
|
8735
|
+
case "symbol":
|
|
8736
|
+
return "null";
|
|
8737
|
+
case "object": {
|
|
8738
|
+
if (Array.isArray(value)) {
|
|
8739
|
+
const parts2 = value.map((item) => {
|
|
8740
|
+
if (item === void 0 || typeof item === "function" || typeof item === "symbol") {
|
|
8741
|
+
return "null";
|
|
8742
|
+
}
|
|
8743
|
+
return stableStringify(item);
|
|
8744
|
+
});
|
|
8745
|
+
return `[${parts2.join(",")}]`;
|
|
8746
|
+
}
|
|
8747
|
+
const obj = value;
|
|
8748
|
+
const keys = Object.keys(obj).sort();
|
|
8749
|
+
const parts = [];
|
|
8750
|
+
for (const key of keys) {
|
|
8751
|
+
const v = obj[key];
|
|
8752
|
+
if (v === void 0 || typeof v === "function" || typeof v === "symbol") {
|
|
8753
|
+
continue;
|
|
8754
|
+
}
|
|
8755
|
+
parts.push(`${JSON.stringify(key)}:${stableStringify(v)}`);
|
|
8756
|
+
}
|
|
8757
|
+
return `{${parts.join(",")}}`;
|
|
8758
|
+
}
|
|
8759
|
+
default:
|
|
8760
|
+
return "null";
|
|
8761
|
+
}
|
|
8762
|
+
}
|
|
8763
|
+
function getCanonicalContentV2(card) {
|
|
8764
|
+
const normalized = {
|
|
8765
|
+
name: card.data.name,
|
|
8766
|
+
description: card.data.description || "",
|
|
8767
|
+
personality: card.data.personality || "",
|
|
8768
|
+
scenario: card.data.scenario || "",
|
|
8769
|
+
first_mes: card.data.first_mes || "",
|
|
8770
|
+
mes_example: card.data.mes_example || "",
|
|
8771
|
+
system_prompt: card.data.system_prompt || "",
|
|
8772
|
+
post_history_instructions: card.data.post_history_instructions || "",
|
|
8773
|
+
alternate_greetings: card.data.alternate_greetings || [],
|
|
8774
|
+
character_book: card.data.character_book ? {
|
|
8775
|
+
entries: (card.data.character_book.entries || []).map((e) => ({
|
|
8776
|
+
keys: e.keys,
|
|
8777
|
+
content: e.content,
|
|
8778
|
+
enabled: e.enabled
|
|
8779
|
+
}))
|
|
8780
|
+
} : null,
|
|
8781
|
+
creator_notes: card.data.creator_notes || ""
|
|
8782
|
+
};
|
|
8783
|
+
return stableStringify(normalized);
|
|
8784
|
+
}
|
|
8722
8785
|
function isWithinTolerance(clientValue, computedValue, tolerance) {
|
|
8723
8786
|
if (clientValue === void 0) return false;
|
|
8724
8787
|
if (computedValue === 0) return clientValue === 0;
|
|
@@ -8739,15 +8802,18 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8739
8802
|
const warnings = [];
|
|
8740
8803
|
const errors = [];
|
|
8741
8804
|
const computedTokens = countTokens(card);
|
|
8742
|
-
const
|
|
8743
|
-
const
|
|
8805
|
+
const canonicalContentV1 = getCanonicalContentV1(card);
|
|
8806
|
+
const canonicalContentV2 = getCanonicalContentV2(card);
|
|
8807
|
+
const computedHashV1 = await computeHash(canonicalContentV1);
|
|
8808
|
+
const computedHashV2 = await computeHash(canonicalContentV2);
|
|
8744
8809
|
const entries = card.data.character_book?.entries || [];
|
|
8745
8810
|
const computedHasLorebook = entries.length > 0;
|
|
8746
8811
|
const computedLorebookCount = entries.length;
|
|
8747
8812
|
const authoritative = {
|
|
8748
8813
|
name: card.data.name,
|
|
8749
8814
|
tokens: computedTokens,
|
|
8750
|
-
contentHash:
|
|
8815
|
+
contentHash: computedHashV1,
|
|
8816
|
+
contentHashV2: computedHashV2,
|
|
8751
8817
|
hasLorebook: computedHasLorebook,
|
|
8752
8818
|
lorebookEntriesCount: computedLorebookCount
|
|
8753
8819
|
};
|
|
@@ -8759,21 +8825,27 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8759
8825
|
withinTolerance: false
|
|
8760
8826
|
});
|
|
8761
8827
|
}
|
|
8762
|
-
|
|
8828
|
+
const matchesV1 = clientMetadata.contentHash === computedHashV1;
|
|
8829
|
+
const matchesV2 = clientMetadata.contentHash === computedHashV2;
|
|
8830
|
+
if (!matchesV1 && !matchesV2) {
|
|
8763
8831
|
const disc = {
|
|
8764
8832
|
field: "contentHash",
|
|
8765
8833
|
clientValue: clientMetadata.contentHash,
|
|
8766
|
-
computedValue:
|
|
8834
|
+
computedValue: computedHashV1,
|
|
8767
8835
|
withinTolerance: false
|
|
8768
8836
|
};
|
|
8769
8837
|
discrepancies.push(disc);
|
|
8770
8838
|
if (allowHashMismatch) {
|
|
8771
8839
|
warnings.push(
|
|
8772
|
-
`Content hash mismatch: client=${clientMetadata.contentHash.substring(0, 8)}..., server=${
|
|
8840
|
+
`Content hash mismatch: client=${clientMetadata.contentHash.substring(0, 8)}..., server(v1)=${computedHashV1.substring(0, 8)}..., server(v2)=${computedHashV2.substring(0, 8)}...`
|
|
8773
8841
|
);
|
|
8774
8842
|
} else {
|
|
8775
8843
|
errors.push("Content hash mismatch - possible tampering or encoding difference");
|
|
8776
8844
|
}
|
|
8845
|
+
} else if (matchesV1 && !matchesV2) {
|
|
8846
|
+
warnings.push(
|
|
8847
|
+
"Client contentHash matches legacy v1 canonicalization. Prefer authoritative.contentHashV2 for new storage."
|
|
8848
|
+
);
|
|
8777
8849
|
}
|
|
8778
8850
|
const tokenFields = [
|
|
8779
8851
|
"description",
|
|
@@ -8854,7 +8926,11 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8854
8926
|
};
|
|
8855
8927
|
}
|
|
8856
8928
|
async function computeContentHash(card) {
|
|
8857
|
-
const content =
|
|
8929
|
+
const content = getCanonicalContentV1(card);
|
|
8930
|
+
return sha256Hash(content);
|
|
8931
|
+
}
|
|
8932
|
+
async function computeContentHashV2(card) {
|
|
8933
|
+
const content = getCanonicalContentV2(card);
|
|
8858
8934
|
return sha256Hash(content);
|
|
8859
8935
|
}
|
|
8860
8936
|
function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
@@ -8870,15 +8946,18 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8870
8946
|
const warnings = [];
|
|
8871
8947
|
const errors = [];
|
|
8872
8948
|
const computedTokens = countTokens(card);
|
|
8873
|
-
const
|
|
8874
|
-
const
|
|
8949
|
+
const canonicalContentV1 = getCanonicalContentV1(card);
|
|
8950
|
+
const canonicalContentV2 = getCanonicalContentV2(card);
|
|
8951
|
+
const computedHashV1 = computeHash(canonicalContentV1);
|
|
8952
|
+
const computedHashV2 = computeHash(canonicalContentV2);
|
|
8875
8953
|
const entries = card.data.character_book?.entries || [];
|
|
8876
8954
|
const computedHasLorebook = entries.length > 0;
|
|
8877
8955
|
const computedLorebookCount = entries.length;
|
|
8878
8956
|
const authoritative = {
|
|
8879
8957
|
name: card.data.name,
|
|
8880
8958
|
tokens: computedTokens,
|
|
8881
|
-
contentHash:
|
|
8959
|
+
contentHash: computedHashV1,
|
|
8960
|
+
contentHashV2: computedHashV2,
|
|
8882
8961
|
hasLorebook: computedHasLorebook,
|
|
8883
8962
|
lorebookEntriesCount: computedLorebookCount
|
|
8884
8963
|
};
|
|
@@ -8890,11 +8969,13 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8890
8969
|
withinTolerance: false
|
|
8891
8970
|
});
|
|
8892
8971
|
}
|
|
8893
|
-
|
|
8972
|
+
const matchesV1 = clientMetadata.contentHash === computedHashV1;
|
|
8973
|
+
const matchesV2 = clientMetadata.contentHash === computedHashV2;
|
|
8974
|
+
if (!matchesV1 && !matchesV2) {
|
|
8894
8975
|
discrepancies.push({
|
|
8895
8976
|
field: "contentHash",
|
|
8896
8977
|
clientValue: clientMetadata.contentHash,
|
|
8897
|
-
computedValue:
|
|
8978
|
+
computedValue: computedHashV1,
|
|
8898
8979
|
withinTolerance: false
|
|
8899
8980
|
});
|
|
8900
8981
|
if (allowHashMismatch) {
|
|
@@ -8902,6 +8983,10 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8902
8983
|
} else {
|
|
8903
8984
|
errors.push("Content hash mismatch");
|
|
8904
8985
|
}
|
|
8986
|
+
} else if (matchesV1 && !matchesV2) {
|
|
8987
|
+
warnings.push(
|
|
8988
|
+
"Client contentHash matches legacy v1 canonicalization. Prefer authoritative.contentHashV2 for new storage."
|
|
8989
|
+
);
|
|
8905
8990
|
}
|
|
8906
8991
|
const tokenFields = [
|
|
8907
8992
|
"description",
|
|
@@ -8970,6 +9055,7 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8970
9055
|
}
|
|
8971
9056
|
export {
|
|
8972
9057
|
computeContentHash,
|
|
9058
|
+
computeContentHashV2,
|
|
8973
9059
|
detectFormat,
|
|
8974
9060
|
getContainerFormat,
|
|
8975
9061
|
mightBeCard,
|