Repository navigation
feat(catalog): add kimi-k2.7-code to kmca catalog + qwen-web models discovery - #4185
Conversation
…iscovery (#3931 bug 3, #3737) Task 1 — add moonshotai/kimi-k2.7-code to KIMI_CODING_SHARED.models (shared.ts), propagates to both kimi-coding and kimi-coding-apikey (kmca) providers. Requested by @hana189 in discussion #3737. Task 2 — add qwen-web entry to PROVIDER_MODELS_CONFIG in models/route.ts pointing at chat.qwen.ai/api/v2/models (public, no auth). Fixes #3931 bug 3 (identified by @thezukiru in discussion #3895): the provider models page for the web-cookie provider returned nothing because no discovery config was registered. parseResponse handles both nested data.data and flat data array shapes. Closes #3931 (bug 3). Discussion reply pending.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Code Review
This pull request adds the moonshotai/kimi-k2.7-code model to the Kimi coding provider catalog and introduces a new qwen-web provider configuration to enable model discovery, accompanied by regression unit tests. The review feedback highlights a potential runtime crash in the qwen-web response parser if the upstream API returns an object instead of an array, and notes a testing anti-pattern where the parser logic is duplicated in the unit tests rather than importing the production implementation directly.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| parseResponse: (data: any) => { | ||
| const innerData = data?.data?.data || data?.data || []; | ||
| return innerData | ||
| .map((item: any) => ({ | ||
| id: item.id || item.name, | ||
| name: item.name || item.id, | ||
| owned_by: item.owned_by || "qwen", | ||
| })) | ||
| .filter((m: any) => m.id); | ||
| }, |
There was a problem hiding this comment.
If the upstream API returns an object instead of an array (for example, an error response like { data: { message: "Unauthorized" } }), data?.data will be an object. In this case, innerData will evaluate to that object rather than falling back to [], causing innerData.map to throw a TypeError: innerData.map is not a function at runtime.
Additionally, using optional chaining (item?.id, etc.) inside the .map callback prevents potential crashes if any element in the array is null or undefined.
To ensure robust and defensive programming, we should explicitly verify that the resolved data is an array before attempting to map over it.
parseResponse: (data: any) => {
const rawData = data?.data?.data || data?.data;
const innerData = Array.isArray(rawData) ? rawData : [];
return innerData
.map((item: any) => ({
id: item?.id || item?.name,
name: item?.name || item?.id,
owned_by: item?.owned_by || "qwen",
}))
.filter((m: any) => m?.id);
},| // parseResponse logic matches PROVIDER_MODELS_CONFIG["qwen-web"].parseResponse | ||
| const innerData: Array<Record<string, unknown>> = | ||
| (mockResponse?.data?.data as Array<Record<string, unknown>>) || | ||
| (mockResponse?.data as unknown as Array<Record<string, unknown>>) || | ||
| []; | ||
| const models = innerData | ||
| .map((item) => ({ | ||
| id: (item.id || item.name) as string, | ||
| name: (item.name || item.id) as string, | ||
| owned_by: (item.owned_by || "qwen") as string, | ||
| })) | ||
| .filter((m) => m.id); |
There was a problem hiding this comment.
This test copy-pastes the parsing logic from route.ts instead of importing and testing the actual production implementation. This creates a testing anti-pattern where the test will continue to pass even if the production implementation in route.ts is broken or modified.
To fix this, consider exporting PROVIDER_MODELS_CONFIG (or a specific helper) from src/app/api/providers/[id]/models/route.ts and importing it here to run the assertions directly against the production code.
# Conflicts: # config/quality/file-size-baseline.json # open-sse/config/providers/shared.ts # src/app/api/providers/[id]/models/route.ts
…iscovery (diegosouzapw#3931 bug 3, diegosouzapw#3737) (diegosouzapw#4185) Integrated into release/v3.8.29 — add moonshotai/kimi-k2.7-code to the kmca (kimi-coding-apikey) catalog (KIMI_CODING_SHARED.models), requested in discussion diegosouzapw#3737. On resync: the PR's qwen-web PROVIDER_MODELS_CONFIG addition (issue diegosouzapw#3931 bug diegosouzapw#3) was already shipped by diegosouzapw#4172 — dropped the duplicate, kept release's entry (which has the Array.isArray guard); kept diegosouzapw#4183's KIMI_K27_MODELS spread + added the moonshotai-prefixed entry (union). Also reconciled the file-size baseline for openai-to-gemini.ts (diegosouzapw#4180 merged without its +20 bump). Validated: 13/13 tests (kmca catalog + qwen-web parse + kimi registration) + file-size green.
Summary
moonshotai/kimi-k2.7-codetoKIMI_CODING_SHARED.modelsinopen-sse/config/providers/shared.ts. Propagates automatically to bothkimi-coding(OAuth) andkimi-coding-apikey(kmca) providers. Requested by @hana189.qwen-webentry toPROVIDER_MODELS_CONFIGinsrc/app/api/providers/[id]/models/route.tspointing athttps://chat.qwen.ai/api/v2/models(public endpoint, no auth required). Fixes the provider models page returning nothing for the web-cookie provider. Identified by @thezukiru. TheparseResponsehandles both nesteddata.dataand flatdataarray shapes.Note: Bug #1 of #3931 (validation false-positive) was already fixed by PR #3958 (merged 2026-06-16). Bug #2 (WAF streaming) requires a live Qwen session with valid cookies and is deferred.
Test plan
tests/unit/catalog-updates-v3829-kimi-qwen.test.ts— 5 RED → GREEN (7/7 pass)moonshotai/kimi-k2.7-codewith correct context/output lengthsqwen-webkey present inPROVIDER_MODELS_CONFIG(structural assertion)qwen-webURL targetschat.qwen.ai/api/v2/modelsparseResponsehandles nesteddata.dataand flatdatafallback (pure logic tests)npm run test:unit— 1436 passes, 0 failuresnpm run lint— exit 0npm run typecheck:core— cleannpm run check:file-size— OK (route.ts 2512 → 2527, baseline updated)