From e22b71a8abb6064663667c66fc325d3e550645c3 Mon Sep 17 00:00:00 2001 From: Alex-wuhu Date: Fri, 27 Feb 2026 16:02:19 +0800 Subject: [PATCH 1/4] feat: add Novita AI as optional LLM provider --- v3/@claude-flow/providers/src/index.ts | 2 + .../providers/src/novita-provider.ts | 472 ++++++++++++++++++ .../providers/src/provider-manager.ts | 3 + 3 files changed, 477 insertions(+) create mode 100644 v3/@claude-flow/providers/src/novita-provider.ts diff --git a/v3/@claude-flow/providers/src/index.ts b/v3/@claude-flow/providers/src/index.ts index 335742ca42..8fbb66f326 100644 --- a/v3/@claude-flow/providers/src/index.ts +++ b/v3/@claude-flow/providers/src/index.ts @@ -9,6 +9,7 @@ * - Google (Gemini 2.0, 1.5 Pro, Flash) * - Cohere (Command R+, R, Light) * - Ollama (Local: Llama, Mistral, CodeLlama, Phi) + * - Novita AI (DeepSeek, Llama, Qwen via OpenAI-compatible API) * * Features: * - Load balancing (round-robin, latency, cost-based) @@ -35,6 +36,7 @@ export { GoogleProvider } from './google-provider.js'; export { CohereProvider } from './cohere-provider.js'; export { OllamaProvider } from './ollama-provider.js'; export { RuVectorProvider } from './ruvector-provider.js'; +export { NovitaProvider } from './novita-provider.js'; // Export provider manager export { ProviderManager, createProviderManager } from './provider-manager.js'; diff --git a/v3/@claude-flow/providers/src/novita-provider.ts b/v3/@claude-flow/providers/src/novita-provider.ts new file mode 100644 index 0000000000..68d7295d5a --- /dev/null +++ b/v3/@claude-flow/providers/src/novita-provider.ts @@ -0,0 +1,472 @@ +/** + * V3 Novita AI Provider + * + * OpenAI-compatible provider for Novita AI (https://novita.ai). + * Uses the OpenAI API endpoint with Novita's base URL. + * + * @module @claude-flow/providers/novita-provider + */ + +import { BaseProvider, BaseProviderOptions } from './base-provider.js'; +import { + LLMProvider, + LLMModel, + LLMRequest, + LLMResponse, + LLMStreamEvent, + ModelInfo, + ProviderCapabilities, + HealthCheckResult, + AuthenticationError, + RateLimitError, + ModelNotFoundError, + LLMProviderError, +} from './types.js'; + +interface NovitaRequest { + model: string; + messages: Array<{ + role: 'system' | 'user' | 'assistant' | 'tool'; + content: string; + name?: string; + tool_call_id?: string; + tool_calls?: Array<{ + id: string; + type: 'function'; + function: { name: string; arguments: string }; + }>; + }>; + temperature?: number; + max_tokens?: number; + top_p?: number; + frequency_penalty?: number; + presence_penalty?: number; + stop?: string[]; + stream?: boolean; + tools?: Array<{ + type: 'function'; + function: { + name: string; + description: string; + parameters: unknown; + }; + }>; + tool_choice?: 'auto' | 'none' | 'required' | { type: 'function'; function: { name: string } }; +} + +interface NovitaResponse { + id: string; + object: string; + created: number; + model: string; + choices: Array<{ + index: number; + message: { + role: string; + content: string | null; + tool_calls?: Array<{ + id: string; + type: 'function'; + function: { name: string; arguments: string }; + }>; + }; + finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter'; + }>; + usage: { + prompt_tokens: number; + completion_tokens: number; + total_tokens: number; + }; +} + +export class NovitaProvider extends BaseProvider { + readonly name: LLMProvider = 'novita'; + readonly capabilities: ProviderCapabilities = { + supportedModels: [ + 'deepseek-ai/DeepSeek-V3', + 'deepseek-ai/DeepSeek-R1', + 'meta-llama/llama-3.3-70b-instruct', + 'meta-llama/llama-3.2-3b-instruct', + 'google/gemma-2-9b-it', + 'mistralai/mistral-nemo', + 'qwen/qwen-2.5-72b-instruct', + ], + maxContextLength: { + 'deepseek-ai/DeepSeek-V3': 128000, + 'deepseek-ai/DeepSeek-R1': 128000, + 'meta-llama/llama-3.3-70b-instruct': 128000, + 'meta-llama/llama-3.2-3b-instruct': 128000, + 'google/gemma-2-9b-it': 8192, + 'mistralai/mistral-nemo': 128000, + 'qwen/qwen-2.5-72b-instruct': 128000, + }, + maxOutputTokens: { + 'deepseek-ai/DeepSeek-V3': 8192, + 'deepseek-ai/DeepSeek-R1': 8192, + 'meta-llama/llama-3.3-70b-instruct': 4096, + 'meta-llama/llama-3.2-3b-instruct': 4096, + 'google/gemma-2-9b-it': 4096, + 'mistralai/mistral-nemo': 4096, + 'qwen/qwen-2.5-72b-instruct': 4096, + }, + supportsStreaming: true, + supportsToolCalling: true, + supportsSystemMessages: true, + supportsVision: false, + supportsAudio: false, + supportsFineTuning: false, + supportsEmbeddings: false, + supportsBatching: true, + rateLimit: { + requestsPerMinute: 1000, + tokensPerMinute: 100000, + concurrentRequests: 50, + }, + pricing: { + 'deepseek-ai/DeepSeek-V3': { + promptCostPer1k: 0.00027, + completionCostPer1k: 0.0011, + currency: 'USD', + }, + 'deepseek-ai/DeepSeek-R1': { + promptCostPer1k: 0.00055, + completionCostPer1k: 0.0022, + currency: 'USD', + }, + 'meta-llama/llama-3.3-70b-instruct': { + promptCostPer1k: 0.00075, + completionCostPer1k: 0.0015, + currency: 'USD', + }, + 'meta-llama/llama-3.2-3b-instruct': { + promptCostPer1k: 0.00015, + completionCostPer1k: 0.0003, + currency: 'USD', + }, + 'google/gemma-2-9b-it': { + promptCostPer1k: 0.0001, + completionCostPer1k: 0.0002, + currency: 'USD', + }, + 'mistralai/mistral-nemo': { + promptCostPer1k: 0.0003, + completionCostPer1k: 0.0006, + currency: 'USD', + }, + 'qwen/qwen-2.5-72b-instruct': { + promptCostPer1k: 0.00035, + completionCostPer1k: 0.0007, + currency: 'USD', + }, + }, + }; + + private baseUrl: string = 'https://api.novita.ai/openai'; + private headers: Record = {}; + + constructor(options: BaseProviderOptions) { + super(options); + } + + protected async doInitialize(): Promise { + if (!this.config.apiKey) { + throw new AuthenticationError('Novita API key is required. Set NOVITA_API_KEY environment variable.', 'novita'); + } + + this.baseUrl = this.config.apiUrl || 'https://api.novita.ai/openai'; + this.headers = { + Authorization: `Bearer ${this.config.apiKey}`, + 'Content-Type': 'application/json', + }; + } + + protected async doComplete(request: LLMRequest): Promise { + const novitaRequest = this.buildRequest(request); + + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), this.config.timeout || 60000); + + try { + const response = await fetch(`${this.baseUrl}/chat/completions`, { + method: 'POST', + headers: this.headers, + body: JSON.stringify(novitaRequest), + signal: controller.signal, + }); + + clearTimeout(timeout); + + if (!response.ok) { + await this.handleErrorResponse(response); + } + + const data = await response.json() as NovitaResponse; + return this.transformResponse(data, request); + } catch (error) { + clearTimeout(timeout); + throw this.transformError(error); + } + } + + protected async *doStreamComplete(request: LLMRequest): AsyncIterable { + const novitaRequest = this.buildRequest(request, true); + + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), (this.config.timeout || 60000) * 2); + + try { + const response = await fetch(`${this.baseUrl}/chat/completions`, { + method: 'POST', + headers: this.headers, + body: JSON.stringify(novitaRequest), + signal: controller.signal, + }); + + if (!response.ok) { + await this.handleErrorResponse(response); + } + + const reader = response.body!.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() || ''; + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data === '[DONE]') { + const promptTokens = this.estimateTokens(JSON.stringify(request.messages)); + const model = request.model || this.config.model; + const pricing = this.capabilities.pricing[model]; + const promptCostPer1k = pricing?.promptCostPer1k ?? 0; + const completionCostPer1k = pricing?.completionCostPer1k ?? 0; + + yield { + type: 'done', + usage: { + promptTokens, + completionTokens: 100, + totalTokens: promptTokens + 100, + }, + cost: { + promptCost: (promptTokens / 1000) * promptCostPer1k, + completionCost: (100 / 1000) * completionCostPer1k, + totalCost: + (promptTokens / 1000) * promptCostPer1k + + (100 / 1000) * completionCostPer1k, + currency: 'USD', + }, + }; + continue; + } + + try { + const chunk = JSON.parse(data); + const delta = chunk.choices?.[0]?.delta; + + if (delta?.content) { + yield { + type: 'content', + delta: { content: delta.content }, + }; + } + + if (delta?.tool_calls) { + for (const toolCall of delta.tool_calls) { + yield { + type: 'tool_call', + delta: { + toolCall: { + id: toolCall.id, + type: 'function', + function: toolCall.function, + }, + }, + }; + } + } + } catch { + // Ignore parse errors + } + } + } + } + } catch (error) { + clearTimeout(timeout); + throw this.transformError(error); + } finally { + clearTimeout(timeout); + } + } + + async listModels(): Promise { + return this.capabilities.supportedModels; + } + + async getModelInfo(model: LLMModel): Promise { + const descriptions: Record = { + 'deepseek-ai/DeepSeek-V3': 'DeepSeek V3 - High performance model', + 'deepseek-ai/DeepSeek-R1': 'DeepSeek R1 - Reasoning model', + 'meta-llama/llama-3.3-70b-instruct': 'Llama 3.3 70B - Meta\'s latest large model', + 'meta-llama/llama-3.2-3b-instruct': 'Llama 3.2 3B - Lightweight model', + 'google/gemma-2-9b-it': 'Google Gemma 2 9B', + 'mistralai/mistral-nemo': 'Mistral Nemo - Efficient model', + 'qwen/qwen-2.5-72b-instruct': 'Qwen 2.5 72B - Alibaba\'s large model', + }; + + return { + model, + name: model, + description: descriptions[model] || 'Novita AI language model', + contextLength: this.capabilities.maxContextLength[model] || 8192, + maxOutputTokens: this.capabilities.maxOutputTokens[model] || 4096, + supportedFeatures: [ + 'chat', + 'completion', + 'tool_calling', + ], + pricing: this.capabilities.pricing[model], + }; + } + + protected async doHealthCheck(): Promise { + try { + const response = await fetch(`${this.baseUrl}/models`, { + headers: this.headers, + }); + + return { + healthy: response.ok, + timestamp: new Date(), + ...(response.ok ? {} : { error: `HTTP ${response.status}` }), + }; + } catch (error) { + return { + healthy: false, + error: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date(), + }; + } + } + + private buildRequest(request: LLMRequest, stream = false): NovitaRequest { + const novitaRequest: NovitaRequest = { + model: request.model || this.config.model, + messages: request.messages.map((msg) => ({ + role: msg.role, + content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), + ...(msg.name && { name: msg.name }), + ...(msg.toolCallId && { tool_call_id: msg.toolCallId }), + ...(msg.toolCalls && { tool_calls: msg.toolCalls }), + })), + stream, + }; + + if (request.temperature !== undefined || this.config.temperature !== undefined) { + novitaRequest.temperature = request.temperature ?? this.config.temperature; + } + + if (request.maxTokens || this.config.maxTokens) { + novitaRequest.max_tokens = request.maxTokens || this.config.maxTokens; + } + + if (request.topP !== undefined || this.config.topP !== undefined) { + novitaRequest.top_p = request.topP ?? this.config.topP; + } + + if (request.frequencyPenalty !== undefined || this.config.frequencyPenalty !== undefined) { + novitaRequest.frequency_penalty = request.frequencyPenalty ?? this.config.frequencyPenalty; + } + + if (request.presencePenalty !== undefined || this.config.presencePenalty !== undefined) { + novitaRequest.presence_penalty = request.presencePenalty ?? this.config.presencePenalty; + } + + if (request.stopSequences || this.config.stopSequences) { + novitaRequest.stop = request.stopSequences || this.config.stopSequences; + } + + if (request.tools) { + novitaRequest.tools = request.tools; + novitaRequest.tool_choice = request.toolChoice; + } + + return novitaRequest; + } + + private transformResponse(data: NovitaResponse, request: LLMRequest): LLMResponse { + const choice = data.choices[0]; + const model = request.model || this.config.model; + const pricing = this.capabilities.pricing[model]; + + const promptCostPer1k = pricing?.promptCostPer1k ?? 0; + const completionCostPer1k = pricing?.completionCostPer1k ?? 0; + + const promptCost = (data.usage.prompt_tokens / 1000) * promptCostPer1k; + const completionCost = (data.usage.completion_tokens / 1000) * completionCostPer1k; + + return { + id: data.id, + model: model as LLMModel, + provider: 'novita', + content: choice.message.content || '', + toolCalls: choice.message.tool_calls, + usage: { + promptTokens: data.usage.prompt_tokens, + completionTokens: data.usage.completion_tokens, + totalTokens: data.usage.total_tokens, + }, + cost: { + promptCost, + completionCost, + totalCost: promptCost + completionCost, + currency: 'USD', + }, + finishReason: choice.finish_reason, + }; + } + + private async handleErrorResponse(response: Response): Promise { + const errorText = await response.text(); + let errorData: { error?: { message?: string } }; + + try { + errorData = JSON.parse(errorText); + } catch { + errorData = { error: { message: errorText } }; + } + + const message = errorData.error?.message || 'Unknown error'; + + switch (response.status) { + case 401: + throw new AuthenticationError(message, 'novita', errorData); + case 429: + const retryAfter = response.headers.get('retry-after'); + throw new RateLimitError( + message, + 'novita', + retryAfter ? parseInt(retryAfter) : undefined, + errorData + ); + case 404: + throw new ModelNotFoundError(this.config.model, 'novita', errorData); + default: + throw new LLMProviderError( + message, + `NOVITA_${response.status}`, + 'novita', + response.status, + response.status >= 500, + errorData + ); + } + } +} diff --git a/v3/@claude-flow/providers/src/provider-manager.ts b/v3/@claude-flow/providers/src/provider-manager.ts index 506185afa6..366da039ce 100644 --- a/v3/@claude-flow/providers/src/provider-manager.ts +++ b/v3/@claude-flow/providers/src/provider-manager.ts @@ -35,6 +35,7 @@ import { GoogleProvider } from './google-provider.js'; import { CohereProvider } from './cohere-provider.js'; import { OllamaProvider } from './ollama-provider.js'; import { RuVectorProvider } from './ruvector-provider.js'; +import { NovitaProvider } from './novita-provider.js'; /** * Cache entry for request caching @@ -127,6 +128,8 @@ export class ProviderManager extends EventEmitter { return new OllamaProvider(options); case 'ruvector': return new RuVectorProvider(options); + case 'novita': + return new NovitaProvider(options); default: throw new Error(`Unknown provider: ${config.provider}`); } From 5d1be3308b0e9f396b31f2864a1030f372ee4b40 Mon Sep 17 00:00:00 2001 From: Alex-wuhu Date: Fri, 27 Feb 2026 17:16:44 +0800 Subject: [PATCH 2/4] fix(providers): align novita type and openai-compatible v1 paths --- .../providers/src/novita-provider.ts | 29 +++++++++++-------- v3/@claude-flow/providers/src/types.ts | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/v3/@claude-flow/providers/src/novita-provider.ts b/v3/@claude-flow/providers/src/novita-provider.ts index 68d7295d5a..d4156156df 100644 --- a/v3/@claude-flow/providers/src/novita-provider.ts +++ b/v3/@claude-flow/providers/src/novita-provider.ts @@ -83,8 +83,8 @@ export class NovitaProvider extends BaseProvider { readonly name: LLMProvider = 'novita'; readonly capabilities: ProviderCapabilities = { supportedModels: [ - 'deepseek-ai/DeepSeek-V3', - 'deepseek-ai/DeepSeek-R1', + 'deepseek/deepseek-v3', + 'deepseek/deepseek-r1', 'meta-llama/llama-3.3-70b-instruct', 'meta-llama/llama-3.2-3b-instruct', 'google/gemma-2-9b-it', @@ -92,8 +92,8 @@ export class NovitaProvider extends BaseProvider { 'qwen/qwen-2.5-72b-instruct', ], maxContextLength: { - 'deepseek-ai/DeepSeek-V3': 128000, - 'deepseek-ai/DeepSeek-R1': 128000, + 'deepseek/deepseek-v3': 128000, + 'deepseek/deepseek-r1': 128000, 'meta-llama/llama-3.3-70b-instruct': 128000, 'meta-llama/llama-3.2-3b-instruct': 128000, 'google/gemma-2-9b-it': 8192, @@ -101,8 +101,8 @@ export class NovitaProvider extends BaseProvider { 'qwen/qwen-2.5-72b-instruct': 128000, }, maxOutputTokens: { - 'deepseek-ai/DeepSeek-V3': 8192, - 'deepseek-ai/DeepSeek-R1': 8192, + 'deepseek/deepseek-v3': 8192, + 'deepseek/deepseek-r1': 8192, 'meta-llama/llama-3.3-70b-instruct': 4096, 'meta-llama/llama-3.2-3b-instruct': 4096, 'google/gemma-2-9b-it': 4096, @@ -123,12 +123,12 @@ export class NovitaProvider extends BaseProvider { concurrentRequests: 50, }, pricing: { - 'deepseek-ai/DeepSeek-V3': { + 'deepseek/deepseek-v3': { promptCostPer1k: 0.00027, completionCostPer1k: 0.0011, currency: 'USD', }, - 'deepseek-ai/DeepSeek-R1': { + 'deepseek/deepseek-r1': { promptCostPer1k: 0.00055, completionCostPer1k: 0.0022, currency: 'USD', @@ -161,7 +161,7 @@ export class NovitaProvider extends BaseProvider { }, }; - private baseUrl: string = 'https://api.novita.ai/openai'; + private baseUrl: string = 'https://api.novita.ai/openai/v1'; private headers: Record = {}; constructor(options: BaseProviderOptions) { @@ -173,7 +173,7 @@ export class NovitaProvider extends BaseProvider { throw new AuthenticationError('Novita API key is required. Set NOVITA_API_KEY environment variable.', 'novita'); } - this.baseUrl = this.config.apiUrl || 'https://api.novita.ai/openai'; + this.baseUrl = this.normalizeBaseUrl(this.config.apiUrl || 'https://api.novita.ai/openai'); this.headers = { Authorization: `Bearer ${this.config.apiKey}`, 'Content-Type': 'application/json', @@ -312,8 +312,8 @@ export class NovitaProvider extends BaseProvider { async getModelInfo(model: LLMModel): Promise { const descriptions: Record = { - 'deepseek-ai/DeepSeek-V3': 'DeepSeek V3 - High performance model', - 'deepseek-ai/DeepSeek-R1': 'DeepSeek R1 - Reasoning model', + 'deepseek/deepseek-v3': 'DeepSeek V3 - High performance model', + 'deepseek/deepseek-r1': 'DeepSeek R1 - Reasoning model', 'meta-llama/llama-3.3-70b-instruct': 'Llama 3.3 70B - Meta\'s latest large model', 'meta-llama/llama-3.2-3b-instruct': 'Llama 3.2 3B - Lightweight model', 'google/gemma-2-9b-it': 'Google Gemma 2 9B', @@ -401,6 +401,11 @@ export class NovitaProvider extends BaseProvider { return novitaRequest; } + private normalizeBaseUrl(apiUrl: string): string { + const normalized = apiUrl.replace(/\/+$/, ''); + return normalized.endsWith('/v1') ? normalized : `${normalized}/v1`; + } + private transformResponse(data: NovitaResponse, request: LLMRequest): LLMResponse { const choice = data.choices[0]; const model = request.model || this.config.model; diff --git a/v3/@claude-flow/providers/src/types.ts b/v3/@claude-flow/providers/src/types.ts index f9d23d25e1..62a79261ae 100644 --- a/v3/@claude-flow/providers/src/types.ts +++ b/v3/@claude-flow/providers/src/types.ts @@ -18,6 +18,7 @@ export type LLMProvider = | 'cohere' | 'ollama' | 'ruvector' + | 'novita' | 'openrouter' | 'litellm' | 'custom'; From 64725a887f4f751cd991815c56d0d95fa0a48523 Mon Sep 17 00:00:00 2001 From: Alex-wuhu Date: Fri, 27 Feb 2026 17:21:16 +0800 Subject: [PATCH 3/4] chore(providers): switch novita models to current top offerings --- .../providers/src/novita-provider.ts | 81 +++++++------------ 1 file changed, 27 insertions(+), 54 deletions(-) diff --git a/v3/@claude-flow/providers/src/novita-provider.ts b/v3/@claude-flow/providers/src/novita-provider.ts index d4156156df..9e508e7125 100644 --- a/v3/@claude-flow/providers/src/novita-provider.ts +++ b/v3/@claude-flow/providers/src/novita-provider.ts @@ -83,31 +83,22 @@ export class NovitaProvider extends BaseProvider { readonly name: LLMProvider = 'novita'; readonly capabilities: ProviderCapabilities = { supportedModels: [ - 'deepseek/deepseek-v3', - 'deepseek/deepseek-r1', - 'meta-llama/llama-3.3-70b-instruct', - 'meta-llama/llama-3.2-3b-instruct', - 'google/gemma-2-9b-it', - 'mistralai/mistral-nemo', - 'qwen/qwen-2.5-72b-instruct', + 'deepseek/deepseek-r1-0528', + 'deepseek/deepseek-v3-0324', + 'qwen/qwen3-coder-480b-a35b-instruct', + 'qwen/qwen3-235b-a22b-instruct-2507', ], maxContextLength: { - 'deepseek/deepseek-v3': 128000, - 'deepseek/deepseek-r1': 128000, - 'meta-llama/llama-3.3-70b-instruct': 128000, - 'meta-llama/llama-3.2-3b-instruct': 128000, - 'google/gemma-2-9b-it': 8192, - 'mistralai/mistral-nemo': 128000, - 'qwen/qwen-2.5-72b-instruct': 128000, + 'deepseek/deepseek-r1-0528': 163840, + 'deepseek/deepseek-v3-0324': 163840, + 'qwen/qwen3-coder-480b-a35b-instruct': 262144, + 'qwen/qwen3-235b-a22b-instruct-2507': 131072, }, maxOutputTokens: { - 'deepseek/deepseek-v3': 8192, - 'deepseek/deepseek-r1': 8192, - 'meta-llama/llama-3.3-70b-instruct': 4096, - 'meta-llama/llama-3.2-3b-instruct': 4096, - 'google/gemma-2-9b-it': 4096, - 'mistralai/mistral-nemo': 4096, - 'qwen/qwen-2.5-72b-instruct': 4096, + 'deepseek/deepseek-r1-0528': 32768, + 'deepseek/deepseek-v3-0324': 163840, + 'qwen/qwen3-coder-480b-a35b-instruct': 65536, + 'qwen/qwen3-235b-a22b-instruct-2507': 16384, }, supportsStreaming: true, supportsToolCalling: true, @@ -123,39 +114,24 @@ export class NovitaProvider extends BaseProvider { concurrentRequests: 50, }, pricing: { - 'deepseek/deepseek-v3': { - promptCostPer1k: 0.00027, - completionCostPer1k: 0.0011, - currency: 'USD', - }, - 'deepseek/deepseek-r1': { - promptCostPer1k: 0.00055, - completionCostPer1k: 0.0022, - currency: 'USD', - }, - 'meta-llama/llama-3.3-70b-instruct': { - promptCostPer1k: 0.00075, - completionCostPer1k: 0.0015, - currency: 'USD', - }, - 'meta-llama/llama-3.2-3b-instruct': { - promptCostPer1k: 0.00015, - completionCostPer1k: 0.0003, + 'deepseek/deepseek-r1-0528': { + promptCostPer1k: 0.0007, + completionCostPer1k: 0.0025, currency: 'USD', }, - 'google/gemma-2-9b-it': { - promptCostPer1k: 0.0001, - completionCostPer1k: 0.0002, + 'deepseek/deepseek-v3-0324': { + promptCostPer1k: 0.00027, + completionCostPer1k: 0.00112, currency: 'USD', }, - 'mistralai/mistral-nemo': { + 'qwen/qwen3-coder-480b-a35b-instruct': { promptCostPer1k: 0.0003, - completionCostPer1k: 0.0006, + completionCostPer1k: 0.0013, currency: 'USD', }, - 'qwen/qwen-2.5-72b-instruct': { - promptCostPer1k: 0.00035, - completionCostPer1k: 0.0007, + 'qwen/qwen3-235b-a22b-instruct-2507': { + promptCostPer1k: 0.00009, + completionCostPer1k: 0.00058, currency: 'USD', }, }, @@ -312,13 +288,10 @@ export class NovitaProvider extends BaseProvider { async getModelInfo(model: LLMModel): Promise { const descriptions: Record = { - 'deepseek/deepseek-v3': 'DeepSeek V3 - High performance model', - 'deepseek/deepseek-r1': 'DeepSeek R1 - Reasoning model', - 'meta-llama/llama-3.3-70b-instruct': 'Llama 3.3 70B - Meta\'s latest large model', - 'meta-llama/llama-3.2-3b-instruct': 'Llama 3.2 3B - Lightweight model', - 'google/gemma-2-9b-it': 'Google Gemma 2 9B', - 'mistralai/mistral-nemo': 'Mistral Nemo - Efficient model', - 'qwen/qwen-2.5-72b-instruct': 'Qwen 2.5 72B - Alibaba\'s large model', + 'deepseek/deepseek-r1-0528': 'DeepSeek R1 0528 - Reasoning model', + 'deepseek/deepseek-v3-0324': 'DeepSeek V3 0324 - General reasoning and coding model', + 'qwen/qwen3-coder-480b-a35b-instruct': 'Qwen3 Coder 480B A35B - Coding and tool use model', + 'qwen/qwen3-235b-a22b-instruct-2507': 'Qwen3 235B A22B Instruct 2507 - General-purpose instruction model', }; return { From 7076f96cf189c98d83f0c05209afa37774807be3 Mon Sep 17 00:00:00 2001 From: Alex-wuhu Date: Fri, 27 Feb 2026 17:22:59 +0800 Subject: [PATCH 4/4] chore(providers): switch novita defaults to DeepSeek V3.2 GLM-5 and MiniMax M2.5 --- .../providers/src/novita-provider.ts | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/v3/@claude-flow/providers/src/novita-provider.ts b/v3/@claude-flow/providers/src/novita-provider.ts index 9e508e7125..f2c096cc0e 100644 --- a/v3/@claude-flow/providers/src/novita-provider.ts +++ b/v3/@claude-flow/providers/src/novita-provider.ts @@ -83,22 +83,19 @@ export class NovitaProvider extends BaseProvider { readonly name: LLMProvider = 'novita'; readonly capabilities: ProviderCapabilities = { supportedModels: [ - 'deepseek/deepseek-r1-0528', - 'deepseek/deepseek-v3-0324', - 'qwen/qwen3-coder-480b-a35b-instruct', - 'qwen/qwen3-235b-a22b-instruct-2507', + 'deepseek/deepseek-v3.2', + 'zai-org/glm-5', + 'minimax/minimax-m2.5', ], maxContextLength: { - 'deepseek/deepseek-r1-0528': 163840, - 'deepseek/deepseek-v3-0324': 163840, - 'qwen/qwen3-coder-480b-a35b-instruct': 262144, - 'qwen/qwen3-235b-a22b-instruct-2507': 131072, + 'deepseek/deepseek-v3.2': 163840, + 'zai-org/glm-5': 202800, + 'minimax/minimax-m2.5': 204800, }, maxOutputTokens: { - 'deepseek/deepseek-r1-0528': 32768, - 'deepseek/deepseek-v3-0324': 163840, - 'qwen/qwen3-coder-480b-a35b-instruct': 65536, - 'qwen/qwen3-235b-a22b-instruct-2507': 16384, + 'deepseek/deepseek-v3.2': 65536, + 'zai-org/glm-5': 131072, + 'minimax/minimax-m2.5': 131100, }, supportsStreaming: true, supportsToolCalling: true, @@ -114,24 +111,19 @@ export class NovitaProvider extends BaseProvider { concurrentRequests: 50, }, pricing: { - 'deepseek/deepseek-r1-0528': { - promptCostPer1k: 0.0007, - completionCostPer1k: 0.0025, + 'deepseek/deepseek-v3.2': { + promptCostPer1k: 0.000269, + completionCostPer1k: 0.0004, currency: 'USD', }, - 'deepseek/deepseek-v3-0324': { - promptCostPer1k: 0.00027, - completionCostPer1k: 0.00112, + 'zai-org/glm-5': { + promptCostPer1k: 0.001, + completionCostPer1k: 0.0032, currency: 'USD', }, - 'qwen/qwen3-coder-480b-a35b-instruct': { + 'minimax/minimax-m2.5': { promptCostPer1k: 0.0003, - completionCostPer1k: 0.0013, - currency: 'USD', - }, - 'qwen/qwen3-235b-a22b-instruct-2507': { - promptCostPer1k: 0.00009, - completionCostPer1k: 0.00058, + completionCostPer1k: 0.0012, currency: 'USD', }, }, @@ -288,10 +280,9 @@ export class NovitaProvider extends BaseProvider { async getModelInfo(model: LLMModel): Promise { const descriptions: Record = { - 'deepseek/deepseek-r1-0528': 'DeepSeek R1 0528 - Reasoning model', - 'deepseek/deepseek-v3-0324': 'DeepSeek V3 0324 - General reasoning and coding model', - 'qwen/qwen3-coder-480b-a35b-instruct': 'Qwen3 Coder 480B A35B - Coding and tool use model', - 'qwen/qwen3-235b-a22b-instruct-2507': 'Qwen3 235B A22B Instruct 2507 - General-purpose instruction model', + 'deepseek/deepseek-v3.2': 'DeepSeek V3.2 - General reasoning and coding model', + 'zai-org/glm-5': 'GLM-5 - Long-horizon reasoning and system engineering model', + 'minimax/minimax-m2.5': 'MiniMax M2.5 - Agentic productivity and coding model', }; return {