v3.6.2: Fix relationship field in context for manually added characters, add empty field placeholders and mobile support
This commit is contained in:
@@ -86,8 +86,8 @@ function buildHistoricalContextMap() {
|
||||
// For user_message_end: start from the last assistant message (we need its context for the preceding user message)
|
||||
// For assistant_message_end: start from before the last assistant message (it gets current context via setExtensionPrompt)
|
||||
let processedCount = 0;
|
||||
const startIndex = position === 'user_message_end'
|
||||
? lastAssistantIndex
|
||||
const startIndex = position === 'user_message_end'
|
||||
? lastAssistantIndex
|
||||
: (lastAssistantIndex > 0 ? lastAssistantIndex - 1 : chat.length - 2);
|
||||
|
||||
for (let i = startIndex; i >= 0 && (messageCount === 0 || processedCount < maxMessages); i--) {
|
||||
@@ -201,7 +201,7 @@ function prepareHistoricalContextInjection() {
|
||||
/**
|
||||
* Finds the best match position for message content in the prompt.
|
||||
* Tries full content first, then progressively smaller suffixes.
|
||||
*
|
||||
*
|
||||
* @param {string} prompt - The prompt to search in
|
||||
* @param {string} messageContent - The message content to find
|
||||
* @returns {{start: number, end: number}|null} - Position info or null if not found
|
||||
@@ -213,7 +213,7 @@ function findMessageInPrompt(prompt, messageContent) {
|
||||
|
||||
// Try to find the full content first
|
||||
let searchIndex = prompt.lastIndexOf(messageContent);
|
||||
|
||||
|
||||
if (searchIndex !== -1) {
|
||||
return { start: searchIndex, end: searchIndex + messageContent.length };
|
||||
}
|
||||
@@ -221,15 +221,15 @@ function findMessageInPrompt(prompt, messageContent) {
|
||||
// If full content not found, try last N characters with progressively smaller chunks
|
||||
// This handles cases where messages are truncated in the prompt
|
||||
const searchLengths = [500, 300, 200, 100, 50];
|
||||
|
||||
|
||||
for (const len of searchLengths) {
|
||||
if (messageContent.length <= len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const searchContent = messageContent.slice(-len);
|
||||
searchIndex = prompt.lastIndexOf(searchContent);
|
||||
|
||||
|
||||
if (searchIndex !== -1) {
|
||||
return { start: searchIndex, end: searchIndex + searchContent.length };
|
||||
}
|
||||
@@ -241,7 +241,7 @@ function findMessageInPrompt(prompt, messageContent) {
|
||||
/**
|
||||
* Injects historical context into a text completion prompt string.
|
||||
* Searches for message content in the prompt and appends context after matches.
|
||||
*
|
||||
*
|
||||
* @param {string} prompt - The text completion prompt
|
||||
* @returns {string} - The modified prompt with injected context
|
||||
*/
|
||||
@@ -268,7 +268,7 @@ function injectContextIntoTextPrompt(prompt) {
|
||||
|
||||
// Find the message content in the prompt
|
||||
const position = findMessageInPrompt(modifiedPrompt, message.mes);
|
||||
|
||||
|
||||
if (!position) {
|
||||
// Message not found in prompt (might be truncated or not included)
|
||||
console.debug(`[RPG Companion] Could not find message ${msgIdx} in prompt for context injection`);
|
||||
@@ -290,7 +290,7 @@ function injectContextIntoTextPrompt(prompt) {
|
||||
/**
|
||||
* Injects historical context into a chat completion message array.
|
||||
* Modifies the content of messages in the array directly.
|
||||
*
|
||||
*
|
||||
* @param {Array} chatMessages - The chat completion message array
|
||||
* @returns {Array} - The modified message array with injected context
|
||||
*/
|
||||
@@ -315,7 +315,7 @@ function injectContextIntoChatPrompt(chatMessages) {
|
||||
// Find this message in the chat completion array by matching content
|
||||
// Try full content first, then progressively smaller suffixes
|
||||
let found = false;
|
||||
|
||||
|
||||
for (const promptMsg of chatMessages) {
|
||||
if (!promptMsg.content || typeof promptMsg.content !== 'string') {
|
||||
continue;
|
||||
@@ -335,7 +335,7 @@ function injectContextIntoChatPrompt(chatMessages) {
|
||||
if (messageContent.length <= len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const searchContent = messageContent.slice(-len);
|
||||
if (promptMsg.content.includes(searchContent)) {
|
||||
promptMsg.content = promptMsg.content + ctxContent;
|
||||
@@ -344,12 +344,12 @@ function injectContextIntoChatPrompt(chatMessages) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!found) {
|
||||
console.debug(`[RPG Companion] Could not find message ${msgIdx} in chat prompt for context injection`);
|
||||
}
|
||||
@@ -365,7 +365,7 @@ function injectContextIntoChatPrompt(chatMessages) {
|
||||
/**
|
||||
* Injects historical context into finalMesSend message array (text completion).
|
||||
* Iterates through chat and finalMesSend in order, matching by content to skip injected messages.
|
||||
*
|
||||
*
|
||||
* @param {Array} finalMesSend - The array of message objects {message: string, extensionPrompts: []}
|
||||
* @returns {number} - Number of injections made
|
||||
*/
|
||||
@@ -381,20 +381,20 @@ function injectContextIntoFinalMesSend(finalMesSend) {
|
||||
}
|
||||
|
||||
let injectedCount = 0;
|
||||
|
||||
|
||||
// Build a map from chat index to finalMesSend index by matching content in order
|
||||
// This handles injected messages (author's note, OOC, etc.) that exist in finalMesSend but not in chat
|
||||
const chatToMesSendMap = new Map();
|
||||
let mesSendIdx = 0;
|
||||
|
||||
|
||||
for (let chatIdx = 0; chatIdx < chat.length && mesSendIdx < finalMesSend.length; chatIdx++) {
|
||||
const chatMsg = chat[chatIdx];
|
||||
if (!chatMsg || chatMsg.is_system) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const chatContent = chatMsg.mes || '';
|
||||
|
||||
|
||||
// Look for this chat message in finalMesSend starting from current position
|
||||
// Skip any finalMesSend entries that don't match (they're injected content)
|
||||
while (mesSendIdx < finalMesSend.length) {
|
||||
@@ -403,40 +403,40 @@ function injectContextIntoFinalMesSend(finalMesSend) {
|
||||
mesSendIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Check if this finalMesSend message contains the chat content
|
||||
// Use a substring match since instruct formatting adds prefixes/suffixes
|
||||
// Match with sufficient content (first 50 chars or full message if shorter)
|
||||
const matchContent = chatContent.length > 50
|
||||
? chatContent.substring(0, 50)
|
||||
const matchContent = chatContent.length > 50
|
||||
? chatContent.substring(0, 50)
|
||||
: chatContent;
|
||||
|
||||
|
||||
if (matchContent && mesSendObj.message.includes(matchContent)) {
|
||||
// Found a match - record the mapping
|
||||
chatToMesSendMap.set(chatIdx, mesSendIdx);
|
||||
mesSendIdx++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// This finalMesSend entry doesn't match - it's injected content, skip it
|
||||
mesSendIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now inject context using the map
|
||||
for (const [chatIdx, ctxContent] of pendingContextMap) {
|
||||
const targetMesSendIdx = chatToMesSendMap.get(chatIdx);
|
||||
|
||||
|
||||
if (targetMesSendIdx === undefined) {
|
||||
console.debug(`[RPG Companion] Chat message ${chatIdx} not found in finalMesSend mapping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const mesSendObj = finalMesSend[targetMesSendIdx];
|
||||
if (!mesSendObj || !mesSendObj.message) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Append context to this message
|
||||
mesSendObj.message = mesSendObj.message + ctxContent;
|
||||
injectedCount++;
|
||||
@@ -450,7 +450,7 @@ function injectContextIntoFinalMesSend(finalMesSend) {
|
||||
* Event handler for GENERATE_BEFORE_COMBINE_PROMPTS (text completion).
|
||||
* Injects historical context into the finalMesSend array before prompt combination.
|
||||
* This is more reliable than post-combine string searching.
|
||||
*
|
||||
*
|
||||
* @param {Object} eventData - Event data with finalMesSend and other properties
|
||||
*/
|
||||
function onGenerateBeforeCombinePrompts(eventData) {
|
||||
@@ -478,7 +478,7 @@ function onGenerateBeforeCombinePrompts(eventData) {
|
||||
/**
|
||||
* Event handler for GENERATE_AFTER_COMBINE_PROMPTS (text completion).
|
||||
* This is now a backup/fallback - primary injection happens in BEFORE_COMBINE.
|
||||
*
|
||||
*
|
||||
* @param {Object} eventData - Event data with prompt property
|
||||
*/
|
||||
function onGenerateAfterCombinePrompts(eventData) {
|
||||
@@ -508,7 +508,7 @@ function onGenerateAfterCombinePrompts(eventData) {
|
||||
/**
|
||||
* Event handler for CHAT_COMPLETION_PROMPT_READY.
|
||||
* Injects historical context into the chat message array.
|
||||
*
|
||||
*
|
||||
* @param {Object} eventData - Event data with chat property
|
||||
*/
|
||||
function onChatCompletionPromptReady(eventData) {
|
||||
@@ -938,16 +938,16 @@ Ensure these details naturally reflect and influence the narrative. Character be
|
||||
export function initHistoryInjectionListeners() {
|
||||
// Register persistent listeners for prompt injection
|
||||
// These check pendingContextMap and only inject if there's data
|
||||
|
||||
|
||||
// Primary: BEFORE_COMBINE for text completion (more reliable - modifies message objects)
|
||||
eventSource.on(event_types.GENERATE_BEFORE_COMBINE_PROMPTS, onGenerateBeforeCombinePrompts);
|
||||
|
||||
|
||||
// Fallback: AFTER_COMBINE for text completion (string-based injection)
|
||||
eventSource.on(event_types.GENERATE_AFTER_COMBINE_PROMPTS, onGenerateAfterCombinePrompts);
|
||||
|
||||
|
||||
// Chat completion (OpenAI, etc.)
|
||||
eventSource.on(event_types.CHAT_COMPLETION_PROMPT_READY, onChatCompletionPromptReady);
|
||||
|
||||
|
||||
console.log('[RPG Companion] History injection listeners initialized');
|
||||
}
|
||||
|
||||
|
||||
@@ -725,13 +725,14 @@ function formatTrackerDataForContext(jsonData, trackerType, userName) {
|
||||
}
|
||||
}
|
||||
|
||||
// Relationship
|
||||
if (char.relationship) {
|
||||
// Relationship - check both Relationship (new format) and relationship (old format)
|
||||
const relationshipValue = char.Relationship || char.relationship;
|
||||
if (relationshipValue) {
|
||||
let relValue;
|
||||
if (typeof char.relationship === 'object' && !Array.isArray(char.relationship) && 'status' in char.relationship) {
|
||||
relValue = getValue(char.relationship.status);
|
||||
if (typeof relationshipValue === 'object' && !Array.isArray(relationshipValue) && 'status' in relationshipValue) {
|
||||
relValue = getValue(relationshipValue.status);
|
||||
} else {
|
||||
relValue = getValue(char.relationship);
|
||||
relValue = getValue(relationshipValue);
|
||||
}
|
||||
if (relValue) formatted += ` Relationship: ${relValue}\n`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user