feat: 提示窗流式文本预览+回调链路+自动淡出调整

This commit is contained in:
Youzini-afk
2026-03-27 14:13:11 +08:00
parent 62902c9867
commit 477fa40049
4 changed files with 46 additions and 4 deletions

View File

@@ -89,6 +89,7 @@ export async function extractMemories({
extractPrompt, extractPrompt,
signal = undefined, signal = undefined,
settings = {}, settings = {},
onStreamProgress = null,
}) { }) {
throwIfAborted(signal); throwIfAborted(signal);
if (!messages || messages.length === 0) { if (!messages || messages.length === 0) {
@@ -184,6 +185,7 @@ export async function extractMemories({
debugContext: createTaskLlmDebugContext(promptBuild, extractRegexInput), debugContext: createTaskLlmDebugContext(promptBuild, extractRegexInput),
promptMessages: promptPayload.promptMessages, promptMessages: promptPayload.promptMessages,
additionalMessages: promptPayload.additionalMessages, additionalMessages: promptPayload.additionalMessages,
onStreamProgress,
}); });
throwIfAborted(signal); throwIfAborted(signal);

View File

@@ -416,11 +416,11 @@ function getStageNoticeTitle(stage) {
function getStageNoticeDuration(level = "info") { function getStageNoticeDuration(level = "info") {
switch (level) { switch (level) {
case "error": case "error":
return 5600; return 6000;
case "warning": case "warning":
return 4600; return 5000;
case "success": case "success":
return 2800; return 3000;
default: default:
return 3200; return 3200;
} }
@@ -2967,6 +2967,16 @@ async function executeExtractionBatch({
extractPrompt: undefined, extractPrompt: undefined,
settings, settings,
signal, signal,
onStreamProgress: ({ previewText, receivedChars }) => {
const preview = previewText?.length > 80
? "…" + previewText.slice(-80)
: previewText || "";
setLastExtractionStatus(
"AI 生成中",
`${preview}\n已接收 ${receivedChars} 字符`,
"running",
);
},
}); });
if (!result.success) { if (!result.success) {
@@ -3737,6 +3747,17 @@ async function runRecall(options = {}) {
schema: getSchema(), schema: getSchema(),
signal: recallSignal, signal: recallSignal,
settings, settings,
onStreamProgress: ({ previewText, receivedChars }) => {
const preview = previewText?.length > 80
? "…" + previewText.slice(-80)
: previewText || "";
setLastRecallStatus(
"AI 生成中",
`${preview}\n已接收 ${receivedChars} 字符`,
"running",
{ syncRuntime: true },
);
},
options: { options: {
topK: settings.recallTopK, topK: settings.recallTopK,
maxRecallNodes: settings.recallMaxNodes, maxRecallNodes: settings.recallMaxNodes,

17
llm.js
View File

@@ -836,7 +836,7 @@ function isAbortError(error) {
async function parseDedicatedStreamingResponse( async function parseDedicatedStreamingResponse(
response, response,
{ taskKey = "", streamState = null } = {}, { taskKey = "", streamState = null, onStreamProgress = null } = {},
) { ) {
const reader = response?.body?.getReader?.(); const reader = response?.body?.getReader?.();
if (!reader) { if (!reader) {
@@ -938,6 +938,15 @@ async function parseDedicatedStreamingResponse(
streamState.previewText, streamState.previewText,
deltaText, deltaText,
); );
if (typeof onStreamProgress === "function") {
try {
onStreamProgress({
previewText: streamState.previewText,
chunkCount: streamState.chunkCount,
receivedChars: streamState.receivedChars,
});
} catch {}
}
} }
if (reasoningDelta) { if (reasoningDelta) {
@@ -1004,6 +1013,7 @@ async function executeDedicatedRequest(
jsonMode = false, jsonMode = false,
taskKey = "", taskKey = "",
streamState = null, streamState = null,
onStreamProgress = null,
} = {}, } = {},
) { ) {
const requestBody = cloneRuntimeDebugValue(body, {}) || {}; const requestBody = cloneRuntimeDebugValue(body, {}) || {};
@@ -1064,6 +1074,7 @@ async function executeDedicatedRequest(
return await parseDedicatedStreamingResponse(response, { return await parseDedicatedStreamingResponse(response, {
taskKey, taskKey,
streamState, streamState,
onStreamProgress,
}); });
} }
@@ -1079,6 +1090,7 @@ async function callDedicatedOpenAICompatible(
maxCompletionTokens = null, maxCompletionTokens = null,
taskType = "", taskType = "",
requestSource = "", requestSource = "",
onStreamProgress = null,
} = {}, } = {},
) { ) {
const privateRequestSource = resolvePrivateRequestSource( const privateRequestSource = resolvePrivateRequestSource(
@@ -1246,6 +1258,7 @@ async function callDedicatedOpenAICompatible(
jsonMode, jsonMode,
taskKey, taskKey,
streamState, streamState,
onStreamProgress,
}); });
} catch (error) { } catch (error) {
if ( if (
@@ -1332,6 +1345,7 @@ export async function callLLMForJSON({
additionalMessages = [], additionalMessages = [],
promptMessages = [], promptMessages = [],
debugContext = null, debugContext = null,
onStreamProgress = null,
} = {}) { } = {}) {
const override = getLlmTestOverride("callLLMForJSON"); const override = getLlmTestOverride("callLLMForJSON");
if (override) { if (override) {
@@ -1370,6 +1384,7 @@ export async function callLLMForJSON({
jsonMode: true, jsonMode: true,
taskType, taskType,
requestSource: privateRequestSource, requestSource: privateRequestSource,
onStreamProgress,
maxCompletionTokens: maxCompletionTokens:
attempt === 0 attempt === 0
? DEFAULT_JSON_COMPLETION_TOKENS ? DEFAULT_JSON_COMPLETION_TOKENS

View File

@@ -80,6 +80,7 @@ export async function retrieve({
signal = undefined, signal = undefined,
options = {}, options = {},
settings = {}, settings = {},
onStreamProgress = null,
}) { }) {
throwIfAborted(signal); throwIfAborted(signal);
const topK = options.topK ?? 20; const topK = options.topK ?? 20;
@@ -286,6 +287,7 @@ export async function retrieve({
options.recallPrompt, options.recallPrompt,
settings, settings,
signal, signal,
onStreamProgress,
); );
selectedNodeIds = llmResult.selectedNodeIds; selectedNodeIds = llmResult.selectedNodeIds;
llmMeta = { llmMeta = {
@@ -429,6 +431,7 @@ async function llmRecall(
customPrompt, customPrompt,
settings = {}, settings = {},
signal, signal,
onStreamProgress = null,
) { ) {
throwIfAborted(signal); throwIfAborted(signal);
const contextStr = recentMessages.join("\n---\n"); const contextStr = recentMessages.join("\n---\n");
@@ -496,6 +499,7 @@ async function llmRecall(
), ),
promptMessages: promptPayload.promptMessages, promptMessages: promptPayload.promptMessages,
additionalMessages: promptPayload.additionalMessages, additionalMessages: promptPayload.additionalMessages,
onStreamProgress,
}); });
if (result?.selected_ids && Array.isArray(result.selected_ids)) { if (result?.selected_ids && Array.isArray(result.selected_ids)) {