ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+207
View File
@@ -0,0 +1,207 @@
// The knowledge module's page, on the shell's F10 contract (docs/reference/app-kit.md): a loader the web
// shell runs on the server under `/<org>/<workspace>/<project>/knowledge`, and the view of what it
// returned. Every read is a procedure through the same caller the API uses, and every label is translated
// in the loader; 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, notFound, type TransportCaller } from "@conusai-kit/core"
import type { I18n } from "@conusai-kit/i18n"
import { type ProjectPage, type ProjectPageViewProps, projectPage } from "@conusai-kit/ui"
import { FactList, Page, PageHeader, PageSection } from "@conusai-kit/ui/patterns"
import { Alert, AlertDescription } from "@conusai-kit/ui/primitives"
import type { ReactElement } from "react"
import {
autoIndexGet,
type CollectionView,
collectionList,
type DocumentView,
documentList,
knowledgeStatus,
} from "../contract/index.js"
import { AutoIndexForm, type AutoIndexFormLabels } from "./auto-index-form.js"
import { IndexForm, type IndexFormLabels } from "./index-form.js"
import {
failureLabels,
type RefusalNotice,
refusalLabels,
type SearchFormLabels,
type StatusLabels,
searchFormLabels,
serviceStateLabel,
statusLabels,
} from "./labels.js"
import { CollectionDocuments, type DocumentListLabels } from "./live-documents.js"
import { SearchForm } from "./search-form.js"
/** One collection and its documents: the seed of its live list. */
export interface KnowledgeCollectionRow {
readonly name: string
readonly documents: readonly DocumentView[]
}
export interface KnowledgePageData {
readonly title: string
readonly intro: string
readonly status: {
readonly enabled: boolean
readonly labels: StatusLabels
/** The service's state in the reader's language. */
readonly state: string
readonly reasons: readonly string[]
/** Why the service will not serve this deployment, when that is the answer. */
readonly refusal?: RefusalNotice
}
readonly collections: readonly KnowledgeCollectionRow[]
readonly documents: DocumentListLabels
readonly index: IndexFormLabels
readonly search: SearchFormLabels
/** The project's automatic PDF indexing: the collection it fills, or null when it is off. */
readonly autoIndex: { readonly current: string | null; readonly labels: AutoIndexFormLabels }
}
export type KnowledgePage = ProjectPage<TransportCaller, I18n, Container, KnowledgePageData>
const indexFormLabels = (t: (key: string, values?: Record<string, string | number>) => 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"),
})
const documentStatusKey: Record<DocumentView["status"], string> = {
queued: "documents.statusQueued",
indexing: "documents.statusIndexing",
indexed: "documents.statusIndexed",
failed: "documents.statusFailed",
cancelled: "documents.statusCancelled",
}
export const knowledgePage: KnowledgePage = projectPage({
async load({ slugs, segments, caller, i18n }): Promise<KnowledgePageData> {
const t = (key: string, values?: Record<string, string | number>) => i18n.message(`knowledge.${key}`, values)
if (segments.length > 0) throw notFound("no such page")
const [{ collections }, status, auto] = await Promise.all([
caller.call(collectionList, slugs),
caller.call(knowledgeStatus, slugs),
caller.call(autoIndexGet, slugs),
])
const rows = await Promise.all(
collections.map(async (collection: CollectionView): Promise<KnowledgeCollectionRow> => {
const { documents } = await caller.call(documentList, { ...slugs, collectionName: collection.name })
return { name: collection.name, documents }
}),
)
return {
title: t("title"),
intro: t("intro"),
status: {
enabled: status.enabled,
labels: statusLabels(t, status),
state: serviceStateLabel(t, status.service.state),
reasons: status.service.reasons,
...(status.service.refusal === undefined
? {}
: {
refusal: {
code: status.service.refusal,
text: refusalLabels(t)[status.service.refusal],
},
}),
},
collections: rows,
documents: {
caption: t("documents.heading"),
file: t("documents.file"),
status: t("documents.status"),
error: t("documents.error"),
statuses: Object.fromEntries(
Object.entries(documentStatusKey).map(([status, key]) => [status, t(key)]),
) as DocumentListLabels["statuses"],
failures: failureLabels(t),
},
index: indexFormLabels(t),
search: searchFormLabels(t),
autoIndex: {
current: auto.collectionName,
labels: {
heading: t("autoIndex.heading"),
hint: t("autoIndex.hint"),
label: t("autoIndex.label"),
off: t("autoIndex.off"),
submit: t("autoIndex.submit"),
busy: t("autoIndex.busy"),
done: t("autoIndex.done"),
},
},
}
},
View({ slugs, locale, data }: ProjectPageViewProps<KnowledgePageData>): ReactElement {
const { labels, enabled, state, reasons, refusal } = data.status
return (
<Page>
<PageHeader title={data.title} description={data.intro} />
<PageSection title={labels.heading} variant="card">
{refusal ? (
<Alert variant="warning" role="status" data-state={refusal.code}>
<AlertDescription>{refusal.text}</AlertDescription>
</Alert>
) : null}
{enabled ? (
<FactList
facts={[
{ label: labels.state, value: state },
...(reasons.length > 0
? [
{
label: labels.reasons,
value: (
<ul>
{reasons.map((reason) => (
<li key={reason}>{reason}</li>
))}
</ul>
),
},
]
: []),
{ label: labels.indexing, value: labels.documents },
]}
/>
) : (
<p role="status">{labels.flagOff}</p>
)}
</PageSection>
{enabled && data.collections.length > 0 ? (
<AutoIndexForm
slugs={slugs}
collections={data.collections.map((collection) => collection.name)}
current={data.autoIndex.current}
labels={data.autoIndex.labels}
/>
) : null}
{enabled
? data.collections.map((collection) => (
<PageSection key={collection.name} title={collection.name}>
<IndexForm slugs={slugs} collectionName={collection.name} labels={data.index} />
<SearchForm slugs={slugs} collectionName={collection.name} labels={data.search} locale={locale} />
<CollectionDocuments
slugs={slugs}
collectionName={collection.name}
seed={collection.documents}
labels={data.documents}
/>
</PageSection>
))
: null}
</Page>
)
},
})