feat: variables 2.0 state + L0 summary integration

This commit is contained in:
2026-01-31 23:06:03 +08:00
parent 201c74dc71
commit 4b0541610b
22 changed files with 1949 additions and 2314 deletions

View File

@@ -1,6 +1,6 @@
// 删掉getRequestHeaders, extractMessageFromData, getStreamingReply, tryParseStreamingError, getEventSourceStream
import { eventSource, event_types, chat, name1, activateSendButtons, deactivateSendButtons } from "../../../../../script.js";
import { eventSource, event_types, chat, name1, activateSendButtons, deactivateSendButtons, substituteParams } from "../../../../../script.js";
import { chat_completion_sources, oai_settings, promptManager, getChatCompletionModel } from "../../../../openai.js";
import { ChatCompletionService } from "../../../../custom-request.js";
import { getContext } from "../../../../st-context.js";
@@ -12,6 +12,7 @@ import { power_user } from "../../../../power-user.js";
import { world_info } from "../../../../world-info.js";
import { xbLog, CacheRegistry } from "../core/debug-core.js";
import { getTrustedOrigin } from "../core/iframe-messaging.js";
import { replaceXbGetVarInString, replaceXbGetVarYamlInString } from "./variables/var-commands.js";
const EVT_DONE = 'xiaobaix_streaming_completed';
@@ -366,11 +367,28 @@ class StreamingGeneration {
async _emitPromptReady(chatArray) {
try {
if (Array.isArray(chatArray)) {
await eventSource?.emit?.(event_types.CHAT_COMPLETION_PROMPT_READY, { chat: chatArray, dryRun: false });
const snapshot = this._cloneChat(chatArray);
await eventSource?.emit?.(event_types.CHAT_COMPLETION_PROMPT_READY, { chat: snapshot, dryRun: false });
}
} catch {}
}
_cloneChat(chatArray) {
try {
if (typeof structuredClone === 'function') return structuredClone(chatArray);
} catch {}
try {
return JSON.parse(JSON.stringify(chatArray));
} catch {}
try {
return Array.isArray(chatArray)
? chatArray.map(m => (m && typeof m === 'object' ? { ...m } : m))
: chatArray;
} catch {
return chatArray;
}
}
async processGeneration(generateData, prompt, sessionId, stream = true) {
const session = this._ensureSession(sessionId, prompt);
const abortController = new AbortController();
@@ -788,6 +806,10 @@ class StreamingGeneration {
.replace(/<\s*user\s*>/gi, String(ctx?.name1 || 'User'))
.replace(/<\s*(char|character)\s*>/gi, String(ctx?.name2 || 'Assistant'))
.replace(/<\s*persona\s*>/gi, String(f.persona || ''));
try {
out = replaceXbGetVarInString(out);
out = replaceXbGetVarYamlInString(out);
} catch {}
const snap = this._getLastMessagesSnapshot();
const lastDict = {
'{{lastmessage}}': snap.lastMessage,
@@ -855,13 +877,14 @@ class StreamingGeneration {
/\{\{getvar::([\s\S]*?)\}\}/gi,
(root) => `/getvar key=${escapeForCmd(root)}`
);
await apply(
/\{\{getglobalvar::([\s\S]*?)\}\}/gi,
(root) => `/getglobalvar ${escapeForCmd(root)}`
);
return txt;
};
out = await expandVarMacros(out);
await apply(
/\{\{getglobalvar::([\s\S]*?)\}\}/gi,
(root) => `/getglobalvar ${escapeForCmd(root)}`
);
return txt;
};
out = await expandVarMacros(out);
try { out = substituteParams(out); } catch {}
return out;
}
@@ -964,16 +987,12 @@ class StreamingGeneration {
}
return out;
};
let topMsgs = await mapHistoryPlaceholders(
[]
.concat(topComposite ? this._parseCompositeParam(topComposite) : [])
.concat(createMsgs('top'))
);
let bottomMsgs = await mapHistoryPlaceholders(
[]
.concat(bottomComposite ? this._parseCompositeParam(bottomComposite) : [])
.concat(createMsgs('bottom'))
);
let topMsgs = []
.concat(topComposite ? this._parseCompositeParam(topComposite) : [])
.concat(createMsgs('top'));
let bottomMsgs = []
.concat(bottomComposite ? this._parseCompositeParam(bottomComposite) : [])
.concat(createMsgs('bottom'));
const expandSegmentInline = async (arr) => {
for (const m of arr) {
if (m && typeof m.content === 'string') {
@@ -988,10 +1007,13 @@ class StreamingGeneration {
await expandSegmentInline(bottomMsgs);
topMsgs = await mapHistoryPlaceholders(topMsgs);
bottomMsgs = await mapHistoryPlaceholders(bottomMsgs);
if (typeof prompt === 'string' && prompt.trim()) {
const beforeP = await resolveHistoryPlaceholder(prompt);
const afterP = await this.expandInline(beforeP);
prompt = afterP && afterP.length ? afterP : beforeP;
const afterP = await this.expandInline(prompt);
const beforeP = await resolveHistoryPlaceholder(afterP);
prompt = beforeP && beforeP.length ? beforeP : afterP;
}
try {
const needsWI = [...topMsgs, ...bottomMsgs].some(m => m && typeof m.content === 'string' && m.content.includes('{$worldInfo}')) || (typeof prompt === 'string' && prompt.includes('{$worldInfo}'));