Skip to content

feat(web): add Moonshot and Kimi native search - #5686

Closed
h3c-hexin wants to merge 2 commits into
Hmbown:mainfrom
Pinvou:feat/moonshot-kimi-provider-native-search
Closed

feat(web): add Moonshot and Kimi native search#5686
h3c-hexin wants to merge 2 commits into
Hmbown:mainfrom
Pinvou:feat/moonshot-kimi-provider-native-search

Conversation

@h3c-hexin

@h3c-hexin h3c-hexin commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add native web search for exact Moonshot/Kimi product routes: K3 Formula tools/fibers, legacy K2.6 $web_search, and Kimi Code membership /search.
  • Bound provider-controlled execution to four rounds and eight total tool calls, reject unexpected tools, and recover citations only from structured results or final answer URLs.
  • Accept both exact Moonshot international and China direct endpoints while keeping adjacent paths, K2.7 direct models, and cross-product model IDs fail-closed.

Refs #5681 (partial).

No-Issue: partial delivery tracked by #5681; this slice must not close the umbrella issue.
Depends on #5682 for the exact K3 180-second native-stage budget and independent configured/local fallback timeout.

Testing

  • cargo fmt --all -- --check
  • cargo test -p codewhale-config moonshot_native_search_requires_exact_product_model_pair -- --nocapture
  • cargo test -p codewhale-config moonshot_route_fact_is_exact_to_product_and_model -- --nocapture
  • cargo test -p codewhale-tui client::provider_native_search::kimi::tests -- --nocapture — 4 passed
  • cargo test -p codewhale-tui client::provider_native_search::tests -- --nocapture — 7 passed
  • cargo check -p codewhale-config -p codewhale-tui
  • git diff --check

The K3 HTTP mock covers authenticated tool discovery, a chat tool call with max_completion_tokens: 4096, fiber execution, encrypted-result replay, and final citation extraction.

Safety boundary

  • Formula and built-in loops accept only the documented search function name.
  • Total provider tool calls are capped across rounds, not per round.
  • Domain-constrained requests use the configured/local fallback because these provider contracts do not expose a proven server-side domain filter.
  • The exact Kimi Code endpoint constant is shared with existing route configuration; neighboring coding paths do not match.

Honesty boundary

This exact upstream commit was verified with deterministic mocks, not a new funded live Moonshot request. The earlier downstream implementation completed a live Kimi Code provider-native search, but that is not presented as verification of this commit or of K3 Formula. No credentials, release, tag, deployment, or publication action is part of this PR.

Signed-off-by: hexin <372726039@qq.com>
Signed-off-by: hexin <372726039@qq.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 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-08-29T02:58:54.488799Z abb9978 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.

@Hmbown

Hmbown commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Rebased this PR onto current main (dde9cdb) and resolved all conflicts preserving both intents:

  • capabilities.rs / resolver.rs: kept main's Xiaomi MiMo / Z.AI / ModelStudio Token Plan / DeepSeek native-search facts and added this PR's Moonshot/Kimi facts (both documented_zai_web_search_for_route and documented_moonshot_web_search_for_route; provider lists are the union).
  • provider_native_search.rs: kept main's single-shot body/url/parse dispatch for its providers and added this PR's Moonshot early-return to kimi::search, plus the PR's post_json/get_json helpers the kimi module needs. Main's ResponsesSearchDialect superset (ModelStudio, Deepseek) is kept.
  • route/tests.rs / CHANGELOG.md: kept main's mimo/zai/qwen tests and entries and this PR's moonshot test and entry.

Verification on the rebased head: cargo fmt --check clean; cargo clippy -p codewhale-config -p codewhale-tui --all-targets --all-features --locked with CI's exact allowlist clean; cargo test -p codewhale-config route:: 77 passed; cargo test -p codewhale-tui --lib provider_native_search 22 passed (incl. kimi tests); cargo test -p codewhale-config moonshot 11 passed.

Rebased head (original authors and Signed-off-by preserved): 5523f8d0f67fb18258586b21205a7a9d9dc47d0f, also pushed to origin as feat/moonshot-kimi-provider-native-search.

Blocker for updating this PR's head: the branch lives in the Pinvou fork and the Hmbown/hunterbown credentials on this machine have push:false there (git push 403, Git Data API 404), so the fork branch could not be force-updated from here. The PR is now marked ready for review. Founder action needed: force-push 5523f8d0f to Pinvou/CodeWhale:feat/moonshot-kimi-provider-native-search (fetchable from Hmbown/CodeWhale at the same branch name), or re-point/reopen this PR against the origin branch. No-Issue: partial delivery tracked by #5681; this slice must not close the umbrella issue.

@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: abb9978056

ℹ️ 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".

matches!(
inner.api_provider,
ApiProvider::Openai | ApiProvider::Anthropic | ApiProvider::Xai
ApiProvider::Openai | ApiProvider::Anthropic | ApiProvider::Xai | ApiProvider::Moonshot

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route Moonshot domain filters to the configured fallback

When web_search includes any domains on a newly enabled Moonshot/Kimi route, this provider falls through maximum_domain_count() to Some(0); ProviderNativeSearchBackend::search converts that into InvalidInput, and run_backend_chain treats that error as fail-closed, so the configured or DuckDuckGo fallback is never attempted. Every domain-constrained search on these routes therefore fails instead of preserving the constraint through fallback.

Useful? React with 👍 / 👎.

Comment on lines +41 to +45
fn is_kimi_code_route(base_url: &str) -> bool {
base_url
.trim()
.trim_end_matches('/')
.eq_ignore_ascii_case(DEFAULT_KIMI_CODE_BASE_URL)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reuse the path-sensitive Kimi Code route classifier

When a configured endpoint differs only in path casing, such as https://api.kimi.com/Coding/v1, this case-insensitive comparison classifies it as the official membership route and sends /search to that neighboring path. URL paths are case-sensitive, and the existing codewhale_config::provider::is_exact_kimi_code_route deliberately accepts case-insensitive scheme/host but requires the exact coding/v1 path; reuse that predicate here and in capability resolution so custom paths remain fail-closed.

AGENTS.md reference: AGENTS.md:L11-L14

Useful? React with 👍 / 👎.

Comment on lines +33 to +35
.eq_ignore_ascii_case(MOONSHOT_KIMI_K3_MODEL)
{
search_formula(client, request).await

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 Reserve the K3 Formula stage's provider timeout

When the new kimi-k3 route takes the Formula path, its discovery/chat/fiber sequence runs under the generic search-chain slice: web_search defaults to 15 seconds, caps callers at 60 seconds, and run_backend_chain divides that time among all configured fallbacks. Thus K3 normally receives only about 5 seconds and can never receive its required 180-second native-stage budget, so otherwise valid Formula searches are cancelled before completion; reserve the provider stage independently and leave the caller-requested timeout available for configured/local fallback.

Useful? React with 👍 / 👎.

Comment on lines +434 to +440
let end = tail
.char_indices()
.find_map(|(index, ch)| {
(index > 0
&& (ch.is_whitespace()
|| matches!(ch, ')' | ']' | '}' | '>' | '"' | '\'' | '`')))
.then_some(index)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve balanced parentheses in extracted citation URLs

When a K2.6 or K3 final answer cites a valid URL containing parentheses, such as https://en.wikipedia.org/wiki/Foo_(bar), this scanner treats the first ) as an unconditional delimiter and records https://en.wikipedia.org/wiki/Foo_(bar instead. The malformed-but-still-parseable URL survives citation registration and is returned to the user as a broken source, so extraction needs to distinguish balanced URL parentheses from the closing delimiter of a Markdown link.

Useful? React with 👍 / 👎.

Hmbown pushed a commit that referenced this pull request Aug 29, 2026
The contribution gate leaves an unlisted contributor's workflow runs at
`action_required`, so their CI never starts and the PR sits looking stalled
through no fault of theirs. whp233's #5714 and #5716 had SEVEN workflows each
parked that way; I approved those runs by hand, but the allowlist is the actual
fix.

Added (all five have landed or open work):
  whp233    open PRs #5714, #5716 — the runs that were parked
  musichen  merged #5689 (DeepSeek configured-view picker)
  M-Maciej  merged #5591 (goal continuation cadence)
  serephus  merged #5669 (nixpkgs update)
  Pinvou    fork owner behind #5686 (Moonshot/Kimi native search)

Entries use `all:` to match the existing convention for active contributors.

No-Issue: contribution-gate hygiene; no issue tracks it
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Hmbown pushed a commit that referenced this pull request Aug 29, 2026
Every rule here is something that actually went wrong on the 2026-08-29 night
shift, written down so the next agent does not rediscover it.

Landing other people's work:
- A contributor's branch goes stale because WE land things. #5686 was
  CONFLICTING purely from Route Contract Phase 1 plus that same contributor's
  own earlier PRs merging into the same files. A maintainer resolves that.
- Conflicts that split mid-function do not resolve by keeping both sides — the
  markers landed inside two function bodies and the naive resolution failed to
  compile with 'unclosed delimiter'. Take one side whole, re-insert the other's
  additions at their anchor.
- maintainerCanModify did not grant push access to the fork (403), so the
  resolved merge went to integration/moonshot-kimi-5686-20260829 instead. That
  integration-branch path is now the documented default for conflicted work.
- whp233's #5714 and #5716 each had SEVEN workflows parked at action_required
  because the author was not on .github/APPROVED_CONTRIBUTORS. The PRs looked
  stalled; nobody had looked. Five contributors have since been added.
- Credit is mechanical: AUTHOR_MAP and .mailmap are project conventions and
  GitHub reads neither for the contribution graph.

Merging under a gate:
- #5698 merged while ACCEPTANCE_MATRIX.md still said FAIL and 37 minutes after
  a review confirming five findings were unchanged. Five real bugs reached
  main. A gate is its artifact, and check rollups are not the review thread.

Claiming a test passed:
- cargo test with a non-matching filter exits 0 having run ZERO tests; that was
  briefly mistaken for a pass here.
- A harness scored 72 PASS of which 12 were never evaluated: 'ok = ok and X or
  True' parses as '(ok and X) or True'.

CLAUDE.md already imports this file, so no second entrypoint was created.

No-Issue: process documentation from the night shift
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
@Hmbown Hmbown closed this in #5720 Aug 30, 2026
Hmbown added a commit that referenced this pull request Aug 30, 2026
feat(web): Moonshot and Kimi native search (rescue of #5686, review findings fixed)
pull Bot pushed a commit to Stars1233/DeepSeek-TUI that referenced this pull request Aug 30, 2026
… native search

Rescue merge of abb9978 (Pinvou feat/moonshot-kimi-provider-native-search,
PR Hmbown#5686) onto current main (142 ahead). Contributor head preserved verbatim
as the second parent; conflicts resolved following the landed native-search
adapter pattern (Hmbown#5682/Hmbown#5683/Hmbown#5690/Hmbown#5691/Hmbown#5693): main's Mimo/Zai/ModelStudio/
DeepSeek adapters and the post-fallback domain-constraint/budget plumbing
stay, the Kimi module + Moonshot dispatch and capability wiring join them.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
pull Bot pushed a commit to Stars1233/DeepSeek-TUI that referenced this pull request Aug 30, 2026
…losed

Moonshot/Kimi (and the other contracts without a domain filter field) report
maximum_domain_count() == Some(0), so a domain-filtered query hit the shared
InvalidInput branch and killed the whole backend chain instead of reaching
the configured provider or DuckDuckGo. Decline with NotAvailable for that
case so the chain falls back; keep InvalidInput for genuinely over-limit
counts on providers that do honor domains (Hmbown#5686 review).

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
pull Bot pushed a commit to Stars1233/DeepSeek-TUI that referenced this pull request Aug 30, 2026
The local case-insensitive whole-URL comparison let differently-cased paths
(https://API.KIMI.COM/CODING/V1) inherit the official membership /search
service. Reuse config's exact matcher (scheme/authority case-insensitive,
path exact) for both the kimi.rs dispatch and the capability gate, matching
the is_exact_kimi_code_route discipline everywhere else (Hmbown#5686 review).

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
pull Bot pushed a commit to Stars1233/DeepSeek-TUI that referenced this pull request Aug 30, 2026
Wikipedia-style URLs such as .../wiki/Foo_(bar) lost their balanced closing
paren to the terminator scan. Track paren depth while scanning so balanced
pairs stay part of the URL and an unmatched closer still ends it (Hmbown#5686
review).

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
@Hmbown

Hmbown commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Merged — thank you @h3c-hexin. Your Moonshot/Kimi native search landed on main today through #5720, merge commit e1a8fb8db00241caad34587ac606333c772f0646.

Your two commits are in main's history exactly as you wrote them, with your authorship intact:

  • 2258bf3cf7 feat(web): add Moonshot and Kimi native search
  • abb997805 chore(changelog): 同步 Web 搜索变更记录

On top of them #5720 resolved the conflict with current main (additive — main's adapter roster plus your Moonshot/Kimi modules) and fixed three review findings: domain-filtered queries on zero-domain providers now decline with NotAvailable so the chain falls back instead of erroring, Kimi Code dispatch uses the exact route matcher so https://API.KIMI.COM/CODING/V1 no longer misroutes, and citations_from_text tracks paren depth so wiki/Foo_(bar) extracts intact. Focused native search was 24/24 on the final tree.

With this slice the #5681 umbrella is complete. Much appreciated — the K3 Formula tool/fiber mock in particular made this straightforward to verify.

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