## Problem
Two audits of the repository (a workflow of finder, dedup and per-file verifier agents, run on 2026-10-11 against 1f4141e and again against 07f3e3c after a first round of refactoring) found dead code and features that were more machinery than the app needs: an Electron configuration-preset system with its own settings window, three copies of the about page, a hand-written `.env` parser, an "extended" system prompt nobody selected, two data migrations for formats from 2025-12 and 2026-01, a server-side example cache, type-to-confirm provider deletion, 81 unused dictionary keys, wrapper components around single call sites, and a long tail of unused exports, props, options and tests.
## Change
Every item below was either approved one by one or covered by "fix all of the others".
- **Electron:** the configuration-preset system is gone (settings window, preload, IPC, menu entry, dev watcher); `config-manager.ts` keeps only `userLocale`; `.env` files are parsed with `dotenv`. Entitlements file and a duplicate CI workflow removed; `test.yml` gets a type check and concurrency.
- **Server:** no extended prompt, no example cache, no `ENABLE_HISTORY_XML_REPLACE`, no message metadata or `hasConfig`; the connection test is one shared helper; EdgeOne loses its mock branch and model aliases; `DEBUG_LLM_PAYLOAD` logs message structure instead of payloads; Langfuse scoring helper; `apiKeyEnv` arrays kept and documented in `env.example` and the provider docs.
- **Pages:** one about page per language from a single component (old `/cn` and `/ja` URLs redirect with 308); layout uses `hasLocale`; the GitHub icon is a local component instead of `react-icons`; Cloudflare deploys without an R2 cache by default.
- **Chat and canvas:** the legacy `diagramHistory` conversion, the localStorage chat migration and the templates storage are gone; `chat-engine` reads the diagram through the context's refs; the diagram context has one tagged export path (`requestTaggedExport` / `fetchDiagramXml`); the screenshot check uses fetch + JSON and `generateText` with `Output.object`; `load-diagram` accepts `<svg:svg>` and strips the XML prolog.
- **Settings UI:** `model-selector` inlines its Dialog, Command and Tooltip; `ai-elements/model-selector`, `button-with-tooltip`, `error-toast` removed; no type-to-confirm, no footer, no `bedrockApiKey`; `use-model-config` loses the old-format migration; one reasoning component; the shimmer is CSS (no `motion`, no `@radix-ui/react-use-controllable-state`); 81 dictionary keys removed in all four languages.
- **MCP server:** `registerTool` / `ok` / `fail` replace per-tool try/catch; `syncFromBrowser`, `commitDocument`, `describePages`; the hand-written XML syntax check, unused result fields, `pickPageSelector`, `expandStyles` and the `host` attribute handling are gone; tests get a shared `setup.ts` and drive the server through the SDK client.
- **Prompt:** the web app's style rules come from the MCP drawing guide (`styleRules`), byte-identical to before.
- **Tests:** shared e2e helpers (`openApp`, `sse`, `toolCallEvents`, `chunkedReplies`); placeholder specs dropped; `settings-review-fixes` split by topic; unit tests use `vi.stubEnv`.
- **Dependencies removed:** `@xmldom/xmldom`, `remark-gfm`, `@anthropic-ai/tokenizer`, `@testing-library/user-event`, `concurrently`, `wait-on`, `eslint`, `eslint-config-next`, `@vitest/coverage-v8`, `shx`, `motion`, `@radix-ui/react-use-controllable-state`, `react-icons`.
Source lines: 74,983 before, 67,418 after (excluding lockfiles).
The last commit merges #984 (the canvas shell). Where the shell, the classic page or their tests depend on a wire format or signature this branch had changed, main's version wins (export fields of the poll response, `addHistory` signature); where main only extended code this branch restructured, main's change is carried into the new structure (`start_session`, `get_selection`, `prepareNewDiagram`, the diagram context's `requestExport`).
## Testing
- `tsc --noEmit` for the web app, `packages/mcp-server`, its shell and `electron`: clean
- `biome ci`: 0 errors (37 pre-existing warnings)
- Root `vitest run`: 719 passed; `packages/mcp-server` `vitest run`: 372 passed
- `next build`: clean
- Playwright, whole web suite on the dev server (4 workers): 280 tests, 279 passed; `language.spec.ts` "a stale offer to switch without saving does nothing once a message is being sent" failed under parallel load and passed alone, as it does on main
11 KiB
AI 提供商配置
本指南介绍如何为 next-ai-draw-io 配置不同的 AI 模型提供商。
快速开始
- 将
.env.example复制为.env.local - 设置所选提供商的 API 密钥
- 将
AI_MODEL设置为所需的模型 - 运行
npm run dev
支持的提供商
豆包 (字节跳动火山引擎)
DOUBAO_API_KEY=your_api_key
AI_MODEL=doubao-seed-1-8-251215 # 或其他豆包模型
Google Gemini
GOOGLE_GENERATIVE_AI_API_KEY=your_api_key
AI_MODEL=gemini-2.0-flash
可选的自定义端点:
GOOGLE_BASE_URL=https://your-custom-endpoint
OpenAI
OPENAI_API_KEY=your_api_key
AI_MODEL=gpt-4o
可选的自定义端点(用于 OpenAI 兼容服务):
OPENAI_BASE_URL=https://your-custom-endpoint/v1
LM Studio 等本地 OpenAI 兼容服务也用同样的方式:把 base URL 设为 http://localhost:1234/v1(LM Studio 的默认端口),API 密钥填任意非空值即可,例如 lm-studio。在上面的环境变量或模型设置里配置都可以。
AIHubMix
AIHubMix 通过单个 API Key 聚合 Claude、GPT、Gemini、DeepSeek 等模型。
AIHUBMIX_API_KEY=your_api_key
AI_MODEL=claude-sonnet-4-5-20250929
可选的自定义端点:
AIHUBMIX_BASE_URL=https://aihubmix.com/v1
Anthropic
ANTHROPIC_API_KEY=your_api_key
AI_MODEL=claude-sonnet-4-5-20250514
或者使用 Bearer 认证令牌(例如通过会下发 OAuth 风格 token 的网关时)。ANTHROPIC_AUTH_TOKEN 会作为 Authorization: Bearer <token> 头发送,而 ANTHROPIC_API_KEY 会作为 x-api-key 头发送。两者互斥,只能设置其中之一:
ANTHROPIC_AUTH_TOKEN=your_auth_token
AI_MODEL=claude-sonnet-4-5-20250514
可选的自定义端点:
ANTHROPIC_BASE_URL=https://your-custom-endpoint
DeepSeek
DEEPSEEK_API_KEY=your_api_key
AI_MODEL=deepseek-chat
可选的自定义端点:
DEEPSEEK_BASE_URL=https://your-custom-endpoint
SiliconFlow (OpenAI 兼容)
SILICONFLOW_API_KEY=your_api_key
AI_MODEL=deepseek-ai/DeepSeek-V3 # 示例;使用任何 SiliconFlow 模型 ID
可选的自定义端点(默认为推荐域名):
SILICONFLOW_BASE_URL=https://api.siliconflow.com/v1 # 或 https://api.siliconflow.cn/v1
SGLang
SGLANG_API_KEY=your_api_key
AI_MODEL=your_model_id
可选的自定义端点:
SGLANG_BASE_URL=https://your-custom-endpoint/v1
Azure OpenAI
AZURE_API_KEY=your_api_key
AZURE_RESOURCE_NAME=your-resource-name # 必填:您的 Azure 资源名称
AI_MODEL=your-deployment-name
或者使用自定义端点代替资源名称:
AZURE_API_KEY=your_api_key
AZURE_BASE_URL=https://your-resource.openai.azure.com # AZURE_RESOURCE_NAME 的替代方案
AI_MODEL=your-deployment-name
可选的推理配置:
AZURE_REASONING_EFFORT=low # 可选:low, medium, high
AZURE_REASONING_SUMMARY=detailed # 可选:none, brief, detailed
AWS Bedrock
AWS_REGION=us-west-2
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AI_MODEL=global.anthropic.claude-sonnet-5-5
较新的 Claude 模型只能通过推理配置文件(inference profile)的 ID 调用,这种 ID 以地区前缀开头,例如 global. 或 us.。直接用 anthropic.claude-sonnet-5-5 这样的 ID 会报错 “on-demand throughput isn't supported”。
注意:在 AWS 环境(Lambda、带有 IAM 角色的 EC2)中,凭证会自动从 IAM 角色获取。
OpenRouter
OPENROUTER_API_KEY=your_api_key
AI_MODEL=anthropic/claude-sonnet-4
可选的自定义端点:
OPENROUTER_BASE_URL=https://your-custom-endpoint
Ollama (本地)
AI_PROVIDER=ollama
AI_MODEL=llama3.2
ModelScope
MODELSCOPE_API_KEY=your_api_key
AI_MODEL=Qwen/Qwen3-235B-A22B-Instruct-2507
可选的自定义端点:
MODELSCOPE_BASE_URL=https://your-custom-endpoint
可选的自定义 URL:
OLLAMA_BASE_URL=http://localhost:11434/api
Vercel AI Gateway
Vercel AI Gateway 通过单个 API 密钥提供对多个 AI 提供商的统一访问。这简化了身份验证,让您无需管理多个 API 密钥即可在不同提供商之间切换。
基本用法(Vercel 托管网关):
AI_GATEWAY_API_KEY=your_gateway_api_key
AI_MODEL=openai/gpt-4o
自定义网关 URL(用于本地开发或自托管网关):
AI_GATEWAY_API_KEY=your_custom_api_key
AI_GATEWAY_BASE_URL=https://your-custom-gateway.com/v1/ai
AI_MODEL=openai/gpt-4o
模型格式使用 provider/model 语法:
openai/gpt-4o- OpenAI GPT-4oanthropic/claude-sonnet-4-5- Anthropic Claude Sonnet 4.5google/gemini-2.0-flash- Google Gemini 2.0 Flash
配置说明:
- 如果未设置
AI_GATEWAY_BASE_URL,则使用默认的 Vercel Gateway URL (https://ai-gateway.vercel.sh/v1/ai) - 自定义基础 URL 适用于:
- 使用自定义网关实例进行本地开发
- 自托管 AI Gateway 部署
- 企业代理配置
- 当使用自定义基础 URL 时,必须同时提供
AI_GATEWAY_API_KEY
从 Vercel AI Gateway 仪表板 获取您的 API 密钥。
MiniMax
MiniMax 支持两种 API 格式:
- Anthropic 兼容(
/anthropic端点)— 推荐,支持 interleaved thinking - OpenAI 兼容(
/v1端点)— 标准 OpenAI 聊天补全格式
MINIMAX_API_KEY=your_api_key
AI_MODEL=MiniMax-M3
可选配置:
# 中国大陆版,Anthropic 兼容(默认)
MINIMAX_BASE_URL=https://api.minimaxi.com/anthropic
# 中国大陆版,OpenAI 兼容
MINIMAX_BASE_URL=https://api.minimaxi.com/v1
# 国际版,Anthropic 兼容
MINIMAX_BASE_URL=https://api.minimax.io/anthropic
# 国际版,OpenAI 兼容
MINIMAX_BASE_URL=https://api.minimax.io/v1
GLM (智谱 AI)
GLM_API_KEY=your_api_key
AI_MODEL=glm-4
可选的自定义端点:
GLM_BASE_URL=https://your-custom-endpoint
Qwen (阿里云通义千问)
QWEN_API_KEY=your_api_key
AI_MODEL=qwen-turbo
可选的自定义端点:
QWEN_BASE_URL=https://your-custom-endpoint
Kimi (月之暗面 Moonshot AI)
KIMI_API_KEY=your_api_key
AI_MODEL=kimi-latest
可选的自定义端点:
KIMI_BASE_URL=https://your-custom-endpoint
Qiniu (七牛云)
QINIU_API_KEY=your_api_key
AI_MODEL=your_model_id
可选的自定义端点:
QINIU_BASE_URL=https://your-custom-endpoint
MiMo (小米)
MIMO_API_KEY=your_api_key
AI_MODEL=mimo-v2.5-pro
可选的自定义端点(Token Plan 订阅用户请设置专属 Base URL):
MIMO_BASE_URL=https://token-plan-cn.xiaomimimo.com/v1
自动检测
如果您只配置了一个提供商的 API 密钥,系统将自动检测并使用该提供商。无需设置 AI_PROVIDER。
如果您配置了多个 API 密钥,则必须显式设置 AI_PROVIDER:
AI_PROVIDER=google # 或:openai, anthropic, aihubmix, deepseek, siliconflow, doubao, azure, bedrock, openrouter, ollama, gateway, sglang, modelscope, minimax, glm, qwen, kimi, qiniu, mimo
服务端多模型配置
管理员可以配置多个服务端模型,让所有用户无需提供个人 API Key 即可使用。
配置方式
方式一:环境变量(推荐用于云部署)
设置 AI_MODELS_CONFIG 为 JSON 字符串:
AI_MODELS_CONFIG='{"providers":[{"name":"OpenAI","provider":"openai","models":["gpt-4o"],"default":true}]}'
方式二:配置文件
在项目根目录创建 ai-models.json 文件(或通过 AI_MODELS_CONFIG_PATH 指定路径)。
方式三:AI_MODEL 用逗号分隔(单 provider 的快速配置)
如果只需要暴露同一 provider 下的多个模型,可以直接在 AI_MODEL 里用逗号分隔。第一个模型会作为默认值。
AI_PROVIDER=doubao
AI_MODEL=doubao-seed-1-8-251215,doubao-seed-1-6-flash,doubao-seed-1-6-pro
这是等价 ai-models.json 的简写形式。如果需要配置多个 provider,或自定义 apiKeyEnv / baseUrlEnv,请使用方式一或方式二。
配置示例
{
"providers": [
{
"name": "OpenAI Production",
"provider": "openai",
"models": ["gpt-4o", "gpt-4o-mini"],
"default": true
},
{
"name": "Custom DeepSeek",
"provider": "deepseek",
"models": ["deepseek-chat"],
"apiKeyEnv": "MY_DEEPSEEK_KEY",
"baseUrlEnv": "MY_DEEPSEEK_URL"
}
]
}
字段说明
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 显示名称(支持同一提供商多个配置) |
provider |
是 | 提供商类型(openai, anthropic, google, bedrock 等) |
models |
是 | 模型 ID 列表 |
default |
否 | 设为 true 表示默认选中该提供商的第一个模型 |
apiKeyEnv |
否 | 自定义 API Key 环境变量名(默认使用提供商标准变量如 OPENAI_API_KEY)。也可以写成环境变量名数组,每次请求从有值的变量中随机选一个,把负载分摊到多个 Key 上 |
baseUrlEnv |
否 | 自定义 Base URL 环境变量名 |
说明
- API Key 和凭证通过环境变量提供。默认使用标准变量名(如
OPENAI_API_KEY),也可通过apiKeyEnv指定自定义变量名。 name字段允许同一提供商多个配置(例如 "OpenAI Production" 和 "OpenAI Staging" 都使用provider: "openai"但apiKeyEnv不同)。- 如果配置不存在,应用会回退到
AI_PROVIDER/AI_MODEL环境变量配置。
模型能力要求
此任务对模型能力要求极高,因为它涉及生成具有严格格式约束(draw.io XML)的长文本。
推荐模型:
- Claude Sonnet 4.5 / Opus 4.5
关于 Ollama 的说明:虽然支持将 Ollama 作为提供商,但除非您在本地运行像 DeepSeek R1 或 Qwen3-235B 这样的高性能模型,否则对于此用例通常不太实用。
温度设置 (Temperature)
您可以通过环境变量选择性地配置温度:
TEMPERATURE=0 # 输出更具确定性(推荐用于图表)
重要提示:对于不支持温度设置的模型(例如以下模型),请勿设置 TEMPERATURE:
- GPT-5.1 和其他推理模型
- 某些专用模型
未设置时,模型将使用其默认行为。
推荐
- 最佳体验:使用支持视觉的模型(GPT-4o, Claude, Gemini)以获得图像转图表功能
- 经济实惠:DeepSeek 提供具有竞争力的价格
- 隐私保护:使用 Ollama 进行完全本地、离线的操作(需要强大的硬件支持)
- 灵活性:OpenRouter 通过单一 API 提供对众多模型的访问