-
Notifications
You must be signed in to change notification settings - Fork 448
feat: add DeepSeek + GLM Coding Plan providers, fix DeepSeek reasonin… #604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
49a5144
feat: add DeepSeek + GLM Coding Plan providers, fix DeepSeek reasonin…
ngduyanhece 5eb365e
Merge remote-tracking branch 'origin/main' into proj/llm-providers-ex…
cuongdo-byterover f5a334d
Merge pull request #606 from campfirein/chore/llm-providers-expansion…
cuongdo-byterover c4e225a
fix: [ENG-2606] replace DeepSeek logo with monochrome variant for the…
cuongdo-byterover d78ab72
fix: [ENG-2608] correct apiKeyUrl for GLM Coding Plan
cuongdo-byterover 3287f57
fix: [ENG-2609] iterate ChatBasedModelFetcher candidate models when v…
cuongdo-byterover 1aae446
fix: [ENG-2607] round-trip reasoning_content for DeepSeek-R1 / Reasoner
cuongdo-byterover b31fd36
fix: [ENG-2608] also patch server-side provider-registry apiKeyUrl
cuongdo-byterover b7752f5
chore: address PR #609 review feedback
cuongdo-byterover 9913ff5
Merge pull request #609 from campfirein/fix/ENG-2603
cuongdo-byterover File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -210,7 +210,7 @@ | |
| * | ||
| * @param sessionId - Unique identifier for this session | ||
| * @param generator - Content generator for LLM calls (with decorators pre-applied) | ||
| * @param config - LLM service configuration (model, tokens, temperature) | ||
|
Check warning on line 213 in src/agent/infra/llm/agent-llm-service.ts
|
||
| * @param options - Service dependencies | ||
| * @param options.toolManager - Tool manager for executing agent tools | ||
| * @param options.systemPromptManager - System prompt manager for building system prompts | ||
|
|
@@ -571,9 +571,13 @@ | |
| try { | ||
| const response = await this.generator.generateContent(request) | ||
|
|
||
| // Convert response to InternalMessage format | ||
| // Convert response to InternalMessage format. The reasoning field must | ||
| // round-trip on the next turn for some providers (e.g. DeepSeek-R1 | ||
| // rejects with "reasoning_content must be passed back to the API" | ||
| // otherwise). | ||
| const message: InternalMessage = { | ||
| content: response.content, | ||
| ...(response.reasoning && {reasoning: response.reasoning}), | ||
| role: 'assistant', | ||
| toolCalls: response.toolCalls, | ||
| } | ||
|
|
@@ -616,12 +620,16 @@ | |
| ): Promise<InternalMessage> { | ||
| try { | ||
| let accumulatedContent = '' | ||
| let accumulatedReasoning = '' | ||
| let accumulatedToolCalls: ToolCall[] = [] | ||
|
|
||
| // Stream chunks and accumulate content | ||
| for await (const chunk of this.generator.generateContentStream(request)) { | ||
| // Emit thinking/reasoning chunks as events for TUI display | ||
| // Emit thinking/reasoning chunks as events for TUI display + accumulate | ||
| // for the InternalMessage so it round-trips on the next turn (DeepSeek-R1 | ||
| // requires reasoning_content to be passed back). | ||
| if (chunk.type === StreamChunkType.THINKING && chunk.reasoning) { | ||
| accumulatedReasoning += chunk.reasoning | ||
| this.sessionEventBus.emit('llmservice:chunk', { | ||
| content: chunk.reasoning, | ||
| isComplete: chunk.isComplete, | ||
|
|
@@ -652,6 +660,7 @@ | |
| // Convert accumulated response to InternalMessage format | ||
| const message: InternalMessage = { | ||
| content: accumulatedContent || null, | ||
| ...(accumulatedReasoning && {reasoning: accumulatedReasoning}), | ||
| role: 'assistant', | ||
| toolCalls: accumulatedToolCalls.length > 0 ? accumulatedToolCalls : undefined, | ||
| } | ||
|
|
@@ -1281,8 +1290,10 @@ | |
| taskId: taskId || undefined, | ||
| }) | ||
|
|
||
| // Add assistant message to context | ||
| await this.contextManager.addAssistantMessage(content) | ||
| // Add assistant message to context. Pass reasoning so it round-trips to | ||
| // providers that demand it (DeepSeek-R1 rejects with "reasoning_content | ||
| // must be passed back to the API" otherwise). | ||
| await this.contextManager.addAssistantMessage(content, undefined, lastMessage.reasoning) | ||
|
|
||
| return content | ||
| } | ||
|
|
@@ -1427,9 +1438,10 @@ | |
| // Emit thought events if present | ||
| this.handleThoughts(lastMessage, taskId) | ||
|
|
||
| // Has tool calls - add assistant message with tool calls | ||
| // Has tool calls - add assistant message with tool calls. Pass reasoning | ||
| // so it round-trips to providers that demand it. | ||
| const assistantContent = this.extractTextContent(lastMessage) | ||
| await this.contextManager.addAssistantMessage(assistantContent, lastMessage.toolCalls) | ||
| await this.contextManager.addAssistantMessage(assistantContent, lastMessage.toolCalls, lastMessage.reasoning) | ||
|
|
||
| // Step 1: Create pending tool parts for all tool calls | ||
| for (const toolCall of lastMessage.toolCalls) { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /** | ||
| * DeepSeek Provider Module | ||
| * | ||
| * Access to DeepSeek V3 (deepseek-chat) and R1 (deepseek-reasoner) via their | ||
| * OpenAI-compatible API. The reasoner model streams thinking through the | ||
| * native `reasoning_content` field rather than `<think>` tags — see | ||
| * model-capabilities.ts for the parser routing. | ||
| */ | ||
|
|
||
| import {createOpenAICompatible} from '@ai-sdk/openai-compatible' | ||
|
|
||
| import type {GeneratorFactoryConfig, ProviderModule} from './types.js' | ||
|
|
||
| import {AiSdkContentGenerator} from '../generators/ai-sdk-content-generator.js' | ||
|
|
||
| export const deepseekProvider: ProviderModule = { | ||
| apiKeyUrl: 'https://platform.deepseek.com/api_keys', | ||
| authType: 'api-key', | ||
| baseUrl: 'https://api.deepseek.com/v1', | ||
| category: 'other', | ||
| createGenerator(config: GeneratorFactoryConfig) { | ||
| const provider = createOpenAICompatible({ | ||
| apiKey: config.apiKey!, | ||
| baseURL: 'https://api.deepseek.com/v1', | ||
|
cuongdo-byterover marked this conversation as resolved.
|
||
| name: 'deepseek', | ||
| }) | ||
|
|
||
| return new AiSdkContentGenerator({ | ||
| model: provider.chatModel(config.model), | ||
| }) | ||
| }, | ||
| defaultModel: 'deepseek-chat', | ||
| description: 'DeepSeek V3 and R1 reasoning models', | ||
| envVars: ['DEEPSEEK_API_KEY'], | ||
| id: 'deepseek', | ||
| name: 'DeepSeek', | ||
| priority: 19, | ||
|
|
||
| providerType: 'openai', | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /** | ||
| * GLM Coding Plan (Z.AI) Provider Module | ||
| * | ||
| * Same Z.AI account as the standard `glm` provider but routes through the | ||
| * coding-plan endpoint so subscription quota is consumed instead of | ||
| * pay-per-token billing. | ||
| */ | ||
|
|
||
| import {createOpenAICompatible} from '@ai-sdk/openai-compatible' | ||
|
|
||
| import type {GeneratorFactoryConfig, ProviderModule} from './types.js' | ||
|
|
||
| import {AiSdkContentGenerator} from '../generators/ai-sdk-content-generator.js' | ||
|
|
||
| export const glmCodingPlanProvider: ProviderModule = { | ||
| apiKeyUrl: 'https://z.ai/manage-apikey/apikey-list', | ||
| authType: 'api-key', | ||
| baseUrl: 'https://api.z.ai/api/coding/paas/v4', | ||
| category: 'other', | ||
| createGenerator(config: GeneratorFactoryConfig) { | ||
| const provider = createOpenAICompatible({ | ||
| apiKey: config.apiKey!, | ||
| baseURL: 'https://api.z.ai/api/coding/paas/v4', | ||
|
cuongdo-byterover marked this conversation as resolved.
|
||
| name: 'glm-coding-plan', | ||
| }) | ||
|
|
||
| return new AiSdkContentGenerator({ | ||
| model: provider.chatModel(config.model), | ||
| }) | ||
| }, | ||
| defaultModel: 'glm-4.7', | ||
| description: 'GLM models on the Z.AI Coding Plan subscription', | ||
| envVars: ['ZHIPU_API_KEY'], | ||
| id: 'glm-coding-plan', | ||
| name: 'GLM Coding Plan (Z.AI)', | ||
| priority: 17.5, | ||
|
cuongdo-byterover marked this conversation as resolved.
|
||
|
|
||
| providerType: 'openai', | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.