Early bird: 30% off Dashral ProSee pricing

Dashral

Knowledge sourcesPro

What your AI assistant reads before it answers: files, websites and connected apps, each indexing live with its chunks counting up, a source opened with its chunks, and a retrieval test that shows what a question would find. Drop files on it to add them. On motion.

Installation

When to use

  • The screen where a team manages what its AI assistant knows: files, websites and connected apps, and how far each is indexed.
  • Products with retrieval (RAG), where people add sources, fix one that failed and check what a question would find.

When not to use

  • Plain file storage with nothing indexed: a file list or Data Table fits better.
  • One upload in a form: File Dropzone on its own.

Usage

Knowledge sources with your own data: every prop has the sample as its default, so pass only what you have.

example.tsx
"use client"

import { useRef, useState } from "react"
import { KnowledgeSources, type KnowledgeSource, type KnowledgeSourcesHandle } from "@/components/dashral/blocks/knowledge-sources"

export default function Knowledge() {
  const knowledge = useRef<KnowledgeSourcesHandle>(null)
  // Kept in state: a new array replaces what's shown.
  const [sources] = useState<KnowledgeSource[]>([
    { id: "doc-1", name: "Refund policy.pdf", kind: "file", format: "pdf", size: 412_000, chunks: 38, tokens: 21_400, status: "ready", syncedAt: "2 hours ago", enabled: true },
    { id: "web-1", name: "docs.acme.com", kind: "website", url: "docs.acme.com", status: "indexing", progress: 0.4, chunks: 120, enabled: true },
  ])
  // As your indexer reports: knowledge.current?.update("web-1", { progress: 0.8, chunks: 240 })
  return (
    <KnowledgeSources
      ref={knowledge}
      sources={sources}
      // Return the rows to show (with your ids); while the promise is pending the button shows it.
      onAdd={async (input) => console.log("add", input.files?.length ?? 0, "files", input.url ?? "", input.app ?? "")}
      onResync={async (source) => console.log("sync", source.id)}
      onToggle={async (source, enabled) => console.log(source.id, enabled ? "in use" : "left out")}
      onRemove={async (source) => console.log("remove", source.id)}
    />
  )
}

API reference

KnowledgeSources

What an AI assistant knows: its sources (files, websites, connected apps), each with its indexing status and progress, the totals in chunks and tokens, a source opened with its chunks, and a retrieval test that shows what a question would find. Drop files on the list to add them. Every change calls your handler first.

PropTypeDefault
titleReact.ReactNode"Knowledge"
sourcesKnowledgeSource[]

The sources at first. A new array replaces what's shown (and what was added here), so keep yours in state.

sample
onAdd(input: AddSourceInput) => Promise<KnowledgeSource[] | void> | KnowledgeSource[] | void

Files dropped or picked, a website, or an app to connect. Return the sources to show (their ids are yours); left out, or returning nothing, a queued row is added for each file or the website. While the promise is pending the menu's button shows it; a thrown Error's message shows above the list.

—
onRemove(source: KnowledgeSource) => Promise<void> | void

Removed after its confirm: the dialog waits for the promise; a throw keeps it and says why.

—
onResync(source: KnowledgeSource) => Promise<void> | void

Sync again (or retry a failed one): it goes back to Queued at once, and back as it was if this throws.

—
onToggle(source: KnowledgeSource, enabled: boolean) => Promise<void> | void

Use it in answers or not: shown at once, put back if this throws.

—
onRetrieve(query: string) => Promise<RetrievalMatch[]> | RetrievalMatch[]

The retrieval test, with your own search; left out, a keyword match over the sources' preview chunks.

—
refReact.Ref<KnowledgeSourcesHandle>—
classNamestring—

SourceDetail

One source opened: what it is, its status (progress, the error), whether answers use it, its chunks, and its actions.

PropTypeDefault
sourceKnowledgeSource

Required.

—
onResync() => void

Required.

—
onToggle(enabled: boolean) => void

Required.

—
onRemove() => Promise<void> | void

Required.

—

RetrievalTest

A question, and the chunks it would find, best first with how close each is; one picked opens its source.

PropTypeDefault
sourcesKnowledgeSource[]

Required.

—
onRetrieveKnowledgeSourcesProps["onRetrieve"]—
onPick(sourceId: string) => void—

type SourceKind

= "file" | "website" | "app"

type SourceStatus

= "queued" | "uploading" | "indexing" | "ready" | "failed"

type SourceApp

A connected app, by the brand catalog's role: docs (Notion), files (Dropbox), code (GitHub), support (Intercom).

= "docs" | "files" | "code" | "support"

type SourceChunk

PropTypeDefault
idstring—
textstring—
tokensnumber—
pagenumber—

type KnowledgeSource

PropTypeDefault
idstring—
namestring—
kindSourceKind—
formatstring

A file's type, for its icon: "pdf", "docx", "csv", "md"…

—
appSourceApp—
urlstring—
sizenumber

In bytes.

—
pagesnumber—
chunksnumber—
tokensnumber—
statusSourceStatus—
progressnumber

0–1 while uploading or indexing.

—
errorstring

Why it failed.

—
syncedAtstring

When it was last synced, as shown: "2 hours ago".

—
enabledboolean

Whether the assistant uses it in its answers.

—
previewSourceChunk[]

A few of its chunks, for the preview and the retrieval test.

—

type RetrievalMatch

PropTypeDefault
sourceIdstring—
chunkSourceChunk—
scorenumber—

type AddSourceInput

PropTypeDefault
filesFile[]—
urlstring—
appSourceApp—

type KnowledgeSourcesHandle

PropTypeDefault
update(id: string, patch: Partial<KnowledgeSource>) => void

Change a source as your indexer reports (status, progress, chunks, error…).

—
add(source: KnowledgeSource) => void

A source added elsewhere: it grows in at the top.

—