BUG-729: dropped history rounds leave an omission marker in the model-visible summary slot. BUG-730: checkpoint threshold is 0.4 of historyBudgetChars (128k still 16,000). BUG-731: session_full new chat copies owned context_summary on the server; clients send only continued_from_session_id.
68 lines
3.7 KiB
TypeScript
68 lines
3.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
const consultRoute = readFileSync(new URL("../src/app/api/consult/route.ts", import.meta.url), "utf8");
|
|
const history = readFileSync(new URL("../src/lib/consultation-session-history.ts", import.meta.url), "utf8");
|
|
const migration = readFileSync(
|
|
new URL("../supabase/migrations/20260906010000_chat_session_context_summary.sql", import.meta.url),
|
|
"utf8",
|
|
);
|
|
const generation = readFileSync(new URL("../src/lib/agent-generation-settings.ts", import.meta.url), "utf8");
|
|
|
|
test("consult history uses the checkpoint tail and puts the summary after the time line", () => {
|
|
assert.match(consultRoute, /consultationHistoryWindow\(chatSession\.messages, contextSummary/);
|
|
assert.match(consultRoute, /SESSION_CONTEXT_SUMMARY_HEADING|consultationUserTurnContent/);
|
|
assert.match(consultRoute, /summaryText: historyWindow\.summaryText/);
|
|
assert.match(consultRoute, /droppedCount: historyWindow\.droppedCount/);
|
|
assert.match(history, /【会话摘要(服务端维护)】/);
|
|
assert.match(history, /droppedRoundsMarker/);
|
|
assert.doesNotMatch(history, /16_000|16000/);
|
|
const helper = history.slice(history.indexOf("export function consultationUserTurnContent"));
|
|
const timeLine = helper.indexOf("input.currentTime");
|
|
const summaryLine = helper.indexOf("SESSION_CONTEXT_SUMMARY_HEADING");
|
|
const questionLine = helper.indexOf("input.question");
|
|
assert.ok(timeLine >= 0 && summaryLine > timeLine && questionLine > summaryLine);
|
|
});
|
|
|
|
test("consult retries once on context overflow with summary plus the last pair", () => {
|
|
assert.match(consultRoute, /isContextOverflowError/);
|
|
assert.match(consultRoute, /streamWithOverflowRetry/);
|
|
assert.match(consultRoute, /consultationBaseMessages\(true\)/);
|
|
assert.match(consultRoute, /lastConsultationPair\(history\)/);
|
|
assert.match(history, /context_length_exceeded/);
|
|
});
|
|
|
|
test("consult checkpoints the session summary after a successful completion", () => {
|
|
assert.match(consultRoute, /void checkpointConsultationContext\(\)/);
|
|
assert.match(consultRoute, /checkpointSessionContextSummary/);
|
|
assert.match(consultRoute, /contextWindow: sessionContextWindow/);
|
|
assert.match(consultRoute, /context_summary ->>updatedAt|context_summary->>updatedAt/);
|
|
assert.match(consultRoute, /console\.warn\("session context summary failed"/);
|
|
assert.doesNotMatch(consultRoute, /AbortSignal\.timeout\(\s*15/);
|
|
const summary = readFileSync(new URL("../src/lib/session-context-summary.ts", import.meta.url), "utf8");
|
|
assert.match(summary, /consultationHistoryCheckpointChars/);
|
|
assert.doesNotMatch(summary, /CONSULTATION_HISTORY_TAIL_MAX_CHARS/);
|
|
});
|
|
|
|
test("the context summary migration only adds one jsonb column", () => {
|
|
assert.match(migration, /add column if not exists context_summary jsonb null/);
|
|
assert.match(migration, /jsonb_typeof\(context_summary\) = 'object'/);
|
|
assert.match(migration, /grant update \(context_summary\)/);
|
|
assert.doesNotMatch(migration, /create index|backfill|update public\.chat_sessions set/);
|
|
});
|
|
|
|
test("Anthropic history cache is applied only to the last history message", () => {
|
|
assert.match(consultRoute, /cachedHistoryMessage/);
|
|
assert.match(generation, /export function cachedHistoryMessage/);
|
|
const helper = consultRoute.slice(consultRoute.indexOf("const consultationBaseMessages"));
|
|
assert.match(helper, /mapped\.length > 0/);
|
|
assert.match(helper, /cachedHistoryMessage\(mapped\[mapped\.length - 1\]/);
|
|
});
|
|
|
|
test("the published model catalog reads context_window", () => {
|
|
const catalog = readFileSync(new URL("../src/lib/model-catalog.ts", import.meta.url), "utf8");
|
|
assert.match(catalog, /v\.context_window/);
|
|
assert.match(catalog, /contextWindow:/);
|
|
});
|