Skip to content

fix: complete GitHub Copilot TUI & auth-files support#503

Closed
conversun wants to merge 23 commits intorouter-for-me:mainfrom
conversun:fix/github-copilot-tui-support
Closed

fix: complete GitHub Copilot TUI & auth-files support#503
conversun wants to merge 23 commits intorouter-for-me:mainfrom
conversun:fix/github-copilot-tui-support

Conversation

@conversun
Copy link
Copy Markdown

Summary

  • Add GitHub Copilot to TUI OAuth tab with device-flow user code display
  • Fix auth-files tab reading non-existent channel/auth_type fields; use actual API response fields (type/provider)
  • Add github-copilot to NormalizeOAuthProvider for callback routing consistency
  • Clear stale OAuth session state (userCode, providerName, etc.) on flow reset to prevent cross-provider UI leaks

Changes

File Change
internal/tui/oauth_tab.go Add GitHub Copilot provider entry; propagate user_code from API; show device-flow code in remote mode; hide callback input for device-flow; reset transient state on Esc/re-enter
internal/tui/auth_tab.go List view: channeltype; Detail view: ChannelType, Auth Type/auth_typeProvider/provider, File Name/file_nameFile Name/name
internal/tui/i18n.go Add oauth_user_code i18n string (zh: 验证码, en: User Code)
internal/api/handlers/management/oauth_sessions.go NormalizeOAuthProvider: "github""github", "github-copilot", "copilot" all return "github-copilot"

Testing

  • go build ./internal/tui/... ./internal/api/handlers/management/... — compiles cleanly
  • go test ./internal/tui/... ./internal/api/handlers/management/... -count=1 — all tests pass

wykk-12138 and others added 23 commits April 9, 2026 00:06
Three changes to avoid Anthropic's content-based system prompt validation:

1. Fix identity prefix: Use 'You are Claude Code, Anthropic's official CLI
   for Claude.' instead of the SDK agent prefix, matching real Claude Code.

2. Move user system instructions to user message: Only keep billing header +
   identity prefix in system[] array. User system instructions are prepended
   to the first user message as <system-reminder> blocks.

3. Enable cch signing for OAuth tokens by default: The xxHash64 cch integrity
   check was previously gated behind experimentalCCHSigning config flag.
   Now automatically enabled when using OAuth tokens.

Related: router-for-me#2599
…er cache scopes

Previous fix only injected billing header + agent identifier (2 blocks).
Anthropic's updated detection now validates system prompt content depth:
- Block count (needs 4-6 blocks, not 2)
- Cache control scopes (org for agent, global for core prompt)
- Presence of known Claude Code instruction sections

Changes:
- Add claude_system_prompt.go with extracted Claude Code v2.1.63 system prompt
  sections (intro, system instructions, doing tasks, tone & style, output efficiency)
- Rewrite checkSystemInstructionsWithSigningMode to build 5 system blocks:
  [0] billing header (no cache_control)
  [1] agent identifier (cache_control: ephemeral, scope=org)
  [2] core intro prompt (cache_control: ephemeral, scope=global)
  [3] system instructions (no cache_control)
  [4] doing tasks (no cache_control)
- Third-party client system instructions still moved to first user message

Follow-up to 69b950d
The previous commit used fmt.Sprintf with %s to insert multi-line string
constants into JSON strings. Go raw string literals contain actual newline
bytes, which produce invalid JSON (control characters in string values).

Replace with buildTextBlock() helper that uses sjson.SetBytes to properly
escape text content for JSON serialization.
sjson treats 'cache_control.type' as nested path, creating
{ephemeral: {scope: org}} instead of {type: ephemeral, scope: org}.
Pass the whole map to sjson.SetBytes as a single value.
Only for Claude OAuth requests, sanitize forwarded system-prompt context before
it is prepended into the first user message. This preserves neutral task/tool
instructions while removing OpenCode branding, docs links, environment banners,
and product-specific workflow sections that still triggered Anthropic extra-usage
classification after top-level system[] cloaking.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…rd-party fingerprint detection

A/B testing confirmed that Anthropic uses tool name fingerprinting to detect
third-party clients on OAuth traffic. OpenCode-style lowercase names like
'bash', 'read', 'todowrite' trigger extra-usage billing, while Claude Code
TitleCase names like 'Bash', 'Read', 'TodoWrite' pass through normally.

Changes:
- Add oauthToolRenameMap: maps lowercase tool names to Claude Code equivalents
- Add oauthToolsToRemove: removes 'question' and 'skill' (no Claude Code counterpart)
- remapOAuthToolNames: renames tools, removes blacklisted ones, updates tool_choice and messages
- reverseRemapOAuthToolNames/reverseRemapOAuthToolNamesFromStreamLine: reverse map for responses
- Apply in Execute(), ExecuteStream(), and CountTokens() for OAuth token requests
…dation

Antigravity 的 Claude thinking signature 处理新增 cache/bypass 双模式,
并为 bypass 模式实现按 SIGNATURE-CHANNEL-SPEC.md 的签名校验。

新增 antigravity-signature-cache-enabled 配置项(默认 true):
- cache mode(true):使用服务端缓存的签名,行为与原有逻辑完全一致
- bypass mode(false):直接使用客户端提供的签名,经过校验和归一化

支持配置热重载,运行时可切换模式。

校验流程:
1. 剥离历史 cache-mode 的 'modelGroup#' 前缀(如 claude#Exxxx → Exxxx)
2. 首字符必须为 'E'(单层编码)或 'R'(双层编码),否则拒绝
3. R 开头:base64 解码 → 内层必须以 'E' 开头 → 继续单层校验
4. E 开头:base64 解码 → 首字节必须为 0x12(Claude protobuf 标识)
5. 所有合法签名归一化为 R 形式(双层 base64)发往 Antigravity 后端

非法签名处理策略:
- 非严格模式(默认):translator 静默丢弃无签名的 thinking block
- 严格模式(antigravity-signature-bypass-strict: true):
  executor 层在请求发往上游前直接返回 HTTP 400

按 SIGNATURE-CHANNEL-SPEC.md 解析 Claude 签名的完整 protobuf 结构:
- Top-level Field 2(容器)→ Field 1(渠道块)
- 渠道块提取:channel_id (Field 1)、infrastructure (Field 2)、
  model_text (Field 6)、field7 (Field 7)
- 计算 routing_class、infrastructure_class、schema_features
- 使用 google.golang.org/protobuf/encoding/protowire 解析

- resolveThinkingSignature 拆分为 resolveCacheModeSignature / resolveBypassModeSignature
- hasResolvedThinkingSignature:mode-aware 签名有效性判断
  (cache: len>=50 via HasValidSignature,bypass: non-empty)
- validateAntigravityRequestSignatures:executor 预检,
  仅在 bypass + strict 模式下拦截非法签名返回 400
- 响应侧签名缓存逻辑与 cache mode 集成
- Cache mode 行为完全保留:无 '#' 前缀的原生签名静默丢弃
Add package-level comment documenting the protobuf tree structure,
base64 encoding equivalence proof, output dimensions, and spec
section references. Remove unreachable legacy_vertex_group dead code.
Includes: restore SDK docs under docs/; update antigravity executor credits tests; gofmt.
…che-toggle

feat: configurable signature cache toggle for Antigravity/Claude thinking blocks
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Use buildTextBlock for billing header to avoid raw JSON string interpolation
- Fix empty array edge case in prependToFirstUserMessage
- Allow remapOAuthToolNames to process messages even without tools array
- Move claude_system_prompt.go to helps/ per repo convention
- Export prompt constants (ClaudeCode* prefix) for cross-package access

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…-usage-detection

fix(claude): prevent OAuth extra-usage billing via tool name fingerprinting and system prompt cloaking
# Conflicts:
#	internal/api/server.go
- Add GitHub Copilot to OAuth tab provider list with device flow user_code display
- Fix auth-files tab reading non-existent 'channel' field; use 'type'/'provider' from API
- Add 'github-copilot' to NormalizeOAuthProvider for callback routing
- Add i18n strings for user code display (zh/en)
Prevent userCode/providerName from leaking across OAuth sessions,
which would hide the callback input for redirect-based providers
after visiting a device-flow provider like GitHub Copilot.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a signature cache and bypass validation mechanism for Antigravity/Claude thinking blocks, refactors 429 error handling with more granular retry logic and short cooldowns, and introduces tool remapping for Claude OAuth requests to avoid third-party fingerprinting. Additionally, it adds GitHub Copilot support to the TUI and updates the system prompt injection to align with Claude Code. A high-severity security issue was identified where the OAuth callback forwarder was changed to listen on all interfaces (0.0.0.0), potentially exposing it to untrusted networks.

}

addr := fmt.Sprintf("127.0.0.1:%d", port)
addr := fmt.Sprintf("0.0.0.0:%d", port)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Changing the listening address from 127.0.0.1 to 0.0.0.0 exposes the OAuth callback forwarder to the entire network. This is a security risk, especially if the proxy is running on a machine with a public IP or in an untrusted network. Unless there is a specific requirement for remote access to this temporary port, it should remain bound to the loopback interface.

@conversun
Copy link
Copy Markdown
Author

Closing in favor of a clean rebased PR (v2 branch based on origin/main to avoid unrelated diff noise).

@conversun conversun closed this Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants