@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/loader.d.cts
CHANGED
|
@@ -13,8 +13,8 @@ export type BinaryData = Uint8Array;
|
|
|
13
13
|
declare const CCv3CharacterBookSchema: z.ZodObject<{
|
|
14
14
|
name: z.ZodOptional<z.ZodString>;
|
|
15
15
|
description: z.ZodOptional<z.ZodString>;
|
|
16
|
-
scan_depth: z.ZodOptional<z.ZodNumber>;
|
|
17
|
-
token_budget: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
17
|
+
token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
18
18
|
recursive_scanning: z.ZodOptional<z.ZodBoolean>;
|
|
19
19
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
20
|
entries: z.ZodArray<z.ZodObject<{
|
|
@@ -250,8 +250,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
|
|
|
250
250
|
}, z.ZodTypeAny, "passthrough">[];
|
|
251
251
|
name?: string | undefined;
|
|
252
252
|
description?: string | undefined;
|
|
253
|
-
scan_depth?:
|
|
254
|
-
token_budget?:
|
|
253
|
+
scan_depth?: unknown;
|
|
254
|
+
token_budget?: unknown;
|
|
255
255
|
recursive_scanning?: boolean | undefined;
|
|
256
256
|
extensions?: Record<string, unknown> | undefined;
|
|
257
257
|
}>;
|
|
@@ -276,8 +276,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
276
276
|
character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
277
277
|
name: z.ZodOptional<z.ZodString>;
|
|
278
278
|
description: z.ZodOptional<z.ZodString>;
|
|
279
|
-
scan_depth: z.ZodOptional<z.ZodNumber>;
|
|
280
|
-
token_budget: z.ZodOptional<z.ZodNumber>;
|
|
279
|
+
scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
280
|
+
token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
281
281
|
recursive_scanning: z.ZodOptional<z.ZodBoolean>;
|
|
282
282
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
283
283
|
entries: z.ZodArray<z.ZodObject<{
|
|
@@ -513,14 +513,14 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
513
513
|
}, z.ZodTypeAny, "passthrough">[];
|
|
514
514
|
name?: string | undefined;
|
|
515
515
|
description?: string | undefined;
|
|
516
|
-
scan_depth?:
|
|
517
|
-
token_budget?:
|
|
516
|
+
scan_depth?: unknown;
|
|
517
|
+
token_budget?: unknown;
|
|
518
518
|
recursive_scanning?: boolean | undefined;
|
|
519
519
|
extensions?: Record<string, unknown> | undefined;
|
|
520
520
|
}>>>;
|
|
521
521
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
522
522
|
assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
523
|
-
type: z.ZodEnum<[
|
|
523
|
+
type: z.ZodEffects<z.ZodEnum<[
|
|
524
524
|
"icon",
|
|
525
525
|
"background",
|
|
526
526
|
"emotion",
|
|
@@ -529,7 +529,7 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
529
529
|
"video",
|
|
530
530
|
"custom",
|
|
531
531
|
"x-risu-asset"
|
|
532
|
-
]>;
|
|
532
|
+
]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
|
|
533
533
|
uri: z.ZodString;
|
|
534
534
|
name: z.ZodString;
|
|
535
535
|
ext: z.ZodString;
|
|
@@ -540,15 +540,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
540
540
|
ext: string;
|
|
541
541
|
}, {
|
|
542
542
|
name: string;
|
|
543
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
544
543
|
uri: string;
|
|
545
544
|
ext: string;
|
|
545
|
+
type?: unknown;
|
|
546
546
|
}>, "many">>;
|
|
547
547
|
nickname: z.ZodOptional<z.ZodString>;
|
|
548
548
|
creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
549
549
|
source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
550
|
-
creation_date: z.ZodOptional<z.ZodNumber>;
|
|
551
|
-
modification_date: z.ZodOptional<z.ZodNumber>;
|
|
550
|
+
creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
551
|
+
modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
552
552
|
}, "strip", z.ZodTypeAny, {
|
|
553
553
|
name: string;
|
|
554
554
|
description: string;
|
|
@@ -689,8 +689,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
689
689
|
}, z.ZodTypeAny, "passthrough">[];
|
|
690
690
|
name?: string | undefined;
|
|
691
691
|
description?: string | undefined;
|
|
692
|
-
scan_depth?:
|
|
693
|
-
token_budget?:
|
|
692
|
+
scan_depth?: unknown;
|
|
693
|
+
token_budget?: unknown;
|
|
694
694
|
recursive_scanning?: boolean | undefined;
|
|
695
695
|
extensions?: Record<string, unknown> | undefined;
|
|
696
696
|
} | null | undefined;
|
|
@@ -700,15 +700,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
700
700
|
group_only_greetings?: string[] | undefined;
|
|
701
701
|
assets?: {
|
|
702
702
|
name: string;
|
|
703
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
704
703
|
uri: string;
|
|
705
704
|
ext: string;
|
|
705
|
+
type?: unknown;
|
|
706
706
|
}[] | undefined;
|
|
707
707
|
nickname?: string | undefined;
|
|
708
708
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
709
709
|
source?: string[] | undefined;
|
|
710
|
-
creation_date?:
|
|
711
|
-
modification_date?:
|
|
710
|
+
creation_date?: unknown;
|
|
711
|
+
modification_date?: unknown;
|
|
712
712
|
}>;
|
|
713
713
|
}, "strip", z.ZodTypeAny, {
|
|
714
714
|
data: {
|
|
@@ -855,8 +855,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
855
855
|
}, z.ZodTypeAny, "passthrough">[];
|
|
856
856
|
name?: string | undefined;
|
|
857
857
|
description?: string | undefined;
|
|
858
|
-
scan_depth?:
|
|
859
|
-
token_budget?:
|
|
858
|
+
scan_depth?: unknown;
|
|
859
|
+
token_budget?: unknown;
|
|
860
860
|
recursive_scanning?: boolean | undefined;
|
|
861
861
|
extensions?: Record<string, unknown> | undefined;
|
|
862
862
|
} | null | undefined;
|
|
@@ -866,15 +866,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
866
866
|
group_only_greetings?: string[] | undefined;
|
|
867
867
|
assets?: {
|
|
868
868
|
name: string;
|
|
869
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
870
869
|
uri: string;
|
|
871
870
|
ext: string;
|
|
871
|
+
type?: unknown;
|
|
872
872
|
}[] | undefined;
|
|
873
873
|
nickname?: string | undefined;
|
|
874
874
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
875
875
|
source?: string[] | undefined;
|
|
876
|
-
creation_date?:
|
|
877
|
-
modification_date?:
|
|
876
|
+
creation_date?: unknown;
|
|
877
|
+
modification_date?: unknown;
|
|
878
878
|
};
|
|
879
879
|
spec: "chara_card_v3";
|
|
880
880
|
spec_version: "3.0";
|
|
@@ -1194,6 +1194,13 @@ export interface AuthoritativeMetadata {
|
|
|
1194
1194
|
tokens: TokenCounts;
|
|
1195
1195
|
/** Content hash computed server-side */
|
|
1196
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;
|
|
1197
1204
|
/** Whether the card has a lorebook */
|
|
1198
1205
|
hasLorebook: boolean;
|
|
1199
1206
|
/** Number of lorebook entries */
|
|
@@ -1293,6 +1300,13 @@ export declare function validateClientMetadata(clientMetadata: ClientMetadata, p
|
|
|
1293
1300
|
* @returns SHA-256 hash of canonical content
|
|
1294
1301
|
*/
|
|
1295
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>;
|
|
1296
1310
|
/**
|
|
1297
1311
|
* Options for synchronous metadata validation
|
|
1298
1312
|
*/
|
package/dist/loader.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export type BinaryData = Uint8Array;
|
|
|
13
13
|
declare const CCv3CharacterBookSchema: z.ZodObject<{
|
|
14
14
|
name: z.ZodOptional<z.ZodString>;
|
|
15
15
|
description: z.ZodOptional<z.ZodString>;
|
|
16
|
-
scan_depth: z.ZodOptional<z.ZodNumber>;
|
|
17
|
-
token_budget: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
17
|
+
token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
18
18
|
recursive_scanning: z.ZodOptional<z.ZodBoolean>;
|
|
19
19
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
20
|
entries: z.ZodArray<z.ZodObject<{
|
|
@@ -250,8 +250,8 @@ declare const CCv3CharacterBookSchema: z.ZodObject<{
|
|
|
250
250
|
}, z.ZodTypeAny, "passthrough">[];
|
|
251
251
|
name?: string | undefined;
|
|
252
252
|
description?: string | undefined;
|
|
253
|
-
scan_depth?:
|
|
254
|
-
token_budget?:
|
|
253
|
+
scan_depth?: unknown;
|
|
254
|
+
token_budget?: unknown;
|
|
255
255
|
recursive_scanning?: boolean | undefined;
|
|
256
256
|
extensions?: Record<string, unknown> | undefined;
|
|
257
257
|
}>;
|
|
@@ -276,8 +276,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
276
276
|
character_book: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
277
277
|
name: z.ZodOptional<z.ZodString>;
|
|
278
278
|
description: z.ZodOptional<z.ZodString>;
|
|
279
|
-
scan_depth: z.ZodOptional<z.ZodNumber>;
|
|
280
|
-
token_budget: z.ZodOptional<z.ZodNumber>;
|
|
279
|
+
scan_depth: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
280
|
+
token_budget: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
281
281
|
recursive_scanning: z.ZodOptional<z.ZodBoolean>;
|
|
282
282
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
283
283
|
entries: z.ZodArray<z.ZodObject<{
|
|
@@ -513,14 +513,14 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
513
513
|
}, z.ZodTypeAny, "passthrough">[];
|
|
514
514
|
name?: string | undefined;
|
|
515
515
|
description?: string | undefined;
|
|
516
|
-
scan_depth?:
|
|
517
|
-
token_budget?:
|
|
516
|
+
scan_depth?: unknown;
|
|
517
|
+
token_budget?: unknown;
|
|
518
518
|
recursive_scanning?: boolean | undefined;
|
|
519
519
|
extensions?: Record<string, unknown> | undefined;
|
|
520
520
|
}>>>;
|
|
521
521
|
extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
522
522
|
assets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
523
|
-
type: z.ZodEnum<[
|
|
523
|
+
type: z.ZodEffects<z.ZodEnum<[
|
|
524
524
|
"icon",
|
|
525
525
|
"background",
|
|
526
526
|
"emotion",
|
|
@@ -529,7 +529,7 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
529
529
|
"video",
|
|
530
530
|
"custom",
|
|
531
531
|
"x-risu-asset"
|
|
532
|
-
]>;
|
|
532
|
+
]>, "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset", unknown>;
|
|
533
533
|
uri: z.ZodString;
|
|
534
534
|
name: z.ZodString;
|
|
535
535
|
ext: z.ZodString;
|
|
@@ -540,15 +540,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
540
540
|
ext: string;
|
|
541
541
|
}, {
|
|
542
542
|
name: string;
|
|
543
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
544
543
|
uri: string;
|
|
545
544
|
ext: string;
|
|
545
|
+
type?: unknown;
|
|
546
546
|
}>, "many">>;
|
|
547
547
|
nickname: z.ZodOptional<z.ZodString>;
|
|
548
548
|
creator_notes_multilingual: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
549
549
|
source: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
550
|
-
creation_date: z.ZodOptional<z.ZodNumber>;
|
|
551
|
-
modification_date: z.ZodOptional<z.ZodNumber>;
|
|
550
|
+
creation_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
551
|
+
modification_date: z.ZodEffects<z.ZodOptional<z.ZodNumber>, number | undefined, unknown>;
|
|
552
552
|
}, "strip", z.ZodTypeAny, {
|
|
553
553
|
name: string;
|
|
554
554
|
description: string;
|
|
@@ -689,8 +689,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
689
689
|
}, z.ZodTypeAny, "passthrough">[];
|
|
690
690
|
name?: string | undefined;
|
|
691
691
|
description?: string | undefined;
|
|
692
|
-
scan_depth?:
|
|
693
|
-
token_budget?:
|
|
692
|
+
scan_depth?: unknown;
|
|
693
|
+
token_budget?: unknown;
|
|
694
694
|
recursive_scanning?: boolean | undefined;
|
|
695
695
|
extensions?: Record<string, unknown> | undefined;
|
|
696
696
|
} | null | undefined;
|
|
@@ -700,15 +700,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
700
700
|
group_only_greetings?: string[] | undefined;
|
|
701
701
|
assets?: {
|
|
702
702
|
name: string;
|
|
703
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
704
703
|
uri: string;
|
|
705
704
|
ext: string;
|
|
705
|
+
type?: unknown;
|
|
706
706
|
}[] | undefined;
|
|
707
707
|
nickname?: string | undefined;
|
|
708
708
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
709
709
|
source?: string[] | undefined;
|
|
710
|
-
creation_date?:
|
|
711
|
-
modification_date?:
|
|
710
|
+
creation_date?: unknown;
|
|
711
|
+
modification_date?: unknown;
|
|
712
712
|
}>;
|
|
713
713
|
}, "strip", z.ZodTypeAny, {
|
|
714
714
|
data: {
|
|
@@ -855,8 +855,8 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
855
855
|
}, z.ZodTypeAny, "passthrough">[];
|
|
856
856
|
name?: string | undefined;
|
|
857
857
|
description?: string | undefined;
|
|
858
|
-
scan_depth?:
|
|
859
|
-
token_budget?:
|
|
858
|
+
scan_depth?: unknown;
|
|
859
|
+
token_budget?: unknown;
|
|
860
860
|
recursive_scanning?: boolean | undefined;
|
|
861
861
|
extensions?: Record<string, unknown> | undefined;
|
|
862
862
|
} | null | undefined;
|
|
@@ -866,15 +866,15 @@ declare const CCv3DataSchema: z.ZodObject<{
|
|
|
866
866
|
group_only_greetings?: string[] | undefined;
|
|
867
867
|
assets?: {
|
|
868
868
|
name: string;
|
|
869
|
-
type: "custom" | "icon" | "background" | "emotion" | "user_icon" | "sound" | "video" | "x-risu-asset";
|
|
870
869
|
uri: string;
|
|
871
870
|
ext: string;
|
|
871
|
+
type?: unknown;
|
|
872
872
|
}[] | undefined;
|
|
873
873
|
nickname?: string | undefined;
|
|
874
874
|
creator_notes_multilingual?: Record<string, string> | undefined;
|
|
875
875
|
source?: string[] | undefined;
|
|
876
|
-
creation_date?:
|
|
877
|
-
modification_date?:
|
|
876
|
+
creation_date?: unknown;
|
|
877
|
+
modification_date?: unknown;
|
|
878
878
|
};
|
|
879
879
|
spec: "chara_card_v3";
|
|
880
880
|
spec_version: "3.0";
|
|
@@ -1194,6 +1194,13 @@ export interface AuthoritativeMetadata {
|
|
|
1194
1194
|
tokens: TokenCounts;
|
|
1195
1195
|
/** Content hash computed server-side */
|
|
1196
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;
|
|
1197
1204
|
/** Whether the card has a lorebook */
|
|
1198
1205
|
hasLorebook: boolean;
|
|
1199
1206
|
/** Number of lorebook entries */
|
|
@@ -1293,6 +1300,13 @@ export declare function validateClientMetadata(clientMetadata: ClientMetadata, p
|
|
|
1293
1300
|
* @returns SHA-256 hash of canonical content
|
|
1294
1301
|
*/
|
|
1295
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>;
|
|
1296
1310
|
/**
|
|
1297
1311
|
* Options for synchronous metadata validation
|
|
1298
1312
|
*/
|
package/dist/loader.js
CHANGED
|
@@ -413,6 +413,58 @@ import { z } from "zod";
|
|
|
413
413
|
import { z as z2 } from "zod";
|
|
414
414
|
import { z as z3 } from "zod";
|
|
415
415
|
import "zod";
|
|
416
|
+
function preprocessTimestamp(val) {
|
|
417
|
+
if (val === null || val === void 0) return void 0;
|
|
418
|
+
let num;
|
|
419
|
+
if (typeof val === "number") {
|
|
420
|
+
num = val;
|
|
421
|
+
} else if (typeof val === "string") {
|
|
422
|
+
const trimmed = val.trim();
|
|
423
|
+
if (!trimmed) return void 0;
|
|
424
|
+
const parsed = Number(trimmed);
|
|
425
|
+
if (!isNaN(parsed)) {
|
|
426
|
+
num = parsed;
|
|
427
|
+
} else {
|
|
428
|
+
const date = new Date(trimmed);
|
|
429
|
+
if (isNaN(date.getTime())) return void 0;
|
|
430
|
+
num = Math.floor(date.getTime() / 1e3);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
return void 0;
|
|
434
|
+
}
|
|
435
|
+
if (num > 1e10) {
|
|
436
|
+
num = Math.floor(num / 1e3);
|
|
437
|
+
}
|
|
438
|
+
if (num < 0) return void 0;
|
|
439
|
+
return num;
|
|
440
|
+
}
|
|
441
|
+
function preprocessNumeric(val) {
|
|
442
|
+
if (val === null || val === void 0) return void 0;
|
|
443
|
+
if (typeof val === "number") {
|
|
444
|
+
return isNaN(val) ? void 0 : val;
|
|
445
|
+
}
|
|
446
|
+
if (typeof val === "string") {
|
|
447
|
+
const trimmed = val.trim();
|
|
448
|
+
if (!trimmed) return void 0;
|
|
449
|
+
const parsed = Number(trimmed);
|
|
450
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
451
|
+
}
|
|
452
|
+
return void 0;
|
|
453
|
+
}
|
|
454
|
+
var KNOWN_ASSET_TYPES = /* @__PURE__ */ new Set([
|
|
455
|
+
"icon",
|
|
456
|
+
"background",
|
|
457
|
+
"emotion",
|
|
458
|
+
"user_icon",
|
|
459
|
+
"sound",
|
|
460
|
+
"video",
|
|
461
|
+
"custom",
|
|
462
|
+
"x-risu-asset"
|
|
463
|
+
]);
|
|
464
|
+
function preprocessAssetType(val) {
|
|
465
|
+
if (typeof val !== "string") return "custom";
|
|
466
|
+
return KNOWN_ASSET_TYPES.has(val) ? val : "custom";
|
|
467
|
+
}
|
|
416
468
|
var ISO8601Schema = z.string().datetime();
|
|
417
469
|
var UUIDSchema = z.string().uuid();
|
|
418
470
|
var SpecSchema = z.enum(["v2", "v3"]);
|
|
@@ -435,16 +487,19 @@ var SourceFormatSchema = z.enum([
|
|
|
435
487
|
// VoxPkg format
|
|
436
488
|
]);
|
|
437
489
|
var OriginalShapeSchema = z.enum(["wrapped", "unwrapped", "legacy"]);
|
|
438
|
-
var AssetTypeSchema = z.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
490
|
+
var AssetTypeSchema = z.preprocess(
|
|
491
|
+
preprocessAssetType,
|
|
492
|
+
z.enum([
|
|
493
|
+
"icon",
|
|
494
|
+
"background",
|
|
495
|
+
"emotion",
|
|
496
|
+
"user_icon",
|
|
497
|
+
"sound",
|
|
498
|
+
"video",
|
|
499
|
+
"custom",
|
|
500
|
+
"x-risu-asset"
|
|
501
|
+
])
|
|
502
|
+
);
|
|
448
503
|
var AssetDescriptorSchema = z.object({
|
|
449
504
|
type: AssetTypeSchema,
|
|
450
505
|
uri: z.string(),
|
|
@@ -478,8 +533,8 @@ var CCv2LorebookEntrySchema = z2.object({
|
|
|
478
533
|
var CCv2CharacterBookSchema = z2.object({
|
|
479
534
|
name: z2.string().optional(),
|
|
480
535
|
description: z2.string().optional(),
|
|
481
|
-
scan_depth: z2.number().int().nonnegative().optional(),
|
|
482
|
-
token_budget: z2.number().int().nonnegative().optional(),
|
|
536
|
+
scan_depth: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
|
|
537
|
+
token_budget: z2.preprocess(preprocessNumeric, z2.number().int().nonnegative().optional()),
|
|
483
538
|
recursive_scanning: z2.boolean().optional(),
|
|
484
539
|
extensions: z2.record(z2.unknown()).optional(),
|
|
485
540
|
entries: z2.array(CCv2LorebookEntrySchema)
|
|
@@ -553,8 +608,8 @@ var CCv3LorebookEntrySchema = z3.object({
|
|
|
553
608
|
var CCv3CharacterBookSchema = z3.object({
|
|
554
609
|
name: z3.string().optional(),
|
|
555
610
|
description: z3.string().optional(),
|
|
556
|
-
scan_depth: z3.number().int().nonnegative().optional(),
|
|
557
|
-
token_budget: z3.number().int().nonnegative().optional(),
|
|
611
|
+
scan_depth: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
|
|
612
|
+
token_budget: z3.preprocess(preprocessNumeric, z3.number().int().nonnegative().optional()),
|
|
558
613
|
recursive_scanning: z3.boolean().optional(),
|
|
559
614
|
extensions: z3.record(z3.unknown()).optional(),
|
|
560
615
|
entries: z3.array(CCv3LorebookEntrySchema)
|
|
@@ -586,10 +641,9 @@ var CCv3DataInnerSchema = z3.object({
|
|
|
586
641
|
nickname: z3.string().optional(),
|
|
587
642
|
creator_notes_multilingual: z3.record(z3.string()).optional(),
|
|
588
643
|
source: z3.array(z3.string()).optional(),
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
modification_date: z3.number().int().nonnegative().optional()
|
|
592
|
-
// Unix timestamp in seconds
|
|
644
|
+
// Unix timestamps - preprocess to handle ISO strings, numeric strings, milliseconds
|
|
645
|
+
creation_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional()),
|
|
646
|
+
modification_date: z3.preprocess(preprocessTimestamp, z3.number().int().nonnegative().optional())
|
|
593
647
|
});
|
|
594
648
|
var CCv3DataSchema = z3.object({
|
|
595
649
|
spec: z3.literal("chara_card_v3"),
|
|
@@ -8697,7 +8751,7 @@ function defaultTokenCounter(_card) {
|
|
|
8697
8751
|
total: 0
|
|
8698
8752
|
};
|
|
8699
8753
|
}
|
|
8700
|
-
function
|
|
8754
|
+
function getCanonicalContentV1(card) {
|
|
8701
8755
|
const normalized = {
|
|
8702
8756
|
name: card.data.name,
|
|
8703
8757
|
description: card.data.description || "",
|
|
@@ -8719,6 +8773,69 @@ function getCanonicalContent(card) {
|
|
|
8719
8773
|
};
|
|
8720
8774
|
return JSON.stringify(normalized, Object.keys(normalized).sort());
|
|
8721
8775
|
}
|
|
8776
|
+
function stableStringify(value) {
|
|
8777
|
+
if (value === null) return "null";
|
|
8778
|
+
switch (typeof value) {
|
|
8779
|
+
case "string":
|
|
8780
|
+
return JSON.stringify(value);
|
|
8781
|
+
case "number":
|
|
8782
|
+
return Number.isFinite(value) ? String(value) : "null";
|
|
8783
|
+
case "boolean":
|
|
8784
|
+
return value ? "true" : "false";
|
|
8785
|
+
case "bigint":
|
|
8786
|
+
return JSON.stringify(value.toString());
|
|
8787
|
+
case "undefined":
|
|
8788
|
+
case "function":
|
|
8789
|
+
case "symbol":
|
|
8790
|
+
return "null";
|
|
8791
|
+
case "object": {
|
|
8792
|
+
if (Array.isArray(value)) {
|
|
8793
|
+
const parts2 = value.map((item) => {
|
|
8794
|
+
if (item === void 0 || typeof item === "function" || typeof item === "symbol") {
|
|
8795
|
+
return "null";
|
|
8796
|
+
}
|
|
8797
|
+
return stableStringify(item);
|
|
8798
|
+
});
|
|
8799
|
+
return `[${parts2.join(",")}]`;
|
|
8800
|
+
}
|
|
8801
|
+
const obj = value;
|
|
8802
|
+
const keys = Object.keys(obj).sort();
|
|
8803
|
+
const parts = [];
|
|
8804
|
+
for (const key of keys) {
|
|
8805
|
+
const v = obj[key];
|
|
8806
|
+
if (v === void 0 || typeof v === "function" || typeof v === "symbol") {
|
|
8807
|
+
continue;
|
|
8808
|
+
}
|
|
8809
|
+
parts.push(`${JSON.stringify(key)}:${stableStringify(v)}`);
|
|
8810
|
+
}
|
|
8811
|
+
return `{${parts.join(",")}}`;
|
|
8812
|
+
}
|
|
8813
|
+
default:
|
|
8814
|
+
return "null";
|
|
8815
|
+
}
|
|
8816
|
+
}
|
|
8817
|
+
function getCanonicalContentV2(card) {
|
|
8818
|
+
const normalized = {
|
|
8819
|
+
name: card.data.name,
|
|
8820
|
+
description: card.data.description || "",
|
|
8821
|
+
personality: card.data.personality || "",
|
|
8822
|
+
scenario: card.data.scenario || "",
|
|
8823
|
+
first_mes: card.data.first_mes || "",
|
|
8824
|
+
mes_example: card.data.mes_example || "",
|
|
8825
|
+
system_prompt: card.data.system_prompt || "",
|
|
8826
|
+
post_history_instructions: card.data.post_history_instructions || "",
|
|
8827
|
+
alternate_greetings: card.data.alternate_greetings || [],
|
|
8828
|
+
character_book: card.data.character_book ? {
|
|
8829
|
+
entries: (card.data.character_book.entries || []).map((e) => ({
|
|
8830
|
+
keys: e.keys,
|
|
8831
|
+
content: e.content,
|
|
8832
|
+
enabled: e.enabled
|
|
8833
|
+
}))
|
|
8834
|
+
} : null,
|
|
8835
|
+
creator_notes: card.data.creator_notes || ""
|
|
8836
|
+
};
|
|
8837
|
+
return stableStringify(normalized);
|
|
8838
|
+
}
|
|
8722
8839
|
function isWithinTolerance(clientValue, computedValue, tolerance) {
|
|
8723
8840
|
if (clientValue === void 0) return false;
|
|
8724
8841
|
if (computedValue === 0) return clientValue === 0;
|
|
@@ -8739,15 +8856,18 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8739
8856
|
const warnings = [];
|
|
8740
8857
|
const errors = [];
|
|
8741
8858
|
const computedTokens = countTokens(card);
|
|
8742
|
-
const
|
|
8743
|
-
const
|
|
8859
|
+
const canonicalContentV1 = getCanonicalContentV1(card);
|
|
8860
|
+
const canonicalContentV2 = getCanonicalContentV2(card);
|
|
8861
|
+
const computedHashV1 = await computeHash(canonicalContentV1);
|
|
8862
|
+
const computedHashV2 = await computeHash(canonicalContentV2);
|
|
8744
8863
|
const entries = card.data.character_book?.entries || [];
|
|
8745
8864
|
const computedHasLorebook = entries.length > 0;
|
|
8746
8865
|
const computedLorebookCount = entries.length;
|
|
8747
8866
|
const authoritative = {
|
|
8748
8867
|
name: card.data.name,
|
|
8749
8868
|
tokens: computedTokens,
|
|
8750
|
-
contentHash:
|
|
8869
|
+
contentHash: computedHashV1,
|
|
8870
|
+
contentHashV2: computedHashV2,
|
|
8751
8871
|
hasLorebook: computedHasLorebook,
|
|
8752
8872
|
lorebookEntriesCount: computedLorebookCount
|
|
8753
8873
|
};
|
|
@@ -8759,21 +8879,27 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8759
8879
|
withinTolerance: false
|
|
8760
8880
|
});
|
|
8761
8881
|
}
|
|
8762
|
-
|
|
8882
|
+
const matchesV1 = clientMetadata.contentHash === computedHashV1;
|
|
8883
|
+
const matchesV2 = clientMetadata.contentHash === computedHashV2;
|
|
8884
|
+
if (!matchesV1 && !matchesV2) {
|
|
8763
8885
|
const disc = {
|
|
8764
8886
|
field: "contentHash",
|
|
8765
8887
|
clientValue: clientMetadata.contentHash,
|
|
8766
|
-
computedValue:
|
|
8888
|
+
computedValue: computedHashV1,
|
|
8767
8889
|
withinTolerance: false
|
|
8768
8890
|
};
|
|
8769
8891
|
discrepancies.push(disc);
|
|
8770
8892
|
if (allowHashMismatch) {
|
|
8771
8893
|
warnings.push(
|
|
8772
|
-
`Content hash mismatch: client=${clientMetadata.contentHash.substring(0, 8)}..., server=${
|
|
8894
|
+
`Content hash mismatch: client=${clientMetadata.contentHash.substring(0, 8)}..., server(v1)=${computedHashV1.substring(0, 8)}..., server(v2)=${computedHashV2.substring(0, 8)}...`
|
|
8773
8895
|
);
|
|
8774
8896
|
} else {
|
|
8775
8897
|
errors.push("Content hash mismatch - possible tampering or encoding difference");
|
|
8776
8898
|
}
|
|
8899
|
+
} else if (matchesV1 && !matchesV2) {
|
|
8900
|
+
warnings.push(
|
|
8901
|
+
"Client contentHash matches legacy v1 canonicalization. Prefer authoritative.contentHashV2 for new storage."
|
|
8902
|
+
);
|
|
8777
8903
|
}
|
|
8778
8904
|
const tokenFields = [
|
|
8779
8905
|
"description",
|
|
@@ -8854,7 +8980,11 @@ async function validateClientMetadata(clientMetadata, parseResult, options = {})
|
|
|
8854
8980
|
};
|
|
8855
8981
|
}
|
|
8856
8982
|
async function computeContentHash(card) {
|
|
8857
|
-
const content =
|
|
8983
|
+
const content = getCanonicalContentV1(card);
|
|
8984
|
+
return sha256Hash(content);
|
|
8985
|
+
}
|
|
8986
|
+
async function computeContentHashV2(card) {
|
|
8987
|
+
const content = getCanonicalContentV2(card);
|
|
8858
8988
|
return sha256Hash(content);
|
|
8859
8989
|
}
|
|
8860
8990
|
function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
@@ -8870,15 +9000,18 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8870
9000
|
const warnings = [];
|
|
8871
9001
|
const errors = [];
|
|
8872
9002
|
const computedTokens = countTokens(card);
|
|
8873
|
-
const
|
|
8874
|
-
const
|
|
9003
|
+
const canonicalContentV1 = getCanonicalContentV1(card);
|
|
9004
|
+
const canonicalContentV2 = getCanonicalContentV2(card);
|
|
9005
|
+
const computedHashV1 = computeHash(canonicalContentV1);
|
|
9006
|
+
const computedHashV2 = computeHash(canonicalContentV2);
|
|
8875
9007
|
const entries = card.data.character_book?.entries || [];
|
|
8876
9008
|
const computedHasLorebook = entries.length > 0;
|
|
8877
9009
|
const computedLorebookCount = entries.length;
|
|
8878
9010
|
const authoritative = {
|
|
8879
9011
|
name: card.data.name,
|
|
8880
9012
|
tokens: computedTokens,
|
|
8881
|
-
contentHash:
|
|
9013
|
+
contentHash: computedHashV1,
|
|
9014
|
+
contentHashV2: computedHashV2,
|
|
8882
9015
|
hasLorebook: computedHasLorebook,
|
|
8883
9016
|
lorebookEntriesCount: computedLorebookCount
|
|
8884
9017
|
};
|
|
@@ -8890,11 +9023,13 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8890
9023
|
withinTolerance: false
|
|
8891
9024
|
});
|
|
8892
9025
|
}
|
|
8893
|
-
|
|
9026
|
+
const matchesV1 = clientMetadata.contentHash === computedHashV1;
|
|
9027
|
+
const matchesV2 = clientMetadata.contentHash === computedHashV2;
|
|
9028
|
+
if (!matchesV1 && !matchesV2) {
|
|
8894
9029
|
discrepancies.push({
|
|
8895
9030
|
field: "contentHash",
|
|
8896
9031
|
clientValue: clientMetadata.contentHash,
|
|
8897
|
-
computedValue:
|
|
9032
|
+
computedValue: computedHashV1,
|
|
8898
9033
|
withinTolerance: false
|
|
8899
9034
|
});
|
|
8900
9035
|
if (allowHashMismatch) {
|
|
@@ -8902,6 +9037,10 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8902
9037
|
} else {
|
|
8903
9038
|
errors.push("Content hash mismatch");
|
|
8904
9039
|
}
|
|
9040
|
+
} else if (matchesV1 && !matchesV2) {
|
|
9041
|
+
warnings.push(
|
|
9042
|
+
"Client contentHash matches legacy v1 canonicalization. Prefer authoritative.contentHashV2 for new storage."
|
|
9043
|
+
);
|
|
8905
9044
|
}
|
|
8906
9045
|
const tokenFields = [
|
|
8907
9046
|
"description",
|
|
@@ -8970,6 +9109,7 @@ function validateClientMetadataSync(clientMetadata, parseResult, options) {
|
|
|
8970
9109
|
}
|
|
8971
9110
|
export {
|
|
8972
9111
|
computeContentHash,
|
|
9112
|
+
computeContentHashV2,
|
|
8973
9113
|
detectFormat,
|
|
8974
9114
|
getContainerFormat,
|
|
8975
9115
|
mightBeCard,
|