Repository navigation
feat(provider): add cheapaimodel - #2476
Conversation
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Provider configuration and tests src/main/provider/defaults.ts, src/main/provider/providerRegistry.ts, test/main/provider/basicApiKeyProviders.test.ts, test/main/provider/defaultProviders.test.ts |
The provider defaults and registry add cheapaimodel as an OpenAI-compatible provider with API-key credentials and embedding support disabled. Tests check the provider definition and default configuration. |
Provider icon and README entries src/renderer/src/components/icons/modelIconRegistry.ts, README.md, README.jp.md, README.zh.md |
The icon registry maps cheapaimodel to its icon. The README files add a cheapaimodel provider entry. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Feature
Suggested reviewers: zerob13
Merge Risk: 
Minimal · up to 24899
-
The cheapaimodel provider addition is consistent across configuration, runtime registration, icon assets, and localized documentation.
Pre-merge checks: 
5
-
Full details: Docstring Coverage
-
Explanation
No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 5 files. (3 skipped: 3 unsupported.)
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
zerob13
left a comment
There was a problem hiding this comment.
Verdict: approve
This adds cheapaimodel as a disabled, OpenAI-compatible built-in provider. The change is registration only: one DEFAULT_PROVIDERS entry, one PROVIDER_ID_REGISTRY entry, an icon, three README cells and two tests. There is no new provider class and no change to shared provider behavior. The entry ships with enable: false, so nothing changes for current users until someone turns it on. No breaking change.
What I checked
- Shape: the same as AtmoRouter (#2464).
OPENAI_BASEpluscredentialStrategy: 'api-key'andembeddingStrategy: 'none'resolves toopenai-compatible/modelSource: 'openai'/checkStrategy: 'fetch-models', which is what the new test asserts. - The connection check really validates a key.
GET https://api.cheapaimodel.ai/v1/modelsreturns 401 without a key today, sofetch-modelscannot pass with a wrong key. This is the difference from apimodels.app (#2454), where the model list was public and a bad key still passed. - Icon: a 336-byte static SVG with no script. It is registered in
modelIconsand deliberately left out ofmonoIconUrls, the same asatmorouter.svg, which also has its own dark background. Dark-mode inversion is skipped, which is what you want here. - Links:
cheapaimodel.ai,console.cheapaimodel.ai/keys,/docsand/modelsall return 200. - Tests:
test/main/provider/defaultProviders.test.tsandbasicApiKeyProviders.test.ts→ 85 passed locally.oxfmt --check,oxlintandicons:checkare clean on the changed files. - CI: both workflow runs were waiting for first-time-contributor approval; I approved them. PR Check and Package Check are now green at
24899ba9.
Minor notes, not blocking
modelSource: 'openai'lists every id the gateway returns. Today that is five chat models, so nothing is mislabeled. If cheapaimodel later publishes image, audio or embedding ids, they will show up in the picker as chat models — the failure mode reported in #2454. A chat-only filter can wait until the catalog actually contains those.- The README provider table's last row now has seven cells while the earlier rows have four or five. It renders, but that row is wider than the rest. Optional cleanup.
- Capability flags (reasoning, tools, vision) resolve through the global model-id fallback in
src/main/provider/modelCapabilities.ts(getModelMatch→findModelAcrossProvidersMatch), becausecheapaimodelhas no entry inresources/model-db/providers.json. All five ids in your live test already exist there under other providers, so the flags come from those entries. AtmoRouter works the same way. Nothing to change; this is only why the provider behaves correctly without a catalog entry.
Sources
- Reviewed commit:
24899ba998998acdd78dd383cde48805e1de1a54 - Provider defaults:
src/main/provider/defaults.ts:682 - Registry:
src/main/provider/providerRegistry.ts:336 - Model URL and default catalog mapping:
src/main/provider/providers/aiSdkProvider.ts:756-769,1080-1105 - Capability fallback:
src/main/provider/modelCapabilities.ts:529-590
Adds cheapaimodel as a built-in, disabled-by-default OpenAI-compatible provider. cheapaimodel (https://cheapaimodel.ai) is a pay-per-token API gateway for open-weight models (DeepSeek, GLM, Kimi) plus Grok, at
https://api.cheapaimodel.ai/v1(POST /chat/completions,GET /models). I work on cheapaimodel.It needs no special provider class. The registry entry is
OPENAI_BASEwithcredentialStrategy: 'api-key'andembeddingStrategy: 'none', so it resolves to the existingopenai-compatibleruntime withmodelSource: 'openai'andcheckStrategy: 'fetch-models', the same shape as AtmoRouter (#2464).GET /v1/modelsrequires the API key, whichfetch-modelssends.Files changed
src/main/provider/defaults.tsDEFAULT_PROVIDERSentry (enable: false), after CloudGPUsrc/main/provider/providerRegistry.tsPROVIDER_ID_REGISTRYdefinitionsrc/renderer/src/assets/llm-icons/cheapaimodel.svgsrc/renderer/src/components/icons/modelIconRegistry.tsmodelIconskeyREADME.md,README.zh.md,README.jp.mdtest/main/provider/defaultProviders.test.tstest/main/provider/basicApiKeyProviders.test.tsInsertions only.
resources/model-db/providers.jsonis not touched, because the provider uses live/modelsdiscovery.Website links point at browsable pages; all four returned 200 on 2026-10-28:
officialhttps://cheapaimodel.ai/?utm_source=deepchatapiKeyhttps://console.cheapaimodel.ai/keys?utm_source=deepchatdocshttps://cheapaimodel.ai/docs?utm_source=deepchatmodelshttps://cheapaimodel.ai/models?utm_source=deepchatTesting
Run locally (macOS, pnpm 10.34.5, dependencies installed with
--frozen-lockfile --ignore-scripts):pnpm vitest run --config vitest.config.ts test/main/providerpnpm vitest run --config vitest.config.renderer.ts test/renderer/components/ModelIcon.test.tspnpm run format:checkpnpm run lintpnpm run typecheck:node/typecheck:webpnpm run i18npnpm run icons:checkNot run:
pnpm run devandpnpm run build(no Electron binary with--ignore-scripts).Live test
Run on 2026-10-28 (UTC) against
https://api.cheapaimodel.ai/v1with a real cheapaimodel key. The key is not included in this PR or its logs.Through DeepChat's own provider code: a temporary vitest file, not committed, built
AiSdkProviderfrom the newDEFAULT_PROVIDERSentry, with the same Electron, logger, proxy and providerDbLoader mocks asbasicApiKeyProviders.test.ts, but with the AI SDK not mocked, so the calls went over the network.check()(thefetch-modelsstrategy) returnedisOk: truein 1.40s. With a fake key it returnedisOk: falsewithInvalid token.fetchModels()returned all 5 models in 0.87s, mapped withproviderId: 'cheapaimodel'.Prompt
Reply with exactly: pong, temperature 0.2 (1 forkimi-k3, see below), max tokens 256:completions()coreStream()(total / first text)deepseek-v4-1-flashpongglm-5.3pongglm-5.3-flashpongkimi-k3ponggrok-4.7pongkimi-k3only accepts its own sampling values (temperature 0.6 or 1; 0.2 returns a 400), the same rule as on Moonshot's API, so users need to set its temperature in the model settings.Summary by CodeRabbit