| import { config } from "./config"; |
|
|
| export type AdapterId = |
| | "anthropic" |
| | "openai" |
| | "gemini" |
| | "deepseek" |
| | "kimi" |
| | "zhipu" |
| | "minimax" |
| | "qwen" |
| | "codex-cli"; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| export type ModelSource = |
| | "replit-integration" |
| | "byok-direct" |
| | "china-direct"; |
|
|
| export interface ModelInfo { |
| id: string; |
| name: string; |
| provider: string; |
| description: string; |
| context_length: number; |
| capabilities: Array<"text" | "vision" | "tools" | "streaming">; |
| pricing: { input_per_1k: number; output_per_1k: number }; |
| default: boolean; |
| available: boolean; |
| |
| tier: "S" | "A"; |
| adapter: AdapterId; |
| upstreamModel: string; |
| |
| |
| |
| |
| |
| sources: ModelSource[]; |
| } |
|
|
| const ALL_MODELS: ModelInfo[] = [ |
| |
| { |
| id: "mdl_claude-sonnet-4-6", |
| name: "DoAtlas Pro", |
| provider: "DoAtlas", |
| description: |
| "旗舰研究模型,深度推理与代码能力最强,适合复杂文献综述、机制推理与多步分析。", |
| context_length: 200_000, |
| capabilities: ["text", "vision", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "S", |
| adapter: "anthropic", |
| upstreamModel: "claude-sonnet-4-6", |
| sources: ["replit-integration", "byok-direct"], |
| }, |
| { |
| id: "mdl_gpt-5_2", |
| name: "DoAtlas Pro X", |
| provider: "DoAtlas", |
| description: |
| "多模态旗舰模型,视觉与文本兼顾,适合图表解读、影像分析与通用研究问答。", |
| context_length: 128_000, |
| capabilities: ["text", "vision", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "S", |
| adapter: "openai", |
| upstreamModel: "gpt-5.2", |
| sources: ["replit-integration", "byok-direct"], |
| }, |
| { |
| id: "mdl_gemini-2_5-pro", |
| name: "DoAtlas Vision", |
| provider: "DoAtlas", |
| description: |
| "Gemini 2.5 Pro 多模态旗舰,超长上下文与图表理解,适合长文档解析与多模态研究问答。", |
| context_length: 1_000_000, |
| capabilities: ["text", "vision", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "S", |
| adapter: "gemini", |
| upstreamModel: "gemini-2.5-pro", |
| sources: ["replit-integration", "byok-direct"], |
| }, |
| { |
| id: "mdl_deepseek-r1", |
| name: "DoAtlas Reason Pro", |
| provider: "DoAtlas", |
| description: |
| "DeepSeek R1 推理模型,专注链式推理与数学/科学论证,适合机制假设与复杂证据综合。", |
| context_length: 128_000, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "S", |
| adapter: "deepseek", |
| upstreamModel: "deepseek-reasoner", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_codex-cli", |
| name: "DoAtlas Code", |
| provider: "DoAtlas Local", |
| description: |
| "本地代码助手,运行在你自己的机器上,可读写本地文件与执行命令;需在本地部署中配置。", |
| context_length: 200_000, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "S", |
| adapter: "codex-cli", |
| upstreamModel: "codex-cli", |
| sources: ["byok-direct"], |
| }, |
|
|
| |
| { |
| id: "mdl_glm-4_6", |
| name: "DoAtlas Air", |
| provider: "DoAtlas", |
| description: |
| "智谱 GLM-4 系列,长上下文 128k,响应快速,适合日常问答与长文本处理。", |
| context_length: 131_072, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "zhipu", |
| upstreamModel: "glm-4-plus", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_minimax-m2", |
| name: "DoAtlas Search", |
| provider: "DoAtlas", |
| description: |
| "MiniMax M2 智能体模型,配合统一 web_search 工具实现实时联网检索,适合需要最新资料的研究问答。", |
| context_length: 200_000, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "minimax", |
| upstreamModel: "MiniMax-M2.7-highspeed", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_deepseek-v3", |
| name: "DoAtlas Chat", |
| provider: "DoAtlas", |
| description: |
| "DeepSeek V3 通用对话模型,性价比高,适合日常问答与代码补全。", |
| context_length: 128_000, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "deepseek", |
| upstreamModel: "deepseek-chat", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_kimi-k2", |
| name: "DoAtlas Long", |
| provider: "DoAtlas", |
| description: |
| "Kimi 长文本模型,超长上下文与文档检索能力强,适合大文档/多 PDF 阅读。", |
| context_length: 256_000, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "kimi", |
| upstreamModel: "kimi-k2-0905-preview", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_qwen-max", |
| name: "DoAtlas Bilingual", |
| provider: "DoAtlas", |
| description: |
| "通义千问 Max 双语通用模型,中英推理与工具调用稳定,适合中文研究场景。", |
| context_length: 131_072, |
| capabilities: ["text", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "qwen", |
| upstreamModel: "qwen-max", |
| sources: ["china-direct"], |
| }, |
| { |
| id: "mdl_gemini-2_5-flash", |
| name: "DoAtlas Vision Lite", |
| provider: "DoAtlas", |
| description: |
| "Gemini 2.5 Flash 轻量多模态模型,速度快、成本低,适合实时问答与轻量视觉任务。", |
| context_length: 1_000_000, |
| capabilities: ["text", "vision", "tools", "streaming"], |
| pricing: { input_per_1k: 0, output_per_1k: 0 }, |
| default: false, |
| available: false, |
| tier: "A", |
| adapter: "gemini", |
| upstreamModel: "gemini-2.5-flash", |
| sources: ["replit-integration", "byok-direct"], |
| }, |
| ]; |
|
|
| |
| |
| |
| |
| function sourceAvailable(adapter: AdapterId, source: ModelSource): boolean { |
| switch (adapter) { |
| case "anthropic": |
| if (source === "replit-integration") return config.hasAnthropicCloud; |
| if (source === "byok-direct") return config.hasAnthropicDirect; |
| return false; |
| case "openai": |
| if (source === "replit-integration") return config.hasOpenAICloud; |
| if (source === "byok-direct") return config.hasOpenAIDirect; |
| return false; |
| case "gemini": |
| if (source === "replit-integration") return config.hasGeminiCloud; |
| if (source === "byok-direct") return config.hasGeminiDirect; |
| return false; |
| case "deepseek": |
| return source === "china-direct" && config.hasDeepseek; |
| case "kimi": |
| return source === "china-direct" && config.hasKimi; |
| case "zhipu": |
| return source === "china-direct" && config.hasZhipu; |
| case "minimax": |
| return source === "china-direct" && config.hasMinimax; |
| case "qwen": |
| return source === "china-direct" && config.hasQwen; |
| case "codex-cli": |
| return source === "byok-direct" && config.hasCodexCli; |
| default: |
| return false; |
| } |
| } |
|
|
| function isAvailable(m: ModelInfo): boolean { |
| return m.sources.some((s) => sourceAvailable(m.adapter, s)); |
| } |
|
|
| |
| |
| |
| |
| export function resolveSource(m: ModelInfo): ModelSource | null { |
| for (const s of m.sources) { |
| if (sourceAvailable(m.adapter, s)) return s; |
| } |
| return null; |
| } |
|
|
| export function listModels(): ModelInfo[] { |
| const profile = config.profile; |
| const out = ALL_MODELS.map((m) => ({ |
| ...m, |
| available: isAvailable(m), |
| })); |
| |
| |
| |
| const preferCloud = profile === "cloud"; |
| const candidates = preferCloud |
| ? out.filter( |
| (m) => |
| m.available && |
| m.sources.some((s) => s === "replit-integration" || s === "byok-direct"), |
| ) |
| : out.filter((m) => m.available); |
| const first = candidates[0] ?? out.find((m) => m.available); |
| if (first) { |
| const target = out.find((m) => m.id === first.id); |
| if (target) target.default = true; |
| } |
| return out; |
| } |
|
|
| export function findModel(id: string | null | undefined): ModelInfo | null { |
| if (!id) return null; |
| return listModels().find((m) => m.id === id) ?? null; |
| } |
|
|
| export function pickDefaultModel(): ModelInfo | null { |
| return listModels().find((m) => m.default) ?? null; |
| } |
|
|
| export function publicModel(m: ModelInfo) { |
| |
| const { tier: _t, adapter: _a, upstreamModel: _u, sources: _s, ...pub } = m; |
| return pub; |
| } |
|
|