diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png deleted file mode 100644 index 26ebefc..0000000 Binary files a/public/android-chrome-192x192.png and /dev/null differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png deleted file mode 100644 index 7b10f7d..0000000 Binary files a/public/android-chrome-512x512.png and /dev/null differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index 2c91d4b..0000000 Binary files a/public/apple-touch-icon.png and /dev/null differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png index 2c29f4b..6223e14 100644 Binary files a/public/favicon-16x16.png and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index e2c03c8..0000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 5fa7f96..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/site.webmanifest b/public/site.webmanifest deleted file mode 100644 index 45dc8a2..0000000 --- a/public/site.webmanifest +++ /dev/null @@ -1 +0,0 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/public/test-output.json b/public/test-output.json new file mode 100644 index 0000000..f10f816 --- /dev/null +++ b/public/test-output.json @@ -0,0 +1,84 @@ +{ + "entries": { + "0": { + "key": [ + "setting" + ], + "keysecondary": [], + "comment": "πŸ—ΊοΈ SETTING [ General Modern Fantasy ]", + "content": "\nThis world involves both humans and supernatural creatures coexisting on modern day Earth.\n", + "constant": true, + "vectorized": false, + "selective": true, + "selectiveLogic": 0, + "addMemo": true, + "order": 100, + "position": 0, + "disable": false, + "excludeRecursion": false, + "preventRecursion": false, + "matchPersonaDescription": false, + "matchCharacterDescription": false, + "matchCharacterPersonality": false, + "matchCharacterDepthPrompt": false, + "matchScenario": false, + "matchCreatorNotes": false, + "delayUntilRecursion": false, + "probability": 100, + "useProbability": true, + "depth": 4, + "group": "", + "groupOverride": false, + "groupWeight": 100, + "scanDepth": null, + "caseSensitive": null, + "matchWholeWords": null, + "useGroupScoring": false, + "automationId": "", + "role": null, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "uid": 0, + "displayIndex": 0, + "extensions": { + "position": 0, + "exclude_recursion": false, + "display_index": 0, + "probability": 100, + "useProbability": true, + "depth": 4, + "selectiveLogic": 0, + "group": "", + "group_override": false, + "group_weight": 100, + "prevent_recursion": false, + "delay_until_recursion": false, + "scan_depth": null, + "match_whole_words": null, + "use_group_scoring": false, + "case_sensitive": null, + "automation_id": "", + "role": 0, + "vectorized": false, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "match_persona_description": false, + "match_character_description": false, + "match_character_personality": false, + "match_character_depth_prompt": false, + "match_scenario": false, + "match_creator_notes": false + }, + "ignoreBudget": false, + "outletName": "", + "triggers": [], + "characterFilter": { + "isExclude": false, + "names": [], + "tags": [] + } + } + } +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 35bad08..38f98a5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -9,16 +9,7 @@ export const metadata: Metadata = { description: "Convert Janitor AI lorebook format to SillyTavern format with comprehensive editing capabilities", icons: { icon: [ - { url: '/favicon.ico' }, { url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' }, - { url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, - ], - apple: [ - { url: '/apple-touch-icon.png' } - ], - other: [ - { url: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' }, - { url: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' }, ], }, }; diff --git a/src/app/page.tsx b/src/app/page.tsx index 91ac037..7e6cc60 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -101,7 +101,7 @@ export default function Home() { } setOriginalFileName(file.name.replace('.json', '')); - + const reader = new FileReader(); reader.onload = (e) => { try { @@ -130,26 +130,79 @@ export default function Home() { e.preventDefault(); }; - const convertJanitorToSillyTavern = (janitorData: any[]): ConvertedLorebook => { - const entries: { [key: string]: LorebookEntry } = {}; + const convertJanitorToSillyTavern = (janitorData: any[]): any => { + const entries: { [key: string]: any } = {}; + const originalDataEntries: any[] = []; - janitorData.forEach((entry, uid) => { - entries[uid.toString()] = { - uid: entry.id !== undefined ? entry.id : uid, - key: entry.key || [], - keysecondary: entry.keysecondary || [], - comment: entry.comment || entry.name || "Entry", - content: entry.content || "", - constant: entry.constant || false, - vectorized: false, - selective: entry.selectiveLogic !== undefined ? true : true, - selectiveLogic: entry.selectiveLogic || 0, - addMemo: true, - order: entry.insertion_order || entry.order || 100, + janitorData.forEach((entry, index) => { + // Handle both integer IDs and UUID IDs + const entryId = entry.id; + const isIntegerId = typeof entryId === 'number' || (typeof entryId === 'string' && /^\d+$/.test(entryId)); + const uid = isIntegerId ? (typeof entryId === 'number' ? entryId : parseInt(entryId, 10)) : index; + const displayIndex = entry.priority !== undefined ? entry.priority + 20 : (isIntegerId ? uid + 20 : index + 20); + const order = entry.insertion_order || entry.order || 100; + const probability = entry.probability || 100; + const depth = entry.depth || 4; + const selectiveLogic = entry.selectiveLogic || 0; + const groupWeight = entry.groupWeight || 100; + const group = entry.inclusionGroupRaw || ""; + const caseSensitive = entry.case_sensitive ? true : null; + const disable = entry.enabled !== undefined ? !entry.enabled : false; + const constant = entry.constant || false; + // Strip emojis from comment + const rawComment = entry.comment || entry.name || ""; + const comment = rawComment.replace(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2300}-\u{23FF}]|[\u{2B50}]|[\u{2934}-\u{2935}]|[\u{25AA}-\u{25AB}]|[\u{25B6}]|[\u{25C0}]|[\u{25FB}-\u{25FE}]|[\u{2614}-\u{2615}]|[\u{2648}-\u{2653}]|[\u{267F}]|[\u{2693}]|[\u{26A1}]|[\u{26AA}-\u{26AB}]|[\u{26BD}-\u{26BE}]|[\u{26C4}-\u{26C5}]|[\u{26CE}]|[\u{26D4}]|[\u{26EA}]|[\u{26F2}-\u{26F3}]|[\u{26F5}]|[\u{26FA}]|[\u{26FD}]|[\u{2702}]|[\u{2705}]|[\u{2708}-\u{270D}]|[\u{270F}]|[\u{2712}]|[\u{2714}]|[\u{2716}]|[\u{271D}]|[\u{2721}]|[\u{2728}]|[\u{2733}-\u{2734}]|[\u{2744}]|[\u{2747}]|[\u{274C}]|[\u{274E}]|[\u{2753}-\u{2755}]|[\u{2757}]|[\u{2763}-\u{2764}]|[\u{2795}-\u{2797}]|[\u{27A1}]|[\u{27B0}]|[\u{27BF}]|[\u{2B05}-\u{2B07}]|[\u{2B1B}-\u{2B1C}]|[\u{2B55}]|[\u{3030}]|[\u{303D}]|[\u{3297}]|[\u{3299}]|[\u{FE0F}]|[♠♣β™₯β™¦β™€β™§β™‘β™’βœ¦βœ§β˜…β˜†β—β—‹β—†β—‡β– β–‘β–²β–³β–Όβ–½β—€β–Άβ—β–·]/gu, '').trim(); + const keys = entry.key || []; + const keysecondary = entry.keysecondary || []; + const content = entry.content || ""; + + // Build extensions object for both entries and originalData + const extensionsObj = { position: 0, - disable: entry.enabled !== undefined ? !entry.enabled : false, - excludeRecursion: true, - preventRecursion: true, + exclude_recursion: !constant, + display_index: displayIndex, + probability: probability, + useProbability: true, + depth: depth, + selectiveLogic: selectiveLogic, + group: group, + group_override: false, + group_weight: groupWeight, + prevent_recursion: !constant, + delay_until_recursion: false, + scan_depth: null, + match_whole_words: null, + use_group_scoring: false, + case_sensitive: caseSensitive, + automation_id: "", + role: 0, + vectorized: false, + sticky: 0, + cooldown: 0, + delay: 0, + match_persona_description: false, + match_character_description: false, + match_character_personality: false, + match_character_depth_prompt: false, + match_scenario: false, + match_creator_notes: false + }; + + entries[index.toString()] = { + key: keys, + keysecondary: keysecondary, + comment: comment, + content: content, + constant: constant, + vectorized: false, + selective: true, + selectiveLogic: selectiveLogic, + addMemo: true, + order: order, + position: 0, + disable: disable, + excludeRecursion: !constant, + preventRecursion: !constant, matchPersonaDescription: false, matchCharacterDescription: false, matchCharacterPersonality: false, @@ -157,29 +210,57 @@ export default function Home() { matchScenario: false, matchCreatorNotes: false, delayUntilRecursion: false, - probability: entry.probability || 100, - useProbability: entry.probability !== undefined, - depth: entry.depth || 4, - group: entry.inclusionGroupRaw || entry.category || "", + probability: probability, + useProbability: true, + depth: depth, + group: group, groupOverride: false, - groupWeight: entry.groupWeight || 100, + groupWeight: groupWeight, scanDepth: null, - caseSensitive: entry.case_sensitive || false, - matchWholeWords: entry.matchWholeWords !== undefined ? entry.matchWholeWords : true, + caseSensitive: caseSensitive, + matchWholeWords: null, useGroupScoring: false, automationId: "", role: null, sticky: 0, cooldown: 0, delay: 0, - displayIndex: entry.id !== undefined ? entry.id : uid, - filterToCharacters: "", - filterToGenerationTriggers: "", - excludeFromGeneration: false + uid: uid, + displayIndex: displayIndex, + extensions: extensionsObj, + ignoreBudget: false, + outletName: "", + triggers: [], + characterFilter: { + isExclude: false, + names: [], + tags: [] + } }; + + // Add to originalData entries array + originalDataEntries.push({ + id: index, + keys: keys, + secondary_keys: keysecondary, + comment: comment, + content: content, + constant: constant, + selective: true, + insertion_order: order, + enabled: !disable, + position: "before_char", + use_regex: true, + extensions: extensionsObj + }); }); - return { entries }; + return { + entries, + originalData: { + entries: originalDataEntries + } + }; }; const downloadLorebook = () => { @@ -221,10 +302,10 @@ export default function Home() { const deleteEntry = (entryId: string) => { if (!convertedData) return; - + const newEntries = { ...convertedData.entries }; delete newEntries[entryId]; - + setConvertedData({ ...convertedData, entries: newEntries @@ -463,7 +544,7 @@ export default function Home() {
{entry.comment}
- UID: {entry.uid} β€’ Order: {entry.order} β€’ + UID: {entry.uid} β€’ Order: {entry.order} β€’ {entry.key.length > 0 ? ` Keys: ${entry.key.join(', ')}` : ' No keys'}
@@ -508,14 +589,14 @@ export default function Home() { )} - + {entry.group && (

Group

{entry.group}

)} - +

Content

@@ -531,7 +612,7 @@ export default function Home() { {entry.content}
- +
Constant: {entry.constant ? 'Yes' : 'No'} diff --git a/test-minimal.json b/test-minimal.json new file mode 100644 index 0000000..ca01610 --- /dev/null +++ b/test-minimal.json @@ -0,0 +1,139 @@ +{ + "entries": { + "0": { + "key": [ + "Dean Archer Wolfwood", + "human students", + "integrated education", + "2002" + ], + "keysecondary": [], + "comment": "Founding of SUCC", + "content": "\n\nFounding of SUCC\nIn 2002, facing declining supernatural enrollment as young monsters increasingly chose to attend human colleges, visionary Dean Archer Wolfwood made the bold decision to open SUCC's doors to human students for the first time in the school's history. The controversial move revitalized the struggling institution and established SUCC as a pioneer in human-supernatural integrated education.\n\n", + "constant": false, + "vectorized": false, + "selective": true, + "selectiveLogic": 0, + "addMemo": true, + "order": 100, + "position": 0, + "disable": false, + "excludeRecursion": true, + "preventRecursion": true, + "matchPersonaDescription": false, + "matchCharacterDescription": false, + "matchCharacterPersonality": false, + "matchCharacterDepthPrompt": false, + "matchScenario": false, + "matchCreatorNotes": false, + "delayUntilRecursion": false, + "probability": 100, + "useProbability": true, + "depth": 4, + "group": "", + "groupOverride": false, + "groupWeight": 100, + "scanDepth": null, + "caseSensitive": null, + "matchWholeWords": null, + "useGroupScoring": false, + "automationId": "", + "role": null, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "uid": 0, + "displayIndex": 28, + "extensions": { + "position": 0, + "exclude_recursion": true, + "display_index": 28, + "probability": 100, + "useProbability": true, + "depth": 4, + "selectiveLogic": 0, + "group": "", + "group_override": false, + "group_weight": 100, + "prevent_recursion": true, + "delay_until_recursion": false, + "scan_depth": null, + "match_whole_words": null, + "use_group_scoring": false, + "case_sensitive": null, + "automation_id": "", + "role": 0, + "vectorized": false, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "match_persona_description": false, + "match_character_description": false, + "match_character_personality": false, + "match_character_depth_prompt": false, + "match_scenario": false, + "match_creator_notes": false + }, + "ignoreBudget": false, + "outletName": "", + "triggers": [], + "characterFilter": { + "isExclude": false, + "names": [], + "tags": [] + } + } + }, + "originalData": { + "entries": [ + { + "id": 0, + "keys": [ + "Dean Archer Wolfwood", + "human students", + "integrated education", + "2002" + ], + "secondary_keys": [], + "comment": "Founding of SUCC", + "content": "\n\nFounding of SUCC\nIn 2002, facing declining supernatural enrollment as young monsters increasingly chose to attend human colleges, visionary Dean Archer Wolfwood made the bold decision to open SUCC's doors to human students for the first time in the school's history. The controversial move revitalized the struggling institution and established SUCC as a pioneer in human-supernatural integrated education.\n\n", + "constant": false, + "selective": true, + "insertion_order": 100, + "enabled": true, + "position": "before_char", + "use_regex": true, + "extensions": { + "position": 0, + "exclude_recursion": true, + "display_index": 28, + "probability": 100, + "useProbability": true, + "depth": 4, + "selectiveLogic": 0, + "group": "", + "group_override": false, + "group_weight": 100, + "prevent_recursion": true, + "delay_until_recursion": false, + "scan_depth": null, + "match_whole_words": null, + "use_group_scoring": false, + "case_sensitive": null, + "automation_id": "", + "role": 0, + "vectorized": false, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "match_persona_description": false, + "match_character_description": false, + "match_character_personality": false, + "match_character_depth_prompt": false, + "match_scenario": false, + "match_creator_notes": false + } + } + ] + } +} \ No newline at end of file diff --git a/test-output.json b/test-output.json new file mode 100644 index 0000000..f10f816 --- /dev/null +++ b/test-output.json @@ -0,0 +1,84 @@ +{ + "entries": { + "0": { + "key": [ + "setting" + ], + "keysecondary": [], + "comment": "πŸ—ΊοΈ SETTING [ General Modern Fantasy ]", + "content": "\nThis world involves both humans and supernatural creatures coexisting on modern day Earth.\n", + "constant": true, + "vectorized": false, + "selective": true, + "selectiveLogic": 0, + "addMemo": true, + "order": 100, + "position": 0, + "disable": false, + "excludeRecursion": false, + "preventRecursion": false, + "matchPersonaDescription": false, + "matchCharacterDescription": false, + "matchCharacterPersonality": false, + "matchCharacterDepthPrompt": false, + "matchScenario": false, + "matchCreatorNotes": false, + "delayUntilRecursion": false, + "probability": 100, + "useProbability": true, + "depth": 4, + "group": "", + "groupOverride": false, + "groupWeight": 100, + "scanDepth": null, + "caseSensitive": null, + "matchWholeWords": null, + "useGroupScoring": false, + "automationId": "", + "role": null, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "uid": 0, + "displayIndex": 0, + "extensions": { + "position": 0, + "exclude_recursion": false, + "display_index": 0, + "probability": 100, + "useProbability": true, + "depth": 4, + "selectiveLogic": 0, + "group": "", + "group_override": false, + "group_weight": 100, + "prevent_recursion": false, + "delay_until_recursion": false, + "scan_depth": null, + "match_whole_words": null, + "use_group_scoring": false, + "case_sensitive": null, + "automation_id": "", + "role": 0, + "vectorized": false, + "sticky": 0, + "cooldown": 0, + "delay": 0, + "match_persona_description": false, + "match_character_description": false, + "match_character_personality": false, + "match_character_depth_prompt": false, + "match_scenario": false, + "match_creator_notes": false + }, + "ignoreBudget": false, + "outletName": "", + "triggers": [], + "characterFilter": { + "isExclude": false, + "names": [], + "tags": [] + } + } + } +} \ No newline at end of file