Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions src/lib/claude-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, unknown> = {
...parsed,
...(nextModel !== undefined && { model: nextModel }),
Expand Down
32 changes: 32 additions & 0 deletions tests/unit/claude-settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, unknown>

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<string, unknown>

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.
Expand Down
12 changes: 12 additions & 0 deletions wiki/EN-Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:4142
ANTHROPIC_AUTH_TOKEN=<dummy local token>
CLAUDE_CODE_MAX_CONTEXT_TOKENS=<discovered GPT context window>
CLAUDE_CODE_MAX_OUTPUT_TOKENS=<largest discovered output budget of the model pair>
CLAUDE_CODE_AUTO_MODE_SERVER=0
```

into:
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions wiki/EN-Logging-Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions wiki/ZH-Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ ANTHROPIC_BASE_URL=http://127.0.0.1:4142
ANTHROPIC_AUTH_TOKEN=<dummy local token>
CLAUDE_CODE_MAX_CONTEXT_TOKENS=<发现的 GPT context 窗口>
CLAUDE_CODE_MAX_OUTPUT_TOKENS=<两个配置模型中最大的已公布输出预算>
CLAUDE_CODE_AUTO_MODE_SERVER=0
```

这里的 token 是本地 relay 占位值。真正访问 GitHub Copilot 用的是
Expand All @@ -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)。

Expand Down
14 changes: 14 additions & 0 deletions wiki/ZH-Logging-Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,提示词、工具参数/结果、签名
Expand Down
Loading