dsh-web-kimi
One Kimi Coding key, both halves of the web pipeline — web search and web fetch for the DeepSeek Harness.
English | 中文
- What it is
- Why
- How it works
- Quick start
- Settings GUI card
- Configuration
- Wire mapping
- Troubleshooting
- How it compares
- Known limitations
- Repository architecture
- Development
- Credits
- License
What it is
A DSH plugin that registers two providers into the ctx.web seam:
kimi-coding— aWebSearchProviderbacked by the Kimi Coding API search endpoint (POST /v1/search). Search results map to the harness'sWebSearchSourceshape:url,title,snippet, andpublishedAt(from the resultdate).kimi-coding-fetch— aWebFetchProviderbacked by the Kimi Coding API fetch endpoint (POST /v1/fetch). Any http(s) URL is extracted server-side — JavaScript rendering included — and returned as clean markdown.
Both halves authenticate with the same credential and read the same settings section, so a key saved once covers every web operation. A dedicated settings card in the GUI stores the key through the DSH credentials service, and a saved value takes effect on the very next search or fetch — no restart.
┌─────────────────────────────────────────────┐
│ ctx.web seam │
├──────────────────────┬──────────────────────┤
│ web_search tool │ web_fetch tool │
│ WebSearchProvider │ WebFetchProvider │
│ kimi-coding │ kimi-coding-fetch │
└──────────┬───────────┴──────────┬───────────┘
│ POST /v1/search │ POST /v1/fetch
▼ ▼
┌─────────────────────────────────────────────┐
│ api.kimi.com/coding/v1 │
│ one Bearer key, one subscription │
└─────────────────────────────────────────────┘
Why
The DSH ecosystem already has search aggregators and OAuth bridges; what it lacked was a vendor-native two-seam integration for Kimi. This package brings the coding-plan subscription you already pay for into both web_search routing and web_fetch routing — no per-call search billing, no second account, no aggregator in the middle.
If you already run Kimi Code (the CLI), it is zero-config: the credential chain falls back through your ~/.kimi-code/config.toml and picks the key up on its own.
How it works
Registration — the plugin injects into
ctx.weband registers both providers. The bundle overlay selectssearchProvider: kimi-codingandfetchProvider: kimi-coding-fetchon install.Credential resolution (per operation, no restart) — the card's stored value wins, then the credentials service's secondary reference, then the config literal, then the launching environment, then the Kimi CLI config file:
settings card → KIMI_CODING_API_KEY → KIMI_API_KEY → config apiKey → launch environment → ~/.kimi-code/config.toml → ~/.kimi/config.tomlRequest shaping —
text_queryplus a server-sidelimit(clamped to the API's 1–20 bound),enable_page_crawlingfrom the toggle,timeout_seconds, and a freshX-Msh-Tool-Call-Idcorrelation id on every call.Hardening — only absolute http(s) URLs are forwarded or surfaced; search response bodies are bounded at 5 MB before buffering; fetch content is capped at 2 MB with a
truncatedflag. Every failure surfaces as a typedWebError(WEB_PROVIDER_ERROR,WEB_PROVIDER_CREDENTIAL_MISSING,WEB_ABORTED) with the upstream HTTP status preserved in the message.
The web_fetch tool itself stays gated by dsh-tool-web (the harness keeps fetch off by default over SSRF concerns); this package registers the provider and the routing for when you enable it.
Quick start
dsh plugin --profile web add dsh-web-kimi
Then open Settings → Web Search (Kimi) in the DSH web GUI, paste your Kimi Coding API key, and Save. The key lands in the DSH credentials service (~/.dsh/.credentials.yaml) — never in settings.yaml.
No GUI? Any of these works too:
export KIMI_CODING_API_KEY=sk-... # launching environment
# or: store through the credentials service under KIMI_CODING_API_KEY / KIMI_API_KEY
# or: ~/.kimi/config.toml with api_key = "..." (Kimi Code CLI users — picked up automatically)
The provider id kimi-coding deliberately matches quei4r/dsh-host-kimi-search, so installing this package is a drop-in replacement for that script, not a duplicate-id conflict.
Settings GUI card
The card covers three fields, all stored under credential references:
| Field | Type | Stored as |
|---|---|---|
| API key | password | KIMI_CODING_API_KEY |
| Base URL | text | KIMI_SEARCH_BASE_URL |
| Page crawling | select (true / false) |
KIMI_SEARCH_PAGE_CRAWLING |
- A masked input, a "Get an API key ↗" link straight to the Kimi console, and a live configured/not-configured badge that refreshes on save.
- Leave a field blank to keep its current value; Reset clears all three references.
- The CLI-config fallback is read-only — this package never writes
~/.kimi/config.toml.
Configuration
Settings section web-kimi (file-based edits of the same fields the card writes):
| Field | Default | Meaning |
|---|---|---|
apiKey |
— | Literal key; a stored credential-reference value wins over it |
apiKeyEnv |
KIMI_CODING_API_KEY |
Primary credential reference |
baseURL |
https://api.kimi.com/coding/v1 |
Endpoint base (/search, /fetch appended) |
pageCrawling |
false |
Send enable_page_crawling so results carry full content |
timeoutSeconds |
30 |
Server-side timeout_seconds |
Wire mapping
Kimi /v1/search field |
WebSearchSource |
|---|---|
url |
url (required; non-http(s) results dropped) |
title |
title (omitted when blank) |
snippet, then content |
snippet (first non-blank wins) |
date |
publishedAt (omitted when blank) |
site_name, icon, mime |
not mapped |
/v1/fetch responses arrive as markdown and map to WebFetchResult { statusCode, body: { kind: 'text' }, truncated } — content past 2 MB is capped and flagged.
Troubleshooting
Every failure carries the HTTP status in its message, which makes most problems one-glance diagnosable:
| You see | What it means | What to do |
|---|---|---|
url.not_found |
The base URL points at a surface without /search — typically the chat API (https://api.moonshot.cn/v1) |
Set the base URL to https://api.kimi.com/coding/v1; the coding endpoints need a coding credential |
Kimi search error (HTTP 401): … |
The key was recognized but rejected — it is not a Coding credential | Use a Kimi Coding API key, not a chat/API-platform key |
Kimi search error (HTTP 403): … |
The key is valid, but the plan lacks the search/fetch service | Enable the search/fetch service on the coding plan |
… (HTTP 5xx): … / non-JSON body |
Upstream-side fault | Retry; the status tells you it is not your config |
WEB_PROVIDER_CREDENTIAL_MISSING |
No key resolved anywhere in the chain | Paste it in the settings card, store it under KIMI_CODING_API_KEY / KIMI_API_KEY, export it, or put it in ~/.kimi/config.toml |
Results carry no content |
Page crawling is off | Turn on the page-crawling toggle |
How it compares
| dsh-web-kimi | dsh-web-search-doubao | dsh-web-search-zai | quei4r/dsh-host-kimi-search | |
|---|---|---|---|---|
| Seams filled | search + fetch | search | search | search |
| Credential | one coding-plan key | separate Doubao Search key | reuses ZAI_API_KEY |
coding key chain |
| Settings GUI card | yes | yes | — | — |
| CLI-config fallback | yes | — | — | yes |
| Typed error taxonomy | yes | yes | yes | partial |
| On npm | yes | yes | yes | — |
Known limitations
- Entitlement: the coding-plan account must include the search/fetch service; otherwise the endpoint answers 403.
contentneeds crawling: result bodies stay empty unlesspageCrawlingis on.- Fetch tool gating: enable
web_fetchindsh-tool-webto route fetches through this provider. - One
searchProviderper profile: installing this plugin switches the profile's selection from any previous search plugin; remove it (or override the config) to switch back. - No DeepSeek-key fallback (a deliberate divergence from quei4r's chain): a DeepSeek API key would only 401 at
api.kimi.com.
Repository architecture
dsh-web-kimi/
├── package.json # dsh.bundle.patch + dsh.client manifest, exports ./client
├── tsdown.config.ts # client-half build (ModuleLoader-wrapped browser bundle)
├── cordis.patch.yml # searchProvider + fetchProvider selection, insert entry
├── src/
│ ├── index.ts # node entry: Config, credential chain, apply()
│ ├── provider.ts # KimiSearchProvider + shared headers/abort plumbing
│ ├── fetch-provider.ts # KimiFetchProvider (the second seam)
│ ├── types.ts # wire types
│ ├── invariant.ts # no-op invariant companion
│ └── client/
│ ├── card.tsx # reusable settings-card factory
│ └── index.tsx # Kimi instantiation (refs, locales, console link)
├── tests/ # 79 unit tests across search, fetch, and card suites
└── lib/ # committed build output — git installs need no build step
Development
pnpm install
pnpm typecheck && pnpm build && pnpm test
- Node 22.19+ / 24, pnpm 11 — same floor as the harness.
- The test suites run against a mocked
fetch(79 tests); the live smoke intests/kimi.e2e.tsself-skips without$KIMI_CODING_API_KEY. - CI runs the full gate (typecheck, build, test) on Node 22/24 × Ubuntu/Windows on every push and PR.
Credits
The multi-source credential chain (KIMI_CODING_API_KEY → KIMI_API_KEY → Kimi CLI config) and the http(s)-only/size-cap hardening originate from quei4r/dsh-host-kimi-search — this package extends that idea to the fetch seam, a settings card, a test suite, and npm distribution. Card architecture follows the verified settings.section/credential-reference conventions of the sibling DSH search plugins.
No comments yet. Be the first to write one.