Skip to content

feat(web-search): add Kimi search with shared chat credentials (opt-in) - #1911

Merged
wyuc merged 4 commits into
mainfrom
feat/kimi-web-search
Oct 16, 2026
Merged

wyuc merged 4 commits into
mainfrom
feat/kimi-web-search

Conversation

@wyuc

@wyuc wyuc commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add Kimi web search using the existing Kimi chat account's API key and base URL, with explicit opt-in. This AI-assisted PR implements the web-search portion of #1909.

Moonshot Open Platform accounts use /tools/search_pro and combine page chunks, falling back to snippets. Coding Plan accounts use /search, enable page crawling, and prefer page content over snippets. The adapter uses Bearer authentication, a 30-second server timeout, the shared 400-character query limit, at most 20 results enforced locally for both endpoints, and proxy-aware fetch with caller cancellation.

Configuration and review corrections

  • Opt-in: A Kimi chat key alone creates no legacy search entry, search default, or operator-preferred backend. Existing SearXNG/Tavily defaults and user Tavily requests remain intact. Explicitly assign webSearch in openmaic.yml or workspace settings, add web-search.kimi in server-providers.yml, or set WEB_SEARCH_KIMI_ENABLED=true to opt into legacy search with shared credentials.
  • Disable switch and model pins: WEB_SEARCH_KIMI_ENABLED=false force-disables search. WEB_SEARCH_KIMI_ENABLED is the only Kimi search switch. KIMI_MODELS remains chat-only.
  • Shared accounts: Legacy search entries cannot overwrite chat credentials, endpoint, or model pins. Conflicting accounts produce a warning and are skipped during translation/default assignment. Separate accounts must use separate provider ids in openmaic.yml.
  • Wizard: It checks the same official account-base list used by server search validation and does not recommend search for a custom workspace chat proxy, even if a view offers search capability.
  • Documentation: Restore the existing localized Coding Plan names, append localized search capability names, translate the new supported-provider sections in five non-English locales, and restore Arabic list separators. Configuration additions remain English to match their surrounding sections.
  • File-backed configuration: When openmaic.yml exists without a webSearch assignment, a loaded legacy Kimi search opt-in produces a specific one-time startup warning telling the operator to declare the provider and assign slots.webSearch. The docs include this requirement in every maintained locale.
  • Proxy paths: After removing trailing slashes, a base path ending in /coding/v1 selects /search; otherwise the adapter selects /tools/search_pro. Deployment-configured proxies must preserve this path layout.

Opting in on a deployment with no other search provider makes Kimi the default search provider for all workspaces.

The existing switch dispatch remains. Existing search defaults retain precedence after Kimi opt-in; webFetch and published packages are unchanged. Existing Kimi labels and logo are reused across settings; the 12 settings locales already contain the label.

Verification

All commands run with Node 22.22.0 and the required environment cleanup. Dependencies were installed with pnpm install; standalone render-service test dependencies remain installed from CI's PUPPETEER_SKIP_DOWNLOAD=true npm ci step.

Command Result
pnpm check Passed
pnpm lint Passed; 0 errors, 18 warnings in unrelated files
pnpm exec tsc --noEmit Passed
pnpm check:i18n-keys Passed; 12 locales
pnpm exec vitest run tests/web-search tests/config tests/model-settings tests/server tests/providers 2,116 tests passed, 141 skipped; 155 files passed, 7 skipped
pnpm test 11,234 tests passed, 243 skipped; 929 files passed, 29 skipped
pnpm build Passed; Edge Runtime and middleware warnings

Regression coverage includes both API contracts and result mapping; query/result limits, including 19 returned results for a request limited to 3 on both endpoints; malformed/HTTP errors and cancellation; chat-only Kimi; Kimi plus SearXNG/Tavily; user Tavily requests under operator preference; explicit env/YAML opt-in; no activation without credentials; the dedicated search switch; opted-in Kimi preserving existing SearXNG/Brave/Doubao defaults while remaining assignable; chat pins; conflicting legacy accounts; wizard official/proxy bases; and the ignored file-backed opt-in warning, its once-only logging, and absence for assigned/disabled slots or inactive opt-ins.

Self-review checked opt-in activation and both default-selection paths, account collision handling, credential/base-URL precedence, endpoint validation, locale consistency, and scope. All local automated Kimi requests are mocked; this implementation run made no live authenticated calls. No open design questions remain for this scope.

Maintainer live verification

Open Platform search was verified end-to-end by a maintainer with a real key against api.moonshot.cn: two full course generations used current search results in their outlines, and page chunks provided substantial body content. The maintainer also verified the legacy regressions: a chat key alone leaves search disabled; explicit opt-in with no other search provider makes Kimi the default; an existing Tavily provider keeps precedence. With openmaic.yml, declaring the Kimi provider and assigning slots.webSearch enabled search.

Coding Plan /search response fields were verified with a real key: content, date, icon, mime, site_name, snippet, title, and url. The endpoint ignored limit: 3 and returned 19 results; the adapter therefore enforces the requested result cap locally. This verifies the Coding Plan response contract, rather than a full Coding Plan course-generation run.

International Open Platform search Pro availability remains unverified.

Related #1909

@CXuPercy

Copy link
Copy Markdown
Collaborator

Live-tested with a real Moonshot Open Platform key (api.moonshot.cn).

API contract: /tools/search_pro responses match the adapter's mapping exactly; search_results[].chunks[].text joins into substantial body content (6k+ chars for a single result).

End-to-end (two runs, both full course generations):

  • Topic "2026 年 Kimi K3 大模型的最新进展与能力评测" (agent-driven test): search returned 10 highly relevant sources (Xinhua, TMTPost, Tencent Cloud, CSDN, …); the outline contained facts that only exist in that week's search results (release date, WAIC context, 2.8T parameters), and one scene title came verbatim from the TMTPost review's headline.
  • Topic "我想通过一节课学习2026的诺贝尔奖的相关情况" (manual test): all 10 returned sources were published within the past few days (People's Daily Online / Xinhua: the three Physiology-or-Medicine laureates, Physics laureate Francis Halzen, …); the generated outline accurately stated the 2026 winners and dates (manually cross-checked).

Legacy regressions: KIMI_API_KEY alone (switch off) → 0 search providers loaded, search stays disabled; WEB_SEARCH_KIMI_ENABLED=true with no other search provider → Kimi becomes the default; with a Tavily key already present, the default remains Tavily.

One configuration-interplay observation (repro included), as a supplement: with an openmaic.yml present that assigns no webSearch slot, setting KIMI_API_KEY + WEB_SEARCH_KIMI_ENABLED=true does load 1 WebSearch provider server-side, yet GET /api/generate-classroom/capabilities still returns webSearch: false and course generation skips search; the only log line is the generic "openmaic.yml is present, so slot resolution uses it and not the legacy provider variables" warning — nothing Kimi-specific. Adding providers.kimi (preset: kimi) + slots.webSearch: kimi fixes it. Per the PR description this is by design; sharing it here as a supplement.

@wyuc

wyuc commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough live test.

  • The openmaic.yml interplay is now explicit: when openmaic.yml is present and no webSearch slot is assigned, setting WEB_SEARCH_KIMI_ENABLED=true logs a one-time warning that names the fix (declare a kimi provider and assign slots.webSearch). The docs say the same in all locales (bdd8d90).
  • Coding Plan: I checked POST https://api.kimi.com/coding/v1/search with a real Coding Plan key. The response fields match the adapter (search_results[].content, snippet, title, url, …), but the endpoint ignores limit (it returned 19 results when asked for 3). Both endpoints now truncate to the requested count, and there are tests for it.

@wyuc wyuc closed this Oct 14, 2026
@wyuc wyuc reopened this Oct 14, 2026
@wyuc
wyuc force-pushed the feat/kimi-web-search branch from bdd8d90 to daf7e3e Compare October 14, 2026 09:47
@wyuc
wyuc force-pushed the feat/kimi-web-search branch from daf7e3e to 522d59d Compare October 16, 2026 06:16
@wyuc
wyuc marked this pull request as ready for review October 16, 2026 06:16
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T06:21:57.596039Z 522d59d Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 522d59da48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +194 to +198
if (
slot.capability === 'webSearch' &&
!isOfficialWebSearchBaseUrl(offered.registryId ?? model, provider.baseUrl)
)
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve search for official Kimi alternate URLs

When a workspace user selects an official non-default Kimi endpoint such as https://api.moonshot.ai/v1, modelSettingsView classifies every stored chat baseUrl as custom and exposes that provider as chat-only, so offered is already undefined before this allowlist check runs. Consequently the wizard does not assign web search; if an existing assignment survives, resolve-slot.ts marks the URL as customBaseUrl and media.ts rejects the search at runtime. The official Kimi URLs need to be recognized in the model-settings capability and resolution path, not only here.

Useful? React with 👍 / 👎.

@wyuc
wyuc merged commit 941f688 into main Oct 16, 2026
12 of 13 checks passed
@wyuc
wyuc deleted the feat/kimi-web-search branch October 16, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants