chore: 1.7

This commit is contained in:
Severian
2025-05-24 18:57:44 +08:00
parent 58d8155984
commit a4b5041657
3 changed files with 105 additions and 28 deletions

View File

@@ -4,6 +4,7 @@ Check package.json for commands, I can't be bothered.
### Changelog ### Changelog
- 1.7: Handling for nested XML character tags
- 1.6: First message formatting, copy button for first message and other fields - 1.6: First message formatting, copy button for first message and other fields
- 1.5: {{user}} substitution for user persona name - 1.5: {{user}} substitution for user persona name
- 1.4: Mooth just keeps finding bugs, damn. - 1.4: Mooth just keeps finding bugs, damn.

View File

@@ -40,49 +40,118 @@ interface PersonaMatch {
function findTagsBetween(content: string, startMarker: string): PersonaMatch[] { function findTagsBetween(content: string, startMarker: string): PersonaMatch[] {
const startMarkerTag = `<${startMarker}>`; const startMarkerTag = `<${startMarker}>`;
const startIdx = content.indexOf(startMarkerTag); const startIdx = content.indexOf(startMarkerTag);
if (startIdx === -1) return []; if (startIdx === -1) return [];
const scenarioIdx = content.indexOf("<scenario>"); const scenarioIdx = content.indexOf("<scenario>");
const exampleIdx = content.indexOf("<example_dialogs>"); const exampleIdx = content.indexOf("<example_dialogs>");
let endIdx = content.length; let endIdx = content.length;
if (scenarioIdx !== -1) endIdx = Math.min(endIdx, scenarioIdx); if (scenarioIdx !== -1) endIdx = Math.min(endIdx, scenarioIdx);
if (exampleIdx !== -1) endIdx = Math.min(endIdx, exampleIdx); if (exampleIdx !== -1) endIdx = Math.min(endIdx, exampleIdx);
const section = content.slice(startIdx, endIdx); const section = content.slice(startIdx, endIdx);
const matches: PersonaMatch[] = []; const matches: PersonaMatch[] = [];
const tagPattern = /<([^/>\s][^>]*)>([\s\S]*?)<\/\1>/g; let position = 0;
let match;
while (position < section.length) {
try { const tagStart = section.indexOf("<", position);
while ((match = tagPattern.exec(section)) !== null) { if (tagStart === -1) break;
// Skip the system tag
if (match[1] !== startMarker) { const tagNameEnd = section.indexOf(">", tagStart);
matches.push({ if (tagNameEnd === -1) break;
tag: match[1].trim(),
content: match[2].trim() const tagName = section.substring(tagStart + 1, tagNameEnd).trim();
});
if (tagName.startsWith("/") || tagName === startMarker) {
position = tagNameEnd + 1;
continue;
}
const openTag = `<${tagName}>`;
const closeTag = `</${tagName}>`;
let openTagPos = tagStart;
let closeTagPos = -1;
let tagCount = 1;
let searchPos = tagNameEnd + 1;
while (searchPos < section.length && tagCount > 0) {
const nextOpen = section.indexOf(openTag, searchPos);
const nextClose = section.indexOf(closeTag, searchPos);
if (nextClose === -1) break;
if (nextOpen !== -1 && nextOpen < nextClose) {
tagCount++;
searchPos = nextOpen + openTag.length;
} else {
tagCount--;
searchPos = nextClose + closeTag.length;
if (tagCount === 0) {
closeTagPos = nextClose;
}
} }
} }
} catch (error) {
console.error("Error during regex execution:", error); if (closeTagPos !== -1) {
const tagContent = section.substring(tagNameEnd + 1, closeTagPos);
matches.push({
tag: tagName,
content: tagContent.trim(),
});
position = closeTagPos + closeTag.length;
} else {
position = tagNameEnd + 1;
}
} }
return matches; return matches;
} }
function extractBetweenTags(content: string, tag: string): string { function extractBetweenTags(content: string, tag: string): string {
const startTag = `<${tag}>`; const startTag = `<${tag}>`;
const endTag = `</${tag}>`; const endTag = `</${tag}>`;
const startIndex = content.indexOf(startTag); const startIndex = content.indexOf(startTag);
if (startIndex === -1) return ""; if (startIndex === -1) return "";
const endIndex = content.indexOf(endTag, startIndex); // Handle nested tags by counting opening and closing tags
let openTagCount = 1;
let position = startIndex + startTag.length;
let endIndex = -1;
while (position < content.length && openTagCount > 0) {
const nextOpenTag = content.indexOf(startTag, position);
const nextCloseTag = content.indexOf(endTag, position);
// No more closing tags found
if (nextCloseTag === -1) break;
// Found another opening tag before the next closing tag
if (nextOpenTag !== -1 && nextOpenTag < nextCloseTag) {
openTagCount++;
position = nextOpenTag + startTag.length;
}
// Found a closing tag
else {
openTagCount--;
position = nextCloseTag + endTag.length;
// If we've found the matching closing tag for our initial opening tag
if (openTagCount === 0) {
endIndex = nextCloseTag;
break;
}
}
}
if (endIndex === -1) return ""; if (endIndex === -1) return "";
return content.slice(startIndex + startTag.length, endIndex).trim(); return content.slice(startIndex + startTag.length, endIndex).trim();
} }
@@ -96,7 +165,7 @@ function extractCardData(messages: Message[]): CardData {
// Find all persona tags between system and the first optional tag (scenario or example_dialogs) // Find all persona tags between system and the first optional tag (scenario or example_dialogs)
const personas = findTagsBetween(content0, "system"); const personas = findTagsBetween(content0, "system");
const userPersona = personas[personas.length - 2]; const userPersona = personas[personas.length - 2];
const charPersona = personas[personas.length - 1]; const charPersona = personas[personas.length - 1];
const charName = charPersona?.tag || ""; const charName = charPersona?.tag || "";
@@ -117,7 +186,11 @@ function extractCardData(messages: Message[]): CardData {
if (field !== "name") { if (field !== "name") {
const val = cardData[field as keyof CardData]; const val = cardData[field as keyof CardData];
if (typeof val === "string") { if (typeof val === "string") {
cardData[field as keyof CardData] = safeReplace(val, userName, "{{user}}"); cardData[field as keyof CardData] = safeReplace(
val,
userName,
"{{user}}"
);
} }
} }
} }
@@ -127,7 +200,11 @@ function extractCardData(messages: Message[]): CardData {
if (field !== "name") { if (field !== "name") {
const val = cardData[field as keyof CardData]; const val = cardData[field as keyof CardData];
if (typeof val === "string") { if (typeof val === "string") {
cardData[field as keyof CardData] = safeReplace(val, charName, "{{char}}"); cardData[field as keyof CardData] = safeReplace(
val,
charName,
"{{char}}"
);
} }
} }
} }

View File

@@ -191,10 +191,9 @@ export default function Home() {
<div className="container mx-auto px-4 py-8"> <div className="container mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<div> <div>
<h1 className="text-3xl font-bold">Sucker v1.6</h1> <h1 className="text-3xl font-bold">Sucker v1.7</h1>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Wherein Myscell&apos;s Not-Unreasonable, Yet Still Annoying, Handles nested XML character tags now, let me know how it goes.
Request is Delivered with a Heavy Sigh
</p> </p>
</div> </div>
<Button <Button