Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/main/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ export function getConfig(): DeepBotConfig {
}

// 从环境变量读取配置
const apiKey = process.env.AI_API_KEY || '';
const baseUrl = process.env.AI_BASE_URL || '';
const modelId = process.env.AI_MODEL_ID || '';
const modelName = process.env.AI_MODEL_NAME || '';
const providerName = process.env.AI_PROVIDER_NAME || '';
const hasAtlasEnv = !!process.env.ATLASCLOUD_API_KEY;
const apiKey = process.env.AI_API_KEY || process.env.ATLASCLOUD_API_KEY || '';
const baseUrl = process.env.AI_BASE_URL || (hasAtlasEnv ? process.env.ATLASCLOUD_API_BASE || 'https://api.atlascloud.ai/v1' : '');
const modelId = process.env.AI_MODEL_ID || (hasAtlasEnv ? process.env.ATLASCLOUD_MODEL || 'qwen/qwen3.5-flash' : '');
const modelName = process.env.AI_MODEL_NAME || modelId;
const providerName = process.env.AI_PROVIDER_NAME || (hasAtlasEnv ? 'atlascloud' : '');
const apiType = process.env.AI_API_TYPE || 'openai-completions'; // 默认 OpenAI 兼容
const modelId2 = process.env.AI_MODEL_ID_2 || ''; // 快速模型(选填)
const modelId2 = process.env.AI_MODEL_ID_2 || (hasAtlasEnv ? process.env.ATLASCLOUD_MODEL_2 || '' : ''); // 快速模型(选填)

// 如果没有配置,抛出错误
if (!apiKey || !baseUrl || !modelId) {
Expand Down Expand Up @@ -99,9 +100,10 @@ export function hasConfig(): boolean {
}

// 检查环境变量
const apiKey = process.env.AI_API_KEY || '';
const baseUrl = process.env.AI_BASE_URL || '';
const modelId = process.env.AI_MODEL_ID || '';
const hasAtlasEnv = !!process.env.ATLASCLOUD_API_KEY;
const apiKey = process.env.AI_API_KEY || process.env.ATLASCLOUD_API_KEY || '';
const baseUrl = process.env.AI_BASE_URL || (hasAtlasEnv ? process.env.ATLASCLOUD_API_BASE || 'https://api.atlascloud.ai/v1' : '');
const modelId = process.env.AI_MODEL_ID || (hasAtlasEnv ? process.env.ATLASCLOUD_MODEL || 'qwen/qwen3.5-flash' : '');

return !!(apiKey && baseUrl && modelId);
}
2 changes: 1 addition & 1 deletion src/main/database/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface WorkspaceSettings {
* 模型配置
*/
export interface ModelConfig {
providerType: 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'custom' | 'anthropic'; // 提供商类型(用于 UI 下拉选择)
providerType: 'deepbot' | 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'atlascloud' | 'custom' | 'anthropic'; // 提供商类型(用于 UI 下拉选择)
providerId: string; // 提供商 ID
providerName: string; // 提供商名称
baseUrl: string; // API 地址
Expand Down
12 changes: 7 additions & 5 deletions src/main/database/model-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,22 @@ export function clearModelConfigCache(): void {
* 仅在数据库中没有配置时使用
*/
function getModelConfigFromEnv(): ModelConfig | null {
const apiKey = process.env.AI_API_KEY;
const baseUrl = process.env.AI_BASE_URL;
const modelId = process.env.AI_MODEL_ID;
const hasAtlasEnv = !!process.env.ATLASCLOUD_API_KEY;
const apiKey = process.env.AI_API_KEY || process.env.ATLASCLOUD_API_KEY;
const baseUrl = process.env.AI_BASE_URL || (hasAtlasEnv ? process.env.ATLASCLOUD_API_BASE || 'https://api.atlascloud.ai/v1' : undefined);
const modelId = process.env.AI_MODEL_ID || (hasAtlasEnv ? process.env.ATLASCLOUD_MODEL || 'qwen/qwen3.5-flash' : undefined);

// 三个核心字段都必须有才能构建有效配置
if (!apiKey || !baseUrl || !modelId) return null;

const apiType = process.env.AI_API_TYPE || 'openai-completions';
const modelId2 = process.env.AI_MODEL_ID_2 || undefined;
const providerName = process.env.AI_PROVIDER_NAME || '自定义';
const modelId2 = process.env.AI_MODEL_ID_2 || (hasAtlasEnv ? process.env.ATLASCLOUD_MODEL_2 || undefined : undefined);
const providerName = process.env.AI_PROVIDER_NAME || (hasAtlasEnv ? 'Atlas Cloud' : '自定义');

// 根据 apiType 推断 providerType
const providerType = apiType === 'google-generative-ai' ? 'gemini'
: apiType === 'anthropic-messages' ? 'anthropic'
: hasAtlasEnv ? 'atlascloud'
: 'custom';

console.info('[ModelConfig] 使用环境变量中的模型配置(数据库中无配置)');
Expand Down
3 changes: 3 additions & 0 deletions src/main/tools/api-tool.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,14 @@ export const SetWorkspaceConfigSchema = Type.Object({
*/
export const SetModelConfigSchema = Type.Object({
providerType: Type.Optional(Type.Union([
Type.Literal('deepbot', { description: 'DeepBot' }),
Type.Literal('qwen', { description: '通义千问' }),
Type.Literal('deepseek', { description: 'DeepSeek' }),
Type.Literal('gemini', { description: 'Google Gemini' }),
Type.Literal('minimax', { description: 'MiniMax' }),
Type.Literal('atlascloud', { description: 'Atlas Cloud' }),
Type.Literal('custom', { description: '自定义提供商' }),
Type.Literal('anthropic', { description: 'Anthropic' }),
])),

providerId: Type.Optional(Type.String({
Expand Down
4 changes: 2 additions & 2 deletions src/main/tools/handlers/config-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export async function handleSetWorkspaceConfig(
*/
export async function handleSetModelConfig(
params: Partial<{
providerType: 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'custom' | 'anthropic';
providerType: 'deepbot' | 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'atlascloud' | 'custom' | 'anthropic';
providerId: string;
providerName: string;
baseUrl: string;
Expand Down Expand Up @@ -329,4 +329,4 @@ export async function handleSetWebSearchConfig(
} catch (error) {
return createErrorResponse(error, '设置 Web 搜索工具配置');
}
}
}
20 changes: 17 additions & 3 deletions src/renderer/components/settings/ModelConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import { showToast } from '../../utils/toast';
import { ApiKeyHelpModal } from './ApiKeyHelpModal';
import { getLanguage } from '../../i18n';

type ModelProviderType = 'deepbot' | 'atlascloud' | 'gemini' | 'custom' | 'anthropic';

interface ModelConfig {
providerType: 'deepbot' | 'gemini' | 'custom' | 'anthropic';
providerType: ModelProviderType;
providerId: string;
providerName: string;
baseUrl: string;
Expand Down Expand Up @@ -124,7 +126,7 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
};

// 处理提供商类型变化
const handleProviderTypeChange = (providerType: 'deepbot' | 'gemini' | 'custom' | 'anthropic') => {
const handleProviderTypeChange = (providerType: ModelProviderType) => {
const preset = PROVIDER_PRESETS[providerType];

setConfig({
Expand Down Expand Up @@ -281,10 +283,11 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
</label>
<select
value={config.providerType}
onChange={(e) => handleProviderTypeChange(e.target.value as 'deepbot' | 'gemini' | 'custom' | 'anthropic')}
onChange={(e) => handleProviderTypeChange(e.target.value as ModelProviderType)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="deepbot">{lang === 'zh' ? 'DeepBot(推荐)' : 'DeepBot (Recommended)'}</option>
<option value="atlascloud">Atlas Cloud</option>
<option value="custom">{lang === 'zh' ? 'OpenAI 兼容' : 'OpenAI Compatible'}</option>
<option value="gemini">{lang === 'zh' ? 'Google Gemini 兼容' : 'Google Gemini Compatible'}</option>
<option value="anthropic">{lang === 'zh' ? 'Anthropic 兼容' : 'Anthropic Compatible'}</option>
Expand All @@ -308,6 +311,8 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
? 'https://api.anthropic.com'
: config.providerType === 'gemini'
? 'https://generativelanguage.googleapis.com/v1beta'
: config.providerType === 'atlascloud'
? 'https://api.atlascloud.ai/v1'
: 'https://api.example.com/v1'
}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
Expand All @@ -317,6 +322,8 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
? (lang === 'zh' ? '输入 Anthropic 兼容的 API 地址,不含 /v1/messages(如 https://api.anthropic.com)' : 'Enter Anthropic-compatible API URL without /v1/messages (e.g. https://api.anthropic.com)')
: config.providerType === 'gemini'
? (lang === 'zh' ? '输入 Google Generative AI 格式的地址' : 'Enter Google Generative AI compatible URL')
: config.providerType === 'atlascloud'
? (lang === 'zh' ? 'Atlas Cloud 的 OpenAI 兼容 API 地址' : 'Atlas Cloud OpenAI-compatible API URL')
: config.providerType === 'custom'
? (lang === 'zh' ? '输入 OpenAI 兼容的 API 地址(如 https://api.openai.com/v1)' : 'Enter OpenAI-compatible API URL (e.g. https://api.openai.com/v1)')
: (lang === 'zh' ? '预设提供商的 API 地址(可修改)' : 'Preset provider API URL (editable)')}
Expand Down Expand Up @@ -407,6 +414,8 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
? 'gemini-3-pro-preview'
: config.providerType === 'anthropic'
? 'claude-sonnet-4-6'
: config.providerType === 'atlascloud'
? 'qwen/qwen3.5-flash'
: 'model-id'
}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
Expand All @@ -415,6 +424,7 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
<p className="mt-1 text-xs text-gray-500">
{config.providerType === 'deepbot' && (lang === 'zh' ? '推荐 DeepSeek V4 模型,从列表选择或输入自定义模型 ID' : 'DeepSeek V4 models recommended. Select from the list or enter a custom model ID')}
{config.providerType === 'custom' && (lang === 'zh' ? '输入 OpenAI 兼容的模型 ID' : 'Enter OpenAI-compatible model ID')}
{config.providerType === 'atlascloud' && (lang === 'zh' ? '输入 Atlas Cloud 模型 ID(如 qwen/qwen3.5-flash)' : 'Enter an Atlas Cloud model ID (e.g. qwen/qwen3.5-flash)')}
{config.providerType === 'anthropic' && (lang === 'zh' ? '输入 Claude 模型 ID(如 claude-sonnet-4-6)' : 'Enter Claude model ID (e.g. claude-sonnet-4-6)')}
{config.providerType === 'gemini' && (lang === 'zh' ? '输入 Gemini 模型 ID' : 'Enter Gemini model ID')}
</p>
Expand All @@ -438,6 +448,8 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
placeholder={
config.providerType === 'gemini'
? 'AIza...'
: config.providerType === 'atlascloud'
? 'your-api-key-here'
: config.providerType === 'anthropic' || config.apiType === 'anthropic-messages'
? 'sk-...'
: 'sk-...'
Expand All @@ -447,6 +459,8 @@ export function ModelConfig({ onClose, tabId }: ModelConfigProps) {
<p className="mt-1 text-xs text-gray-500">
{config.providerType === 'gemini'
? (lang === 'zh' ? 'Google AI Studio API Key(以 AIza 开头)将加密存储在本地' : 'Google AI Studio API Key (starts with AIza) will be encrypted and stored locally')
: config.providerType === 'atlascloud'
? (lang === 'zh' ? 'Atlas Cloud API Key 将加密存储在本地' : 'Atlas Cloud API Key will be encrypted and stored locally')
: config.providerType === 'anthropic' || config.apiType === 'anthropic-messages'
? (lang === 'zh' ? 'Anthropic API Key(用于 x-api-key 请求头)将加密存储在本地' : 'Anthropic API Key (used in x-api-key header) will be encrypted and stored locally')
: (lang === 'zh' ? 'API 密钥将加密存储在本地' : 'API key will be encrypted and stored locally')}
Expand Down
7 changes: 7 additions & 0 deletions src/shared/config/default-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export const PROVIDER_PRESETS = {
defaultModelId2: 'MiniMax-M2.5-highspeed', // 快速模型
apiType: 'openai-completions',
},
atlascloud: {
name: 'Atlas Cloud',
baseUrl: 'https://api.atlascloud.ai/v1',
defaultModelId: 'qwen/qwen3.5-flash',
defaultModelId2: 'qwen/qwen3.5-flash', // 快速模型
apiType: 'openai-completions',
},
custom: {
name: 'OpenAI 兼容',
baseUrl: 'https://api.openai.com/v1',
Expand Down
2 changes: 1 addition & 1 deletion src/types/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ export interface SetDefaultSkillDirResponse {

// 模型配置
export interface ModelConfig {
providerType: 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'custom' | 'anthropic'; // 提供商类型(用于 UI 下拉选择)
providerType: 'deepbot' | 'qwen' | 'deepseek' | 'gemini' | 'minimax' | 'atlascloud' | 'custom' | 'anthropic'; // 提供商类型(用于 UI 下拉选择)
providerId: string;
providerName: string;
baseUrl: string;
Expand Down