ai-chatbot/lib/ai/conversation-thread-state-builder.ts
Your Name e7812060b8
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Update conversation memory and canvas persistence
2026-03-13 12:31:13 +08:00

134 lines
5.7 KiB
TypeScript

import "server-only";
import type { AgentThreadState } from "@/lib/ai/runtime/agent-thread-state";
import type { PromptMemoryEntry } from "@/lib/ai/prompt-memory";
import type { ImageWorkflowMemory } from "@/lib/ai/image-workflow-memory";
import type { StoryboardPreferenceMemory } from "@/lib/video-agent/storyboard-preference-memory";
import { buildAgentThreadStateFromStoryboardTask } from "@/lib/video-agent/agent-thread-state";
type StoryboardTaskDetail = Parameters<typeof buildAgentThreadStateFromStoryboardTask>[0];
function normalizeText(value: unknown, max = 240): string | undefined {
const normalized = String(value || "").trim();
if (!normalized) return undefined;
return normalized.slice(0, max);
}
export function buildConversationThreadState(params: {
activeStoryboardTask?: StoryboardTaskDetail | null;
storyboardPreferenceMemory?: StoryboardPreferenceMemory | null;
promptMemory?: PromptMemoryEntry | null;
imageWorkflowMemory?: ImageWorkflowMemory | null;
}): AgentThreadState | null {
const storyboardState = buildAgentThreadStateFromStoryboardTask(
params.activeStoryboardTask,
{
storyboardPreferenceMemory: params.storyboardPreferenceMemory,
promptMemory: params.promptMemory,
},
);
if (params.activeStoryboardTask?.task?.id) {
return {
workflowState: storyboardState?.workflowState || null,
memoryHints: [
...(storyboardState?.memoryHints || []),
params.imageWorkflowMemory?.lastOptimizedPrompt
? "当前会话里也保留了最近一次图片工作流记忆,可辅助理解用户是在继续哪一轮生图。"
: "",
].filter(Boolean),
contextSummary:
storyboardState?.contextSummary ||
normalizeText(params.imageWorkflowMemory?.lastUserPrompt, 320),
metadata: {
...(storyboardState?.metadata || {}),
imageWorkflowMemory: params.imageWorkflowMemory || undefined,
},
};
}
const hasImageFollowup =
Boolean(params.promptMemory?.optimizedPrompt) ||
Boolean(params.imageWorkflowMemory?.lastOptimizedPrompt) ||
Boolean(params.imageWorkflowMemory?.lastResultImageUrls?.length) ||
Boolean(params.imageWorkflowMemory?.lastSourceImageUrls?.length);
if (!hasImageFollowup && !params.storyboardPreferenceMemory) {
return null;
}
const preferredCount = params.imageWorkflowMemory?.lastRequestedImageCount;
const preferredRatio = params.imageWorkflowMemory?.lastAspectRatio;
const preferredSize = params.imageWorkflowMemory?.lastImageSize;
const sourceCount = params.imageWorkflowMemory?.lastSourceImageUrls?.length || 0;
const resultCount = params.imageWorkflowMemory?.lastResultImageUrls?.length || 0;
const imageFollowupType =
params.imageWorkflowMemory?.lastIntent === "image_edit"
? "image_edit_followup"
: "image_generation_followup";
const imageFollowupTitle =
imageFollowupType === "image_edit_followup"
? "连续修图工作流"
: "连续生图工作流";
return {
workflowState: hasImageFollowup
? {
workflowId: "image-generation-followup",
type: imageFollowupType,
status: "draft",
title: imageFollowupTitle,
summary: [
params.promptMemory?.optimizedPrompt || params.imageWorkflowMemory?.lastOptimizedPrompt
? "当前会话中存在上一轮可复用提示词。"
: "",
preferredCount ? `上一轮目标出图数:${preferredCount} 张。` : "",
preferredRatio ? `上一轮画幅:${preferredRatio}。` : "",
preferredSize ? `上一轮清晰度:${preferredSize}。` : "",
sourceCount > 0 ? `上一轮参考图数:${sourceCount}。` : "",
resultCount > 0 ? `上一轮结果图数:${resultCount}。` : "",
]
.filter(Boolean)
.join(" "),
confirmPhrases: ["按上一个提示词生成", "继续生成", "就按这个来"],
revisionHints: ["换一版", "保持提示词不变再来一组", "沿用上一个提示词"],
pendingItems: [],
metadata: {
promptMemory: params.promptMemory || undefined,
imageWorkflowMemory: params.imageWorkflowMemory || undefined,
storyboardPreferenceMemory: params.storyboardPreferenceMemory || undefined,
},
}
: null,
memoryHints: [
params.promptMemory?.optimizedPrompt
? "当前会话存在上一轮可复用提示词;如果用户明确要求沿用它继续生成,应优先复用。"
: "",
params.imageWorkflowMemory?.lastResultImageUrls?.length
? "当前会话保留了上一轮生成结果图,可用于理解“继续做这张/沿用上一版”的指代。"
: "",
params.imageWorkflowMemory?.lastSourceImageUrls?.length
? "当前会话保留了上一轮参考图/目标图,可用于连续图生图理解。"
: "",
params.storyboardPreferenceMemory
? "当前会话也存在 storyboard 偏好记忆,后续如果转入分镜任务可继续复用。"
: "",
].filter(Boolean),
contextSummary: [
params.promptMemory?.optimizedPrompt
? `上一轮提示词摘要:${normalizeText(params.promptMemory.optimizedPrompt, 180)}`
: "",
params.imageWorkflowMemory?.lastUserPrompt
? `上一轮用户原始需求:${normalizeText(params.imageWorkflowMemory.lastUserPrompt, 180)}`
: "",
]
.filter(Boolean)
.join("\n"),
metadata: {
promptMemory: params.promptMemory || undefined,
imageWorkflowMemory: params.imageWorkflowMemory || undefined,
storyboardPreferenceMemory: params.storyboardPreferenceMemory || undefined,
},
};
}