111 lines
3.9 KiB
TypeScript
111 lines
3.9 KiB
TypeScript
import "server-only";
|
||
|
||
import type { AgentThreadState } from "@/lib/ai/runtime/agent-thread-state";
|
||
|
||
export interface StoryboardPreferenceMemory {
|
||
preferredGridType?: "grid_2x2" | "grid_3x2" | "grid_3x3";
|
||
preferredShotCount?: number;
|
||
prefersConfirmation?: boolean;
|
||
lastUsedGridType?: "grid_2x2" | "grid_3x2" | "grid_3x3";
|
||
lastUsedShotCount?: number;
|
||
}
|
||
|
||
function normalizeGridType(value: unknown) {
|
||
const normalized = String(value || "").trim();
|
||
if (normalized === "grid_2x2" || normalized === "grid_3x2" || normalized === "grid_3x3") {
|
||
return normalized;
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
function normalizeShotCount(value: unknown) {
|
||
const parsed = Number(value);
|
||
if (!Number.isFinite(parsed)) return undefined;
|
||
const rounded = Math.round(parsed);
|
||
if (rounded === 4 || rounded === 6 || rounded === 9) return rounded;
|
||
return undefined;
|
||
}
|
||
|
||
export function extractStoryboardPreferenceMemory(
|
||
workingState?: {
|
||
lastTurnSummary?: unknown;
|
||
} | null,
|
||
): StoryboardPreferenceMemory | null {
|
||
const summary = workingState?.lastTurnSummary;
|
||
if (!summary || typeof summary !== "object") return null;
|
||
const summaryRecord = summary as Record<string, unknown>;
|
||
const memory = summaryRecord.storyboardMemory;
|
||
if (!memory || typeof memory !== "object") return null;
|
||
const memoryRecord = memory as Record<string, unknown>;
|
||
|
||
const normalized: StoryboardPreferenceMemory = {
|
||
preferredGridType: normalizeGridType(memoryRecord.preferredGridType),
|
||
preferredShotCount: normalizeShotCount(memoryRecord.preferredShotCount),
|
||
prefersConfirmation:
|
||
typeof memoryRecord.prefersConfirmation === "boolean"
|
||
? memoryRecord.prefersConfirmation
|
||
: undefined,
|
||
lastUsedGridType: normalizeGridType(memoryRecord.lastUsedGridType),
|
||
lastUsedShotCount: normalizeShotCount(memoryRecord.lastUsedShotCount),
|
||
};
|
||
|
||
if (
|
||
!normalized.preferredGridType &&
|
||
!normalized.preferredShotCount &&
|
||
normalized.prefersConfirmation === undefined &&
|
||
!normalized.lastUsedGridType &&
|
||
!normalized.lastUsedShotCount
|
||
) {
|
||
return null;
|
||
}
|
||
|
||
return normalized;
|
||
}
|
||
|
||
export function buildStoryboardPreferenceMemoryUpdate(params: {
|
||
existing?: StoryboardPreferenceMemory | null;
|
||
preferredGridType?: "grid_2x2" | "grid_3x2" | "grid_3x3";
|
||
preferredShotCount?: number;
|
||
prefersConfirmation?: boolean;
|
||
lastUsedGridType?: "grid_2x2" | "grid_3x2" | "grid_3x3";
|
||
lastUsedShotCount?: number;
|
||
}) {
|
||
const next: StoryboardPreferenceMemory = {
|
||
preferredGridType: params.preferredGridType ?? params.existing?.preferredGridType,
|
||
preferredShotCount: params.preferredShotCount ?? params.existing?.preferredShotCount,
|
||
prefersConfirmation: params.prefersConfirmation ?? params.existing?.prefersConfirmation,
|
||
lastUsedGridType: params.lastUsedGridType ?? params.existing?.lastUsedGridType,
|
||
lastUsedShotCount: params.lastUsedShotCount ?? params.existing?.lastUsedShotCount,
|
||
};
|
||
return next;
|
||
}
|
||
|
||
export function getStoryboardPreferencePlanningHints(
|
||
threadState?: AgentThreadState | null,
|
||
): string[] {
|
||
const metadata = threadState?.metadata;
|
||
const memory =
|
||
metadata && typeof metadata === "object" && !Array.isArray(metadata)
|
||
? ((metadata.storyboardPreferenceMemory as StoryboardPreferenceMemory | undefined) || undefined)
|
||
: undefined;
|
||
if (!memory) return [];
|
||
|
||
const hints: string[] = [];
|
||
if (memory.preferredGridType) {
|
||
hints.push(`用户最近偏好宫格版式:${memory.preferredGridType}。`);
|
||
}
|
||
if (memory.preferredShotCount) {
|
||
hints.push(`用户最近常用镜头数:${memory.preferredShotCount} 段。`);
|
||
}
|
||
if (memory.prefersConfirmation === true) {
|
||
hints.push("用户偏好先确认分镜草案,再开始执行。");
|
||
}
|
||
if (memory.lastUsedGridType && memory.lastUsedShotCount) {
|
||
hints.push(
|
||
`用户最近一次分镜任务使用的是 ${memory.lastUsedGridType}(${memory.lastUsedShotCount} 段)。`
|
||
);
|
||
}
|
||
return hints;
|
||
}
|
||
|