135 lines
5.0 KiB
TypeScript
135 lines
5.0 KiB
TypeScript
import "server-only";
|
|
|
|
import type { ConversationActionResolution } from "@/lib/ai/conversation-action-resolver";
|
|
import type { TaskBoundaryDecision } from "@/lib/ai/runtime/task-boundary-classifier";
|
|
|
|
export interface MemoryRelevancePolicy {
|
|
includePromptMemory: boolean;
|
|
includeImageWorkflowMemory: boolean;
|
|
includeStoryboardPreferenceMemory: boolean;
|
|
includeWorkflowState: boolean;
|
|
maxMemoryHints: number;
|
|
maxContextLines: number;
|
|
reason: string;
|
|
}
|
|
|
|
export function resolveMemoryRelevancePolicy(params: {
|
|
taskBoundaryDecision: TaskBoundaryDecision;
|
|
actionResolution: ConversationActionResolution;
|
|
hasActiveStoryboardTask: boolean;
|
|
hasPendingGridConfirmation: boolean;
|
|
hasCurrentImageInput: boolean;
|
|
hasCanvasSelection: boolean;
|
|
}) {
|
|
const { taskBoundaryDecision, actionResolution } = params;
|
|
|
|
switch (taskBoundaryDecision.taskType) {
|
|
case "greeting":
|
|
return {
|
|
includePromptMemory: false,
|
|
includeImageWorkflowMemory: false,
|
|
includeStoryboardPreferenceMemory: false,
|
|
includeWorkflowState: false,
|
|
maxMemoryHints: 0,
|
|
maxContextLines: 2,
|
|
reason: "greeting_turn_ignores_task_memory",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "chat":
|
|
return {
|
|
includePromptMemory: false,
|
|
includeImageWorkflowMemory: false,
|
|
includeStoryboardPreferenceMemory: false,
|
|
includeWorkflowState: false,
|
|
maxMemoryHints: 1,
|
|
maxContextLines: 3,
|
|
reason: "chat_turn_prefers_clean_context",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "prompt_only":
|
|
return {
|
|
includePromptMemory: false,
|
|
includeImageWorkflowMemory: false,
|
|
includeStoryboardPreferenceMemory: false,
|
|
includeWorkflowState: false,
|
|
maxMemoryHints: 2,
|
|
maxContextLines: 4,
|
|
reason: "prompt_only_turn_ignores_execution_memory",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "analysis_only":
|
|
return {
|
|
includePromptMemory: false,
|
|
includeImageWorkflowMemory: false,
|
|
includeStoryboardPreferenceMemory: false,
|
|
includeWorkflowState: false,
|
|
maxMemoryHints: 2,
|
|
maxContextLines: 4,
|
|
reason: "analysis_only_turn_ignores_workflow_memory",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "execution_video":
|
|
return {
|
|
includePromptMemory: false,
|
|
includeImageWorkflowMemory: false,
|
|
includeStoryboardPreferenceMemory: true,
|
|
includeWorkflowState:
|
|
params.hasActiveStoryboardTask || params.hasPendingGridConfirmation,
|
|
maxMemoryHints: 4,
|
|
maxContextLines: 6,
|
|
reason: "video_execution_prefers_storyboard_preferences",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "workflow_followup":
|
|
return {
|
|
includePromptMemory:
|
|
actionResolution.kind === "image_generation_followup" ||
|
|
actionResolution.kind === "prompt_carry_forward",
|
|
includeImageWorkflowMemory:
|
|
actionResolution.kind === "image_edit_followup" ||
|
|
actionResolution.kind === "image_generation_followup" ||
|
|
actionResolution.kind === "prompt_carry_forward",
|
|
includeStoryboardPreferenceMemory:
|
|
actionResolution.kind === "grid_confirmation_followup" ||
|
|
actionResolution.kind === "active_storyboard_followup",
|
|
includeWorkflowState: true,
|
|
maxMemoryHints: 6,
|
|
maxContextLines: 8,
|
|
reason: "workflow_followup_requires_workflow_memory",
|
|
} satisfies MemoryRelevancePolicy;
|
|
case "execution_image":
|
|
default:
|
|
return {
|
|
includePromptMemory:
|
|
actionResolution.usePromptCarryForward ||
|
|
taskBoundaryDecision.taskMode === "continue",
|
|
includeImageWorkflowMemory:
|
|
taskBoundaryDecision.taskMode === "continue" ||
|
|
(!params.hasCurrentImageInput && !params.hasCanvasSelection),
|
|
includeStoryboardPreferenceMemory: false,
|
|
includeWorkflowState:
|
|
taskBoundaryDecision.taskMode === "continue" &&
|
|
(actionResolution.kind === "image_edit_followup" ||
|
|
actionResolution.kind === "image_generation_followup" ||
|
|
actionResolution.kind === "prompt_carry_forward"),
|
|
maxMemoryHints: taskBoundaryDecision.taskMode === "continue" ? 5 : 3,
|
|
maxContextLines: taskBoundaryDecision.taskMode === "continue" ? 7 : 5,
|
|
reason:
|
|
taskBoundaryDecision.taskMode === "continue"
|
|
? "image_execution_continue_reuses_relevant_memory"
|
|
: "image_execution_new_task_limits_old_memory",
|
|
} satisfies MemoryRelevancePolicy;
|
|
}
|
|
}
|
|
|
|
export function applyMemoryHintLimit(hints: string[], maxHints: number) {
|
|
if (!Array.isArray(hints) || maxHints <= 0) return [] as string[];
|
|
return hints.slice(0, maxHints);
|
|
}
|
|
|
|
export function applyContextLineLimit(summary: string | undefined, maxLines: number) {
|
|
const normalized = String(summary || "").trim();
|
|
if (!normalized || maxLines <= 0) return "";
|
|
return normalized
|
|
.split("\n")
|
|
.map((line) => line.trim())
|
|
.filter(Boolean)
|
|
.slice(0, maxLines)
|
|
.join("\n");
|
|
}
|