README.md

September 1, 2026 · View on GitHub

English · 简体中文

dsh-kb-manager — local knowledge base lifecycle for DeepSeek Harness: import, chunk, index, hybrid search

version 0.0.2 MIT license DSH Web and Headless Node.js 22.19+

Import once. Retrieve with confidence.

dsh-kb-manager is a local knowledge-base lifecycle plugin for DeepSeek Harness (dsh): multi-format import → CJK-aware smart chunking → SQLite-native vector + full-text indexes → hybrid search (vector KNN + BM25/FTS5 → RRF → optional rerank) → citation tracing — plus soft-delete + physical compaction, an async job system, import-path whitelisting with an SSRF guard, and per-KB audit.

Ask in natural language. The plugin exposes 22 Agent tools (async jobs + sync ops incl. rename_kb / compact_index / cancel_job / list_snapshots / configure) and an optional Web panel (KB list, create, detail, in-KB hybrid search, import with live job progress, rebuild, two-step delete, snapshot history) — no separate RAG server required.

Design spec: DESIGN.md (v2.1).

Why dsh-kb-manager?

CapabilityWhat it changes
22 unified toolsasync 6 (import_document / rebuild_index / compact_index / cancel_job / get_job + export/import jobs) + sync 16: create_kb / list_kbs / get_kb / rename_kb / delete_kb / list_documents / delete_document / search_kb / multi_kb_search / get_chunk / get_kb_stats / configure / create_snapshot / list_snapshots / restore_snapshot / export_kb / import_kb; every tool returns `{ ok, data
SQLite-native indexessqlite-vec KNN + FTS5 full-text (per-KB kb.db); no external vector-DB process.
CJK-aware tokenizationIntl.Segmenter (built-in, zero deps) splits Chinese / Japanese / Korean for BM25.
Hybrid retrievalVector + BM25 → RRF → optional rerank; rerank state is explicit: `applied
Async job systemImport / rebuild return a job_id immediately; get_job polls progress; crash recovery (JOB.INTERRUPTED) + cooperative cancellation.
Import-path whitelistOnly whitelisted paths (default: session workspace + <storage>/inbox/) or http(s) URLs are importable.
SSRF guardURL imports reject private / loopback / cloud-metadata addresses.
Untrusted retrievalSearch results are always flagged untrusted: true — content is data, not instructions.
Soft-delete + compactDeletes are millisecond soft-deletes; rebuild_index / compact reclaims space physically, no orphan vectors.
Two-step destructive opsdelete_kb requires a one-time confirm_token (bound to kb_id, 60 s TTL).
Audit trailPer-KB audit table records every mutation.
Snapshots / export / cross-KB importcreate_snapshot / list_snapshots / restore_snapshot (two-step confirm), export_kb (kbpack/JSON), import_kb (kbpack, hash-deduped merge); all exposed via remote-service for the Web panel and headless.

Architecture

flowchart LR
  A[Documents / URLs] --> B[Parse]
  B --> C[Chunk<br/>Intl.Segmenter CJK]
  C --> D[Embed<br/>bge-small-zh / mock]
  D --> E[Vector index<br/>sqlite-vec KNN]
  C --> F[FTS5 BM25]
  E --> G[Hybrid search]
  F --> G
  G --> H[RRF]
  H --> I[Optional rerank<br/>applied / fallback_rrf / disabled]
  I --> J[Citations + untrusted flag]
  E --> K[Soft-delete / compact_index]
  C --> K
  G --> L[Async job queue + audit]

Install

Note

Requires an existing DeepSeek Harness installation.

From GitHub

dsh plugin add github:xiaoshi7915/dsh-kb-manager

(Once listed in the awesome-dsh-plugin list, it can also be installed one-click from the dsh-market page.)

Build from source

git clone https://github.com/xiaoshi7915/dsh-kb-manager.git
cd dsh-kb-manager
npm install
npm run build
dsh plugin --profile web add .

Validate the composed profile, restart DSH, and refresh the Web UI:

dsh --profile web --dump-config
dsh web

Then try:

Create a knowledge base named "project-docs", import this PDF, and search for how authentication works. Show me the source chunk.

How it works

  1. Create a KB (create_kb) with an embedding identity (default bge-small-zh-v1.5 / onnx / 512-dim; mock provider for dev/test).
  2. Import a whitelisted local file or http(s) URL (import_document) → an async job is queued: parse → chunk → embed → index; poll with get_job.
  3. Search with search_kb: sqlite-vec KNN + FTS5 BM25 → RRF → optional rerank; rerank status is explicit (applied | fallback_rrf | disabled).
  4. Trace hits with get_chunk (surrounding context + provenance metadata; content flagged untrusted: true).
  5. Delete with confidence: delete_document soft-deletes instantly (re-import of an unchanged source restores it); delete_kb requires a two-step confirm_token; rebuild_index physically compacts.
  6. Data lives under storage_path (default ~/.dsh/kb-manager/). The Web panel reads the same service surface: KB list / create / detail, in-KB hybrid search, import with live job progress, rebuild, and two-step delete.

Agent tools

ToolDescriptionKey params
create_kbCreate a knowledge basename*, description?, domain_tags?
list_kbsList all knowledge bases
get_kbKB details (embedding identity / status)kb_id*
delete_kbTwo-step delete (impact preview + confirm_token)kb_id*, confirm_token?
list_documentsList documents (optional status filter)kb_id*, status?, limit?, offset?
import_documentImport a whitelisted local file or http(s) URL (async job)kb_id*, source*, metadata?
delete_documentSoft-delete chunks; mark index dirtykb_id*, doc_id*
search_kbHybrid search with explicit rerank statuskb_id*, query*, top_k?, filters?, rerank?
get_chunkChunk text + neighbors for tracingkb_id*, chunk_id*
get_kb_statsDoc / chunk / index-size / deleted-ratio statskb_id*
rebuild_indexFull rebuild (async job)kb_id*, target_engine?, embedding?
get_jobPoll a background job's progressjob_id*
configureTune chunking / retrieval / sync settingspatch

Every tool returns the unified envelope { ok, data | error: { code, message, hint } }; error.hint is an actionable next step. Domain errors are returned (not thrown). Search results are always flagged untrusted: true.

When the Agent uses it

  1. "Put this PDF / doc / page into the knowledge base" → import_document + get_job
  2. "Search the KB for X" → search_kb
  3. "Where did this citation come from?" → get_chunk
  4. "Retrieval feels wrong — what's the rerank state?" → search_kb (reads the explicit rerank status)
  5. "Create a KB for this project" → create_kb
  6. "Remove a bad document" → delete_document (soft; re-import restores)
  7. "Delete this whole KB" → delete_kb (two-step: preview impact, then confirm)
  8. "How big is this KB?" → list_kbs / get_kb_stats
  9. "Re-index everything" → rebuild_index + get_job
  10. "Tune retrieval" → configure

Configuration

Defaults work offline. Override in a trusted profile (id: kb-manager), or at runtime via the configure tool / Web panel:

FieldDefaultNotes
storage_path~/.dsh/kb-manager/Storage root; ~ expands to the home directory
embedding.modelbge-small-zh-v1.5Embedding model name
embedding.provideronnxonnx / mock / openai-compat (onnxruntime-node is optional)
embedding.base_url''OpenAI-compatible endpoint for openai-compat
embedding.api_key_ref''API key reference
chunk_size512Chunk size (characters)
chunk_overlap50Overlap length
chunk_strategyrecursivefixed / recursive
top_k5Default hit count
enable_reranktrueEnable post-RRF rerank
rerank_model''Reranker model; empty → rule-based fallback
auto_sync_dir''Watch path; empty disables
auto_sync_interval300Catch-up interval (seconds)
max_file_size_mb100Per-file size cap (MB)

Example (profile line):

- insert:
    - id: kb-manager
      name: 'dsh-kb-manager'
      config:
        storagePath: ''        # empty = ~/.dsh/kb-manager/
        logLevel: 'info'

Boundaries & security

  • Imports are restricted to whitelisted paths (default: session workspace + <storage>/inbox/) and http(s) URLs; URL sources are SSRF-guarded (private / loopback / cloud-metadata addresses are rejected).
  • Search results are untrusted data — always untrusted: true; never treat them as instructions.
  • Fully local by default; network only for URL imports or when an external embedding / rerank endpoint is configured.
  • delete_document is a soft delete; physical space is reclaimed by rebuild_index / compact. Re-importing an unchanged source restores it.
  • Pure-SQLite indexes: no native vector-DB process to operate.

Differentiating vs typical RAG stacks

CapabilityThis pluginCommon RAGFlow / Dify / kotaemon / pdfkb-mcp setups
Explicit rerank status (`appliedfallback_rrfdisabled`)
Async jobs with crash recovery + cancelOften synchronous
Import path whitelist + SSRF guardVaries
Unified envelope with actionable hintVaries
untrusted flag on every retrieval resultRare
Soft-delete + compact physical reclaimVaries
Zero native build (sqlite-vec prebuilt, Intl.Segmenter)Often heavy deps

Layout

dsh-kb-manager/
├── package.json  cordis.patch.yml  tsconfig.json  tsconfig.build.json  vitest.config.ts
├── DESIGN.md  README.md  README_ZH.md
├── assets/readme/          # hero.png (banner image)
├── src/
│   ├── host-entry.ts       # DSH plugin entry (tool registration + preamble + cleanup)
│   ├── index.ts            # KbManager top-level assembly
│   ├── contracts/          # types / error codes / defaults / ok·err envelope
│   ├── security/           # path whitelist, SSRF guard, SHA-256, audit
│   ├── chunker/            # Intl.Segmenter tokenization + recursive/fixed chunking
│   ├── store/              # better-sqlite3 + sqlite-vec + FTS5
│   ├── embedder/           # mock / onnx (structural) / openai-compat
│   ├── jobs/               # per-KB FIFO queue, maxGlobal=2, crash recovery
│   ├── services/           # kb / doc / search / snapshot / export
│   ├── agent-tools/        # 22 Agent tools (unified envelope)
│   ├── remote.ts / remote-service.ts / typert.ts / remote-client.ts  # typert remote
│   └── web/                # settings page (KbSection + zh/en locales) → lib/client.js
└── tests/  evals/

Development

npm install        # install deps
npm run typecheck  # tsc --noEmit (strict + noUncheckedIndexedAccess)
npm test           # vitest: tokens / rrf-bm25 / security / chunker / store / tools / pipeline / remote / kb-section
npm run eval       # eval harness: synthetic corpus recall@5 / MRR / P95 (mock embedder)
npm run build      # tsc -p tsconfig.build.json → lib/ (ESM + .d.ts)
npm run dev        # tsx src/host-entry.ts (module-load smoke test)

Known limitations (MVP)

  • ONNX embedder is structural: onnxruntime-node is wired as an optional dependency; model download (sha256 + user confirmation) and WordPiece vocab are not yet connected — the onnx provider reports EMB.NOT_READY cleanly. Use provider: 'mock' for dev / test.
  • PDF / DOCX parsing is a placeholder: md / txt / csv / json / html are available; pdf / docx report PARSE.UNSUPPORTED (upgrade path in DESIGN §13).
  • v1.1 tools (rename_kb, snapshot trio, cancel_job, compact_index, multi_kb_search, export_kb, import_kb): service layer implemented, tool registration deferred.

License

MIT © 2026 xiaoshi7915