4972243a93
Restrict PR Agent workflow to trusted collaborators on PR comments only, fix UTF-8 byte counting in gallery-pack, correct portrait-to-landscape fallback orientation, track inserted freeform beats in visitedBeatIds, allow clearing stored TTS key, and guard empty-string fuzzy match in style selector. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import { chat } from "@infiplot/ai-client";
|
|
import type { ProviderConfig } from "@infiplot/types";
|
|
import { STYLE_MAP } from "@/lib/options";
|
|
|
|
const STYLE_NAMES = Object.keys(STYLE_MAP);
|
|
|
|
const SYSTEM = `You are an art director for a visual novel. Given the story premise, pick the single best-matching art style from the list below. Consider the genre, mood, setting, and target audience.
|
|
|
|
Available styles:
|
|
${STYLE_NAMES.map((s) => `- ${s}`).join("\n")}
|
|
|
|
Reply with ONLY the style name, nothing else. If uncertain, default to 吉卜力.`;
|
|
|
|
export async function selectStyle(
|
|
textConfig: ProviderConfig,
|
|
worldSetting: string,
|
|
): Promise<string> {
|
|
const result = await chat(
|
|
textConfig,
|
|
[
|
|
{ role: "system", content: SYSTEM },
|
|
{ role: "user", content: worldSetting },
|
|
],
|
|
{ temperature: 0, tag: "styleSelector" },
|
|
);
|
|
|
|
const picked = result.trim();
|
|
if (STYLE_MAP[picked]) {
|
|
return STYLE_MAP[picked];
|
|
}
|
|
const fuzzy = picked
|
|
? STYLE_NAMES.find((s) => picked.includes(s) || s.includes(picked))
|
|
: undefined;
|
|
if (fuzzy) {
|
|
return STYLE_MAP[fuzzy]!;
|
|
}
|
|
console.warn(`[styleSelector] unrecognized style "${picked}", falling back to 吉卜力`);
|
|
return STYLE_MAP["吉卜力"]!;
|
|
}
|