王一帆 6bc1020d34
feat(knowledge): decouple scope and read-only catalogs (phase 2) (#6904)
* feat(knowledge): decouple scope and read-only catalogs

* docs(knowledge): keep frontend guidance within repository budget

* fix(knowledge): align execution identity and harden provider boundaries

* docs: keep knowledge guidance within CI size budgets

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-10-15 15:10:39 +08:00

235 lines
6.5 KiB
TypeScript

import { describe, expect, test } from "@rstest/core";
import {
buildKnowledgeScopeSnapshot,
knowledgeScopeToSelection,
cloneKnowledgeScopeSelection,
readKnowledgeScopeSnapshot,
type KnowledgeScopeSelection,
} from "@/core/knowledge/scope";
describe("knowledge scope snapshots", () => {
test("preserves 256-code-point dataset and document ids and rejects 257", () => {
const selection = (
datasetId: string,
documentId: string,
): KnowledgeScopeSelection => ({
mode: "selected",
datasets: [
{
id: datasetId,
name: "Dataset",
documents: {
mode: "selected",
items: [{ id: documentId, name: "Document" }],
},
},
],
});
const datasetId = "界".repeat(256);
const documentId = "😀".repeat(256);
const snapshot = buildKnowledgeScopeSnapshot(
selection(datasetId, documentId),
);
expect(snapshot.dataset_ids).toEqual([datasetId]);
expect(snapshot.document_filters).toEqual([
{ dataset_id: datasetId, document_ids: [documentId] },
]);
expect(readKnowledgeScopeSnapshot(snapshot)).toEqual(snapshot);
for (const invalid of [
selection(datasetId + "界", documentId),
selection(datasetId, documentId + "😀"),
]) {
expect(() => buildKnowledgeScopeSnapshot(invalid)).toThrow();
}
});
test("builds selected datasets and file filters with bounded display labels", () => {
const snapshot = buildKnowledgeScopeSnapshot({
mode: "selected",
datasets: [
{
id: " dataset-1 ",
name: "Policies",
documents: {
mode: "selected",
items: [
{ id: "doc-1", name: "Leave.pdf" },
{ id: "doc-1", name: "Duplicate.pdf" },
],
},
},
{
id: "dataset-2",
name: "Handbook",
documents: { mode: "all" },
},
],
});
expect(snapshot).toEqual({
version: 1,
mode: "selected",
dataset_ids: ["dataset-1", "dataset-2"],
document_filters: [{ dataset_id: "dataset-1", document_ids: ["doc-1"] }],
display: {
datasets: [
{
id: "dataset-1",
name: "Policies",
documents: [{ id: "doc-1", name: "Leave.pdf" }],
},
{ id: "dataset-2", name: "Handbook" },
],
},
});
});
test("strips catalog metadata from displayed document snapshots", () => {
const catalogDocument = {
id: "doc-1",
name: "Leave.pdf",
selectable: true,
};
const snapshot = buildKnowledgeScopeSnapshot({
mode: "selected",
datasets: [
{
id: "dataset-1",
name: "Policies",
documents: { mode: "selected", items: [catalogDocument] },
},
],
});
expect(snapshot.display?.datasets[0]?.documents).toEqual([
{ id: "doc-1", name: "Leave.pdf" },
]);
});
test("rejects an empty selected document filter", () => {
expect(() =>
buildKnowledgeScopeSnapshot({
mode: "selected",
datasets: [
{
id: "dataset-1",
name: "Policies",
documents: { mode: "selected", items: [] },
},
],
}),
).toThrow(/at least one document/i);
});
test("omits overlong display names without truncating execution ids", () => {
const snapshot = buildKnowledgeScopeSnapshot({
mode: "selected",
datasets: [
{
id: "dataset-1",
name: "x".repeat(257),
documents: { mode: "all" },
},
],
});
expect(snapshot.dataset_ids).toEqual(["dataset-1"]);
expect(snapshot.display).toBeUndefined();
});
test("counts astral Unicode characters as code points", () => {
const emojiName = "😀".repeat(256);
const snapshot = buildKnowledgeScopeSnapshot({
mode: "selected",
datasets: [
{
id: "dataset-1",
name: emojiName,
documents: { mode: "all" },
},
],
});
expect(snapshot.display?.datasets[0]?.name).toBe(emojiName);
});
test("clones nested selection state for immutable message snapshots", () => {
const selection: KnowledgeScopeSelection = {
mode: "selected",
datasets: [
{
id: "dataset-1",
name: "Policies",
documents: {
mode: "selected",
items: [{ id: "doc-1", name: "Leave.pdf" }],
},
},
],
};
const cloned = cloneKnowledgeScopeSelection(selection);
if (selection.mode === "selected") selection.datasets[0]!.name = "Renamed";
expect(cloned).not.toBe(selection);
expect(cloned.mode === "selected" && cloned.datasets[0]?.name).toBe(
"Policies",
);
});
test("reads only recognized version-one modes", () => {
expect(readKnowledgeScopeSnapshot({ version: 1, mode: "all" })).toEqual({
version: 1,
mode: "all",
});
expect(readKnowledgeScopeSnapshot({ version: 2, mode: "all" })).toBeNull();
expect(
readKnowledgeScopeSnapshot({
version: 1,
mode: "selected",
dataset_ids: ["dataset-1"],
document_filters: [{ dataset_id: "dataset-1", document_ids: null }],
}),
).toBeNull();
});
});
describe("agent knowledge defaults", () => {
test("restores every execution ID even when display labels were capped", () => {
const selection = knowledgeScopeToSelection({
version: 1,
mode: "selected",
dataset_ids: ["a", "b"],
document_filters: [{ dataset_id: "b", document_ids: ["one", "two"] }],
display: { datasets: [{ id: "a", name: "Policies" }] },
});
expect(selection).toEqual({
mode: "selected",
datasets: [
{ id: "a", name: "Policies", documents: { mode: "all" } },
{
id: "b",
name: "b",
documents: {
mode: "selected",
items: [
{ id: "one", name: "one" },
{ id: "two", name: "two" },
],
},
},
],
});
expect(buildKnowledgeScopeSnapshot(selection)).toMatchObject({
dataset_ids: ["a", "b"],
document_filters: [{ dataset_id: "b", document_ids: ["one", "two"] }],
});
});
test("missing defaults inherit all while disabled stays disabled", () => {
expect(knowledgeScopeToSelection(null)).toEqual({ mode: "all" });
expect(knowledgeScopeToSelection({ version: 1, mode: "disabled" })).toEqual(
{ mode: "disabled" },
);
});
});