完善配方驱动的创作编排

为可重复技能补充参数校验与展示,统一配方、编排器和执行单元术语。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
moran
2026-07-30 17:59:20 +08:00
parent e670a5129c
commit 6392af54b4
49 changed files with 1671 additions and 626 deletions

View File

@@ -177,7 +177,7 @@ export async function handleBooksApi(
return true;
}
/** 新建作品:导演一层选型(内部 = recipes catalog */
/** 新建作品:配方一层选型(内部 = recipes catalog */
if (pathname === "/api/directors" && req.method === "GET") {
const { DEFAULT_ORCHESTRATOR_ID } = await import(
"../config/default-orchestrator.js"
@@ -202,7 +202,7 @@ export async function handleBooksApi(
});
} catch (err) {
json(res, 404, {
error: err instanceof Error ? err.message : "未找到导演列表",
error: err instanceof Error ? err.message : "未找到配方列表",
});
}
return true;
@@ -229,13 +229,13 @@ export async function handleBooksApi(
});
} catch (err) {
json(res, 404, {
error: err instanceof Error ? err.message : "未找到能包",
error: err instanceof Error ? err.message : "未找到能包",
});
}
return true;
}
/** 默认导演包的能力池(编排备选) */
/** 默认配方包的技能池(编排备选) */
if (pathname === "/api/modules" && req.method === "GET") {
const { DEFAULT_ORCHESTRATOR_ID } = await import(
"../config/default-orchestrator.js"
@@ -320,9 +320,9 @@ export async function handleBooksApi(
if (pathname === "/api/books" && req.method === "POST") {
const body = JSON.parse(await readBody(req)) as {
title?: string;
/** 导演 Skill / 能力包 idregistry name */
/** 编排器包 idregistry name */
orchestratorId?: string;
/** 用户手动选定的导演 id内部 recipe */
/** 用户手动选定的配方 id内部 recipe */
recipeId?: string;
};
const skills = await listSkills();
@@ -332,7 +332,7 @@ export async function handleBooksApi(
skills.find((s) => s.name === "world-simulator") ||
skills[0];
if (!director) {
json(res, 400, { error: "没有可用的导演 Skill能力包" });
json(res, 400, { error: "没有可用的编排器技能包" });
return true;
}
const book = createBook({ title: body.title });

View File

@@ -1,6 +1,7 @@
/**
* 用户可见中文标签(与 docs/ui-glossary.md 同步)。
* 内部 id 不变;仅展示层映射。
* 口径:配方 / 编排器 / 技能 / 工作流计划 / 运行规格 / 执行单元
*/
const STAGE_LABELS: Record<string, string> = {
@@ -15,15 +16,15 @@ const STAGE_LABELS: Record<string, string> = {
const WORKER_LABELS: Record<string, string> = {
"design-core": "创作 · 核心",
"design-worker": "创作 · 演员规格",
"design-worker": "创作 · 执行单元规格",
"design-fixed": "创作 · 固定上下文",
"design-refine": "创作 · 细化与终稿",
"design-intake": "创作 · 综合收口",
"design-flow": "创作 · 流程编排",
"design-step": "创作 · 执行步骤",
"opening-generator": "开局 · 开场白",
orchestrator: "导演",
"agent-burst": "导演调度",
orchestrator: "编排器",
"agent-burst": "编排器调度",
narrator: "叙事转述",
"role-decide": "角色决策",
"world-simulator": "世界推演",
@@ -57,14 +58,14 @@ export function displayStageLabel(id: string | undefined | null): string {
return STAGE_LABELS[id] ?? id;
}
/** 导演选项 / skill pack 展示名 */
/** 配方选项 / skill pack 展示名 */
export function displaySkillPackLabel(id: string | undefined | null): string {
if (!id) return "";
return SKILL_PACK_LABELS[id] ?? id;
}
/**
* 演员 / 单位 / 能 id → 用户可见名(不含动作后缀)。
* 执行单元 / 单位 / 能 id → 用户可见名(不含动作后缀)。
*/
export function displayWorkerLabel(id: string | undefined | null): string {
if (!id) return "";
@@ -79,11 +80,11 @@ export function displayWorkerLabel(id: string | undefined | null): string {
}
if (trimmed.startsWith("worker:")) {
const ref = trimmed.slice("worker:".length);
return `演员 · ${displayWorkerLabel(ref)}`;
return `执行单元 · ${displayWorkerLabel(ref)}`;
}
if (trimmed.startsWith("fixed:")) {
const topic = trimmed.slice("fixed:".length);
return ` · ${FIXED_TOPIC_LABELS[topic] ?? topic}`;
return `能 · ${FIXED_TOPIC_LABELS[topic] ?? topic}`;
}
if (trimmed.startsWith("resident:")) {
return `常驻 · ${trimmed.slice("resident:".length)}`;
@@ -99,7 +100,7 @@ export function formatWorkerDisplayTitle(
workerId: string | undefined | null,
action: WorkerTitleAction = null,
): string {
const base = displayWorkerLabel(workerId) || "演员";
const base = displayWorkerLabel(workerId) || "执行单元";
switch (action) {
case "output":
return `${base} · 产出`;
@@ -114,8 +115,8 @@ export function formatWorkerDisplayTitle(
}
}
/** 导演(调度 Agent相关标题 */
/** 编排器(调度 Agent相关标题 */
export function formatAgentDisplayTitle(detail?: string): string {
if (detail?.trim()) return `导演 · ${detail.trim()}`;
return "导演";
if (detail?.trim()) return `编排器 · ${detail.trim()}`;
return "编排器";
}