dsh-skill-rag
Optional, configurable skill discovery for DeepSeek Harness. It keeps the
full skill library searchable without advertising every skill in every prompt,
while leaving the original skill loader, instructions, resources and
procedural-learning tools untouched.
Three modes:
| Mode | What it does | Embedding provider | Index |
|---|---|---|---|
catalog |
Standard — no RAG. Leaves DSH's stock full catalog and loader alone. | none | none |
keyword |
Local SQLite FTS5/BM25 search with a small selected catalog. | none | local keyword index |
hybrid |
Keyword + semantic retrieval through a configured embedding provider. | Jetson, Google, OpenRouter or OpenAI-compatible | versioned vector generations |
New installations default to catalog, so installing the plugin does not
require a key, a model service or a network connection. hybrid is opt-in.
Requirements
- DSH
0.2.1-rc.2(tested target), Node>=22.19with nativenode:sqlite. - For
hybrid, one embedding provider:- an existing local TensorRT manager (default
http://127.0.0.1:8110); - a Google Gemini API key;
- an OpenRouter API key;
- an OpenAI-compatible embeddings endpoint and model.
- an existing local TensorRT manager (default
- No SDKs or extra vector database are required.
Install
From a local checkout:
npm ci
npm run verify
dsh plugin --profile web add "$PWD"
From a published Git repository:
dsh plugin --profile web add github:Kosello/dsh-skill-rag
The package declares one bundle row (skill-rag) and an optional browser
client section. The browser client registers Settings → Skill discovery
without editing the DSH shell.
Verify composition before restarting:
dsh --profile web --dump-config | grep -A4 'id: skill-rag'
Then restart the harness through your normal service mechanism. If you are running the agent inside that service, use an external delayed restart rather than interrupting the active turn.
Configuration
Configuration lives on the skill-rag row in the profile's
cordis.patch.yml. The same contract is edited by the settings panel.
Standard catalog (recommended zero-setup default)
- id: skill-rag
config:
mode: catalog
This does not open an index, initialize an embedding provider, register
skill_search, or project a selected catalog. The stock full catalog is used.
Local keyword search
- id: skill-rag
config:
mode: keyword
coreNames: [] # user/project DSH skills are always retained
autoIndex: false
skill_search and the selected catalog are enabled. No embedding provider is
constructed and no embedding request is made.
Hybrid with a local Jetson manager
- id: skill-rag
config:
mode: hybrid
embedding:
provider: jetson
model: Qwen3-Embedding-0.6B-TensorRT
baseURL: http://127.0.0.1:8110
dimensions: 1024
timeoutMs: 15000
index:
content: excerpts
privacy:
allowRemoteEmbeddings: false
autoIndex: true
The Jetson adapter accepts only a loopback HTTP service root and uses its non-fallback embedding route.
Google Gemini
- id: skill-rag
config:
mode: hybrid
embedding:
provider: google
model: gemini-embedding-2
dimensions: 768
apiKeyEnv: GEMINI_API_KEY
index:
content: metadata
privacy:
allowRemoteEmbeddings: true
gemini-embedding-2 is the stable model documented by Google for text and
multimodal embeddings. Recommended output dimensions are 768, 1536 or 3072.
The adapter sends text only; no assets are uploaded.
OpenRouter
- id: skill-rag
config:
mode: hybrid
embedding:
provider: openrouter
model: openai/text-embedding-3-small
dimensions: 1536
apiKeyEnv: OPENROUTER_API_KEY
providerRouting:
allow_fallbacks: false
data_collection: deny
index:
content: metadata
privacy:
allowRemoteEmbeddings: true
OpenRouter model discovery uses its embeddings catalog, not the chat-model list. Model support for dimensions, input types and routing varies by model. An explicit model is required.
OpenAI-compatible endpoint
- id: skill-rag
config:
mode: hybrid
embedding:
provider: openai-compatible
model: your-embedding-model
baseURL: http://127.0.0.1:11434/v1
dimensions: 1024
apiKeyEnv: LOCAL_EMBEDDING_KEY # optional for a loopback server
index:
content: metadata
privacy:
allowRemoteEmbeddings: false
The adapter accepts an explicit endpoint and uses the OpenAI /embeddings
shape. Compatibility is not assumed from a product name; test the endpoint and
its dimensions before relying on it. A remote endpoint requires HTTPS and
explicit remote consent.
Credentials
Configuration contains only environment-variable names, never key values. Put keys in a private environment file and reference it from the service:
install -m 600 /dev/null ~/.dsh/skill-rag.env
printf 'GEMINI_API_KEY=%s\n' "$YOUR_KEY" >> ~/.dsh/skill-rag.env
mkdir -p ~/.config/systemd/user/deepseek-harness.service.d
printf '[Service]\nEnvironmentFile=%%h/.dsh/skill-rag.env\n' \
> ~/.config/systemd/user/deepseek-harness.service.d/skill-rag.conf
systemctl --user daemon-reload
Restart to apply. The settings panel reports only whether the referenced variable is present; it never displays the value and has no secret-write field. The TypeSafe/Jev key file is unrelated and should not be reused.
Using it
The model can call:
{"query":"render a short video from a photograph on my desktop", "limit":5}
skill_search returns names and routing summaries, not instructions. The model
then loads the original skill with the unchanged skill tool. Search and
indexing never synthesize a successful skill result, so read-before-write and
the self-evolve reviewer still observe real loads.
Humans can use:
/skill-search status
/skill-search models
/skill-search test
/skill-search preview
/skill-search reindex # prints the data-consent disclosure
/skill-search reindex --confirm # starts the rebuild
/skill-search cancel
reindex refuses to start without the explicit --confirm step. The settings
panel performs the same sequence through an authenticated owner-only RPC; model
tools cannot change provider settings, credentials or trigger a rebuild.
What gets sent
catalog: nothing.keyword: nothing; local SQLite only.hybridlocal (Jetson/loopback): skill cards and search queries stay on the machine.hybridremote: only the configured card content and search queries are sent.metadatacards contain name, description, trigger guidance and explicit target hints.excerptsalso include headings and a short introduction. Paths and full bodies are never part of a card. Metadata can still be private; remote processing requiresprivacy.allowRemoteEmbeddings: true.
There is no automatic local-to-cloud fallback. If the provider fails, the
configured onEmbeddingError chooses labelled keyword results (default) or a
strict error. Provider errors are returned in sanitized form.
Index generations and upgrades
Embedding spaces are not interchangeable, even at equal dimensions. The namespace fingerprint includes provider, endpoint, model, explicit revision, dimensions, query/document transforms, content policy and adapter format. Credentials, timeout and batch size do not affect the fingerprint.
A model or policy change creates a new private generation; the prior known-good generation stays available until the replacement is complete. Incomplete, cancelled or superseded candidates cannot become active. A key rotation alone reuses the same vectors. Existing 0.1 Jetson caches are adopted into a private snapshot without modifying the old file.
The index is rebuildable local state under the configured database path. It is not a personal-memory store and does not replace Hindsight or any other memory service. Source skill files are never modified or synchronized by this plugin.
Settings panel
The browser client adds a Skill discovery section with:
- mode selector;
- provider, model, environment-variable reference and dimensions;
- Refresh embedding models (embedding-capable models only);
- Test connection using synthetic text, never your skills;
- Preview data sent before a rebuild;
- explicit consent review, rebuild progress and cancel;
- visible keyword-fallback status.
Mode changes take effect through the runtime: catalog removes selective
catalog projection and the search tool; keyword/hybrid add them. Existing
sessions may retain earlier compact catalog messages in history, but no new
compact catalogs are produced in Catalog mode.
Development and verification
npm run check
npm test
npm run build # server + ModuleLoader-wrapped client bundle
npm run smoke # real filesystem -> search -> selected catalog -> stock loader
npm run benchmark # fixed 26-case evaluation against the real library
The suite covers provider fixtures, credential and redirect safety, index generations, mode lifecycle, management RPC, commands, settings controller and DOM panel. Live paid-provider calls are not part of the default test suite.
tsup must keep removeNodeProtocol: false: node:sqlite is a prefix-only
builtin and stripping node: creates an invalid bare import.
Limitations
- Full filesystem catalog discovery still happens internally; the plugin reduces prompt exposure, not discovery I/O.
- Provider input limits, batch limits and pricing vary; consult each provider.
- Dimension support varies by model. Set
dimensionsdeliberately. - A remote provider sees card metadata and queries; review the disclosure.
- A later outermost middleware could still alter the final prompt.
- Malformed legacy catalog messages are left untouched.
- The browser section integrates through the installed client-slot API; a changed host UI contract may require a client rebuild.
License
MIT. See LICENSE.
No comments yet. Be the first to write one.