Skip to content

feat(novita): add deepseek-v4-flash - #2098

Merged
steebchen merged 1 commit into
mainfrom
deepseek-v4-novita
Apr 27, 2026
Merged

steebchen merged 1 commit into
mainfrom
deepseek-v4-novita

Conversation

@steebchen

@steebchen steebchen commented Apr 27, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add Novita provider mapping for deepseek-v4-flash (1.05M context, 393.2K max output, $0.14/$0.28 in/out, $0.028 cache read).
  • Extend the DeepSeek V4 thinking-mode reasoning_content workaround in prepare-request-body.ts to cover Novita-routed deepseek/deepseek-v4-* models. Without this, Novita's upstream rejects follow-up assistant messages with tool_calls but no reasoning_content. Uses a single-space placeholder (same trick as Moonshot k2.5/k2.6) since Novita treats an empty string as missing.

Test plan

  • TEST_MODELS="novita/deepseek-v4-flash" pnpm test:e2e — 72 passed, 42 skipped, 0 failed
  • TEST_MODELS="deepseek/deepseek-v4-flash,moonshot/kimi-k2.6" pnpm test:e2e apps/gateway/src/chat-toolcalls-result.e2e.ts — regression check, all green
  • pnpm test:unit — 970 passed
  • pnpm build

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added support for DeepSeek V4 Flash model via Novita provider, featuring streaming, reasoning, vision, tools, and JSON output capabilities.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 27, 2026 06:52
@coderabbitai

coderabbitai Bot commented Apr 27, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a1b4b64a-19cd-47e7-b315-c544d11b7aed

📥 Commits

Reviewing files that changed from the base of the PR and between 110a6d5 and dc8318f.

📒 Files selected for processing (2)
  • packages/actions/src/prepare-request-body.ts
  • packages/models/src/models/deepseek.ts

Walkthrough

This PR extends support for Novita's DeepSeek V4 proxy models by adding request body preprocessing that detects and handles empty reasoning fields similarly to DeepSeek, and adds the Novita provider configuration for deepseek-v4-flash with pricing and capability metadata.

Changes

Cohort / File(s) Summary
Novita DeepSeek V4 Support
packages/actions/src/prepare-request-body.ts, packages/models/src/models/deepseek.ts
Adds detection for Novita DeepSeek V4 proxy models to handle empty reasoning fields with a " " placeholder fallback. Introduces new provider configuration for deepseek-v4-flash in Novita backend with explicit pricing fields, capability flags, and context size specifications.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(novita): add deepseek-v4-flash' clearly and concisely summarizes the main change: adding support for the deepseek-v4-flash model via the Novita provider, which is the primary objective of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch deepseek-v4-novita

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI 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.

Pull request overview

Adds a Novita-routed mapping for DeepSeek V4 Flash and extends the existing “reasoning_content placeholder” workaround so Novita-proxied DeepSeek V4 tool-calling flows don’t get rejected by the upstream.

Changes:

  • Add novita provider mapping for deepseek-v4-flash (as deepseek/deepseek-v4-flash) with pricing and limits.
  • Extend the DeepSeek/Moonshot reasoning_content reinjection logic to also apply to Novita when routing DeepSeek V4 models.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/models/src/models/deepseek.ts Adds Novita provider mapping for deepseek-v4-flash with prices/context/max output.
packages/actions/src/prepare-request-body.ts Applies the existing tool_calls + missing reasoning_content workaround to Novita-proxied DeepSeek V4 models.
Comments suppressed due to low confidence (1)

packages/actions/src/prepare-request-body.ts:983

  • Add unit coverage for the new Novita DeepSeek-V4 path: when usedProvider is "novita" and usedModel matches "deepseek/deepseek-v4*", assistant messages containing tool_calls should get a non-empty reasoning_content (single-space fallback) when missing. This logic is subtle and regression-prone, and prepare-request-body.ts already has a dedicated spec file where this can be asserted.
	// non-empty placeholder there. Novita proxies DeepSeek V4 with the same
	// upstream constraint, so apply the DeepSeek behavior there too.
	const isNovitaDeepseekV4 =
		usedProvider === "novita" && usedModel.startsWith("deepseek/deepseek-v4");
	if (
		usedProvider === "deepseek" ||
		usedProvider === "moonshot" ||
		isNovitaDeepseekV4
	) {
		const fallback =
			usedProvider === "moonshot" || isNovitaDeepseekV4 ? " " : "";
		processedMessages = processedMessages.map((m) => {
			if (
				m.role !== "assistant" ||
				!m.tool_calls ||
				!Array.isArray(m.tool_calls) ||
				m.tool_calls.length === 0 ||
				m.reasoning_content !== undefined
			) {
				return m;
			}
			const reasoning = m.reasoning ?? fallback;
			return { ...m, reasoning_content: reasoning || fallback };
		});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +960 to +962
// non-empty placeholder there. Novita proxies DeepSeek V4 with the same
// upstream constraint, so apply the DeepSeek behavior there too.
const isNovitaDeepseekV4 =

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

The inline comment says to "apply the DeepSeek behavior" for Novita, but the code uses the Moonshot-style single-space placeholder (because empty string is treated as missing). Consider rewording to explicitly say you're applying the DeepSeek V4 tool_calls/reasoning_content workaround to Novita, and that Novita requires the non-empty placeholder.

Copilot uses AI. Check for mistakes.
@steebchen
steebchen merged commit 0a5541a into main Apr 27, 2026
21 of 22 checks passed
@steebchen
steebchen deleted the deepseek-v4-novita branch April 27, 2026 07:10
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