背景
用户痛点不是“在 TUI 里管理 provider 配置”,而是“已经写进 bytemind 配置的 provider/model,不能在 TUI 里方便切换”。
这次设计保持克制:配置文件负责增加/删除 provider 和 model;TUI 只负责读取、展示、选择当前运行目标。
设计原则
- 配置是 provider/model 列表的唯一来源。
- TUI 不提供
/add model,也不提供 delete,避免误改或破坏配置文件。
- 入口统一为
/model,不再拆成 /models 和 /model picker。
current_provider 必须始终指向当前实际运行模型所在的 provider。
- Provider 和 model 是两个层级,但 TUI 可以用一个
provider/model 列表完成选择。
- 尽量复用现有
provider_runtime、Runner.UpdateProviderRuntime、ListModels、model modal 和 token usage 逻辑。
Provider / Model 层级
Provider 是服务商、协议、端点和账号这一层,例如 deepseek、openai、anthropic、gemini 或一个私有 OpenAI-compatible 网关。
Provider 负责:
- 协议类型:OpenAI-compatible / Anthropic / Gemini。
base_url、api_key / api_key_env、auth header/scheme。
- provider-specific
ListModels、usage 拉取、health check 等能力。
- 当前 provider 下选中的 model。
Model 是 provider 下面的模型 ID 和模型能力这一层,例如 deepseek-v4-flash、deepseek-v4-pro、gpt-5.4-mini。
Model 负责:
- 请求里的
model 字段。
- context window / max output / tools / vision 等 metadata。
- token budget 和后续可能的价格元数据。
因此,base_url 和 key 不属于 model,应该属于 provider。切换 provider 和切换 model 在内部不是一回事:
- 同 provider 下切 model:只更新该 provider 的
model。
- 切到另一个 provider/model:更新
current_provider,并更新目标 provider 的 model。
对用户来说,TUI 可以统一展示为选择一个 provider/model 目标;对实现来说,要保持 provider/model 两层边界。
配置设计
建议把 provider_runtime.current_provider 作为对外语义。为兼容现有配置,可读取旧的 default_provider/default_model 作为 fallback,但写回时优先统一成 current 语义。
当前实际运行模型由这两个值共同决定:
- 当前 provider:
provider_runtime.current_provider
- 当前 model:
provider_runtime.providers[current_provider].model
最小结构:
{
"provider_runtime": {
"current_provider": "deepseek",
"providers": {
"deepseek": {
"type": "openai-compatible",
"base_url": "https://api.deepseek.com",
"api_key_env": "DEEPSEEK_API_KEY",
"model": "deepseek-v4-flash",
"models": ["deepseek-v4-flash", "deepseek-v4-pro"]
},
"openai": {
"type": "openai-compatible",
"base_url": "https://api.openai.com/v1",
"api_key_env": "OPENAI_API_KEY",
"model": "gpt-5.4-mini",
"models": ["gpt-5.4-mini"]
}
}
}
}
说明:
current_provider 决定当前运行 provider。
providers.<id>.model 是该 provider 当前选中的 model。
providers.<id>.models 是该 provider 可在 TUI 中切换的 model 列表。
- 如果
models 为空或缺失,就把 model 当作唯一候选,保证旧配置可用。
- 先不做 TUI 写入新 provider/model;用户要加 provider 或 model,就编辑配置文件。
默认 DeepSeek
默认配置内建 DeepSeek,后续可再改默认 provider:
current_provider: deepseek
model: deepseek-v4-flash
base_url: https://api.deepseek.com
api_key_env: DEEPSEEK_API_KEY
同步更新 config.example.json 和 DeepSeek 默认/fallback model,避免新用户默认落到旧模型名。
TUI 交互
合并当前 /models 和 /model picker 为一个 /model 面板,行为类似 /session:
- 输入
/model 打开模型选择面板。
- 面板自动读取当前配置文件中的所有 provider 和 model。
- 上下键选择
provider/model。
- Enter 即切换当前运行目标。
- 如果选择同 provider 下的 model,只保存该 provider 的
model。
- 如果选择另一个 provider 下的 model,保存
current_provider 和目标 provider 的 model。
- Esc 关闭。
- 面板中标记当前运行项,例如
current。
/models、/model picker 如需兼容,可作为 /model 的别名,但不再有单独语义。
- 移除或隐藏
/add model、/delete model,避免 TUI 负责配置增删。
运行时切换
切换时继续复用现有链路,范围控制在“选择已有配置项”:
- 从配置构建候选
provider/model 列表。
- 选择后更新
current_provider 和对应 providers[provider].model。
- 重建当前 runtime client。
- 调用
Runner.UpdateProviderRuntime。
- 写回配置文件。
如果配置中的 current_provider 不存在,应在启动或打开 /model 时给出明确错误,不要静默运行到别的 provider。
token usage 接入
切换后保持现有 token usage 行为:
- 后续请求使用新的 provider/model。
- usage record 记录新的 model 名称;如需要 provider 维度,记录或推导当前 provider。
- provider-specific 的远端 usage 拉取应跟随
current_provider,因为不同 provider 的 usage API 不同。
- token usage badge 不因切换模型清零。
- token budget 根据当前 model metadata/context window 刷新;没有 metadata 时回退
token_quota。
config.json 配置模板
{
"provider_runtime": {
"current_provider": "deepseek",
"providers": {
"deepseek": {
"type": "openai-compatible",
"base_url": "https://api.deepseek.com",
"api_key_env": "DEEPSEEK_API_KEY",
"model": "deepseek-v4-flash",
"models": [
"deepseek-v4-flash",
"deepseek-v4-pro"
]
},
"openai": {
"type": "openai-compatible",
"base_url": "https://api.openai.com/v1",
"api_key_env": "OPENAI_API_KEY",
"model": "gpt-5.4-mini",
"models": [
"gpt-5.4-mini",
"gpt-5.4"
]
}
}
},
"approval_policy": "on-request",
"approval_mode": "interactive",
"max_iterations": 32,
"stream": true,
"context_budget": {
"warning_ratio": 0.85,
"critical_ratio": 0.95,
"max_reactive_retry": 1
},
"token_usage": {
"storage_type": "file",
"storage_path": "./.bytemind/token_usage.json",
"backup_interval": "1m",
"max_sessions": 10000,
"alert_threshold": 1000000,
"enable_realtime": true,
"retention_days": 30,
"monitor_interval": "30s",
"database_driver": "sqlite3"
}
}
非目标
- 不在 TUI 中新增 provider/model。
- 不在 TUI 中删除 provider/model。
- 不做 provider 健康检查或自动 fallback 策略。
- 不做复杂价格表或模型 catalog 维护。
- 不新建完整设置页。
验收标准
- 空配置或首次启动时,当前 provider 是
deepseek,当前 model 是 deepseek-v4-flash。
- 配置文件中写入多个 provider 和多个 model 后,
/model 能自动列出全部候选项。
- 在
/model 面板中上下选择并按 Enter 后,当前 session 后续请求实际使用选中的 provider/model。
- 同 provider 下切 model 时,不改变
current_provider,只更新该 provider 的 model。
- 切换到另一个 provider/model 时,配置写回后
current_provider 与当前运行模型所属 provider 保持一致。
- URL、key、协议等 provider 字段不会因为切 model 被挪到 model 层或被重复维护。
- TUI 不再引导用户通过
/add model 或 /delete model 修改 provider/model 配置。
/models 和 /model picker 如保留,只作为 /model 的兼容别名。
- token usage 显示不回退;切换后 token budget 跟随当前模型,远端 usage 拉取跟随当前 provider。
- 增加覆盖:配置兼容旧字段、配置读取多个 model、
/model 面板选择、同 provider 切 model、跨 provider 切换、runner runtime 切换、配置写回、token budget 刷新。
背景
用户痛点不是“在 TUI 里管理 provider 配置”,而是“已经写进 bytemind 配置的 provider/model,不能在 TUI 里方便切换”。
这次设计保持克制:配置文件负责增加/删除 provider 和 model;TUI 只负责读取、展示、选择当前运行目标。
设计原则
/add model,也不提供 delete,避免误改或破坏配置文件。/model,不再拆成/models和/model picker。current_provider必须始终指向当前实际运行模型所在的 provider。provider/model列表完成选择。provider_runtime、Runner.UpdateProviderRuntime、ListModels、model modal 和 token usage 逻辑。Provider / Model 层级
Provider 是服务商、协议、端点和账号这一层,例如
deepseek、openai、anthropic、gemini或一个私有 OpenAI-compatible 网关。Provider 负责:
base_url、api_key/api_key_env、auth header/scheme。ListModels、usage 拉取、health check 等能力。Model 是 provider 下面的模型 ID 和模型能力这一层,例如
deepseek-v4-flash、deepseek-v4-pro、gpt-5.4-mini。Model 负责:
model字段。因此,
base_url和 key 不属于 model,应该属于 provider。切换 provider 和切换 model 在内部不是一回事:model。current_provider,并更新目标 provider 的model。对用户来说,TUI 可以统一展示为选择一个
provider/model目标;对实现来说,要保持 provider/model 两层边界。配置设计
建议把
provider_runtime.current_provider作为对外语义。为兼容现有配置,可读取旧的default_provider/default_model作为 fallback,但写回时优先统一成 current 语义。当前实际运行模型由这两个值共同决定:
provider_runtime.current_providerprovider_runtime.providers[current_provider].model最小结构:
{ "provider_runtime": { "current_provider": "deepseek", "providers": { "deepseek": { "type": "openai-compatible", "base_url": "https://api.deepseek.com", "api_key_env": "DEEPSEEK_API_KEY", "model": "deepseek-v4-flash", "models": ["deepseek-v4-flash", "deepseek-v4-pro"] }, "openai": { "type": "openai-compatible", "base_url": "https://api.openai.com/v1", "api_key_env": "OPENAI_API_KEY", "model": "gpt-5.4-mini", "models": ["gpt-5.4-mini"] } } } }说明:
current_provider决定当前运行 provider。providers.<id>.model是该 provider 当前选中的 model。providers.<id>.models是该 provider 可在 TUI 中切换的 model 列表。models为空或缺失,就把model当作唯一候选,保证旧配置可用。默认 DeepSeek
默认配置内建 DeepSeek,后续可再改默认 provider:
current_provider:deepseekmodel:deepseek-v4-flashbase_url:https://api.deepseek.comapi_key_env:DEEPSEEK_API_KEY同步更新
config.example.json和 DeepSeek 默认/fallback model,避免新用户默认落到旧模型名。TUI 交互
合并当前
/models和/model picker为一个/model面板,行为类似/session:/model打开模型选择面板。provider/model。model。current_provider和目标 provider 的model。current。/models、/model picker如需兼容,可作为/model的别名,但不再有单独语义。/add model、/delete model,避免 TUI 负责配置增删。运行时切换
切换时继续复用现有链路,范围控制在“选择已有配置项”:
provider/model列表。current_provider和对应providers[provider].model。Runner.UpdateProviderRuntime。如果配置中的
current_provider不存在,应在启动或打开/model时给出明确错误,不要静默运行到别的 provider。token usage 接入
切换后保持现有 token usage 行为:
current_provider,因为不同 provider 的 usage API 不同。token_quota。config.json 配置模板
非目标
验收标准
deepseek,当前 model 是deepseek-v4-flash。/model能自动列出全部候选项。/model面板中上下选择并按 Enter 后,当前 session 后续请求实际使用选中的 provider/model。current_provider,只更新该 provider 的model。current_provider与当前运行模型所属 provider 保持一致。/add model或/delete model修改 provider/model 配置。/models和/model picker如保留,只作为/model的兼容别名。/model面板选择、同 provider 切 model、跨 provider 切换、runner runtime 切换、配置写回、token budget 刷新。