From 00e2a2739308846372ac6020dc5d50915224042d Mon Sep 17 00:00:00 2001 From: D0n9X1n Date: Sat, 3 Oct 2026 09:07:32 -0700 Subject: [PATCH] Seed CLAUDE_CODE_AUTO_MODE_SERVER=0 with claudeSetup In auto mode Claude Code asks the server to check actions. Through the relay those checks did not reach it on the chat-completions or messages route, so it made its own classifier requests and printed a notice that the session isn't eligible for auto mode's no-charge classifier requests. An interactive session holds the first checked action until the notice is answered. applyClaudeConfig now seeds CLAUDE_CODE_AUTO_MODE_SERVER=0 when the key is absent from Claude Code's settings, as it does for the token budgets; a value already there is kept. With 0, Claude Code skips the server check and the notice, and its classifier requests stay as they were. The Configuration and troubleshooting pages say when to remove it. Closes #162 Co-Authored-By: Claude Opus 5.5 (1M context) --- config.default.yaml | 3 ++- src/lib/claude-settings.ts | 8 ++++++++ tests/unit/claude-settings.test.ts | 32 ++++++++++++++++++++++++++++++ wiki/EN-Configuration.md | 12 +++++++++++ wiki/EN-Logging-Troubleshooting.md | 16 +++++++++++++++ wiki/ZH-Configuration.md | 10 ++++++++++ wiki/ZH-Logging-Troubleshooting.md | 14 +++++++++++++ 7 files changed, 94 insertions(+), 1 deletion(-) diff --git a/config.default.yaml b/config.default.yaml index c255c3b..d15f43f 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -21,7 +21,8 @@ copilotBaseUrl: https://api.githubcopilot.com # When true, start updates ~/.claude/settings.json with ANTHROPIC_BASE_URL # and a dummy ANTHROPIC_AUTH_TOKEN so Claude Code can use this proxy. -# Also seeds context/output budgets from model discovery when not already set. +# Also seeds context/output budgets from model discovery, and +# CLAUDE_CODE_AUTO_MODE_SERVER=0, when not already set. claudeSetup: true # Log verbosity: diff --git a/src/lib/claude-settings.ts b/src/lib/claude-settings.ts index 65ba6eb..f5dbeea 100644 --- a/src/lib/claude-settings.ts +++ b/src/lib/claude-settings.ts @@ -134,6 +134,14 @@ export async function applyClaudeConfig( env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = String(input.maxOutputTokens) } + // In auto mode Claude Code asks the server to check actions. In #162 those checks did not reach + // it through the relay, so it made its own classifier requests and printed a notice asking the + // gateway to support them. "0" skips the server check and the notice; the classifier requests + // stay as they were. Seeded only when absent, so a value the user set is kept. + if (env.CLAUDE_CODE_AUTO_MODE_SERVER === undefined) { + env.CLAUDE_CODE_AUTO_MODE_SERVER = "0" + } + const next: Record = { ...parsed, ...(nextModel !== undefined && { model: nextModel }), diff --git a/tests/unit/claude-settings.test.ts b/tests/unit/claude-settings.test.ts index d7a2371..6ceec30 100644 --- a/tests/unit/claude-settings.test.ts +++ b/tests/unit/claude-settings.test.ts @@ -83,6 +83,38 @@ test("preserves explicit client context and output overrides", async () => { }) }) +// #162: through the relay, auto mode's server checks did not reach Claude Code, and it showed a +// notice. The writer seeds CLAUDE_CODE_AUTO_MODE_SERVER=0, but only when the key is absent. +test("seeds CLAUDE_CODE_AUTO_MODE_SERVER=0 only when it is absent", async () => { + const input = (configPath: string) => ({ + baseUrl: "http://127.0.0.1:4142", + configPath, + gptModel: "gpt-6-astra", + gptLimits: astraLimits, + maxOutputTokens: 128_000, + }) + + await withTemporarySettings(async (configPath) => { + await applyClaudeConfig(input(configPath)) + const env = (await readSettings(configPath)).env as Record + + assert.equal(env.CLAUDE_CODE_AUTO_MODE_SERVER, "0") + assert.equal((await applyClaudeConfig(input(configPath))).changed, false) + }) + + for (const value of ["0", "1"]) { + await withTemporarySettings(async (configPath) => { + await fs.mkdir(path.dirname(configPath), { recursive: true }) + await fs.writeFile(configPath, JSON.stringify({ env: { CLAUDE_CODE_AUTO_MODE_SERVER: value } })) + + await applyClaudeConfig(input(configPath)) + const env = (await readSettings(configPath)).env as Record + + assert.equal(env.CLAUDE_CODE_AUTO_MODE_SERVER, value) + }) + } +}) + // Why: a fresh managed Claude Code setup must actually select the configured GPT // default and expose its 1M client-side context identity without changing the // canonical model that Copilot receives. diff --git a/wiki/EN-Configuration.md b/wiki/EN-Configuration.md index dd5154c..6f3e8ed 100644 --- a/wiki/EN-Configuration.md +++ b/wiki/EN-Configuration.md @@ -665,6 +665,7 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:4142 ANTHROPIC_AUTH_TOKEN= CLAUDE_CODE_MAX_CONTEXT_TOKENS= CLAUDE_CODE_MAX_OUTPUT_TOKENS= +CLAUDE_CODE_AUTO_MODE_SERVER=0 ``` into: @@ -684,6 +685,17 @@ With `claudeSetup: false`, configure these client variables yourself. The settings writer uses the same snapshot/atomic replacement boundary; malformed or existing empty settings files are not overwritten, and unrelated values remain. +`CLAUDE_CODE_AUTO_MODE_SERVER=0` is also written only when the key is absent. In +auto mode, Claude Code asks the server to check actions such as shell commands. +Through the relay those checks did not reach Claude Code on the `chat-completions` +or `messages` route, so it made its own classifier requests and printed a notice +that the session isn't eligible for auto mode's no-charge classifier requests. +With `0`, Claude Code skips the server check and the notice; the classifier +requests stay as they were. The value stays in `~/.claude/settings.json`: remove +or change it when Claude Code connects without the relay, or through a gateway +that supports the server checks. Claude Code documents the variable as temporary; +see [auto mode classifier billing](https://code.claude.com/docs/en/auto-mode-classifier-billing). + The local dummy token is **not network authentication**. Host/Origin checks and JSON content-type validation reduce browser-origin misuse, not access by an arbitrary network client. Keep the listener on loopback; see diff --git a/wiki/EN-Logging-Troubleshooting.md b/wiki/EN-Logging-Troubleshooting.md index 9a88639..918e339 100644 --- a/wiki/EN-Logging-Troubleshooting.md +++ b/wiki/EN-Logging-Troubleshooting.md @@ -924,10 +924,26 @@ Expected values: - `ANTHROPIC_BASE_URL` points at `http://127.0.0.1:4142` - `ANTHROPIC_AUTH_TOKEN` exists; it is a dummy value for local relay use +- `CLAUDE_CODE_AUTO_MODE_SERVER` is `0`, unless you set another value Changing `host` or `port` requires restarting the relay, because the listening socket cannot move during hot reload. +## Claude Code says the session isn't eligible for auto mode + +Claude Code can print a notice like this, in the terminal or, with `claude -p`, +on stderr: + +```text +We're changing auto mode to no longer charge for classifier requests in Claude Code. However, this session isn't eligible because your requests go through 127.0.0.1:4142, which isn't compatible with this update. Nothing breaks: auto mode keeps working, and its classifier requests are billed as before. +``` + +It is expected through the relay: auto mode's server checks do not reach Claude +Code, so it makes its own classifier requests. `CLAUDE_CODE_AUTO_MODE_SERVER=0` in +Claude Code's environment stops the server check and the notice. With +`claudeSetup: true`, `copilot-relay start` writes it when it is absent; see +[Configuration](EN-Configuration.md). + ## Safe log sharing **Never share raw captures wholesale.** Prompts, tool arguments/results, signed diff --git a/wiki/ZH-Configuration.md b/wiki/ZH-Configuration.md index 66212fe..ade9e3f 100644 --- a/wiki/ZH-Configuration.md +++ b/wiki/ZH-Configuration.md @@ -572,6 +572,7 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:4142 ANTHROPIC_AUTH_TOKEN= CLAUDE_CODE_MAX_CONTEXT_TOKENS=<发现的 GPT context 窗口> CLAUDE_CODE_MAX_OUTPUT_TOKENS=<两个配置模型中最大的已公布输出预算> +CLAUDE_CODE_AUTO_MODE_SERVER=0 ``` 这里的 token 是本地 relay 占位值。真正访问 GitHub Copilot 用的是 @@ -584,6 +585,15 @@ CLAUDE_CODE_MAX_OUTPUT_TOKENS=<两个配置模型中最大的已公布输出预 设置写入同样使用快照及原子替换;不会覆盖格式错误或已经存在的空设置文件,其他无关 值也会保留。 +`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](https://code.claude.com/docs/en/auto-mode-classifier-billing)。 + 本地占位 token **不是网络认证**。Host/Origin 与 JSON content-type 检查减少的是浏览器 来源滥用,不能阻止任意网络客户端。请保持 loopback 监听,见[架构](ZH-Architecture.md)。 diff --git a/wiki/ZH-Logging-Troubleshooting.md b/wiki/ZH-Logging-Troubleshooting.md index 465d66c..1d3b382 100644 --- a/wiki/ZH-Logging-Troubleshooting.md +++ b/wiki/ZH-Logging-Troubleshooting.md @@ -816,9 +816,23 @@ cat ~/.claude/settings.json - `ANTHROPIC_BASE_URL` 指向 `http://127.0.0.1:4142` - `ANTHROPIC_AUTH_TOKEN` 存在;它是给本地中继用的占位值 +- `CLAUDE_CODE_AUTO_MODE_SERVER` 为 `0`,除非你设置了其他值 改 `host` 或 `port` 需要重启中继,因为监听 socket 无法在热重载期间迁移。 +## Claude Code 提示会话不符合 auto mode 的条件 + +Claude Code 可能在终端中,或用 `claude -p` 时在 stderr 上,打印类似这样的提示: + +```text +We're changing auto mode to no longer charge for classifier requests in Claude Code. However, this session isn't eligible because your requests go through 127.0.0.1:4142, which isn't compatible with this update. Nothing breaks: auto mode keeps working, and its classifier requests are billed as before. +``` + +经过中继时这是预期行为:auto mode 的服务器检查到达不了 Claude Code,所以它自己发起 +classifier 请求。在 Claude Code 的环境中设置 `CLAUDE_CODE_AUTO_MODE_SERVER=0`,可停止 +服务器检查和这条提示。`claudeSetup: true` 时,`copilot-relay start` 会在缺少该值时 +写入它;见[配置](ZH-Configuration.md)。 + ## 安全分享日志 **绝不要整份分享原始捕获。** 即使排除了认证 header,提示词、工具参数/结果、签名