refactor: extract execution prompt assembly

This commit is contained in:
kris
2026-04-02 22:32:19 +08:00
parent e348d6cc5d
commit 384dd570de
7 changed files with 415 additions and 157 deletions

View File

@@ -0,0 +1,88 @@
import type { MasterAgentMemory } from "@/lib/boss-data";
export type RelevantMemory = Pick<
MasterAgentMemory,
"memoryId" | "scope" | "projectId" | "title" | "content" | "tags" | "memoryType" | "lastUsedAt" | "updatedAt" | "createdAt"
>;
export function resolveRelevantMemories(input: {
projectId: string;
requestText?: string;
memories: RelevantMemory[];
}) {
const lowered = input.requestText?.trim().toLowerCase() ?? "";
const projectScoped = input.memories.filter((memory) => {
if (memory.scope !== "project") {
return false;
}
if (input.projectId !== "master-agent") {
return memory.projectId === input.projectId;
}
return true;
});
const projectMemories =
input.projectId !== "master-agent"
? projectScoped.slice(0, 6)
: !lowered
? projectScoped.slice(0, 6)
: projectScoped
.filter((memory) => {
const haystacks = [memory.projectId, memory.title, memory.content, ...(memory.tags ?? [])]
.filter((value): value is string => Boolean(value))
.map((value) => value.toLowerCase());
return haystacks.some((value) => lowered.includes(value) || value.includes(lowered));
})
.slice(0, 6);
const userMemories = input.memories.filter((memory) => memory.scope === "global").slice(0, 8);
return {
projectMemories,
userMemories,
};
}
function prioritizeRuntimeMemories(memories: RelevantMemory[]) {
const globalMemories = memories
.filter((memory) => memory.scope === "global")
.sort((left, right) => {
const leftPriority =
left.memoryType === "workflow_rule" || left.memoryType === "user_preference" ? 1 : 0;
const rightPriority =
right.memoryType === "workflow_rule" || right.memoryType === "user_preference" ? 1 : 0;
if (leftPriority !== rightPriority) {
return rightPriority - leftPriority;
}
const leftTime = Date.parse(left.lastUsedAt ?? left.updatedAt ?? left.createdAt) || 0;
const rightTime = Date.parse(right.lastUsedAt ?? right.updatedAt ?? right.createdAt) || 0;
return rightTime - leftTime;
});
const projectMemories = memories.filter((memory) => memory.scope === "project");
return [...globalMemories, ...projectMemories];
}
export function resolveRuntimeRelevantMemories(input: {
projectId: string;
requestText?: string;
memories: RelevantMemory[];
}) {
const prioritizedMemories = prioritizeRuntimeMemories(input.memories);
const resolved = resolveRelevantMemories({
projectId: input.projectId,
requestText: input.requestText,
memories: prioritizedMemories,
});
if (input.projectId === "master-agent" && input.requestText?.trim() && resolved.projectMemories.length === 0) {
return {
projectMemories: prioritizedMemories.filter((memory) => memory.scope === "project").slice(0, 6),
userMemories: resolved.userMemories,
};
}
return resolved;
}
export const resolveRelevantMemoriesForTesting = resolveRelevantMemories;
export const resolveRuntimeRelevantMemoriesForTesting = resolveRuntimeRelevantMemories;

View File

@@ -0,0 +1,48 @@
import type { MasterAgentMemory } from "@/lib/boss-data";
type PromptMemory = Pick<MasterAgentMemory, "projectId" | "title" | "content" | "tags">;
function buildProjectMemorySection(memories: PromptMemory[]) {
if (memories.length === 0) {
return null;
}
return [
"项目记忆:",
...memories.map((memory) => `- [${memory.projectId ?? "unknown"}] ${memory.title}: ${memory.content}`),
].join("\n");
}
function buildUserMemorySection(memories: PromptMemory[]) {
if (memories.length === 0) {
return null;
}
return [
"用户通用记忆:",
...memories.map((memory) => `- ${memory.title}: ${memory.content}`),
].join("\n");
}
export function buildExecutionPrompt(input: {
globalPrompt?: string | null;
userPrompt?: string | null;
conversationPrompt?: string | null;
projectMemories: PromptMemory[];
userMemories: PromptMemory[];
requestText: string;
}) {
return [
input.globalPrompt?.trim() ? `管理员全局主提示词:\n${input.globalPrompt.trim()}` : null,
input.userPrompt?.trim() ? `用户私有主提示词:\n${input.userPrompt.trim()}` : null,
input.conversationPrompt?.trim() ? `当前对话附加提示词:\n${input.conversationPrompt.trim()}` : null,
buildProjectMemorySection(input.projectMemories),
buildUserMemorySection(input.userMemories),
`当前消息:\n${input.requestText}`,
]
.filter((value): value is string => value !== null)
.join("\n\n");
}
export const buildExecutionPromptForTesting = buildExecutionPrompt;
export { resolveRelevantMemoriesForTesting } from "@/lib/execution/memory-resolver";