feat: add API Route setup wizard preset (#6579)

* feat: add API Route setup wizard preset

Signed-off-by: dennyho0917 <dennyho0917@gmail.com>

* fix: address API Route wizard review feedback

Signed-off-by: dennyho0917 <dennyho0917@gmail.com>

---------

Signed-off-by: dennyho0917 <dennyho0917@gmail.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
DennyHo0917 2026-10-18 09:26:45 +08:00 committed by GitHub
parent 829edac602
commit 513c03e8c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 92 additions and 0 deletions

View File

@ -328,6 +328,13 @@ streams simulate chunks from a non-streaming response, while no-tool streams sta
api_key: $OPPER_API_KEY
base_url: https://api.opper.ai/v3/compat
- name: api-route-gpt-6.1-sol
display_name: GPT 6.1 Sol (API Route)
use: langchain_openai:ChatOpenAI
model: gpt-6.1-sol
api_key: $API_ROUTE_API_KEY
base_url: https://global.api-route.com/v1
- name: gpt-5-responses
display_name: GPT-5 (Responses API)
use: langchain_openai:ChatOpenAI
@ -351,6 +358,8 @@ streams simulate chunks from a non-streaming response, while no-tool streams sta
OpenRouter and similar OpenAI-compatible gateways should be configured with `langchain_openai:ChatOpenAI` plus `base_url`. If you prefer a provider-specific environment variable name, point `api_key` at that variable explicitly (for example `api_key: $OPENROUTER_API_KEY`).
[API Route](https://www.api-route.com) is also available in the setup wizard. It saves your key as `API_ROUTE_API_KEY` and uses the Chat Completions endpoint above. Model availability depends on your key's group and permissions; check the authenticated `GET https://global.api-route.com/v1/models` catalog before replacing the model in `config.yaml`, and use its returned ID unchanged without an upstream provider prefix.
The `write_file` tool's output-budget hint uses the active model's effective `max_tokens`. Missing or unusable limits, including YAML `.inf`, `-.inf`, `.nan`, and values too large for the character estimate, omit this hint without failing tool assembly; provider-specific model validation still applies.
To route OpenAI models through `/v1/responses`, keep using `langchain_openai:ChatOpenAI` and set `use_responses_api: true` with `output_version: responses/v1`.

View File

@ -179,6 +179,13 @@ YAML 同名模型优先,已有任务保留原配置快照。托管模型使用
api_key: $OPPER_API_KEY
base_url: https://api.opper.ai/v3/compat
- name: api-route-gpt-6.1-sol
display_name: GPT 6.1 Sol (API Route)
use: langchain_openai:ChatOpenAI
model: gpt-6.1-sol
api_key: $API_ROUTE_API_KEY
base_url: https://global.api-route.com/v1
- name: gpt-5-responses
display_name: GPT-5 (Responses API)
use: langchain_openai:ChatOpenAI
@ -202,6 +209,8 @@ YAML 同名模型优先,已有任务保留原配置快照。托管模型使用
OpenRouter 以及类似的 OpenAI 兼容网关,建议通过 `langchain_openai:ChatOpenAI` 配合 `base_url` 来配置。如果你更想用 provider 自己的环境变量名,也可以直接把 `api_key` 指向对应变量,例如 `api_key: $OPENROUTER_API_KEY`。
Setup Wizard 也支持 [API Route](https://www.api-route.com),会将密钥保存为 `API_ROUTE_API_KEY`,并使用上面的 Chat Completions 端点。可用模型取决于密钥所属组别和权限;修改 `config.yaml` 中的模型前,请先查询需要认证的 `GET https://global.api-route.com/v1/models` 模型目录,并原样使用返回的模型 ID,不要添加上游 provider 前缀。
如果要让 OpenAI 模型走 `/v1/responses`,继续使用 `langchain_openai:ChatOpenAI`,并设置 `use_responses_api: true` 和 `output_version: responses/v1`。
如果某个模型的 provider 约定与 DeerFlow 通用的 thinking/effort 假设不同,可以为该模型声明 `reasoning:` 块(thinking 为 `unsupported`/`optional`/`required`、允许的 effort 取值及别名和默认值、payload 方言、推理历史要求)。Setup Wizard 内置的 Z.AI GLM-5.3-Flash 配置就使用了它:前台和后台调用都会保持 thinking 开启,effort 选择器只提供该模型自己的 `low`/`high`/`max` 档位。未声明该块的配置行为保持不变。具体格式与等价的手动配置见 `config.example.yaml`。

View File

@ -0,0 +1,57 @@
"""API Route setup uses the existing OpenAI-compatible wizard path."""
import yaml
from wizard.providers import LLM_PROVIDERS
from wizard.steps import llm as llm_step
from wizard.writer import build_minimal_config
def api_route_provider():
provider = next((p for p in LLM_PROVIDERS if p.name == "api_route"), None)
assert provider is not None
return provider
def test_api_route_uses_versioned_chat_endpoint_and_bare_model_id():
provider = api_route_provider()
assert provider.use == "langchain_openai:ChatOpenAI"
assert provider.package == "langchain-openai"
assert provider.env_var == "API_ROUTE_API_KEY"
assert provider.models == ["gpt-6.1-sol"]
assert provider.default_model == "gpt-6.1-sol"
assert provider.extra_config["base_url"] == "https://global.api-route.com/v1"
def test_api_route_generated_config_preserves_key_reference_and_model():
provider = api_route_provider()
config = yaml.safe_load(
build_minimal_config(
provider_use=provider.use,
model_name=provider.default_model,
display_name=provider.display_name,
api_key_field=provider.api_key_field,
env_var=provider.env_var,
extra_model_config=provider.extra_config_for(provider.default_model),
)
)
model = config["models"][0]
assert model["model"] == "gpt-6.1-sol"
assert model["api_key"] == "$API_ROUTE_API_KEY"
assert model["base_url"] == "https://global.api-route.com/v1"
assert model["use"] == "langchain_openai:ChatOpenAI"
assert model["temperature"] == 0.7
assert "use_responses_api" not in model
assert not model.get("supports_vision", False)
assert not model.get("supports_thinking", False)
def test_api_route_wizard_selects_preset_and_collects_key(monkeypatch):
provider = api_route_provider()
monkeypatch.setattr(llm_step, "LLM_PROVIDERS", [provider])
monkeypatch.setattr(llm_step, "ask_choice", lambda *_args, **_kwargs: 0)
monkeypatch.setattr(llm_step, "ask_secret", lambda prompt: "test-api-route-key" if prompt == "API_ROUTE_API_KEY" else None)
result = llm_step.run_llm_step()
assert result.model_name == "gpt-6.1-sol"
assert result.provider.extra_config["base_url"] == "https://global.api-route.com/v1"
assert result.provider.env_var == "API_ROUTE_API_KEY"
assert result.api_key == "test-api-route-key"

View File

@ -512,6 +512,23 @@ LLM_PROVIDERS: list[LLMProvider] = [
"temperature": 0.7,
},
),
LLMProvider(
name="api_route",
display_name="API Route",
description="OpenAI-compatible gateway (models depend on your API key)",
use="langchain_openai:ChatOpenAI",
models=["gpt-6.1-sol"],
default_model="gpt-6.1-sol",
env_var="API_ROUTE_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://global.api-route.com/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"temperature": 0.7,
},
),
LLMProvider(
name="vllm",
display_name="vLLM",