Bundle
dsh-context-milvus
DSH plugin for semantic code search via Milvus vector database
- Source
- bobjia
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# dsh-context-milvus
[](https://www.npmjs.com/package/dsh-context-milvus)
[](https://dsh-plugin.org/plugins/bobjia/dsh-context-milvus)
**English** | [简体中文](README.zh.md)
A DSH plugin that provides semantic code search over a **Milvus** vector database, with a complete index ↔ search pipeline.
> dsh-context-milvus = **equips your DSH Agent with a dedicated codebase semantic search engine. Milvus handles high-speed vector retrieval, transforming "needle-in-a-haystack grep" into precise recall of relevant code snippets — reducing tokens, minimizing tool calls, and improving coding agent quality on large repositories**.
---
## Why dsh-context-milvus?
`dsh-context-milvus` is an open-source code semantic search plugin for **DeepSeek Harness (DSH) coding agents**, built on Milvus as the vector database and registered as a Cordis Plugin. Its core purpose: **solve the high token consumption, excessive tool calls, context pollution, and poor large-codebase comprehension that plague native DSH Agent grep workflows**.
> Native DSH Agent workflow: encounter a problem → repeatedly `search_code` (grep) → `read` files → search again, flooding the prompt with irrelevant text, exploding tool calls, increasing token costs, and making it easy to miss dependencies in large repositories.
### Solving the key pain points of native grep search
| Native grep workflow pain point | dsh-context-milvus solution |
|---|---|
| Literal string matching only — semantically related but differently named code is missed | **Vector semantic search** — matches by code meaning, not just keywords |
| Multiple tool call rounds, reading many irrelevant files, token explosion | Returns only truly relevant code snippets, split by AST at function/class boundaries for precision |
| Flooding context with grep output and irrelevant source code, causing **context pollution** and degraded model reasoning | Milvus pre-built index, Agent gets concise effective context in one tool call without search noise in the prompt |
| Thousands of files in large repos, Agent traversal is extremely inefficient | Milvus vector DB enables fast retrieval over millions of code blocks, supports incremental index updates without full repo rescanning |
| Can only search already-open or known-path files | After full-repo indexing, can semantically search any code location regardless of file path knowledge |
---
## Features
- **`search_code`** — Semantic code search: natural language query, returns matching code snippets
- **`index_code`** — Index codebase: AST parsing + chunking → Embedding → Milvus storage
- **`index_status`** — View index status: file count, last index time, hash statistics
- **`find_callers`** — Code relationship analysis (impact analysis): find all references to a symbol, with cross-file import resolution
- **`trace_call_chain`** — Call chain tracing: BFS expansion from entry symbol (impact/dependency analysis), with cross-file resolution disambiguation
- **Hybrid search** — BM25 keyword + vector semantic dual-path retrieval, RRF fusion, `hybridMode` toggle
- **Chunk overlap** — AST chunks include surrounding context lines (`chunkContextLines`, default 2) for better recall
- **Query expansion** — expands natural-language queries with code synonyms before embedding (`queryExpansion`, default on)
- **Two-stage reranking** — retrieves a topK×3 pool then applies proportional term-overlap & name-match boosts, keeping the Milvus score primary (`rerankEnabled`, default on)
- **Ignore pattern system** — Three-layer gitignore-style ignore rules (default + codebase + global)
- **Incremental indexing** — Merkle SHA-256 hash tracking, processes only changed files
- **Workspace isolation** — Independent Merkle state files per workspace, no interference
- **ADR decision memory system** — Records design rationale behind code changes (Architecture Decision Records), supports semantic search, CRUD, constraint injection, and consistency checking
- **Code relationship analysis** — Extracts symbol references from AST during indexing (`references`, language-specific syntax nodes), supports cross-file exact matching
- **Cross-file import resolution (V2)** — Scans import/export statements using tree-sitter AST during indexing, builds a persistent bidirectional Import Map, enabling `find_callers`/`trace_call_chain` to perform precise cross-file symbol matching (same-name disambiguation, cross-module tracing)
- **Native telemetry (opt-in)** — `search_code` / `index_code` / `index_status` write one JSONL line per execution (disabled by default, no source code captured), with an analysis script for descriptive stats + Bootstrap CI + correlation
---
## Effectiveness Evaluation
A reproducible statistical evaluation suite (see `scripts/eval/`) quantifies how `dsh-context-milvus` improves retrieval quality and end-to-end agent efficiency. It covers offline retrieval quality, end-to-end agent evaluation, and native telemetry — using nonparametric statistics (Wilcoxon, Bootstrap CI, Cliff's Δ) with a unified file-level relevance standard. Run instructions and full reports live in `scripts/eval/*/output/report.md`.
### Offline retrieval quality — 21 annotated queries × 19-file multi-language corpus
Three retrieval strategies compared: **G** (grep keyword), **R** (naive RAG: sliding-window + pure vector), **P** (plugin: AST chunking + BM25 hybrid + RRF + chunk overlap + query expansion + two-stage reranking).
| Metric | G (grep) | R (naive RAG) | P (plugin) |
|--------|:--------:|:-------------:|:----------:|
| recall@10 | 0.9524 | **1.0000** | 0.9524 |
| MRR | **0.6754** | **0.9524** | 0.8452 |
| nDCG@10 | 0.7446 | **0.9610** | 0.8725 |
| **hit@1** | 0.4762 | 0.9048 | **0.7619** |
| precision@10 (file-level) | **0.4203** | 0.1095 | 0.2730 |
| precision@10 (chunk-level) | — | — | **0.3619** |
> **Note on precision@10**: Two metrics are reported. **File-level** precision@10 de-duplicates results by file path (each file counted once), measuring how many unique relevant files appear in the top-K. **Chunk-level** precision@10 counts each result independently, matching the classic IR definition: "of the 10 entries the Agent sees, how many are from relevant files?" The chunk-level metric is higher because the Agent benefits from multiple chunks of the same relevant file clustering in the top results.
Key findings:
- **Two-stage reranking lifts hit@1 by 6.7%** (from 0.714 to 0.762 vs P0 baseline): proportional term-overlap (+30%) and name-matching (+15%) boosts improve first-hit accuracy. The gap to naive RAG (0.905) narrowed from 0.14 to 0.14.
- **Chunk-level precision@10 = 0.362**: the Agent sees ~3.6 relevant entries per 10 results. This is bounded by the corpus (each query has only 1-2 relevant files, each producing few chunks) — the ceiling is determined by the number of chunks per relevant file, not search quality.
- **AST chunking + query expansion + chunk overlap drive precision**: P vs R precision@10 +0.1635 (p=0.00013, Cliff's Δ=0.868 — large effect). Function/class-boundary chunks with surrounding context lines are far more focused than fixed sliding windows.
- **Semantic search beats keyword grep on ranking**: P vs G MRR +0.1698 (p=0.108), nDCG@10 +0.1280 (p=0.100) — relevant files rank higher, with near-significant p-values.
- **grep precision is high but recall is brittle**: G has the best precision@10 (0.4203) but the worst hit@1 (0.4762) — keyword-only search misses semantically-related code (e.g. "retry with exponential backoff" never matches `withRetry`).
### End-to-end agent evaluation — 8 tasks × 3 runs × 3 strategies
| Group | Average pass rate | Token consumption |
|-------|:-----------------:|:-----------------:|
| G (grep) | 37.5% | baseline |
| R (naive RAG) | 50.0% | −928 vs G |
| **P (plugin)** | **62.5%** | **−2109 vs G** |
Key findings:
- **Highest task pass rate**: P 62.5% vs G 37.5% vs R 50.0%.
- **Significant token reduction**: P vs G Δmean −2109 tokens/task (95% CI [−2325, −1864]), Wilcoxon p=0.014, **significant after Holm correction**, Cliff's Δ=−1.0. P also beats R by −928 tokens/task (p=0.014).
### Native telemetry (opt-in)
`search_code` / `index_code` / `index_status` record execution metrics (query, result count, top score, duration, files/chunks indexed, etc.) as one JSONL line per call — **disabled by default** (`telemetryEnabled: false`), no source code content captured. Run `node scripts/eval/telemetry/run.mjs` to generate a descriptive statistics + Bootstrap CI + correlation report from `~/.milvus-index/telemetry.jsonl`.
---
## What role does Milvus play, and why Milvus?
1. **Stores AST-chunked code vectors**: dsh-context-milvus uses tree-sitter AST to split code at function/class/method boundaries, generates embeddings, and stores them in Milvus — avoiding cutting a function in half.
2. **High-performance vector search**: Encodes the query and performs vector similarity search with low latency, suitable for real-time Agent tool calls.
> Note: BM25 keyword fusion is **already implemented** — Milvus native BM25 full-text search + vector semantic dual-path retrieval, RRF fusion (`hybridMode` enabled by default).
3. **Supports self-hosted Milvus / Zilliz Cloud**, two deployment options; teams can control data; supports incremental indexing after code changes without full rebuild.
4. **Specifically adapted for code RAG**: Supports path-scoped filtering (`search_code` `path` parameter), allowing directory-limited searches — ideal for codebase scenarios.
---
## DSH plugin architecture advantages
It is not a standalone MCP service, but a **DSH plugin** (Cordis Plugin) embedded directly into the DSH Agent process:
- **Zero network overhead**: Plugin and Agent share the same process, tool calls don't go through HTTP, latency far below MCP
- **Naturally shares DSH resource configuration**: Reuses DSH's config management, environment variable injection, and logging system — no additional configuration needed
- **DSH Web GUI integration**: Visual configuration through Settings → Plugins interface, no YAML hand-editing
- **DSH ecosystem compatibility**: Shares the tool registry with other DSH plugins (bash, agent-loop, web-search, etc.), Agents can freely combine them
---
## Core Workflow
### Registered DSH tools
| Tool | Function | Key Parameters |
|------|----------|----------------|
| `search_code` | Semantic code search | `query` (natural language), `topK` (result count), `path` (search scope) |
| `index_code` | Index codebase | `mode` (full/incremental), `path` (target path) |
| `index_status` | View index status | `path` (view per-workspace status) |
| `search_adr` | Semantic ADR search | `query` (natural language), `status`, `topK` |
| `search_adr_by_file` | Find ADRs by file path | `file_path` (code file path), `status` |
| `create_adr` | Create new ADR | `title` (required), `requirement`, `change_type` |
| `update_adr` | Update existing ADR | `adr_id` (required), `content`, `status` |
| `list_adrs` | List ADR records | `status`, `change_type`, `limit` |
| `load_constraints` | Load active ADR constraints | `adr_ids`, `format` |
| `check_adr_consistency` | Check ADR-code consistency | `file_path`, `fix` |
| `find_callers` | Find all references to a symbol for impact analysis, supports cross-file import resolution | `symbol` (required), `direction`, `maxResults`, `sourceFile`, `resolve` |
| `trace_call_chain` | BFS call chain tracing from entry symbol (impact/dependency analysis), supports import resolution disambiguation | `entry` (required), `direction`, `maxDepth`, `maxResults`, `resolve` |
### Workflow
1. Run `index_code`: Parse the project, split code blocks via tree-sitter AST → call Embedding API to generate vectors → store in Milvus collection.
2. Agent encounters a coding problem, calls `search_code` for **hybrid search** (vector semantic + BM25 keyword, RRF fusion).
3. Milvus returns the most relevant code snippets, injected into the Agent's context.
4. Agent debugs, refactors, or develops based on precise context — no more frantic grep file reading.
5. After code changes, run `index_code mode=incremental` to incrementally re-index only changed files.
6. Check index status anytime with `index_status` (indexed files, total code blocks, last index time).
7. Before modifying code, use `find_callers` for impact analysis: see which places reference the symbol to avoid missing cascading effects. For same-name symbols across files, use the `sourceFile` parameter to disambiguate by definition file.
8. Understand call chains with `trace_call_chain`: BFS expansion from entry function, `direction=backward` traces callers, `direction=forward` traces downstream dependencies. `resolve: false` falls back to V1 name-matching mode.
9. Cross-file reference analysis: `find_callers` and `trace_call_chain` enable import resolution by default (`resolve: true`). The Import Map built during indexing automatically maps `import { X } from './foo'` to `foo.ts`'s exports, eliminating same-name ambiguity and supporting cross-module call chain tracing. Falls back to V1 name matching when the import map is not built.
### ADR decision memory workflow
The ADR decision memory system records the "why" behind code changes (design decisions, trade-offs, constraints), enabling the Agent to not only read code but understand its evolution:
> **Note:** ADR functionality is disabled by default. To enable it, set `adrEnabled: true` in the DSH config panel (Settings → Plugins → dsh-context-milvus).
1. **Before modifying code with ADR coverage**, use `search_adr_by_file` to check if the file has decision records, avoiding violation of existing decisions.
2. **When making design decisions**, use `create_adr` to record the context, alternatives, and rationale, and use `update_adr` to maintain code_anchors linking to code locations.
3. **When needing to understand constraints**, use `load_constraints` to load active ADR constraints into the context.
4. **After creating or updating ADRs**, use `check_adr_consistency` to verify ADR-code consistency, with `fix` for auto-repair.
5. Use `search_adr` for semantic search of historical decisions, understanding "why this was done this way."
---
## Spec Document Fusion
When the brainstorming skill produces specification documents, they can be linked to the codebase through the following steps:
1. **Write spec documents**: brainstorming output saved to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
2. **Generate anchors**: Call `index_specs` to automatically detect code references in the document and generate frontmatter + code_anchors
3. **Index**: `index_code` automatically scans `docs/superpowers/specs/` and `docs/superpowers/plans/` directories
4. **Discover**: `search_adr` returns both ADR and spec document results (with `docType` annotation)
### Configuration
| Field | Default | Description |
|-------|---------|-------------|
| `specRoot` | `docs/superpowers/specs` | Spec document directory (relative to indexRoot) |
| `planRoot` | `docs/superpowers/plans` | Implementation plan directory (relative to indexRoot) |
Spec document fusion follows the `adrEnabled` toggle — no additional configuration needed.
---
## Prerequisites
### 1. Install Ollama (Embedding service)
```bash
# macOS
brew install ollama
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Start Ollama service
ollama serve
```
> Or use any OpenAI-compatible Embedding API service (OpenAI, Alibaba Cloud Bailian, etc.) by configuring `embeddingEndpoint` and `embeddingApiKey`.
### 2. Install Embedding model
```bash
# Pull nomic-embed-text model (default)
ollama pull nomic-embed-text
# Or other supported Embedding models:
ollama pull bge-m3
ollama pull mxbai-embed-large
```
### 3. Install Milvus (vector database)
**Docker (recommended):**
```bash
# Pull and start Milvus standalone
docker run -d --name milvus \
-p 19530:19530 \
-p 9091:9091 \
milvusdb/milvus:latest
# Verify connection
docker ps | grep milvus
```
**Milvus cluster mode (Docker Compose):**
```bash
# Download docker-compose file
wget https://github.com/milvus-io/milvus/releases/latest/download/milvus-standalone-docker-compose.yml -O docker-compose.yml
# Start
docker compose up -d
```
> Or use [Zilliz Cloud](https://cloud.zilliz.com) managed service — no self-hosting required.
### Verify installation
```bash
# Verify Ollama
curl http://localhost:11434/api/tags
# Verify Milvus
docker run -it --rm \
-e MILVUS_URL=localhost:19530 \
milvusdb/milvus-sdk-node:latest \
node -e "const {MilvusClient} = require('@zilliz/milvus2-sdk-node'); \
new MilvusClient({address:'localhost:19530'}).listCollections().then(r=>console.log(r))"
```
---
## Install to DSH
### Method 1: From npm (recommended)
The plugin is published to the npm registry. Install directly via DSH CLI:
```bash
dsh plugin --profile web add dsh-context-milvus
```
> The npm package includes pre-built `dist/` output — no build step required during installation, avoiding the `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` error.
### Method 2: From local tarball (offline / local development)
Build and package as a tarball, then install directly:
```bash
# 1. Build
npm run build
# 2. Package as tarball
pnpm pack
# 3. Install to profile
dsh plugin --profile web add ./dsh-context-milvus-0.1.3.tgz
```
> `pnpm pack` produces a tarball containing the compiled `dist/` output — no build step required during installation, so pnpm won't raise `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED`.
### Method 3: From Git (requires additional configuration)
```bash
dsh plugin --profile web add git+https://github.com/bobjia/dsh-context-milvus.git
```
> `dist/` output is not committed to git. The plugin uses the `prepare` script to automatically run `tsc` during installation.
>
> **pnpm 10 limitation**: pnpm 10 blocks execution of build scripts by default. If you see:
> ```
> ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED
> The git-hosted package "dsh-context-milvus@0.1.2" needs to execute build scripts
> but is not in the "onlyBuiltDependencies" allowlist.
> ```
> Add to your profile's `pnpm-workspace.yaml`:
> ```yaml
> # ~/.dsh/profiles/<profile-name>/pnpm-workspace.yaml
> onlyBuiltDependencies:
> - dsh-context-milvus
> ```
> Then re-run the install command. Or run `pnpm approve-builds` and select `dsh-context-milvus`.
>
> To avoid this authorization, use Method 1 (npm) or Method 2 (tarball).
### Configure the plugin
After installation, edit `cordis.patch.yml` under your profile:
```yaml
# ~/.dsh/profiles/<profile-name>/cordis.patch.yml
- id: dsh-context-milvus
config:
milvusAddress: localhost:19530
milvusCollection: code_embeddings
milvusDim: 768
embeddingEndpoint: http://localhost:11434/api/embed
embeddingModel: nomic-embed-text
indexRoot: /path/to/your/code
indexExtensions: .ts,.tsx,.js,.py,.java,.go,.rs,.cpp,.cs,.scala,.php
hybridMode: true
bm25RrfK: 60
```
Restart DSH after configuration.
### Build from source (local development)
If using a local development version:
#### 1. Install dependencies
```bash
cd /mnt/home/bobjia/workspace/dsh-context-milvus
npm install --legacy-peer-deps
```
#### 2. Create symlinks for @deepseek-ai packages
```bash
# Link DSH runtime packages (npm install may break these links)
ln -sf /mnt/home/bobjia/.npm-global/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/cordis \
node_modules/@deepseek-ai/cordis
ln -sf /mnt/home/bobjia/.npm-global/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-tools \
node_modules/@deepseek-ai/dsh-tools
ln -sf /mnt/home/bobjia/.npm-global/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/schemastery \
node_modules/@deepseek-ai/schemastery
```
#### 3. Register with DSH
```bash
# Install as local dependency
dsh plugin --profile web add file:/mnt/home/bobjia/workspace/dsh-context-milvus
```
> `dsh plugin add` automatically adds the plugin to `dsh.profile.bundles` — no need to manually edit `package.json`.
#### 4. Configure plugin
Edit `~/.dsh/profiles/<profile-name>/cordis.patch.yml` (same as above) and restart DSH.
---
## Configuration System
### Priority (highest → lowest)
1. **Cordis Config** (set via `cordis.patch.yml` or DSH Web GUI)
2. **Environment variables** (fallback)
3. **Defaults** (e.g., `localhost:19530`)
### Configuration fields
| Field | Environment Variable | Type | Default | Description |
|-------|---------------------|------|---------|-------------|
| `milvusAddress` | `MILVUS_ADDRESS` | string | `localhost:19530` | Milvus server address |
| `milvusToken` | `MILVUS_TOKEN` | string (secret) | empty | Milvus auth token |
| `milvusCollection` | `MILVUS_COLLECTION` | string | `code_embeddings` | Collection name |
| `milvusDim` | `MILVUS_EMBEDDING_DIM` | number | `768` | Vector dimension |
| `embeddingEndpoint` | `EMBEDDING_ENDPOINT` | string | `http://localhost:11434/api/embed` | Embedding API URL |
| `embeddingApiKey` | `EMBEDDING_API_KEY` | string (secret) | empty | Embedding API key |
| `embeddingModel` | `EMBEDDING_MODEL` | string | `nomic-embed-text` | Embedding model name |
| `indexRoot` | `INDEX_ROOT` | string | `process.cwd()` | Code repository root path |
| `indexExtensions` | `INDEX_EXTENSIONS` | string | all supported extensions | File extensions to index (comma-separated) |
| `hybridMode` | `HYBRID_MODE` | boolean | `true` | Enable hybrid search (BM25 full-text + vector semantic, RRF fusion) |
| `bm25RrfK` | `BM25_RRF_K` | number | `60` | RRF fusion parameter k |
| `indexIgnoreDirs` | `INDEX_IGNORE_DIRS` | string | dist, build, target, vendor, ... | Directories to skip during scan |
| `ignorePatterns` | `IGNORE_PATTERNS` | string (textarea) | empty | Custom gitignore-style ignore rules |
| `merkleFilePath` | `MERKLE_FILE_PATH` | string | `~/.milvus-index/merkle-{name}-{hash}.json` | Merkle state file path |
---
## Tool Reference
### `search_code`
Semantic code search. Automatically invoked when the user asks about code functionality, logic, or needs to find code by natural language.
**Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `query` | string | yes | — | Natural language query |
| `topK` | number | no | 5 | Maximum results to return |
| `path` | string | no | (configured root) | Path scope for search |
**Return format:**
```json
[
{
"filePath": "src/auth/login.ts",
"content": "export async function loginUser(credentials) { ... }",
"score": 0.92,
"language": "typescript",
"chunkType": "function_declaration",
"name": "loginUser",
"startLine": 42,
"endLine": 68
}
]
```
### `index_code`
Index the codebase. Supports two modes:
- **`full`** — Full index of all files
- **`incremental`** — Incremental index (only changed files, based on Merkle hash)
**Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `mode` | string | no | `incremental` | Index mode: `full` or `incremental` |
| `path` | string | no | (configured root) | Path to index |
### `index_status`
View index status, including file count, total code blocks, last index time, etc.
### `find_callers`
Find all references to a symbol (function/variable/class) in the codebase, for impact analysis. V2 adds cross-file import resolution: use `sourceFile` to disambiguate same-name symbols across files.
**Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `symbol` | string | yes | — | Symbol name to find (function, variable, class) |
| `direction` | string | no | `backward` | `backward`=who references me (impact); `forward`=who I reference (dependency) |
| `maxResults` | number | no | 20 | Maximum results |
| `sourceFile` | string | no | — | Definition file path (explicit disambiguation: only return callers that import from this file) |
| `resolve` | boolean | no | `true` | Whether to enable import resolution (`false` falls back to V1 name-matching) |
**Return format:**
```json
{
"chunks": [
{
"filePath": "src/auth/login.ts",
"content": "export async function loginUser(credentials) { ... }",
"startLine": 42,
"endLine": 68,
"chunkType": "function_declaration",
"name": "loginUser",
"resolution": {
"status": "resolved",
"targetFile": "src/auth/session.ts",
"exportedAs": "loginUser"
}
}
]
}
```
> `resolution` field: `status` is `resolved` (resolved to a cross-file import), `local` (defined in the same file), or `unresolved` (fallback to V1 name-matching). Only present when import resolution is enabled and the Import Map is built.
### `trace_call_chain`
Starting from the entry symbol, BFS-traverses the call chain along reference relationships. `direction=backward` for impact analysis (find who calls the entry), `direction=forward` for dependency analysis (what the entry calls). Uses a visited set to prevent cycles. V2 supports import resolution disambiguation (`resolve: true` by default), using `filePath:symbol` composite keys for cross-file call chain tracing.
**Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `entry` | string | yes | — | Entry symbol name |
| `direction` | string | no | `backward` | Traversal direction |
| `maxDepth` | number | no | 3 | Maximum recursion depth |
| `maxResults` | number | no | 10 | Maximum results per level |
| `resolve` | boolean | no | `true` | Whether to enable import resolution (`false` falls back to V1) |
**Return format:**
```json
{
"chain": [
{
"depth": 0,
"symbol": "main",
"filePath": "src/index.ts",
"startLine": 1,
"endLine": 5,
"callers": ["runApp"]
},
{
"depth": 1,
"symbol": "runApp",
"filePath": "src/app.ts",
"startLine": 10,
"endLine": 20,
"callers": ["initConfig"]
}
]
}
```
---
## Code Chunking
| Language | Extensions | Chunking method | Covered AST node types |
|----------|-----------|-----------------|------------------------|
| TypeScript | .ts, .tsx, .mts, .cts | tree-sitter | function_declaration, method_definition, class_declaration, interface_declaration, enum_declaration, type_alias_declaration, arrow_function, generator_function, getter, setter |
| JavaScript | .js, .jsx, .mjs, .cjs | tree-sitter | function_declaration, method_definition, class_declaration, arrow_function, generator_function, getter, setter |
| Python | .py | tree-sitter + regex fallback | function_definition, class_definition, async_function_definition, decorated_definition |
| Java | .java | tree-sitter + regex fallback | class_declaration, interface_declaration, enum_declaration, method_declaration, constructor_declaration, record_declaration |
| Go | .go | tree-sitter + regex fallback | function_declaration, method_declaration, type_declaration, type_spec |
| Rust | .rs | tree-sitter + regex fallback | function_item, impl_item, trait_item, struct_item, enum_item, macro_definition |
| C++ | .cpp, .cxx, .cc, .hpp, .h, .hh | tree-sitter + regex fallback | function_definition, class_specifier, namespace_definition, struct_specifier, enum_specifier |
| C# | .cs | tree-sitter + regex fallback | method_declaration, class_declaration, interface_declaration, struct_declaration, enum_declaration |
| Scala | .scala | tree-sitter + regex fallback | class_definition, function_definition, trait_definition, object_definition, constructor_definition |
| PHP | .php | regex fallback | function_definition, class_declaration, interface_declaration, trait_declaration, enum_declaration |
> All languages except PHP (regex-only) use tree-sitter AST parsing as the primary method. Python, Java, Go, Rust, C++, C#, and Scala automatically fall back to regex when tree-sitter parsing fails; **TypeScript / JavaScript have no regex fallback** — if tree-sitter parsing fails, the file is skipped (no index entry).
---
## Ignore Pattern System (IgnoreMatcher)
Three-layer gitignore-style file ignore rules, ensuring only the code files that need analysis are indexed:
### Three rule layers
1. **Built-in defaults**: Automatically excludes `node_modules/`, `dist/`, `build/`, `.git/`, `__pycache__/`, `*.log`, `*.min.js`, and 30+ common build artifacts and dependency directories
2. **Codebase ignore files**: Automatically reads `.gitignore`, `.ignore`, `.xxxignore`, etc. from the codebase root
3. **Global ignore file**: Reads `~/.context/.contextignore` (user-level global rules)
### Automatic hidden path protection
Automatically ignores path segments starting with `.` (e.g., `.git/`, `.vscode/`, `.env`), preventing hidden directories and files from being indexed.
### Backward compatibility
The `indexIgnoreDirs` config (comma-separated directory names) is automatically converted to gitignore-style patterns (e.g., `dist` → `**/dist/**`), maintaining compatibility with older versions.
---
## Incremental Indexing & Workspace Isolation
### Incremental Indexing (Merkle hash tracking)
- Uses SHA-256 hash tracking for each file's content changes
- Only re-indexes new or modified files; skips unchanged files
- Deleted files are automatically removed from Milvus
- State is persisted to a local JSON file
### Workspace Isolation
- Different workspaces use independent Merkle state files
- State file paths are generated based on the workspace path's SHA-256 hash
- Indexing different workspaces does not interfere with each other
- The `path` parameter in tool calls specifies the workspace, automatically using the corresponding state file
---
## When to Use (and When Not To)
### ✅ Suitable Scenarios
- Codebases from tens of thousands to millions of lines, using DSH Agent for refactoring, bug localization, or cross-file reading
- Want to reduce token overhead and minimize Agent grep tool loops
- Need an open-source, self-hostable solution, avoiding closed-source indexing services
- Already using the DSH framework and want to enhance Agent code comprehension
- Need incremental indexing — code changes frequently but don't want full rebuilds every time
### ❌ Not Suitable / Caveats
1. Requires an embedding API (OpenAI / Ollama, etc.), code snippets are sent to the embedding service during indexing; for high-privacy requirements, use Ollama local embeddings
2. Adds Milvus / Zilliz Cloud as a dependency, increasing operational complexity; small codebases (a few hundred files) may not see significant benefit
3. It is a **retrieval augmentation tool**, **not a replacement for the model's context window** — it filters high-quality context to solve "signal overload," not to infinitely expand the window
4. Requires DSH environment (v0.6+), cannot run independently of DSH
---
## Comparison: DIY Code RAG vs dsh-context-milvus
If you build your own code RAG for DSH Agent: you'd need to handle AST chunking, vector search tuning, incremental sync, DSH tool wrapping, result ranking, and ignore file systems. dsh-context-milvus packages all of this engineering into a plug-and-play solution, specifically tuned for code scenarios.
| Dimension | DIY Code RAG | dsh-context-milvus |
|-----------|-------------|-------------------|
| AST Chunking | Integrate tree-sitter yourself, configure per language | Built-in 10-language tree-sitter chunking, auto fallback to regex |
| Semantic Search | Call embedding service and tune parameters yourself | Built-in vector semantic search, plug-and-play (BM25 keyword fusion) |
| Incremental Indexing | Implement file hash comparison and state management yourself | Built-in Merkle file state tracking, SHA-256, incremental updates |
| Workspace Isolation | Handle multi-workspace state conflicts yourself | Automatic path-hash-based isolation, no interference |
| Ignore Files | Implement .gitignore parsing yourself | Built-in three-layer ignore rule system (default + codebase + global) |
| DSH Tool Wrapping | Wrap DSH tools yourself (defineTool) | 13 native DSH tools (5 code tools + 8 ADR tools), one-click registration, formatted output |
| Configuration UI | Build yourself or hand-write YAML | DSH Web GUI visual configuration, 13 config fields |
| Config Sources | Single source | Three-source merge (Cordis Config > env vars > defaults) |
| Index Status | Build yourself | Built-in `index_status` tool, real-time index status |
---
## DSH Web Configuration
After installation, go to the DSH Web interface (http://127.0.0.1:3080) **Settings → Plugins** to see `dsh-context-milvus` and its configuration form, supporting:
- Text inputs (standard fields)
- Password inputs (secret fields like `milvusToken`, `embeddingApiKey`)
- Number inputs (number fields like `milvusDim`)
- Toggles (boolean fields like `hybridMode`)
- Field descriptions / help text
---
## Architecture
```
┌───────────────────────────────────────────────────────────────────────────────────┐
│ DSH Agent / Web UI │
│ search_code │ index_code │ index_status │ find_callers │ trace_call_chain │
│ search_adr │ create_adr │ list_adrs │ load_constraints │
│ check_adr_consistency │
└───────────────────────────────────────────────────────────────────────────────────┘
│
┌───────────────────────────────────────────────────────────────────────────────────┐
│ dsh-context-milvus │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ chunker │→ │embedding │→ │ milvus │ │ merkle │ │ ADR module set │ │
│ │(AST+regex)│ │ client │ │ service │ │ tracker │ │ frontmatter/ │ │
│ └────┬─────┘ └──────────┘ └────┬─────┘ └────────────┘ │ chunker/anchor/ │ │
│ │ │ │ service/indexer/ │ │
│ ┌────▼───────────────────────────▼───┐ │ tools/constraint │ │
│ │ code-relations.ts (BFS engine) │ └──────────────────┘ │
│ │ findCallers / traceChain │ │
│ └────────────────────────────────────┘ │
│ ┌──────────────────────────────┐ ┌──────────────────────────────────────────┐ │
│ │ import-resolver.ts │ │ ignore-matcher (gitignore-style 3-layer) │ │
│ │ Import Map (persistent bi- │ │ ① DEFAULT_IGNORE_PATTERNS → ② codebase │ │
│ │ directional resolution) │ │ ③ ~/.context/.contextignore │ │
│ └──────────────────────────────┘ └──────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
│ │
┌──────────┐ ┌──────────┐
│ Milvus │ │Embedding │
│ (vector DB) │ API │
└──────────┘ └──────────┘
```
### Module dependency graph
```
index.ts (entry point)
├── config.ts — Config resolution (Cordis config > env vars > defaults)
│ └── DEFAULT_IGNORE_PATTERNS — Built-in gitignore-style ignore rules
├── milvus-service.ts — Milvus vector DB client wrapper (CRUD, search)
│ └── embedding.ts — OpenAI-compatible Embedding API client
├── merkle.ts — SHA-256 hash tracker (incremental indexing, persisted to JSON)
├── tools.ts — DSH tool definitions, formatting, workspace-aware tracker creation
│ └── code-relations.ts — Code relationship analysis engine (BFS call chain + dedup)
│ └── import-resolver.ts — Cross-file Import Map (tree-sitter AST import/export scan)
├── ignore-matcher.ts — gitignore-style pattern matching (file exclusion)
└── indexer.ts — Indexing pipeline orchestration
└── chunker.ts — tree-sitter AST chunking + regex fallback (includes references extraction + language import/export config)
└── adr-frontmatter.ts — YAML frontmatter parsing
└── adr-chunker.ts — Markdown section chunking
└── adr-anchor-index.ts — code_anchors reverse index
└── adr-service.ts — ADR CRUD + state management
└── adr-indexer.ts — ADR indexing pipeline
└── adr-tools.ts — 8 ADR tools
└── constraint-injector.ts — System prompt injection + re-injection
```
---
## Testing
```bash
# Run all tests
npm test
# Test coverage
npm run test:coverage
# Single test file
npx jest test/dsh-context-remdb.spec.ts
# Code relationship analysis tests
npx jest test/code-relations.spec.ts
# Cross-file Import Resolution tests
npx jest test/import-resolver.spec.ts
# ADR module tests
npx jest test/adr-frontmatter.spec.ts
npx jest test/adr-chunker.spec.ts
npx jest test/adr-anchor-index.spec.ts
npx jest test/adr-service.spec.ts
npx jest test/adr-indexer.spec.ts
npx jest test/adr-tools.spec.ts
npx jest test/constraint-injector.spec.ts
```
---
## Development
```bash
# Build
npm run build
# Type check (no output)
npx tsc --noEmit
# Run tests (verbose)
node --experimental-vm-modules node_modules/.bin/jest --no-cache --verbose
```
---
## Dependencies
- [@zilliz/milvus2-sdk-node](https://github.com/milvus-io/milvus-sdk-node) — Milvus Node.js SDK
- `ignore` — gitignore-style pattern matching
- `tree-sitter` — AST parsing engine
- `tree-sitter-typescript` — TypeScript/JSX grammar
- `tree-sitter-python` — Python grammar
- `tree-sitter-java` — Java grammar
- `tree-sitter-go` — Go grammar
- `tree-sitter-rust` — Rust grammar
- `tree-sitter-cpp` — C++ grammar
- `tree-sitter-c-sharp` — C# grammar
- `tree-sitter-scala` — Scala grammar
- `@deepseek-ai/cordis` — DSH framework (provided by DSH runtime)
- `@deepseek-ai/dsh-tools` — DSH tool registration API (provided by DSH runtime)
- `@deepseek-ai/schemastery` — Config schema definition (provided by DSH runtime)
---
## License
MITInstall
dsh plugin --profile web add github:bobjia/dsh-context-milvus
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-context-milvus from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.