jules efc2c18a91 fix(kb-ui): make the object reader readable — reflow, window, jump-to
The reader dumped the whole server slice verbatim: a ~445k-char doc rendered
as a 16,558px wall of one-source-line-per-line ragged text, and the outline
panel showed 8 blank rows (the API's sections carry heading:null — they're
mechanical 60k-char chunks, not headings).

- Reflow: off the citation path, parse the extracted markdown/PDF text into
  real blocks — drop form-feeds, split on blank lines, join soft-wrapped
  lines into paragraphs, lift markdown headings + multi-line bullet lists.
  Cap prose width at 68ch. The citation-highlight path still renders the raw
  slice verbatim so character offsets stay exact.
- Window every load: initial 8k chars, "Read more" +12k, section jump loads a
  bounded window from the section's start (server honours start/end precisely).
  Object height 16,558 → ~5,315px; Read more/citations verified.
- Outline: blank heading:null rows now render as "Part N" jump points and the
  panel is titled "Jump to" (vs "Outline") when there are no real headings;
  aria-current on the active row.

Verified live on dev-knowledge.sky-ai.com.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 08:51:50 +10:00
2026-07-07 10:05:46 +10:00
2026-07-07 10:05:46 +10:00
2026-07-07 10:05:46 +10:00

@crema/knowledge-ui

Management UI for arcadia-knowledge — the hosted knowledge base. Ships the collection browser, object viewer (card + provenance + supersession + citations), claims review queue, and export flow as pure, headless components: shapes and UI, never data fetching. The app injects a KnowledgeTransport; auth stays closed over inside it, so components never see a token.

Built to arcadia-knowledge-ui-spec.md. Two consumers today: the Knowledge area in arcadia-personal-cloud-web (me.sky-ai.com) and the standalone skyai-knowledge-web. Same lib, different shells.

Install (polyrepo — source alias, not npm)

Like every @crema/* lib, this is a path-aliased source folder. A consumer wires it in three places:

  1. vite.config.ts — resolve alias:

    "@crema/knowledge-ui": libSrc("knowledge-ui") + "/index.tsx",
    "@crema/knowledge-ui/": libSrc("knowledge-ui") + "/",
    

    Make sure lucide-react is in your shared-dep dedupe list.

  2. tsconfig.json — paths:

    "@crema/knowledge-ui": ["../lib-knowledge-ui/src/index.tsx"],
    "@crema/knowledge-ui/*": ["../lib-knowledge-ui/src/*"]
    
  3. app/app.css — Tailwind source scan:

    @source "../../lib-knowledge-ui/src";
    

The lib is fully self-contained — it imports only react and lucide-react (no other @crema/* libs), so a fresh consumer wires exactly this one alias. The app may separately use @crema/file-ui for the upload dropzone on its collection page (spec §4.5), but that's the app's choice, not a lib dependency.

The vite alias (step 1) also needs its own step — mirror step 2 in vite.config.ts resolve.alias, and ensure react / react-dom / lucide-react are deduped to the app's copies (sibling libs carry no node_modules).

Wiring the transport

The lib defines KnowledgeTransport; the app implements it over its KB client (a kb.ts factory that closes over the session token and talks to arcadia-knowledge :4025 directly). See arcadia-knowledge-ui-spec.md §4.2.

import { CollectionList, type KnowledgeTransport } from "@crema/knowledge-ui";

const transport: KnowledgeTransport = kbTransport(session.token);
const { collections } = await transport.listCollections();

<CollectionList collections={collections} onOpen={(c) => navigate(`/knowledge/${c.slug}`)} />

For development without a service, use MockKnowledgeTransport — it backs demo/knowledge.tsx with fixtures covering every surface (personal + org corpuses, documents, an image, a superseded doc, a vault doc, an open claim conflict, a proposed claim, a rejected tombstone, an export job).

Conventions

  • Tailwind theme tokens only — no hex. Sensitivity/tier/status/curation colours use --warning / --success / --destructive / --info (falls back to --primary). Works in any Crema theme.
  • Props in, callbacks out. No global state, no context, no fetching.
  • data-action attributes on interactive elements (command-bus contract).
  • Trust is surfaced raw — assertion tier, card_model, extraction_model are shown as first-class facts, never collapsed into a score.

Typecheck

../arcadia-personal-cloud-web/node_modules/.bin/tsc -p tsconfig.check.json

(Borrows a consumer's React types; the lib has no node_modules of its own.)

Surfaces

Module Exports
components-collections CollectionList, CollectionCard, CollectionForm
components-object ObjectList, ObjectViewer, CatalogCard, ProvenancePanel, SupersessionBanner, OutlineNav, TextReader, CitationLink
components-claims ClaimsReviewQueue, ClaimCard, ConflictPair
components-export ExportPanel, ExportJobRow
_internal (re-exported) badges + cn, formatBytes, formatDate, formatRelative, renderValue
Description
No description provided
Readme 162 KiB
Languages
TypeScript 100%