DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-context-milvus

b

dsh-context-milvus

Discovered3

claude-context-milvus like plugin for Deepseek Harness (DSH)

dsh-context-milvus

npm version Listed on dsh-plugin.org

English | 简体中文

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 pointdsh-context-milvus solution
Literal string matching only — semantically related but differently named code is missedVector semantic search — matches by code meaning, not just keywords
Multiple tool call rounds, reading many irrelevant files, token explosionReturns 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 reasoningMilvus 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 inefficientMilvus 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 filesAfter 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

Codex CLI support

The retrieval engine behind this plugin is published separately as dsh-context-milvus-core, so the same code also runs as a stdio MCP server for OpenAI Codex CLI (and any other MCP client) from the codex-context-milvus package. It exposes the five retrieval tools — search_code, index_code, index_status, find_callers, trace_call_chain — and shares the same Milvus collection and per-workspace index state as the DSH plugin. Start it with ADR_ENABLED=true and the 8 ADR decision-memory tools are registered as well; the four that write to disk stay gated behind CONTEXT_MILVUS_ADR_WRITE.

Shortest setup:

codex mcp add context-milvus -- npx -y codex-context-milvus mcp

See packages/codex/README.md for the init wizard, the environment variable reference, the error-code table, and current limitations (ADR tools are off by default, no runtime config hot-reload).

Offline / air-gapped install

An offline machine cannot resolve the ~230-package production closure, so the payload has to be built on a connected one. Seed a scratch install with the package as its only production dependency, then carry either the npm cache or the whole node_modules:

mkdir ctxmilvus-offline && cd ctxmilvus-offline
npm init -y
npm pkg set dependencies.codex-context-milvus=0.7.1
npm install --omit=dev --cache ./npm-cache

tar czf ctxmilvus-offline.tgz npm-cache package.json package-lock.json   # method A
tar czf ctxmilvus-tree.tgz node_modules                                  # method B

On the target, method A installs with npm ci --omit=dev --offline --cache ./npm-cache (--offline makes npm fail on a missing tarball instead of reaching for a network that is not there), while method B only needs the tree extracted and the binary invoked directly. Two traps: the generated config.toml starts the server with npx -y, which is a registry call on every Codex launch, so point command/args at the local bin/mcp.js; and the tree-sitter* prebuilds for linux/darwin/win32 × x64/arm64 come inside the tarballs, so one bundle is cross-platform — any other triple needs a compiler. The full recipe, including the prebuild-pruning trick and the exact TOML, is in packages/codex/README.md → Offline install.


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).

MetricG (grep)R (naive RAG)P (plugin)
recall@100.95241.00000.9524
MRR0.67540.95240.8452
nDCG@100.74460.96100.8725
hit@10.47620.90480.7619
precision@10 (file-level)0.42030.10950.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

GroupAverage pass rateToken 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

ToolFunctionKey Parameters
search_codeSemantic code searchquery (natural language), topK (result count), path (search scope)
index_codeIndex codebasemode (full/incremental), path (target path)
index_statusView index statuspath (view per-workspace status)
search_adrSemantic ADR searchquery (natural language), status, topK
search_adr_by_fileFind ADRs by file pathfile_path (code file path), status
create_adrCreate new ADRtitle (required), requirement, change_type
update_adrUpdate existing ADRadr_id (required), content, status
list_adrsList ADR recordsstatus, change_type, limit
load_constraintsLoad active ADR constraintsadr_ids, format
check_adr_consistencyCheck ADR-code consistencyfile_path, fix
find_callersFind all references to a symbol for impact analysis, supports cross-file import resolutionsymbol (required), direction, maxResults, sourceFile, resolve
trace_call_chainBFS call chain tracing from entry symbol (impact/dependency analysis), supports import resolution disambiguationentry (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

FieldDefaultDescription
specRootdocs/superpowers/specsSpec document directory (relative to indexRoot)
planRootdocs/superpowers/plansImplementation plan directory (relative to indexRoot)

Spec document fusion follows the adrEnabled toggle — no additional configuration needed.


Prerequisites

1. Install Ollama (Embedding service)

# 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

# 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):

# 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):

# 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 managed service — no self-hosting required.

Verify installation

# 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:

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:

# 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)

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:

# ~/.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:

# ~/.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

cd /mnt/home/bobjia/workspace/dsh-context-milvus
npm install --legacy-peer-deps

2. Create symlinks for @deepseek-ai packages

# 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

# 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

FieldEnvironment VariableTypeDefaultDescription
milvusAddressMILVUS_ADDRESSstringlocalhost:19530Milvus server address
milvusTokenMILVUS_TOKENstring (secret)emptyMilvus auth token
milvusCollectionMILVUS_COLLECTIONstringcode_embeddingsCollection name
milvusDimMILVUS_EMBEDDING_DIMnumber768Vector dimension
embeddingEndpointEMBEDDING_ENDPOINTstringhttp://localhost:11434/api/embedEmbedding API URL
embeddingApiKeyEMBEDDING_API_KEYstring (secret)emptyEmbedding API key
embeddingModelEMBEDDING_MODELstringnomic-embed-textEmbedding model name
indexRootINDEX_ROOTstringprocess.cwd()Code repository root path
indexExtensionsINDEX_EXTENSIONSstringall supported extensionsFile extensions to index (comma-separated)
hybridModeHYBRID_MODEbooleantrueEnable hybrid search (BM25 full-text + vector semantic, RRF fusion)
bm25RrfKBM25_RRF_Knumber60RRF fusion parameter k
indexIgnoreDirsINDEX_IGNORE_DIRSstringdist, build, target, vendor, ...Directories to skip during scan
ignorePatternsIGNORE_PATTERNSstring (textarea)emptyCustom gitignore-style ignore rules
merkleFilePathMERKLE_FILE_PATHstring~/.milvus-index/merkle-{name}-{hash}.jsonMerkle 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:

ParameterTypeRequiredDefaultDescription
querystringyesNatural language query
topKnumberno5Maximum results to return
pathstringno(configured root)Path scope for search

Return format:

[
  {
    "filePath": "src/auth/login.ts",
    "content": "export async function loginUser(credentials) { ... }",
    "score": 0.0164,
    "scoreKind": "rrf",
    "language": "typescript",
    "chunkType": "function_declaration",
    "name": "loginUser",
    "startLine": 42,
    "endLine": 68
  }
]

What score means depends on hybridModescoreKind says which. With hybrid search on (the default) Milvus returns an RRF fusion score, roughly 1/(bm25RrfK + rank): it encodes rank, not similarity, sits near 0.016, and must not be read as a match percentage or compared against a cosine value. With hybridMode: false it is a real cosine similarity (typically 0.5–0.8). The rendered text follows suit: RRF results print 排序: N/M instead of a relevance number, so a rank is never mistaken for match quality.

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:

ParameterTypeRequiredDefaultDescription
modestringnoincrementalIndex mode: full or incremental
pathstringno(configured root)Path to index

Large-workspace deferral: when a run would index more than 1000 files, or more than 500 KiB of source text (UTF-8 bytes), index_code only scans and reports, then returns immediately — it does not chunk, call Embedding, or write to Milvus. It also returns a command you can paste into a terminal to run the indexing yourself, carrying the same --mode you asked for (see Standalone Index Script below). This keeps a single tool call from running past its timeout, and from spending embedding money the user never asked to spend.

The threshold is measured on the work the run would actually do, not on the size of the workspace, so a small incremental update on a large repository still runs inline. mode=full and a first index re-index every file, so they defer as soon as the workspace itself is over the limit. The Codex index_code never defers.

index_status

View index status, including file count, total code blocks, last index time, etc.

Large-spec-corpus deferral (index_specs): when the documents that actually need work — those lacking frontmatter under specRoot + planRoot — number more than 100, or hold more than 200 KiB of text, index_specs only scans and reports, then returns immediately — it does not generate frontmatter, write any file, or index anything — and returns a terminal command carrying --specs-only. The threshold is measured on those candidates rather than on the whole corpus, because the incremental index that follows only runs when at least one candidate exists: a corpus whose documents all already have frontmatter has nothing to do, and is never deferred.

index_specs(dry_run=true) is exempt (a preview has no side effects) and is the way to inspect which anchors would be generated.

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:

ParameterTypeRequiredDefaultDescription
symbolstringyesSymbol name to find (function, variable, class)
directionstringnobackwardbackward=who references me (impact); forward=who I reference (dependency)
maxResultsnumberno20Maximum results
sourceFilestringnoDefinition file path (explicit disambiguation: only return callers that import from this file)
resolvebooleannotrueWhether to enable import resolution (false falls back to V1 name-matching)

Return format:

{
  "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:

ParameterTypeRequiredDefaultDescription
entrystringyesEntry symbol name
directionstringnobackwardTraversal direction
maxDepthnumberno3Maximum recursion depth
maxResultsnumberno10Maximum results per level
resolvebooleannotrueWhether to enable import resolution (false falls back to V1)

Return format:

{
  "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"]
    }
  ]
}

Standalone Index Script

On a large workspace the plugin hands the heavy lifting to you to run in a terminal. The script ships with dsh-context-milvus:

# Full index: code → spec/plan frontmatter generation → ADR/spec index
node ~/.dsh/profiles/web/node_modules/dsh-context-milvus/bin/index.js --root /path/to/workspace

# Spec documents only
node ~/.dsh/profiles/web/node_modules/dsh-context-milvus/bin/index.js --root /path/to/workspace --specs-only

# Inspect the scale first (no Milvus connection, writes nothing)
node ~/.dsh/profiles/web/node_modules/dsh-context-milvus/bin/index.js --root /path/to/workspace --dry-run
FlagDescription
--root <path>Workspace root (default: current directory)
--mode full|incrementalIndex mode (default incremental)
--config <path>Explicit run-config (default: derived from --root)
--specs-onlyOnly generate frontmatter and index spec/plan documents
--no-adrSkip the ADR and spec index
--dry-runScan and report only
--verbosePrint per-file progress
-h, --helpShow usage

Exit codes: 0 success, 1 run failure, 2 usage error; Ctrl-C saves progress first and exits 130, so re-running resumes where it left off.

Config source: the script prefers ~/.milvus-index/run-config-<workspace-name>-<hash>.json — the resolved effective config that index_code / index_specs wrote when they deferred (Milvus address/token, embedding endpoint/model, etc., file mode 0600) — so the script and the plugin use exactly the same settings. Without that file it falls back to environment variables and defaults, and prints a warning.

Do not index while the plugin is indexing: the two cannot corrupt each other's data, but they will duplicate work.

Known limitation: sharing one collection across machines

The index key file_path is a machine-absolute path, and "already indexed" is decided by this machine's ~/.milvus-index/merkle-*.json. So when several users clone the same Git repository on different computers but point at the same remote Milvus collection:

  • each clone writes its own rows (same file, different absolute paths → two sets of rows), and deleting in one does not affect the other;
  • neither clone can see the other's Merkle state, so the same code is embedded repeatedly (and billed repeatedly);
  • search results mix in other machines' absolute paths, which do not open locally.

Recommendation: give each workspace/user its own collection (change milvusCollection / adrCollection in the DSH settings panel). Sharing a collection is currently only safe when everyone clones the repository to exactly the same absolute path and the collection name, milvusDim and embedding model all match.


Code Chunking

LanguageExtensionsChunking methodCovered AST node types
TypeScript.ts, .tsx, .mts, .ctstree-sitterfunction_declaration, method_definition, class_declaration, interface_declaration, enum_declaration, type_alias_declaration, arrow_function, generator_function, getter, setter
JavaScript.js, .jsx, .mjs, .cjstree-sitterfunction_declaration, method_definition, class_declaration, arrow_function, generator_function, getter, setter
Python.pytree-sitter + regex fallbackfunction_definition, class_definition, async_function_definition, decorated_definition
Java.javatree-sitter + regex fallbackclass_declaration, interface_declaration, enum_declaration, method_declaration, constructor_declaration, record_declaration
Go.gotree-sitter + regex fallbackfunction_declaration, method_declaration, type_declaration, type_spec
Rust.rstree-sitter + regex fallbackfunction_item, impl_item, trait_item, struct_item, enum_item, macro_definition
C.c, .inctree-sitter + regex fallbackfunction_definition, struct_specifier, enum_specifier, union_specifier, type_definition, preproc_function_def, declaration (prototypes only)
C++.cpp, .cxx, .cc, .hpp, .h, .hhtree-sitter + regex fallbackfunction_definition, class_specifier, namespace_definition, struct_specifier, enum_specifier
C#.cstree-sitter + regex fallbackmethod_declaration, class_declaration, interface_declaration, struct_declaration, enum_declaration
Scala.scalatree-sitter + regex fallbackclass_definition, function_definition, trait_definition, object_definition, constructor_definition
PHP.phpregex fallbackfunction_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.

DimensionDIY Code RAGdsh-context-milvus
AST ChunkingIntegrate tree-sitter yourself, configure per languageBuilt-in 10-language tree-sitter chunking, auto fallback to regex
Semantic SearchCall embedding service and tune parameters yourselfBuilt-in vector semantic search, plug-and-play (BM25 keyword fusion)
Incremental IndexingImplement file hash comparison and state management yourselfBuilt-in Merkle file state tracking, SHA-256, incremental updates
Workspace IsolationHandle multi-workspace state conflicts yourselfAutomatic path-hash-based isolation, no interference
Ignore FilesImplement .gitignore parsing yourselfBuilt-in three-layer ignore rule system (default + codebase + global)
DSH Tool WrappingWrap DSH tools yourself (defineTool)13 native DSH tools (5 code tools + 8 ADR tools), one-click registration, formatted output
Configuration UIBuild yourself or hand-write YAMLDSH Web GUI visual configuration, 13 config fields
Config SourcesSingle sourceThree-source merge (Cordis Config > env vars > defaults)
Index StatusBuild yourselfBuilt-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 (13 tools)       │  │   OpenAI Codex CLI / any MCP client  │
│  search_code │ index_code │ index_status │  │        (5 tools, MCP stdio)          │
│  find_callers │ trace_call_chain         │  │  search_code │ index_code │ ...      │
│  8 × ADR tools (decision memory)         │  │   ADR tools need ADR_ENABLED         │
└────────────────────┬─────────────────────┘  └───────────────────┬──────────────────┘
                     │                                            │
       packages/dsh (Cordis adapter)              packages/codex (MCP adapter + CLI)
       tools.ts / adr-tools.ts /                   server.ts / handlers.ts /
       constraint-injector.ts                      init-wizard.ts / doctor.ts
                     │                                            │
                     └────────────────────┬───────────────────────┘
                                          ▼
                    packages/core — dsh-context-milvus-core (framework-agnostic)
   ┌──────────────────────────────────────────────────────────────────────────────┐
   │  chunker (AST+regex) → embedding → milvus-service        merkle (SHA-256 Δ)  │
   │  code-relations (BFS findCallers/traceChain)             import-resolver     │
   │  query-expansion → reranker                              ignore-matcher (3层) │
   │  telemetry (JSONL, opt-in)                               logger port         │
   │  ADR engine: frontmatter/chunker/anchors/service/indexer/bundle              │
   └──────────────────────────────────────────────────────────────────────────────┘
                                          │
                          ┌───────────────┴───────────────┐
                     ┌──────────┐                   ┌──────────┐
                     │  Milvus  │                   │Embedding │
                     │(vector DB)│                  │   API    │
                     └──────────┘                   └──────────┘

Both adapters depend on the core package; they never depend on each other. The core boundary is machine-enforced: it may not import @deepseek-ai/*, @modelcontextprotocol/* or zod, and may not call console.* directly (logging goes through the injected Logger).

Module dependency graph

Core (packages/core/src/, imported by adapters only through the index.ts barrel):

index.ts (barrel)
  ├── config.ts     — Config resolution (adapter config > env vars > defaults)
  │     └── DEFAULT_IGNORE_PATTERNS — Built-in gitignore-style ignore rules
  ├── milvus-service.ts — Milvus vector DB client wrapper (CRUD, search, ADR collection)
  │     ├── embedding.ts — OpenAI-compatible Embedding API client
  │     ├── query-expansion.ts / reranker.ts — retrieval quality stages
  │     └── logger.ts — Logger port (consoleLogger / silentLogger)
  ├── merkle.ts     — SHA-256 hash tracker (incremental indexing, persisted to JSON)
  ├── 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 (references extraction + language import/export config)

DSH adapter (packages/dsh/src/plugins/dsh-context-milvus/):

index.ts        — Cordis entry: bootstrap, settings panel, register 13 tools
tools.ts        — DSH tool definitions, formatting, workspace-aware tracker creation
adr-frontmatter.ts — YAML frontmatter parsing
adr-chunker.ts     — Markdown section chunking
adr-anchor-index.ts / adr-anchor-generator.ts — code_anchors index + generation
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

Codex adapter (packages/codex/src/): workspace-resolver.tscontext.ts (stderr logger) → workspace-services.ts (per-root cache) → handlers.ts (5 tools) → server.ts (MCP wiring) + result-format.ts / schemas.ts, plus init-wizard.ts and doctor.ts for the CLI.


Testing

# Run all tests (single root Jest project across the three packages)
npm test

# Test coverage
npm run test:coverage

# Single test file — Jest must run under --experimental-vm-modules here,
# so plain `npx jest <file>` fails with "Cannot use import statement outside a module"
node --experimental-vm-modules node_modules/.bin/jest packages/core/test/dsh-context-remdb.spec.ts

# Code relationship analysis tests
node --experimental-vm-modules node_modules/.bin/jest packages/core/test/code-relations.spec.ts

# Cross-file Import Resolution tests
node --experimental-vm-modules node_modules/.bin/jest packages/core/test/import-resolver.spec.ts

# core boundary guard + DSH contract freeze
node --experimental-vm-modules node_modules/.bin/jest packages/core/test/core-boundary.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/public-surface.spec.ts

# ADR module tests
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-frontmatter.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-chunker.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-anchor-index.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-service.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-indexer.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/adr-tools.spec.ts
node --experimental-vm-modules node_modules/.bin/jest packages/dsh/test/constraint-injector.spec.ts

# MCP server smoke test (spawns the built bin over real stdio — build first)
npm run build && node --experimental-vm-modules node_modules/.bin/jest packages/codex/test/mcp-smoke.spec.ts

Development

# Install (see the note below about the peer conflict)
npm install --legacy-peer-deps

# Build all packages in order: core → dsh → codex
npm run build

# Type check all packages (builds core first, since adapters resolve its .d.ts)
npm run typecheck

# Run tests (verbose)
node --experimental-vm-modules node_modules/.bin/jest --no-cache --verbose

@deepseek-ai/dsh-llm and @deepseek-ai/dsh-settings require incompatible @deepseek-ai/dsh-brand versions, so npm needs --legacy-peer-deps (or npm ci --legacy-peer-deps). This predates the workspace split and is unrelated to it.


Dependencies

Core (packages/coredsh-context-milvus-core):

  • @zilliz/milvus2-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-c — C grammar
  • tree-sitter-cpp — C++ grammar
  • tree-sitter-c-sharp — C# grammar
  • tree-sitter-scala — Scala grammar

DSH adapter (packages/dsh), all provided by the DSH runtime:

  • @deepseek-ai/cordis — DSH framework
  • @deepseek-ai/dsh-tools — DSH tool registration API
  • @deepseek-ai/schemastery — Config schema definition
  • @deepseek-ai/dsh-settings — settings panel (installSection)
  • @deepseek-ai/dsh-llm — agent access used by constraint re-injection

Codex adapter (packages/codex):

  • @modelcontextprotocol/sdk — MCP server + stdio transport
  • zod — MCP tool input schemas (kept out of core on purpose)

License

MIT

Comments

Loading…

Similar plugins

dsh-milvus

by zilliztech

DeepSeek Harness(DSH) plugin for Milvus

Tools & CapabilitiesModels & ProvidersManifest valid

3

Apache-2.0

JavaScript

Aug 23, 2026

dsh plugin --profile web add @zilliz/dsh-milvus

by Ceelog

deepseek harness plugins

Workflow & AutomationTools & CapabilitiesManifest valid

8

101/wk

TypeScript

Aug 23, 2026

dsh plugin --profile web add @opendsh/dsh-plugin-scheduled-tasks

by sliverp

Native DSH Hub marketplace plugin for DeepSeek Harness

Tools & CapabilitiesManifest valid

16

TypeScript

Aug 16, 2026

dsh plugin --profile web add dsh-hub

by WShihan

deepseek harness notification plugin for macos

Manifest valid

0

MIT

TypeScript

Sep 18, 2026

dsh plugin --profile web add dsh-macos-notify

by jwilson411

A minimal, tested template for DeepSeek Harness plugins.

Manifest valid

0

MIT

JavaScript

Sep 1, 2026

dsh plugin --profile web add dsh-plugin-kit

by QQQW114

DeepSeek Harness (DSH) plugin - inject context when user input or model output hits configured keywords, with toggleable/configurable rules and model-editable memory.

Manifest valid

0

MIT

JavaScript

Aug 17, 2026

dsh plugin --profile web add dsh-keyword-context