// The knowledge module's page, as the one server component the web shell mounts under // `////knowledge`. Every read is a procedure through the same caller the // API uses; every write is a client component that calls a procedure through the shell's // transport. // // The page renders three things separately on purpose: the service's health (the module flag and // the search service's readiness), the indexing indicator (the per-document progress states), and // the search itself — "indexing" is not "down", and the page never conflates them. import type { Container, TransportCaller } from "@conusai-kit/core" import type { I18n } from "@conusai-kit/i18n" import type { ProjectPage } from "@conusai-kit/ui" import type { ReactElement } from "react" import { type CollectionView, collectionList, type DocumentView, documentList, knowledgeStatus, } from "../contract/index.js" import { IndexForm, type IndexFormLabels } from "./index-form.js" import { searchFormLabels, serviceStateLabel, statusLabels } from "./labels.js" import { SearchForm } from "./search-form.js" export type KnowledgePage = ProjectPage const indexFormLabels = ( t: (key: string, values?: Record) => string, failed: string, ): IndexFormLabels => ({ heading: t("upload.heading"), label: t("upload.label"), hint: t("upload.hint"), submit: t("upload.submit"), busy: t("upload.busy"), done: t("upload.done"), failed, }) const documentStatusKey: Record = { queued: "documents.statusQueued", indexing: "documents.statusIndexing", indexed: "documents.statusIndexed", failed: "documents.statusFailed", cancelled: "documents.statusCancelled", } export const knowledgePage: KnowledgePage = async ({ slugs, caller, i18n }): Promise => { const t = (key: string, values?: Record) => i18n.message(`knowledge.${key}`, values) const failed = i18n.message("app.failed") const [{ collections }, status] = await Promise.all([ caller.call(collectionList, slugs), caller.call(knowledgeStatus, slugs), ]) const documentsByName = new Map() await Promise.all( collections.map(async (collection: CollectionView) => { const answer = await caller.call(documentList, { ...slugs, collectionName: collection.name }) documentsByName.set(collection.name, answer.documents) }), ) const labels = statusLabels(t, status) return ( <>

{t("title")}

{t("intro")}

{labels.heading}

{status.enabled ? (
{labels.state}
{serviceStateLabel(t, status.service.state)}
{status.service.reasons.length > 0 ? ( <>
{labels.reasons}
    {status.service.reasons.map((reason) => (
  • {reason}
  • ))}
) : null}
{labels.indexing}
{labels.documents}
) : (

{labels.flagOff}

)}
{status.enabled ? collections.map((collection) => (

{collection.name}

{(documentsByName.get(collection.name) ?? []).map((document) => ( ))}
{t("documents.heading")}
{t("documents.file")} {t("documents.status")} {t("documents.error")}
{document.filename} {t(documentStatusKey[document.status])} {document.error ?? ""}
)) : null} ) }