52f3c04b3b
Measured use of the three chips above the composer was negligible. They were also not what they appeared to be: the server looked up a fixed triplet by session theme and passed it as metadata that overrode anything the model produced, so the same ten hardcoded sets served every user regardless of question or chart. That is a plausible reason nobody pressed them. Both copies of the per-theme table are gone, reply metadata narrows to the session title, and the two parse entry points collapse into one now that they return the same shape. The write schema still tolerates a suggestions field so a client on the previous bundle does not lose its message mid-deploy, and stored answers containing the legacy hidden block are still stripped rather than shown raw. Co-authored-by: Cursor <cursoragent@cursor.com>
47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import type { ConsultationDomain } from "./consultation-domain-registry.ts";
|
||
|
||
export type ReplyTheme = ConsultationDomain;
|
||
|
||
import type { ConsultationReplyMetadata } from "./consultation-reply-metadata.ts";
|
||
|
||
function readTitle(value: string): string | undefined {
|
||
const title = value.replace(/\s+/g, " ").trim();
|
||
if (!title || /[\d\p{P}\p{S}]/u.test(title)) return undefined;
|
||
if (/\p{Script=Han}/u.test(title)) {
|
||
const length = Array.from(title.replace(/\s/g, "")).length;
|
||
return length >= 6 && length <= 14 ? title : undefined;
|
||
}
|
||
const words = title.split(" ").filter(Boolean);
|
||
return words.length >= 3 && words.length <= 7 && title.length <= 64 ? title : undefined;
|
||
}
|
||
|
||
// AYANAM_SUGGESTIONS blocks are no longer produced anywhere, but stored answers from
|
||
// before the follow-up chips were removed still carry them, so they stay strippable
|
||
// rather than leaking a raw HTML comment into a replayed transcript.
|
||
function stripAgentReplyMetadata(value: string) {
|
||
let title: string | undefined;
|
||
const text = value
|
||
.replace(/<!--AYANAM_SUGGESTIONS:\[[\s\S]*?\]-->/g, "")
|
||
.replace(/<!--AYANAM_TITLE:([\s\S]*?)-->/g, (_, rawTitle: string) => {
|
||
title = readTitle(rawTitle);
|
||
return "";
|
||
})
|
||
.replace(/<!--AYANAM_[\s\S]*$/, "")
|
||
.trim();
|
||
|
||
return { text, title };
|
||
}
|
||
|
||
export function parseAgentReply(value: string, metadata?: ConsultationReplyMetadata) {
|
||
const parsed = stripAgentReplyMetadata(value);
|
||
return { text: parsed.text, title: metadata?.title ?? parsed.title };
|
||
}
|
||
|
||
export function resolveSessionTitle(question: string, modelTitle?: string): string {
|
||
if (modelTitle && modelTitle !== "一般占星咨询") return modelTitle;
|
||
const normalized = question.replace(/\s+/g, " ").trim().replace(/[??!!。.,,;;::]+$/u, "");
|
||
if (!normalized) return "新对话";
|
||
const characters = Array.from(normalized);
|
||
return characters.length > 14 ? `${characters.slice(0, 14).join("")}…` : normalized;
|
||
}
|