From f23ef69bc64ea40d1cf918ca8bc839ea67746910 Mon Sep 17 00:00:00 2001 From: suguanYang Date: Sun, 5 Jul 2026 18:05:59 +0800 Subject: [PATCH] Align remote source processed row state --- src/components/source-row.test.ts | 38 +++++++++++++++++++++++ src/components/source-row.tsx | 5 ++- src/domains/chat/index.test.ts | 6 ++-- src/domains/chat/retrieval.ts | 9 +++++- src/domains/sources/remote-library.ts | 2 +- src/domains/sources/route-service.test.ts | 4 +-- 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/components/source-row.test.ts b/src/components/source-row.test.ts index 26e413f..427e09a 100644 --- a/src/components/source-row.test.ts +++ b/src/components/source-row.test.ts @@ -49,6 +49,44 @@ describe("SourceRow", () => { expect(screen.getByText("Processed · 3 chunks")).toBeTruthy(); }); + it("labels unlocalized remote documents as processed without chunk counts", () => { + const onToggleIncluded = vi.fn(); + + render( + React.createElement(SourceRow, { + isArchiving: false, + isSelected: false, + onSelect: vi.fn(), + onToggleIncluded, + source: { + id: "knowhere-doc:default:doc_remote", + kind: "remote", + mimeType: "application/pdf", + title: "remote.pdf", + status: "ready", + chunkCount: 4, + documentId: "doc_remote", + excludedFromQuery: false, + }, + }), + ); + + const checkbox = screen.getByRole("checkbox", { + name: "Use remote.pdf in answers", + }); + + expect(screen.getByText("Processed")).toBeTruthy(); + expect(screen.queryByText("Processed · 4 chunks")).toBeNull(); + expect(checkbox.getAttribute("aria-checked")).toBe("true"); + + fireEvent.click(checkbox); + + expect(onToggleIncluded).toHaveBeenCalledWith( + "knowhere-doc:default:doc_remote", + false, + ); + }); + it("shows source archive loading locally", () => { render( React.createElement(SourceRow, { diff --git a/src/components/source-row.tsx b/src/components/source-row.tsx index e964c93..9fb87d3 100644 --- a/src/components/source-row.tsx +++ b/src/components/source-row.tsx @@ -42,7 +42,6 @@ export function SourceRow({ const isFailed = source.status === "failed"; const canRetry = isFailed && source.originalFile !== undefined; const isLibrarySource = source.officialLibrary !== undefined; - const isRemoteSource = source.kind === "remote"; const iconBg = fileIconTint(source.title); @@ -63,7 +62,7 @@ export function SourceRow({ > onToggleIncluded?.(source.id, checked === true) } @@ -193,11 +192,11 @@ export function SourceRow({ function getReadySourceLabel(source: SourceView): string { if (source.officialLibrary !== undefined) return "Official Library"; - if (source.kind === "remote") return "Remote"; return "Processed"; } function getReadySourceStatusText(source: SourceView): string { + if (source.kind === "remote") return getReadySourceLabel(source); if (typeof source.chunkCount !== "number") return getReadySourceLabel(source); return `${getReadySourceLabel(source)} · ${source.chunkCount} chunks`; } diff --git a/src/domains/chat/index.test.ts b/src/domains/chat/index.test.ts index 1b51180..59899b0 100644 --- a/src/domains/chat/index.test.ts +++ b/src/domains/chat/index.test.ts @@ -66,7 +66,7 @@ describe("answerQuestionWithRetrieval", () => { question: "What does the document say?", namespace: "notebook-workspace", sources, - excludedSourceIds: ["source_2"], + excludedSourceIds: ["source_2", "knowhere-doc:default:doc_remote"], retrieval, generateAnswer, messages: [], @@ -79,13 +79,13 @@ describe("answerQuestionWithRetrieval", () => { topK: 8, useAgentic: true, dataType: 1, - excludeDocumentIds: ["doc_excluded"], + excludeDocumentIds: ["doc_excluded", "doc_remote"], }); expect(generateAnswer).toHaveBeenCalledWith({ question: "What does the document say?", messages: [], sources, - excludedSourceIds: ["source_2"], + excludedSourceIds: ["source_2", "knowhere-doc:default:doc_remote"], searchSources: expect.any(Function), }); expect(answer).toEqual({ diff --git a/src/domains/chat/retrieval.ts b/src/domains/chat/retrieval.ts index b17add9..4d1103f 100644 --- a/src/domains/chat/retrieval.ts +++ b/src/domains/chat/retrieval.ts @@ -1,6 +1,7 @@ import type { RetrievalQueryParams } from "@ontos-ai/knowhere-sdk" import type { Source } from "@/infrastructure/db/schema" +import { decodeRemoteSourceId } from "@/domains/sources/remote-library" const RETRIEVAL_QUERY_CHAR_LIMIT = 600 @@ -25,10 +26,16 @@ export function excludeDocuments( excludedSourceIds: readonly string[], ): Pick { const excluded = new Set(excludedSourceIds) - const documentIds = sources + const localDocumentIds = sources .filter((source) => excluded.has(source.id)) .map((source) => source.knowhereDocumentId) .filter((documentId): documentId is string => Boolean(documentId)) + const remoteDocumentIds = excludedSourceIds + .map((sourceId) => decodeRemoteSourceId(sourceId)?.documentId) + .filter((documentId): documentId is string => Boolean(documentId)) + const documentIds = Array.from( + new Set([...localDocumentIds, ...remoteDocumentIds]), + ) return documentIds.length > 0 ? { excludeDocumentIds: documentIds } : {} } diff --git a/src/domains/sources/remote-library.ts b/src/domains/sources/remote-library.ts index 87d3fd8..ceb9c80 100644 --- a/src/domains/sources/remote-library.ts +++ b/src/domains/sources/remote-library.ts @@ -280,7 +280,7 @@ function toRemoteSourceView(document: RemoteDocument): SourceView { mimeType: document.mimeType ?? "application/octet-stream", status: document.status, documentId: document.documentId, - excludedFromQuery: true, + excludedFromQuery: false, } } diff --git a/src/domains/sources/route-service.test.ts b/src/domains/sources/route-service.test.ts index 26e60cb..b07439c 100644 --- a/src/domains/sources/route-service.test.ts +++ b/src/domains/sources/route-service.test.ts @@ -301,7 +301,7 @@ describe("source route service", () => { mimeType: "application/pdf", status: "ready", documentId: "doc_default", - excludedFromQuery: true, + excludedFromQuery: false, }, { id: "knowhere-doc:notebook-workspace_1:doc_legacy", @@ -311,7 +311,7 @@ describe("source route service", () => { mimeType: "application/octet-stream", status: "ready", documentId: "doc_legacy", - excludedFromQuery: true, + excludedFromQuery: false, }, ]); });