feat: add admin accounts and image templates
This commit is contained in:
63
lib/prompt/material-draft.ts
Normal file
63
lib/prompt/material-draft.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { extractMaterialPlaceholders } from "@/lib/prompt/material-placeholders";
|
||||
|
||||
export type MaterialDraftKind = "image" | "video" | "audio";
|
||||
|
||||
const tokenBoundaryBeforePattern = /[\s,。;:、((【\[]$/;
|
||||
const tokenBoundaryAfterPattern = /^[\s,。;:、))】\]]/;
|
||||
|
||||
export function detectMaterialDraftStart(previous: string, next: string, cursor: number): { text: string; index: number } | null {
|
||||
const index = cursor - 1;
|
||||
if (index < 0 || next[index] !== "@") return null;
|
||||
if (next.length !== previous.length + 1) return null;
|
||||
if (`${next.slice(0, index)}${next.slice(cursor)}` !== previous) return null;
|
||||
return { text: previous, index };
|
||||
}
|
||||
|
||||
export function normalizeMaterialDraftToken(input: string, prompt: string, defaultKind: MaterialDraftKind = "image"): string | null {
|
||||
const query = input.replace(/^@+/, "").trim().replace(/\s+/g, "");
|
||||
if (!query) return nextMaterialDraftToken(defaultKind, prompt);
|
||||
|
||||
const explicit = query.match(/^(参考视频|图片|图|视频|音频)(\d+)$/);
|
||||
if (explicit) {
|
||||
const kind = kindFromText(explicit[1]);
|
||||
const index = Number(explicit[2]);
|
||||
if (Number.isInteger(index) && index > 0) return labelForDraftKind(kind, index);
|
||||
return null;
|
||||
}
|
||||
|
||||
const kindOnly = query.match(/^(参考视频|图片|图|视频|音频)$/);
|
||||
if (kindOnly) return nextMaterialDraftToken(kindFromText(kindOnly[1]), prompt);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function nextMaterialDraftToken(kind: MaterialDraftKind, prompt: string): string {
|
||||
const placeholders = extractMaterialPlaceholders(prompt).filter((placeholder) => placeholder.type === kind);
|
||||
const nextIndex = placeholders.reduce((max, placeholder) => Math.max(max, placeholder.index), 0) + 1;
|
||||
return labelForDraftKind(kind, nextIndex);
|
||||
}
|
||||
|
||||
export function insertMaterialDraftToken(text: string, index: number, token: string): { text: string; cursor: number } {
|
||||
const safeIndex = Math.max(0, Math.min(index, text.length));
|
||||
const before = text.slice(0, safeIndex);
|
||||
const after = text.slice(safeIndex);
|
||||
const needsLeadingSpace = before.length > 0 && !tokenBoundaryBeforePattern.test(before);
|
||||
const needsTrailingSpace = after.length === 0 || !tokenBoundaryAfterPattern.test(after);
|
||||
const insertion = `${needsLeadingSpace ? " " : ""}${token}${needsTrailingSpace ? " " : ""}`;
|
||||
return {
|
||||
text: `${before}${insertion}${after}`,
|
||||
cursor: before.length + insertion.length
|
||||
};
|
||||
}
|
||||
|
||||
export function labelForDraftKind(kind: MaterialDraftKind, index: number): string {
|
||||
if (kind === "video") return `@视频${index}`;
|
||||
if (kind === "audio") return `@音频${index}`;
|
||||
return `@图片${index}`;
|
||||
}
|
||||
|
||||
function kindFromText(value: string): MaterialDraftKind {
|
||||
if (value === "视频" || value === "参考视频") return "video";
|
||||
if (value === "音频") return "audio";
|
||||
return "image";
|
||||
}
|
||||
Reference in New Issue
Block a user