Add Novita AI provider
Problem
Novita AI (an OpenAI-compatible LLM provider, https://novita.ai/model-api/product/llm-api) is not yet available as a supported provider. Users who want to use Novita's models (e.g. moonshotai/kimi-k2.7-code) currently have no way to configure it in the extension, CLI, or webview settings.
Context
This reimplements the provider-add portion of PR #697 (closed), which bundled this work with an unrelated shared AI-SDK streaming rework. This PR should be rebased on top of the shared-streaming-fix PR (sub-issue: AI-SDK tool-call streaming/error-handling gaps) so NovitaHandler inherits the fixed base-class behavior rather than reintroducing the same gaps.
Desired behavior
- Novita AI is registered as a provider across:
packages/types (model registry, provider schema, secret-key list), src/api/providers (API handler extending OpenAICompatibleHandler), src/shared/ProfileValidator, the CLI (apps/cli: --provider novita, NOVITA_API_KEY env var), the webview settings UI (base URL + API key fields, masked as password), and translated locale strings.
- e2e coverage exercises a real tool-using task through the Novita provider, including error/failure-mode paths (not just the happy path).
- Documentation (
apps/cli/README.md, apps/vscode-e2e/AGENTS.md) reflects Novita as an explicit alternative to the default provider, not as if it were the default.
Constraints / preferences
- Do not reintroduce the issues fixed upstream: missing
supportsTemperature on model definitions, completePrompt ignoring defaultTemperature, or an e2e completion assertion that's conditionally skipped rather than asserting the exact expected value.
novitaBaseUrl should have at least .url() format validation (consistent with what was previously added), documented as an accepted-risk pattern shared with other free-form-endpoint providers (openai/deepseek/poe) rather than a stricter closed-enum (which only applies to fixed-region single-vendor APIs like Moonshot/MiniMax).
- Avoid unused exports (e.g., a
NovitaModelId/*DefaultModelInfo pattern is fine if it matches sibling-provider convention, but shouldn't add new zero-consumer exports beyond that convention).
- AGENTS.md should explain why the e2e mock base URL suffix (
/v1) differs from the real API suffix (/openai), not just state that they differ.
Acceptance criteria
Given a user configures novitaApiKey and selects a Novita model
When they send a message
Then the request is sent to Novita's OpenAI-compatible endpoint and a response streams back correctly, including tool-call handling
Given the e2e suite runs in mock mode
When the Novita test suite executes
Then it asserts the exact expected completion text unconditionally (or an explicitly-justified, narrowly-scoped exception), not a conditionally-skipped check
Request checklist
Related
Add Novita AI provider
Problem
Novita AI (an OpenAI-compatible LLM provider, https://novita.ai/model-api/product/llm-api) is not yet available as a supported provider. Users who want to use Novita's models (e.g.
moonshotai/kimi-k2.7-code) currently have no way to configure it in the extension, CLI, or webview settings.Context
This reimplements the provider-add portion of PR #697 (closed), which bundled this work with an unrelated shared AI-SDK streaming rework. This PR should be rebased on top of the shared-streaming-fix PR (sub-issue: AI-SDK tool-call streaming/error-handling gaps) so
NovitaHandlerinherits the fixed base-class behavior rather than reintroducing the same gaps.Desired behavior
packages/types(model registry, provider schema, secret-key list),src/api/providers(API handler extendingOpenAICompatibleHandler),src/shared/ProfileValidator, the CLI (apps/cli:--provider novita,NOVITA_API_KEYenv var), the webview settings UI (base URL + API key fields, masked as password), and translated locale strings.apps/cli/README.md,apps/vscode-e2e/AGENTS.md) reflects Novita as an explicit alternative to the default provider, not as if it were the default.Constraints / preferences
supportsTemperatureon model definitions,completePromptignoringdefaultTemperature, or an e2e completion assertion that's conditionally skipped rather than asserting the exact expected value.novitaBaseUrlshould have at least.url()format validation (consistent with what was previously added), documented as an accepted-risk pattern shared with other free-form-endpoint providers (openai/deepseek/poe) rather than a stricter closed-enum (which only applies to fixed-region single-vendor APIs like Moonshot/MiniMax).NovitaModelId/*DefaultModelInfopattern is fine if it matches sibling-provider convention, but shouldn't add new zero-consumer exports beyond that convention)./v1) differs from the real API suffix (/openai), not just state that they differ.Acceptance criteria
Given a user configures
novitaApiKeyand selects a Novita modelWhen they send a message
Then the request is sent to Novita's OpenAI-compatible endpoint and a response streams back correctly, including tool-call handling
Given the e2e suite runs in mock mode
When the Novita test suite executes
Then it asserts the exact expected completion text unconditionally (or an explicitly-justified, narrowly-scoped exception), not a conditionally-skipped check
Request checklist
Related