A 👎 now saves, server side, the rated turn plus the context window the model read for it (reconstructed from the stored session with the same consultationHistoryWindow the consult route uses), model and run facts. 👍 is only counted. Switching to 👍 or clearing deletes the snapshot. Bodies are blanked after 90 days; the row cascades on session delete and on account deletion. - Optional 不满意原因 panel under the answer after a 👎 (five reasons, 200-char note, "会把这一轮对话发给我们排查"). - Admin 对话质量记录: 👍/👎 stats by day and model, list without text, audited snapshot open, 处理状态 + note (support.quality.read/write). - Privacy draft: what a 👎 keeps, why, 90 days, deletion. - Migration 20260930050000 is add-only; set_reply_rating() replaced with the same signature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
20 lines
897 B
TypeScript
20 lines
897 B
TypeScript
import { REPLY_QUALITY_RETENTION_DAYS } from "./reply-quality-labels.ts";
|
|
|
|
/**
|
|
* 对话质量记录 retention (compliance round 2026-09-30): snapshot bodies older
|
|
* than 90 days are blanked by expire_reply_quality_snapshot_bodies(); date,
|
|
* model, 不满意原因 and 处理状态 stay for statistics. Logs carry a count only.
|
|
*/
|
|
export const REPLY_QUALITY_RETENTION_TICK_MS = 6 * 60 * 60 * 1000;
|
|
export const REPLY_QUALITY_RETENTION_FIRST_TICK_MS = 2 * 60 * 1000;
|
|
|
|
export async function runReplyQualityRetentionTick(deps: Readonly<{
|
|
expire: (days: number) => Promise<number | null>;
|
|
log: (line: string) => void;
|
|
}>): Promise<number | null> {
|
|
const expired = await deps.expire(REPLY_QUALITY_RETENTION_DAYS);
|
|
if (expired === null) deps.log("[reply-quality-retention] expire failed");
|
|
else if (expired > 0) deps.log(`[reply-quality-retention] expired=${expired}`);
|
|
return expired;
|
|
}
|