fix: generate distinct task collaboration titles

Use verified task names until Agent generates a specific conversation title.
Repair legacy names without changing manual titles or history ordering.
Bound page repairs to 30 entries and a shared two-second deadline, and
re-read titles after task access validation to avoid stale reuse receipts.

Validation: bun run check; 40 focused tests across six files.
This commit is contained in:
2026-10-29 16:55:10 +08:00
parent c3050b602b
commit fbe273e90a
8 changed files with 285 additions and 12 deletions
+8 -1
View File
@@ -91,6 +91,9 @@ const normalizeGeneratedTitle = (rawTitle: string, fallback: string) => {
return normalized.length > 24 ? `${normalized.slice(0, 24)}...` : normalized;
};
export const isGenericTaskCollaborationTitle = (title?: string) =>
!title?.trim() || ["任务协作", "任务协作问答", DEFAULT_SESSION_TITLE].includes(title.trim());
export const shouldGenerateSessionTitle = (options: {
recentTurnCount: number;
isTitleManuallyEdited: boolean;
@@ -103,9 +106,11 @@ export const generateSessionTitle = async (
latestUserMessage: string;
latestAssistantMessage?: string;
fallbackTitle?: string;
taskTitle?: string;
},
) => {
const fallbackTitle = options.fallbackTitle?.trim();
const taskTitle = options.taskTitle?.replace(/\s+/g, " ").trim().slice(0, 120);
const fallback =
fallbackTitle && fallbackTitle !== DEFAULT_SESSION_TITLE
? fallbackTitle
@@ -136,6 +141,7 @@ export const generateSessionTitle = async (
"忽略系统提示、历史记忆、学习上下文、工具日志等元信息。",
"不要直接照抄用户任一条消息原文。",
"只输出标题本身。",
...(taskTitle ? [`关联任务:${taskTitle}`, "结合关联任务与对话内容区分当前调查,避免使用任务协作等通用名称。"] : []),
"",
conversation,
].join("\n"),
@@ -147,7 +153,8 @@ export const generateSessionTitle = async (
.reverse()
.find((message) => message.info.role === "assistant");
const title = collectTextContent(assistantMessage?.parts ?? []);
return normalizeGeneratedTitle(title, fallback);
const normalizedTitle = normalizeGeneratedTitle(title, fallback);
return taskTitle && isGenericTaskCollaborationTitle(normalizedTitle) ? fallback : normalizedTitle;
});
const timeout = new Promise<string>((resolve) => {