@@ -4,9 +4,12 @@ export interface LoreBookEntryData {
44 id : string ;
55 name : string ;
66 keys : string [ ] ;
7+ secondaryKeys : string [ ] ;
78 content : string ;
89 enabled : boolean ;
910 constant : boolean ;
11+ selective : boolean ;
12+ selectiveLogic : "and" | "or" ;
1013 position : string ;
1114 insertionOrder : number ;
1215}
@@ -38,7 +41,29 @@ function normalizeKeyList(input: unknown): string[] {
3841 return out ;
3942}
4043
44+ function normalizeSecondaryKeys ( row : Record < string , unknown > ) : string [ ] {
45+ return normalizeKeyList (
46+ row . secondaryKeys
47+ ?? row . secondary_keys
48+ ?? row . keysecondary
49+ ?? [ ]
50+ ) ;
51+ }
52+
4153function normalizePosition ( input : unknown ) : string {
54+ if ( typeof input === "number" && Number . isFinite ( input ) ) {
55+ switch ( Math . floor ( input ) ) {
56+ case 0 : return "before_char" ;
57+ case 1 : return "after_char" ;
58+ case 2 : return "before_scene" ;
59+ case 3 : return "after_scene" ;
60+ case 4 : return "before_author_note" ;
61+ case 5 : return "after_author_note" ;
62+ case 6 : return "before_history" ;
63+ case 7 : return "after_history" ;
64+ default : return "after_char" ;
65+ }
66+ }
4267 const raw = String ( input || "" ) . trim ( ) . toLowerCase ( ) ;
4368 if ( ! raw ) return "after_char" ;
4469 if ( raw === "before_character" ) return "before_char" ;
@@ -52,26 +77,50 @@ function toInsertionOrder(input: unknown, fallback: number): number {
5277 return Math . floor ( parsed ) ;
5378}
5479
80+ function normalizeSelectiveLogic ( input : unknown ) : "and" | "or" {
81+ if ( typeof input === "string" ) {
82+ const raw = input . trim ( ) . toLowerCase ( ) ;
83+ if ( raw === "or" ) return "or" ;
84+ return "and" ;
85+ }
86+ const numeric = Number ( input ) ;
87+ if ( ! Number . isFinite ( numeric ) ) return "and" ;
88+ return numeric === 1 ? "or" : "and" ;
89+ }
90+
91+ function normalizeEntriesInput ( input : unknown ) : Record < string , unknown > [ ] {
92+ if ( Array . isArray ( input ) ) {
93+ return input . filter ( ( item ) : item is Record < string , unknown > => Boolean ( item ) && typeof item === "object" ) ;
94+ }
95+ if ( input && typeof input === "object" ) {
96+ return Object . values ( input as Record < string , unknown > )
97+ . filter ( ( item ) : item is Record < string , unknown > => Boolean ( item ) && typeof item === "object" ) ;
98+ }
99+ return [ ] ;
100+ }
101+
55102export function normalizeLoreBookEntries ( input : unknown ) : LoreBookEntryData [ ] {
56- if ( ! Array . isArray ( input ) ) return [ ] ;
103+ const rows = normalizeEntriesInput ( input ) ;
104+ if ( rows . length === 0 ) return [ ] ;
57105 const out : LoreBookEntryData [ ] = [ ] ;
58106
59- for ( let index = 0 ; index < input . length ; index += 1 ) {
60- const raw = input [ index ] ;
61- if ( ! raw || typeof raw !== "object" ) continue ;
62- const row = raw as Record < string , unknown > ;
107+ for ( let index = 0 ; index < rows . length ; index += 1 ) {
108+ const row = rows [ index ] ;
63109 const content = String ( row . content || "" ) . trim ( ) ;
64110 if ( ! content ) continue ;
65111 const id = String ( row . id || row . uid || "" ) . trim ( ) || `entry-${ index + 1 } ` ;
66112 out . push ( {
67113 id,
68- name : String ( row . name || "" ) . trim ( ) ,
69- keys : normalizeKeyList ( row . keys ) ,
114+ name : String ( row . name || row . comment || "" ) . trim ( ) ,
115+ keys : normalizeKeyList ( row . keys ?? row . key ) ,
116+ secondaryKeys : normalizeSecondaryKeys ( row ) ,
70117 content,
71- enabled : row . enabled !== false ,
118+ enabled : row . enabled !== false && row . disable !== true ,
72119 constant : row . constant === true ,
120+ selective : row . selective === true ,
121+ selectiveLogic : normalizeSelectiveLogic ( row . selectiveLogic ?? row . selective_logic ) ,
73122 position : normalizePosition ( row . position ) ,
74- insertionOrder : toInsertionOrder ( row . insertion_order ?? row . insertionOrder , ( index + 1 ) * 100 )
123+ insertionOrder : toInsertionOrder ( row . insertion_order ?? row . insertionOrder ?? row . order ?? row . priority , ( index + 1 ) * 100 )
75124 } ) ;
76125 }
77126
@@ -91,14 +140,35 @@ export function parseCharacterLoreBook(rawData: unknown): { name: string; descri
91140 return { name, description, entries } ;
92141}
93142
143+ export function parseSillyTavernWorldInfo ( rawData : unknown ) : { name : string ; description : string ; entries : LoreBookEntryData [ ] } | null {
144+ if ( ! rawData || typeof rawData !== "object" || Array . isArray ( rawData ) ) return null ;
145+ const data = rawData as Record < string , unknown > ;
146+ const entries = normalizeLoreBookEntries ( data . entries ) ;
147+ if ( entries . length === 0 ) return null ;
148+ const name = String ( data . name || "" ) . trim ( ) || "Imported World Info" ;
149+ const description = String ( data . description || "" ) . trim ( ) ;
150+ return { name, description, entries } ;
151+ }
152+
153+ function matchesKeyGroup ( haystack : string , keys : string [ ] , logic : "and" | "or" ) : boolean {
154+ if ( keys . length === 0 ) return true ;
155+ if ( logic === "or" ) {
156+ return keys . some ( ( key ) => matchesLoreKey ( haystack , key ) ) ;
157+ }
158+ return keys . every ( ( key ) => matchesLoreKey ( haystack , key ) ) ;
159+ }
160+
94161export function getTriggeredLoreEntries ( entries : LoreBookEntryData [ ] , timelineTexts : string [ ] ) : LoreBookEntryData [ ] {
95162 const haystack = timelineTexts . join ( "\n" ) . toLowerCase ( ) ;
96163 return entries
97164 . filter ( ( entry ) => entry . enabled && entry . content . trim ( ) )
98165 . filter ( ( entry ) => {
99166 if ( entry . constant ) return true ;
100167 if ( entry . keys . length === 0 ) return false ;
101- return entry . keys . some ( ( key ) => matchesLoreKey ( haystack , key ) ) ;
168+ const primaryMatched = entry . keys . some ( ( key ) => matchesLoreKey ( haystack , key ) ) ;
169+ if ( ! primaryMatched ) return false ;
170+ if ( ! entry . selective || entry . secondaryKeys . length === 0 ) return true ;
171+ return matchesKeyGroup ( haystack , entry . secondaryKeys , entry . selectiveLogic ) ;
102172 } )
103173 . sort ( ( a , b ) => a . insertionOrder - b . insertionOrder ) ;
104174}
0 commit comments