Repository navigation
Conversation
… tools Adds packages/dsh-weknora, an out-of-tree dsh bundle that registers four read-only tools on ctx.tools: weknora_search (hybrid retrieval, source passages verbatim), weknora_read_document (a document's chunks reassembled in order), weknora_ask (WeKnora's own answer over the RAG or ReAct pipeline) and weknora_list_knowledge_bases. The package has no runtime dependencies: it declares the harness contract structurally in src/harness.ts and hands ctx.tools.register() a plain object, so it pins no harness package version while dsh is in developer preview. Configuration is validated at plugin load, so a bad row fails the boot with every violation named instead of failing inside a tool call. Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
Three layers: - unit tests over the built artifact, including a validator for the JSON Schema subset the harness registry enforces, so a canonical value that drifts from its declared output schema fails here rather than in dsh; - a two-sided API contract: test/fixtures/api-contract.json records every WeKnora call the plugin makes, contract/contract_test.go decodes those bodies into the real handler request structs with DisallowUnknownFields and asserts the response fields and SSE event names it reads still exist; - test/e2e/run-in-dsh.mjs installs the package into a throwaway dsh profile with 'dsh plugin add' and boots the headless profile against a mock WeKnora and a deterministic OpenAI-compatible model, asserting the agent loop called the tools and answered from what they returned. Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
Adds the plugin section to the four top-level READMEs and a workflow that typechecks, tests, packs, and runs the in-harness end-to-end check against a pinned dsh release, with a weekly advisory run against dsh@latest to notice a harness breaking change early. Publishing to npm is gated on a dsh-weknora-v* tag. Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
lyingbug
marked this pull request as ready for review
August 13, 2026 17:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
packages/dsh-weknora, the official DeepSeek Harness (dsh) plugin for WeKnora, plus its tests, CI and documentation.dsh ships no retrieval, embedding or knowledge-base capability of its own — its search tools read the workspace (
grep,glob) or the internet (web_search), and the only documented pattern for external knowledge is "attach an MCP server". This plugin makes WeKnora a first-class capability of the harness instead, with tool schemas, prompt budget and citation rendering under our control.Four read-only tools are registered on
ctx.tools:weknora_searchPOST /knowledge-searchknowledge_id, score, chunk indexweknora_read_documentGET /chunks/:knowledge_idweknora_askPOST /sessions+POST /knowledge-chat/:idorPOST /agent-chat/:idsession_idweknora_list_knowledge_basesGET /knowledge-basesDesign decisions worth reviewing:
src/harness.tsandctx.tools.register()receives a plain object, so the package pins no@deepseek-ai/*version. dsh is in developer preview and states breaking changes will happen; this keeps us off its release treadmill.retrieve;weknora_askadditionally needschat.tool_approval_required/mcp_oauth_requiredwould be lost. A native plugin also lets us clip passages (maxChunkChars) and tell the model when we did.cordis.patch.yml; a profile patch can override the row, includingtoolPrefixso two deployments can be mounted side by side.Distribution follows dsh's ecosystem model: DeepSeek does not accept external PRs and asks plugin authors to publish their own package and tag the repository
dsh-plugin. The package therefore lives here and publishes to npm asdsh-weknora(name confirmed available) on adsh-weknora-v*tag, mirroring howmcp-server/publishes to PyPI.Type of Change
Related Issue
None.
Testing
Three layers, all run in this environment.
Unit + contract (35 tests,
node --test, no network beyond loopback) — run against the built artifact with a mock WeKnora server whose routes, envelopes and SSE events are derived from the real Go types. Includes a validator for the JSON Schema subset the harness registry enforces, so a canonical value that drifts from its declaredoutput.schemafails locally rather than inside dsh.Two-sided API contract —
test/fixtures/api-contract.jsonrecords every WeKnora call the plugin makes.test/contract.test.mjsasserts the plugin still emits exactly those calls;contract/contract_test.godecodes those bodies into the real handler structs (session.SearchKnowledgeRequest,session.CreateKnowledgeQARequest,session.CreateSessionRequest,types.Pagination) withDisallowUnknownFields, and asserts the response fields and SSE event names the plugin reads are still served bytypes.SearchResult,types.Chunkandtypes.StreamResponse. A rename on either side now fails CI instead of a user's agent.End-to-end inside a real dsh install —
test/e2e/run-in-dsh.mjsinstalls a clean@deepseek-ai/dsh@0.1.0-rc.6from npm, runsdsh plugin --profile headless add, and boots the harness against the mock WeKnora and a deterministic OpenAI-compatible model. It asserts the profile layer list gained the bundle,--dump-configmounts the row, all four tools appear in the model's tool schemas, the tools reach WeKnora carrying the API key, the retrieved passages arrive at the model verbatim, and the answer dsh prints is grounded in them. Two scenarios run: the shipped env-driven defaults, and a profile override that renames the tool prefix tokb.Manual check in the dsh Web UI — installed the plugin into a
webprofile and asked a Chinese question through the real UI; the agent calledweknora_searchandweknora_read_documentand answered from the retrieved passages, with no approval prompt needed (the tools touch neither filesystem nor shell).Note for reviewers reproducing this: dsh's session persistence needs a Node build with zstd (≥ 22.15 or ≥ 24); on Node 22.14 the harness fails to boot with
createZstdDecompressmissing. The plugin itself runs on Node ≥ 20.11. A real WeKnora backend was not exercised here because ingestion needs an embedding-model credential this environment does not have — hence the Go contract test, which pins the wire format to the real server types.Checklist
git diff --check origin/main...HEADpassesgofmt -lclean,tsc --noEmitclean)README.md/README_CN.md, plus a section in the four top-level READMEs)Follow-ups deliberately left out of this PR: an
Integrations Centertab for the plugin (frontend/src/config/integrations.ts+ i18n), and configuring theNPM_TOKENsecret /npmenvironment the publish job needs.Screenshots / Recordings
The dsh Web UI calling the plugin's tools end to end:
dsh_web_ui_calling_weknora_tools.mp4
Tool cards and the grounded answer:
dsh Web UI showing weknora_search and weknora_read_document tool calls and the final answer
The expanded
weknora_searchresult, with scores and reusableknowledge_ids:Expanded weknora_search tool result showing retrieved passages, scores and knowledge_id
To show artifacts inline, enable in settings.