ZH Configuration - D0n9X1n/copilot-relay GitHub Wiki
copilot-relay 的运行配置在:
~/.copilot-relay/config.yaml
第一次启动时会从包内模板生成。此后加载时,relay 会保留已有文本、注释、键的顺序、 未知的扁平标量键及显式值,只为缺失的键追加默认值。写入基于检查过的文件快照 (snapshot),原子替换解析后的目标,因此符号链接本身不被替换,已检测到的并发编辑 不会被覆盖。升级不会把已保存的值迁移为新默认值。
仅支持扁平标量 YAML。已知键的无效值、重复键(包括别名)及不受支持的语法会在写回前
报错,文件保留原样供你修正。webSearchBackend 留空合法,不代表应清空其他设置。
热重载是**只读(read-only)**的,只接受稳定、有效且包含全部已落盘键的文档;编辑器
保存中的片段或空文件不会替换上一次有效的运行时设置。请补回缺失键,不要靠删除键来
恢复默认值。写入机制的保证见内部实现。
要看补齐默认值后的全部配置项及哪些需要重启,运行 copilot-relay status。这些是
磁盘上的值,不能证明 daemon 已经加载。配置损坏时,status 输出不回显敏感内容的
诊断并以 2 退出;stop 仍可根据已验证的进程身份尝试恢复。见
日志与问题排查。
host: 127.0.0.1
port: 4142
apiKey:
copilotBaseUrl: https://api.githubcopilot.com
upstreamProxy:
claudeSetup: true
logLevel: info
logRetentionDays: 3
thinkEffort: max
upstreamTimeoutSeconds: 180
webSearchBackend:
claudeUpstreamApi: chat-completions
gptModel: gpt-6-astra
opusModel: claude-opus-5.5| 字段 | 作用 |
|---|---|
host |
本地 Claude 兼容 HTTP 服务监听地址。建议保持 127.0.0.1,只允许本机访问;绑定到 loopback 以外的地址前先设置 apiKey。 |
port |
本地端口,默认 4142。 |
apiKey |
可选的客户端密钥,客户端须以 x-api-key 或 Authorization: Bearer 发送。留空(默认)即关闭该检查。支持热重载。参见要求客户端密钥。 |
copilotBaseUrl |
GitHub Copilot API 地址。必须是绝对的 http:// 或 https:// 地址,且不能包含账号密码。一般不要改。参见 copilotBaseUrl 规则。 |
upstreamProxy |
Copilot 与 GitHub 调用(包括登录)使用的出站代理。留空(默认)表示直连;env 表示使用 HTTPS_PROXY、HTTP_PROXY 和 NO_PROXY;否则写绝对的 http:// 或 https:// 代理地址。需要重启。参见 upstreamProxy 规则。 |
claudeSetup |
为 true 时,start 会自动更新 ~/.claude/settings.json。 |
logLevel |
只能是 error、info、debug。debug 除有界日志外还会自动捕获完整的已观察请求/响应正文;启用前先看日志与问题排查。其他值会导致启动失败。 |
logRetentionDays |
普通 relay 日志与 debug 捕获保留的本地日历天数,包含今天;正整数,默认 3。活动/未知捕获受到保护,清理规则见日志与问题排查。 |
thinkEffort |
请求未指定时使用的默认推理强度:low、medium、high、xhigh、max。 |
upstreamTimeoutSeconds |
单个 Claude 请求等待上游 Copilot 调用的最长秒数,默认 180;0 禁用 relay 的总超时。 |
webSearchBackend |
bridge-managed WebSearch 使用的 Copilot Responses 模型;留空使用 gptModel。 |
claudeUpstreamApi |
Claude 上游协议:chat-completions(默认)、auto 或 messages。不改变非 Claude 模型的路由。 |
gptModel |
非 Opus 请求使用的上游模型。 |
opusModel |
请求模型名包含 opus 时使用的上游模型。 |
先按原规则选择模型(opusModel 或 gptModel)。如果选中的上游 ID 以 claude-
开头,再由 claudeUpstreamApi 决定协议:
| 值 | 行为 |
|---|---|
chat-completions |
默认值。保留经翻译的 Copilot /chat/completions 路径。 |
auto |
仅在当前上游的缓存模型目录公布了 /v1/messages 时使用该原生接口,否则走翻译路径。 |
messages |
强制 Claude 模型走原生 /v1/messages,即使目录未公布支持;上游拒绝仍作为错误返回。 |
所有模式下,非 Claude 模型都根据目录选择 chat/Responses。当前提供方的
supported_endpoints 决定使用 /chat/completions 还是 /responses,新增模型 ID
无需加入代码名单。两者都公布时,保留已有偏好:GPT-5.5、GPT-5.6、GPT-6 Astra
系列优先 Responses,其他模型优先 Chat;目录的排列顺序不会改变选择。接口元数据
缺失或格式错误时,保留旧偏好并标为未验证;显式空列表表示没有公布可用接口。
其他协议和非聊天类型仍不受支持,这不等于账号没有权限。
Claude 的 chat-completions 固定使用 Chat;目录排除该接口时报告协议策略冲突,
不会静默切换。auto 未找到原生支持时按目录选择翻译接口;messages 仍显式强制
原生接口,即使目录信息不同。深度检查、启动 preflight 和真实配置目标请求共用
这些规则。只有非成功 HTTP 返回 unsupported_api_for_model,且目录(或缺失的
元数据)与协议策略均允许时,才可从 Chat 向 Responses 重试一次;其他错误、拒答
以及已发送部分内容的流不会触发接口切换。
原生传输保留带签名的 thinking、缓存标记、原位置的 system 角色与控制字段;不会为了绕过拒答或错误而悄悄改走
另一个 API。发布默认值仍为 chat-completions。2026-09-30 的小规模匹配合成试验在
low effort 下测得热回合按 token 加权的缓存读取率:chat 99.8384%,native 99.7980%,
相差约 0.04 个百分点。第二次为平衡执行顺序而让 native 先执行的试验,在其冷回合拒答后
停止;完成的那次试验不能证明广泛无退化或计费成本等价。这些是隔离检查,不是对当前
生产 relay 的验证,端口 4142 未受影响。方法与用量见内部实现。
仍未证明历史拒答是推理内容扁平化导致的。
原生 bridge-managed WebSearch 只支持自动选择。声明 WebSearch 时,any 或显式强制
搜索在检索/SSE 之前返回 HTTP 400 JSON,每回合最多一次搜索。确定性的 relay 标记让续接时能够还原原始、带签名的上游历史。
旧 chat bridge 历史与 native bridge 历史不能透明互换:已有搜索会话应继续使用原路由,
切换后开始新会话。协议边界而不只是模型可用性,详见内部实现。
模型是否可用取决于 Copilot 账号、组织策略及配置的网关。要获取 relay 上游公布的 完整模型目录,运行:
copilot-relay models该命令每次都会向配置的 copilotBaseUrl 发起认证的 GET /models,复用 relay 的
缓存凭据、token 刷新逻辑及 upstreamTimeoutSeconds。没有可用缓存凭据时,现有的
设备登录流程可能要求你完成认证。输出保留上游原始 ID,排序并去重,不会添加
[1m] 等 relay 别名,也不会只列出 gptModel 和 opusModel 配置中的模型。
每行先列出 gptModel 或 opusModel 可直接使用的准确 ID,再列出目录中的显示名称。
请求准入会拒绝的 ID 标为 cannot be gptModel or opusModel 并附原因,例如
not a chat model;判断与真实请求使用的 selectCopilotEndpoint 相同。为确保显示
安全,终端控制字符会被移除,敏感网关 URL 的尾部会被脱敏;普通模型 ID 保持不变。
列表之后,命令会打印配置文件路径、当前的 gptModel 和 opusModel 行及各自处理的
请求。配置的 ID 未被上游公布或无法使用时会给出警告,因为启动检查会拒绝它。
要查找某个模型应填写的值,可按 ID 或显示名称搜索,搜索忽略大小写、空格和标点:
copilot-relay models sol fast搜索只对应一个可路由的模型,或与某个 ID 完全一致时,命令会打印应写入 config.yaml
的行,例如 gptModel: gpt-5.6-sol-fast;包含 opus 的 ID 按路由规则给出
opusModel。没有匹配时,会列出与搜索词开头或结尾最长相同部分的 ID,并以退出码 1
结束。在 2026-10-02 检查的目录中,gpt6-fast 没有匹配,建议了 gpt-5.6-sol-fast 及
gpt-6 系列模型。搜索不能与 --deep 同时使用;检查单个模型请用 --deep --model <id>。
正在运行的 relay 会把 gptModel 或 opusModel 的修改应用到新请求;重启会重新执行
启动检查(见下文“热重载与重启”)。空目录会明确提示,退出码为 0;搜索无匹配,以及
配置、认证、网络、HTTP、超时及目录格式错误时退出码为 1。本地超时与上游真正返回的
HTTP 504 会使用不同提示。
Relay 未运行或配置的模型 ID 已不在上游目录中时,仍可使用此命令,后者会显示为警告。
它不会绑定端口、执行启动预检或推理探测、改变所选模型,也不会修改 Claude 设置。与其他
命令一样,配置加载器仍会把补齐默认值后的配置写回 config.yaml,认证过程也可能更新
token 缓存。
公布在目录中不等于已验证可用。 目录条目不能证明推理请求一定成功,也不能保证
兼容 relay 请求、工具或某个 effort 档位。选好模型后,启动流程会检查配置的 ID 并
发送探测请求;copilot-relay status --deep 则通过正在运行的 relay 检查真实请求。
相比之下,copilot-relay status 显示配置的 relay ID;本地 GET /v1/models 还会在
目录提供数据时返回缓存的 context_window、max_input_tokens 和 max_tokens。
这两者都不会拉取上游目录。
如果需要交互式选择器及其提供的 effort 元数据,也可运行 GitHub Copilot CLI
(copilot),然后在其交互会话中输入 /model。请使用与 relay 相同的账号。
该选择只影响 Copilot CLI 会话,不会修改 relay 配置;自建网关公布的目录可能不同。
不要把 bearer token 粘贴到命令、日志或 issue 中。
普通目录列表不执行推理。深度测试必须显式启用,并且会消耗真实 Copilot 用量。 建议先选择准确模型,避免测试整个目录:
copilot-relay models --deep --model claude-opus-5.5
copilot-relay models --deep --timeout 20 --total-timeout 120
copilot-relay models --deep --model gpt-6-astra --effort low --max-tokens 4096简洁表格显示 MODEL、STATUS、TIME 和简短的 RESULT,最后只汇总非零结果。
模型 ID 只显示一次;长 ID 换行而不静默截断。每次串行探测完成后立即显示一行。
* 表示目录没有公布 effort 或接口元数据,不代表相关能力已被验证。
TTY 输出中,PASS 为绿色、FAIL 为红色、INCOMPLETE 为黄色,SKIPPED/NOT_TESTED
使用弱化颜色。status 和 status --deep 对健康状态、上游检查和版本不匹配使用相同
策略。文字状态始终是判断依据,颜色不会改变退出码。管道和 dumb 终端默认无颜色;
NO_COLOR 或 FORCE_COLOR=0 禁用 ANSI;FORCE_COLOR=1(也接受 2、3、
true 或空值)可明确启用。NO_COLOR 优先。status --json 始终不带颜色。
深度命令的常规启动消息保留在日志文件中,不再挤占表格;必要的登录提示和启动错误
仍可见。不会打印探测响应文本、工具参数或原始异常。未通过的探测显示生成的
request_id,重复的下一步建议会去重。
需要每个探测的安全证据时,在本次调用中加入详情选项:
copilot-relay models --deep --model claude-opus-5.5 --details详情包括计划/实际接口、route_source(catalog、legacy、policy 或
unavailable)、已知 advertised_endpoints、unknown_endpoints 数量、准确的发送/
报告模型 ID、有效 effort/输出上限、客户端/上游 HTTP 状态、完成状态、关联 ID 和
捕获状态。不会打印不可信的未知接口字符串。SKIPPED 表示没有发送推理请求。
只有完整且实际存在的私有捕获才会显示 replay 命令。
它仍然是新的真实探测,不是离线查看之前的失败;见日志与问题排查。
| 状态 | 含义 |
|---|---|
PASS |
所选模型返回已完成的非空文本。不代表验证了工具、所有 effort 或答案正确性。 |
INCOMPLETE |
生成未完成。预算耗尽时的正数输出用量只能证明上游可达,不能当作完整回答。 |
FAIL |
HTTP/认证/网络失败、超时、拒绝、异常输出、缺失或不匹配的模型 ID、上游以 model_not_supported 拒绝的已列出模型、已完成但为空的响应。 |
SKIPPED |
目录元数据不支持 relay 所需的接口/effort、模型不是聊天模型,或 ID 不安全/不规范。 |
NOT_TESTED |
总期限耗尽或中断,当前探测被停止或后续探测未发起;不计为模型失败。 |
测试范围为 isolated relay pipeline; not running-daemon health,即隔离 relay
处理流程,而非正在运行的守护进程健康检查。CLI 使用合成请求经过正常的进程内
Messages handler、翻译、上游客户端、token 刷新和响应翻译。每次串行探测仅在本进程
路由中选择准确上游 ID,结束后恢复状态。如果直接把每个 ID 发给运行中的 daemon,
它们仍会被映射到 gptModel/opusModel,造成虚假的逐模型验证。此命令不会绑定端口、
重启 daemon 或修改模型配置/Claude 设置。检查运行中 daemon 的配置路由请用
status --deep。
| 选项 | 默认值 / 行为 |
|---|---|
--model |
默认测试全部公布的 ID;指定值必须准确匹配目录。需要 --deep。 |
--details |
显示每次探测的安全证据及捕获/replay 可用性。需要 --deep,不会增加探测或重试次数。 |
--max-tokens |
每次 4096,并受目录中的输出上限及原生非流式输出上限约束。 |
--effort |
按 low、medium、high、xhigh、max 选择高于 none 的公布最低档;仅当 none 是唯一公布的档位时才使用它,因为 relay 自身从不发送 none,且部分模型公布了它却拒绝它。无元数据时使用标为未验证的 low。明确不支持 effort 时省略该字段(effort=omitted);目录不支持的显式覆盖值会跳过。 |
--timeout |
每个模型 30 秒,同时不超过正数的 upstreamTimeoutSeconds。 |
--total-timeout |
探测阶段总计 300 秒;目录查询和认证发生在此预算之前。 |
数字选项只接受不超过 2,147,483 的正整数;所有探测选项都需要 --deep。即使配置禁用
上游超时,深度测试仍有自己的期限。缺少接口元数据会标为未验证,而非视为支持证据。
模型匹配会移除 relay 已知的 GPT context 后缀。仅在通过原生 /v1/messages 探测目录
ID claude-opus-5.5 时,还接受已观察到的 provider 拼写 claude-opus-5-5。仅在通过
/responses 探测目录 ID gpt-5.6-sol-fast 时,还接受 gpt-5.6-sol:该目录项是
gpt-5.6-sol 的 priority 服务层级,其回复报告基础模型。对于不带日期的目录 ID,还接受
该 ID 加一个 -YYYY-MM-DD 快照日期,例如 gpt-5.5 对应的 gpt-5.5-2026-04-23;
带日期的 ID 必须完全一致。配置和 --model 仍使用目录拼写,其他不匹配仍失败,包括其他
-fast ID,以及上游改由其他模型应答的别名,例如由 gpt-4.1-2025-04-14 应答的 gpt-4。认证可刷新 token,现有的有界重试可能产生额外调用,但不会新增逐模型重试循环。Ctrl+C 会中止当前
探测,并把后续模型标为未测试。仅这些诊断调用会抑制共享流程的原始日志,正常 relay
日志不受影响。
深度测试退出码:0 所选模型全部通过;1 选项、模型选择、认证或目录查询失败;
2 任何其他未通过结果或无模型;130 中断。普通 models 的空目录仍以 0 退出。
默认 claudeUpstreamApi: chat-completions 下,配置的 Opus 路由使用 Chat Completions,
配置的 GPT 路由在模型需要时使用 Responses。每个新请求按当前模型选择器决定目标,
并从该请求的字段和历史中解析 effort。请求接入后,即使配置在响应或 WebSearch
各阶段执行期间发生变化,它仍保留原来的路由和 effort 快照。
tests/integration/model-effort-switching.test.ts 把 relay 实际返回的 JSON/SSE 内容
带入后续请求,在两个方向上切换模型,覆盖工具结果、长工具名、零参数工具、thinking
文本、消息级 effort 控制和翻译路径 WebSearch 后续对话。测试通过严格的模拟上游请求
检查目标模型、effort、输出上限、工具调用与结果配对,以及流的完整结束。这是对 relay
本地转换和测试中编码的线上格式不变量的离线验证,不是实际 Copilot 接受度的证明,
包括从另一模型保留下来的工具 ID;也不代表缓存命中率保持不变。
原生 Messages 的跨协议迁移不在这组测试覆盖范围内。应选择目标模型支持的 effort; 认证、限流、网络故障、上下文上限和上游拒绝仍可能使请求失败。relay 不会静默替换 模型或 effort 来掩盖这些失败。合并或构建修复不会更新已运行的安装版 relay; 需要另外更新并重启该运行时。
thinkEffort 是默认值,不再覆盖请求。初始 effort 按以下顺序使用第一个非 null 的值:
- Claude Code 原生字段
output_config.effort。 - 兼容旧客户端的请求字段
reasoning_effort。 -
config.yaml中的thinkEffort;未配置时使用发布默认值。
例如,即使配置为 thinkEffort: max,请求中的
output_config: {"effort": "low"} 仍会使用 low。请求字段缺失或为 null 时使用默认值。
thinking.budget_tokens 不是 effort 档位,不会被换算成某个档位。格式不正确的显式
effort 返回 400,不会静默改用默认值。若
capabilities.supports.reasoning_effort 为 false 或合法的空列表,或者格式正确的
supports 对象省略了该键,表示模型不支持 effort:省略隐式默认值,但显式请求(包括
none)在推理/SSE 前返回本地 HTTP 400 relay_unsupported_effort。Copilot 以最后
一种方式列出 gpt-4o、gpt-4.1、claude-haiku-4.5 等较旧的聊天模型,它们都以
invalid_reasoning_effort 拒绝任何 effort。已生效的消息级 effort 也算显式请求。
原生历史会转发控制字段,因此待生效或带 clear_at 的 effort 控制同样被拒绝,
不会静默丢弃。缺少 supports 对象,或 reasoning_effort 为 true、null 或格式错误时
表示未知,而不是不支持。
档位列表非空时,普通请求仍保留选定档位,上游拒绝仍是错误;relay 不会替换档位。
可以在 Claude Code 会话中途切换 effort,无需清空历史。消息级 system output_config
的唯一键为 effort 时,可使用 low、medium、high、xhigh 或 max。
最新 user 回合之前的最后一个标记决定当前档位;仅包含工具结果的 user 回合也算。
位于该 user 回合之后的标记要等下一个 user 回合才生效。旧标记可以保留不同档位,
不必改写原始历史。
在翻译为 chat/Responses 的路径上,relay 把当前档位映射到上游请求字段,保留 system
文本与顺序,省略没有文本、只有控制信息的消息。额外/未知控制键、格式错误的值、
消息级 none 或 clear_at 仍会在推理请求/SSE 之前返回 HTTP 400 JSON。
原生 Messages 保留初始设置和逐消息控制字段,由上游解释。见内部实现。
翻译路径的 JSON/SSE 及 WebSearch 各阶段均使用选定档位;请求接入后的配置热重载
不会改变它。原生后续调用保留控制历史,因此追加 user/工具结果回合时,待生效标记
可能开始生效。启动 preflight 为接受 effort 的模型验证配置默认值;明确不支持
推理档位的模型则不发送 effort,日志显示 think_effort=omitted,不会声称已验证
一个实际未发送的档位。
保持翻译后的消息前缀不变可避免不必要的历史变动,但请求级 effort 变化仍可能使上游
缓存失效。原生逐消息 effort 才是协议提供的缓存保持机制,见
官方 effort 指南。
在 gptModel、opusModel 和已设置的 webSearchBackend 中,所有支持 effort 的
目标都应接受配置默认值。搜索检索仍需要 Responses 内置搜索操作;普通聊天模型
可用不代表支持搜索工具。配置默认值只接受 low、medium、high、xhigh、max。
旧配置值 minimal
会被规范化为 low,不是独立档位。缺少 effort 元数据表示“未公布”,不是“支持所有档位”。
thinkEffort: none 不是合法的 relay 全局默认值。它和其他格式错误的显式值都会在认证、
上游探测和配置写回之前报错:
Invalid thinkEffort. Valid values: low, medium, high, xhigh, max. "none" is not allowed as a configured default.
错误的文件会保留原样,供你修正;relay 不会通过写入 max 隐藏无效值。缺失的键仍使用
发布默认值。无效的热重载只记录一次原因,并保留上一次有效的运行时设置;修正文件后正常
重载会恢复。
这一限制针对配置默认值,而不是请求覆盖值。对于 GPT-5.6 Sol 等支持它的模型,显式请求
中的 none 仍会原样传递。它不是“使用默认值”的指令。
2026-09-05 查询的实时目录显示,gpt-6-astra 和 claude-opus-5 都支持 low、
medium、high、xhigh、max;Astra 未公布 none。更高 effort 通常会以更多
延迟和 token 消耗换取更多推理。切换任意模型时应重新检查选择器,而不是假设所有模型都
接受 max。
全新安装使用 opusModel: claude-opus-5.5;已有配置保留保存的值,包括
claude-opus-5。修改前先运行 copilot-relay models:账号权限、组织策略和网关
可用性仍然适用。2026-09-23 的认证目录查询及隔离 relay 验证确认了准确 ID
claude-opus-5.5,以及 JSON/SSE、自动工具调用及工具结果续接、对话续接、
low/max effort 和 WebSearch 最终回答重组。目录公布了全部五种配置 effort;
relay 不会为该 Opus ID 添加 [1m] 后缀。WebSearch 检索仍使用 webSearchBackend
或 gptModel。
2026-09-23 的验证使用翻译路径: 该模型的 tool_choice 类型 tool 和 any
返回 HTTP 400,自动工具选择可用。该观察不是对原生 API 能力的测量。Relay 会保留
上游错误,不会把必须执行的工具调用静默改成 auto。原生 bridge 搜索的限制见上文。
这些是请求级能力限制,不能据此断定认证失败。
2026-09-30 的隔离检查使用真实 Claude Code 2.1.285,在原生路径上完成了两个模型回合的
Read → 工具结果 → OK。最初两次请求因不支持 safeguards 收到 HTTP 400,随后
Claude Code 自行降低了请求能力。Relay 没有剥离该字段或绕过安全控制。这只是有限的
兼容性证据,不是当前生产验证;缓存计数及重放证据见内部实现。
修改已有的键并保留其他设置。macOS 或 Linux:
${EDITOR:-vi} ~/.copilot-relay/config.yamlWindows PowerShell:
notepad "$env:USERPROFILE\.copilot-relay\config.yaml"在 macOS/Linux 上,可选用 Mike Farah 的 yq v4 切换 GPT 路由并保留你的 Opus
选择;直接用编辑器不需要额外依赖:
cp -p ~/.copilot-relay/config.yaml ~/.copilot-relay/config.yaml.bak
yq -i '.gptModel = "gpt-6-astra" | .thinkEffort = "max"' ~/.copilot-relay/config.yaml确认另一个配置模型支持后再用 max。全新安装的默认组合为:
gptModel: gpt-6-astra
opusModel: claude-opus-5.5
thinkEffort: max这些键支持热重载。如需立即验证两条路由,先等待正在进行的工作结束,再运行
copilot-relay restart,或通过服务管理器重启(见各平台服务页面)。启动会发送少量真实
上游请求并消耗 token;restart 会以前台方式运行 relay。status --deep 只向 GPT
路由发送一次真实请求,不是对两条路由的完整验证。
已有安装会保留已保存的模型选择,升级软件包不会迁移这些值。如果启动报告 Astra 不可用,
请编辑已生成的 config.yaml,选择账号支持的模型,例如目录中存在时使用
gpt-5.6-sol,并设置兼容的 effort。Relay 会明确失败,不会静默回退。需要撤销修改时,
恢复 config.yaml.bak。
Relay 配置保留规范 ID gpt-6-astra。Relay 向 Claude Code 暴露
gpt-6-astra[1m],向 Copilot 只发送 gpt-6-astra。[1m] 控制 Claude Code 的
context 计数,不能扩大上游容量。2026-09-09 查询的实时目录公布了:
| 模型 | 总 context | 最大 prompt | 最大输出 |
|---|---|---|---|
gpt-6-astra |
1,000,000 | 872,000 | 128,000 |
claude-opus-5 |
1,000,000 | 936,000 | 64,000 |
claude-opus-5.5(2026-09-23 验证) |
1,000,000 | 1,000,000 | 128,000 |
gpt-5.6-sol |
1,050,000 | 922,000 | 128,000 |
这些值来自模型发现,并非运行时代码写死的限制,也不是通过生产环境中的百万 token
请求测得。应在总窗口内为输出(包括推理)预留空间。Relay 不会截短输入,也不会扩大
客户端明确指定的较小输出预算。Prompt 是否真正符合限制,仍由上游判定。
本地 /v1/messages/count_tokens 仅供预算参考,不是计费。文本使用可用 tokenizer,
每张图片固定计入 4096-token 余量,不对其 base64/URL 数据做 token 编码、解码或拉取。
原生 usage 分别报告非缓存输入、缓存读取和缓存写入,单独的原生 input_tokens 不是
完整 prompt 大小。实测计数及分母定义见内部实现。
流式和完整 JSON 响应都可以使用模型的完整输出上限。 Opus 5.5 公布的原生非流式输出上限为 16,000 token;超过时 relay 会向上游请求 SSE, 再为 JSON 调用方缓冲完整结果。1M prompt 上限不代表 1M 输入加 128K 输出能够一起 放入 1M 总窗口。
已有 Claude Code 配置需要明确选择新身份:
CLAUDE_CODE_MAX_OUTPUT_TOKENS=128000 claude --model 'gpt-6-astra[1m]'也可以在 Claude Code 中输入 /model gpt-6-astra[1m]。claudeSetup: true 只在没有
主要模型覆盖项时写入默认模型;它会保留已有模型选择和 shell wrapper。如果 wrapper
固定了其他 --model,也需要修改。
应使用配置模型的准确身份,不要假设内置别名具有相同的客户端 context 预算。
如果发现的 GPT 窗口并非恰好 1M,自动设置会使用不带后缀的模型 ID,并将
CLAUDE_CODE_MAX_CONTEXT_TOKENS 初始化为实际窗口。否则 Claude 的 [1m] 后缀会覆盖
该数值设置。以上述目录为例,手动配置 Sol 时可运行:
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1050000 CLAUDE_CODE_MAX_OUTPUT_TOKENS=128000 \
claude --model gpt-5.6-solPowerShell 中用 $env:CLAUDE_CODE_MAX_OUTPUT_TOKENS = "128000" 赋值;需要时同样设置
CLAUDE_CODE_MAX_CONTEXT_TOKENS,再运行对应的 claude 命令。数值应以你的模型目录
为准,不要照搬其他账号的容量。Claude 设置、shell 环境、自动压缩和上游限制仍可能约束
实际可用窗口;自动设置不会禁用压缩。详见 Claude 的
context 覆盖规则。
如果响应可能超过已保存的超时,请明确设置:
upstreamTimeoutSeconds: 0该设置会热重载,只移除 relay 的总超时。客户端取消,以及客户端、上游和传输层自身
的超时仍然有效。全新安装的默认值仍为 180,已有值不会被迁移。
对于文档中的 1M 上下文 Opus 5.5 / GPT-6 Astra 模型对,建议先使用保守的 800K 自动压缩窗口,并保持自动压缩启用。这是留有余量的 relay 建议,不是实测 最优值,也不能保证消除 API 错误。上方注明日期的目录给 Astra 872K prompt 上限和 128K 最大输出;从 1M 总窗口预留 128K 后同样剩余 872K。800K 目标再留约 72K, 用于工具输出、压缩和 token 估算误差。客户端扣除自身输出/缓冲预留后,可能更早压缩。
对当前会话生效并保存到用户设置:
/autocompact 800k
只对一次启动生效,不修改已保存的设置:
claude --autocompact 800k等价的用户设置片段为:
{ "autoCompactWindow": 800000 }环境变量覆盖必须使用纯数字 token 数量:
CLAUDE_CODE_AUTO_COMPACT_WINDOW=800000 claudeCLAUDE_CODE_AUTO_COMPACT_WINDOW 优先于命令、启动参数和已保存设置,不要在这个
环境变量中填写 800k。移除环境覆盖后,/autocompact auto 恢复模型调优的默认值;
claude --autocompact auto 仅对一次启动恢复默认。托管设置可能覆盖交互命令保存的值。
见官方自动压缩窗口说明
和环境变量参考。
如果网关公布更低限制,应使用更小的值。选窗口时可参考上界:
min(最大 prompt, 总上下文 - 计划输出预留) - 额外余量,并按会切换到的模型中最严格
的限制计算。工具/图片输出大、或本地 token 估算不确定时,应增加余量而不是扩大窗口。
部分客户端模型接近 1M 的默认值(约 967K)可能已经超过网关 872K 的输入限制。
[1m] 和客户端窗口设置都不能扩大上游容量。不要通过禁用压缩解决问题,也不要为
应用此建议而自动重写现有设置。
copilotBaseUrl 会在加载配置时校验,不满足以下条件时启动会直接失败:
-
必须是绝对的
http://或https://地址。 相对路径(/tenant/v1)、只写主机名 (api.githubcopilot.com)、以及其他协议(ftp://、file://)都会被拒绝。允许使用 明文 HTTP,所以http://127.0.0.1:8080这类本地网关是合法值。 -
地址里不能带账号密码。
https://user:password@host会被拒绝。上游 HTTP 客户端 在真正发请求时本来也不接受这种写法,放行只会把一个清晰的启动错误变成一个难懂的 请求失败。 -
不能直接写引号、尖括号、空白字符和控制字符。 在日志里,正是这些字符标记一个
URL 到哪里结束;地址里带上它们,之后就没法再把整条 URL 识别出来,尾部会原样打印
出去。请改用百分号编码:
'写成%27,"写成%22,反引号写成%60,</>写成%3C/%3E,空格写成%20,制表符写成%09。编码后的写法会被接受, 并原样使用。值前后的空格或制表符只会被去掉,和其他配置项一样。
错误信息只说明是哪个字段、违反了哪条规则,不会把你配置的值重复出来——因为这条信息 可能出现在终端或日志文件里。
如果 copilotBaseUrl 带有路径、查询参数或 fragment——比如
https://gateway.example/tenant/abc123 这样的自建网关——只会显示它的 origin:
copilot base url: https://gateway.example (path/query/fragment hidden)
copilot-relay status 和 copilot-relay status --json 里的 copilotBaseUrl 一行同理;
~/.copilot-relay/logs/ 中错误信息里出现的上游地址也一样,会写成
https://gateway.example[redacted]。
这么做是因为网关路径里可能带着 token,而日志文件恰恰是报问题时最常被要求附上的东西。
不带路径的地址(比如默认的 https://api.githubcopilot.com)会完整显示——它里面没有
需要隐藏的内容。
默认情况下 relay 不认证调用方。默认的 host: 127.0.0.1 只允许本机进程连接。改成
0.0.0.0 或局域网地址后,任何能访问到该端口的客户端都能发请求,每个请求都使用你的
Copilot 账号。把 host 绑定到 loopback 以外之前,先设置 apiKey:
apiKey: <一个足够长的随机值>生成随机值的一种方式:
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"设置 apiKey 后,除 GET /healthz 和 GET/HEAD /api/hello 外的每个请求都必须以
x-api-key: <key> 或 Authorization: Bearer <key> 携带该密钥。缺少密钥或密钥不符时,
relay 在读取正文、执行任何路由之前返回 HTTP 401 及 Anthropic 风格的
authentication_error。apiKey 留空(默认)即关闭该检查。
- 密钥至少 16 个可见 ASCII 字符,不含空格。像上面那样只由字母和数字组成时不需要加
引号。以
#开头的密钥必须加引号:不加引号时 YAML 会把它当作注释,密钥变成空值, 检查随之关闭。 - 密钥不会写入日志,也不会显示。
copilot-relay status在文本和--json输出中都把它 显示为[redacted],并在GET /v1/models探测和--deep的POST /v1/messages探测中发送它。模型 ID、显示名称、配置的模型或搜索中含有密钥时,copilot-relay models打印[redacted],--deep也不会探测含有密钥的 ID。 - Debug 捕获不记录携带密钥的 header,但请求和响应正文不脱敏,所以客户端放进提示词的 密钥会保存在其中;见日志与问题排查。
- 此时
config.yaml保存着密钥。新建的config.yaml模式为0600,只有你能读取; 已有的文件保留原来的模式,relay 从不修改它。在 Linux 和 macOS 上,设置了apiKey且config.yaml(或它链接到的文件)允许其他本地用户进行任何访问时,启动以及每次 设置或修改密钥的重载都会记录一条错误,写明该文件及其模式,并提示对它运行chmod 600。Windows 没有这类模式位。 -
claudeSetup: true时,start会把密钥写成 Claude Code 的ANTHROPIC_AUTH_TOKEN; 见 Claude Code 配置。 -
host不是 loopback 地址且apiKey为空时,启动会记录一条提到apiKey的警告。 relay 仍会启动,已有的0.0.0.0配置继续可用。 - 接入检查还会校验请求的 Host。远程客户端必须使用
host中设置的地址;0.0.0.0这类 通配监听地址只接受 loopback 名称。见架构。 - relay 使用明文 HTTP。在不受信任的网络上,密钥和提示词可能在传输中被读取。
apiKey 支持热重载:relay 应用一次有效修改后,下一个请求就必须携带新密钥。未通过
校验的修改会保留之前的密钥,并记录原因,但不会记录值。客户端会一直使用它已经加载的
token,因此修改之后:
- 编辑
~/.copilot-relay/config.yaml中的apiKey。 - 更新每个客户端。
claudeSetup: true时,运行copilot-relay restart或通过服务 管理器重启,让启动流程重写ANTHROPIC_AUTH_TOKEN;设置写入只在启动时运行。否则 请在每个客户端中自行设置新密钥。 - 重启正在运行的 Claude Code 会话。重启之前,它们会继续发送旧密钥并收到
401。
upstreamProxy 让 relay 的出站调用经过一个 HTTP 代理:每个 Copilot 请求、启动检查、
token 刷新、GitHub 登录,以及 copilot-relay usage 的请求。调用 relay 自己监听器的
请求(例如 status 探测)从不使用它,也不使用环境中的代理,即使 NODE_USE_ENV_PROXY=1
让 Node 自己的 fetch 使用 HTTP_PROXY。
| 值 | 路由 |
|---|---|
| 空(默认) | 直连,忽略 HTTPS_PROXY 和 HTTP_PROXY。 |
env |
使用 HTTPS_PROXY 或 HTTP_PROXY,在 relay 启动时读取。只设置了 HTTP_PROXY 时,HTTPS 也用它。NO_PROXY 中列出的主机直连。小写变量名同样有效。 |
| URL | 使用该代理,例如 http://proxy.example:3128。 |
relay 通过 CONNECT 在代理中为每个调用建立隧道,所以 HTTPS 调用经过代理时仍然端到端
加密。它不读取其他代理设置,例如操作系统的代理配置或 PAC 文件。
copilot-relay usage 从 config.yaml 读取 upstreamProxy,但不写这个文件。没有
config.yaml 时它直连;文件无法读取或无效时,它在发出任何请求之前就停止。见
日志与问题排查。
upstreamProxy 会在加载配置时校验,不满足以下条件时启动会直接失败:
-
留空、
env,或绝对的http:///https://地址。env必须小写。socks5://等其他协议、只写proxy.example:3128,以及没有主机的地址都会被拒绝。 -
不能带路径、查询参数或 fragment。
http://proxy.example:3128/可以,http://proxy.example:3128/path不行。 -
用户名和密码要么都写,要么都不写。
http://user:[email protected]:3128会 发送BasicProxy-Authorization。只有用户名没有密码(或反过来)会被拒绝,因为那样 根本不会发送凭据。两者中的保留字符要用百分号编码,例如@写成%40,#写成%23。
与 copilotBaseUrl 一样,错误信息只说明字段和规则,不会重复你配置的值。这些规则针对
config.yaml 中的 URL。使用 env 时,undici 按原样读取 HTTPS_PROXY 和 HTTP_PROXY,
不做这些检查:带路径、查询参数或 fragment 的值、百分号转义格式错误的值,以及没有协议的
值会让启动失败,错误信息只写变量名,不写变量值;只有用户名没有密码的值会被接受,且不发送
凭据。
用户名和密码属于凭据。relay 建立上游连接之后,日志中出现的 user:password(原始写法或
解码后)以及它发送的 Basic 值都显示为 [redacted]。单独的用户名或密码在那里不会被
脱敏:脱敏作用于每一行日志,较短或常见的值(例如 copilot)会把普通文本(例如
copilot-relay)中的相同部分也去掉。出于同样的原因,短于 8 个字符的形式不会被脱敏。
上游请求在没有响应的情况下失败时,它的错误在任何日志记录之前就会被清理:其中代理凭据的
每种形式都会被替换,包括较短的形式以及单独的用户名或密码;relay 无法解析的回复的原始字节
也会被丢弃。copilot-relay status 和启动日志只显示代理的 origin:
Upstream proxy: http://proxy.example:3128 (credentials hidden)
readAppConfig() 会把每个键写回 config.yaml。如果默认值是 env,升级时它会写进每个
现有安装,shell 里为其他工具设置了 HTTPS_PROXY 的安装就会在没人要求的情况下改走代理。
请用 env 或 URL 主动开启。
upstreamProxy 为空、又设置了 HTTPS_PROXY 或 HTTP_PROXY 时,如果某个上游请求在没有
响应的情况下失败,relay 每个进程只记录一次:
Upstream request failed without a response. HTTPS_PROXY or HTTP_PROXY is set, but upstreamProxy is empty, so copilot-relay connected directly. To use that proxy, set upstreamProxy: env in <config.yaml 路径>, then run the command again or restart the relay.
服务管理器(launchd、任务计划程序、systemd)不是从你的 shell 启动 relay 的,所以 env
看不到你在 shell 配置文件里导出的变量。优先在 config.yaml 里写 URL,或在服务定义里
设置这些变量。见对应平台的服务页面:macOS、
Windows、Linux。
会热重载(对改动之后开始的请求生效):
logLevellogRetentionDaysthinkEffortupstreamTimeoutSecondscopilotBaseUrlwebSearchBackendclaudeUpstreamApigptModelopusModelapiKey
需要重启:
hostportclaudeSetupupstreamProxy
host 和 port 需要重启,是因为 HTTP 监听 socket 已经绑定,运行中不能自动搬到新的
host/port。claudeSetup 只在启动时读取一次,改了它要等下次启动才生效。upstreamProxy
只在启动时建立一次 relay 的上游连接,重载不会改动它们。
relay 每秒检查一次 config.yaml。未通过校验的修改会保留之前的运行时设置,并记录一条
写明文件和原因的错误:
Could not reload config (<config.yaml 路径>): Invalid upstreamTimeoutSeconds: expected a non-negative integer (0 disables the deadline). Keeping the previous runtime settings.
relay 仍会每秒重试,但不会重复这一行。再次保存文件或原因改变时才会再次记录。修正后的
文件生效时,relay 会以 info 级别记录 Config reloaded:。
每个通过接入检查的请求都会在读取正文前快照路由、协议模式、超时、搜索后端、effort 默认值及目录视图。重载只影响新请求,不改变活动回合的重试或后续调用。凭据是例外: 每次尝试都会读取实时刷新的 token。
改 gptModel 会改变新请求的上游路由,但不会重写 ~/.claude/settings.json 中已有的模型或
token 设置。切换模型时应检查这些设置;自动设置只补充缺失的预算值。
当 claudeSetup: true 时,copilot-relay start 会把下面的配置写入:
~/.claude/settings.json
内容类似:
ANTHROPIC_BASE_URL=http://127.0.0.1:4142
ANTHROPIC_AUTH_TOKEN=<apiKey,或文件中没有 token 时的本地占位 token>
CLAUDE_CODE_MAX_CONTEXT_TOKENS=<发现的 GPT context 窗口>
CLAUDE_CODE_MAX_OUTPUT_TOKENS=<两个配置模型中最大的已公布输出预算>
CLAUDE_CODE_AUTO_MODE_SERVER=0
设置了 apiKey 时,token 就是该密钥,会替换占位值或旧密钥,因为 relay 要求每个请求
都携带它;见要求客户端密钥。之后 start 把该文件发布为只有你能读取
(模式 0600;Windows 没有这类模式位),文件模式允许其他本地用户读取时也会重新发布。
未设置 apiKey 时,start 保留已有的 ANTHROPIC_AUTH_TOKEN,即使它是之前的 apiKey
写入的密钥,也不改变文件模式;只有 token 缺失或为空时才设为 dummy。此时任何值都可以,
因为真正访问 GitHub Copilot 用的是 ~/.copilot-relay/ 里的 GitHub/Copilot token。
两个预算变量仅在缺失时写入;明确设置的较小值会被保留。Relay 会按实际路由到的模型
限制每个请求的输出预算,因此从 Astra 切换到 Opus 时,共用的客户端设置不会让请求
超过 Opus 的上限。若网关没有提供有效的限制元数据,启动日志会说明限制不可用,
并保留客户端的显式预算,而不是猜测容量。claudeSetup: false 时,请自行配置这些
客户端变量。
设置写入同样使用快照及原子替换;不会覆盖格式错误或已经存在的空设置文件,其他无关
值也会保留。
CLAUDE_CODE_AUTO_MODE_SERVER=0 同样只在缺少该键时写入。auto mode 下,Claude Code
会请服务器检查 shell 命令等操作。经过 relay 时,这些检查在 chat-completions 和
messages 路由上都没有到达 Claude Code,于是它自己发起 classifier 请求,并提示该
会话不能享受 auto mode 不再对 classifier 请求收费的变更。设为 0 后,Claude Code
不再请求服务器检查,也不再显示该提示;classifier 请求与原来相同。这个值会留在
~/.claude/settings.json 里:Claude Code 不经过 relay 连接,或改用支持服务器检查的
网关时,请删除或修改它。Claude Code 文档说明该变量是临时的,见
auto mode classifier billing。
占位 token 不是网络认证。Host/Origin 与 JSON content-type 检查减少的是浏览器
来源滥用,不能阻止任意网络客户端。请保持 loopback 监听,或在绑定到 loopback 以外的
地址前设置 apiKey;见要求客户端密钥和架构。
使用 Claude Code 2.1.242 或更新版本时,将以下示例合并到用户级
~/.claude/settings.json,保留已有 relay 连接、预算、权限、hooks 及其他设置:
{
"model": "gpt-6-astra[1m]",
"availableModels": ["opus", "gpt-6-astra[1m]"],
"modelPicker": {
"options": [
{ "model": "opus", "label": "Opus" },
{ "model": "gpt-6-astra[1m]", "label": "GPT-6 Astra" }
],
"replaceBuiltInOptions": true
},
"env": {
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-5.5"
}
}示例使用 relay 默认模型对:opusModel: claude-opus-5.5 与 gptModel: gpt-6-astra。
请让 Opus 覆盖值与实际配置的上游 ID 保持一致。Astra 的客户端 ID 使用 [1m] 表示
发现的一百万 token 窗口;如果网关公布其他窗口,应在 model、availableModels
和 modelPicker.options 中统一使用 relay 暴露的不带后缀 ID。后缀只影响客户端
上下文计算,不能扩大上游容量。
modelPicker 用这两个具名选项替换内置列表,避免继续推荐实际没有独立路由的 Sonnet、
Haiku 或 Fable。Claude Code 仍可能显示 Default 和当前会话模型,因此不能保证界面
恰好只有两行。availableModels 是选择允许列表,也会过滤 picker 项;model 只决定
启动默认值。使用 /model 选择 Opus 或 GPT-6 Astra,也可用 /model gpt-6-astra[1m]
明确选择 Astra。
Picker 设置应放在用户级、托管设置或 --settings 中,不能放在项目/本地设置中。
此示例不能扩展托管允许列表;没有托管列表时,用户/项目/本地的 availableModels
数组可能合并。若希望有效模型对保持精确,应清理你有权修改的设置中的旧条目,并检查
托管限制。普通前缀匹配下,仅设置允许列表不会限制 Default;组织级强制限制还需
在托管设置中使用 enforceAvailableModels。见官方
模型配置与
modelPicker 参考。
显式 --model、导出的 ANTHROPIC_MODEL 或恢复会话中保存的模型都可能覆盖启动选择;
若模型没有变化,请检查 shell wrapper 和更高优先级的设置。claudeSetup 保留已有
model、availableModels 和 modelPicker,不会安装或重置这个列表。Claude Code 可能
将被排除的别名替换为允许的模型,因此应核对实际选择的模型,而不能假定被排除的别名
一定报错。示例为手动选择,不会改变正在运行的 relay。
~/.copilot-relay/
config.yaml
github_token
copilot_token.json
logs/copilot-relay.2026-07-25.log <- 当前文件,本地零点轮转
logs/copilot-relay.2026-07-24.log
captures/<local-date>/<request-id>/ <- 仅 debug;私有完整正文
github_token 是登录来源。copilot_token.json 是短期 Copilot bearer token
缓存和刷新元数据。