|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Development Commands |
| 6 | + |
| 7 | +- **Build**: `bun run build` (uses tsdown) |
| 8 | +- **Development**: `bun run dev` (with file watching) |
| 9 | +- **Production**: `bun run start` (sets NODE_ENV=production) |
| 10 | +- **Lint**: `bun run lint` (uses @echristian/eslint-config with cache) |
| 11 | +- **Lint fix**: `bunx lint-staged` (fixes staged files) |
| 12 | +- **Typecheck**: `bun run typecheck` (runs TypeScript compiler) |
| 13 | +- **Test all**: `bun test` |
| 14 | +- **Test single file**: `bun test tests/[filename].test.ts` |
| 15 | +- **Package**: `bun run prepack` (builds before packaging) |
| 16 | + |
| 17 | +## Project Architecture |
| 18 | + |
| 19 | +### High-Level Structure |
| 20 | +This is a GitHub Copilot API proxy server that exposes Copilot as OpenAI-compatible, Anthropic-compatible, and Gemini-compatible APIs. The server is built with Hono framework and uses Bun as the runtime. |
| 21 | + |
| 22 | +### Core Architecture Components |
| 23 | + |
| 24 | +**API Translation Layer** (`src/routes/messages/`): |
| 25 | +- Translates between Anthropic Messages API format and OpenAI Chat Completions format |
| 26 | +- Translates between Gemini API format and OpenAI Chat Completions format |
| 27 | +- Handles both streaming and non-streaming responses |
| 28 | +- Key files: `handler.ts`, `anthropic-types.ts`, `stream-translation.ts`, `non-stream-translation.ts` |
| 29 | +- Gemini files: `gemini-handler.ts`, `gemini-translation.ts`, `gemini-types.ts`, `gemini-route.ts` |
| 30 | + |
| 31 | +**Token Counting for Anthropic Models** (`src/lib/tokenizer.ts`): |
| 32 | +- Uses `gpt-tokenizer/model/gpt-4o` for token counting |
| 33 | +- Separates input tokens (all messages except last assistant message) from output tokens (last assistant message) |
| 34 | +- Filters out tool messages and extracts text content from multipart messages |
| 35 | +- Used by `/v1/messages/count_tokens` endpoint for Anthropic compatibility |
| 36 | + |
| 37 | +**GitHub Copilot Integration** (`src/services/`): |
| 38 | +- Authentication flow using device code OAuth |
| 39 | +- Token management and refresh |
| 40 | +- API requests to GitHub Copilot endpoints |
| 41 | +- Usage monitoring and quota tracking |
| 42 | + |
| 43 | +**Rate Limiting & Controls** (`src/lib/`): |
| 44 | +- Rate limiting between requests (`rate-limit.ts`) |
| 45 | +- Manual approval system for requests (`approval.ts`) |
| 46 | +- State management for server configuration (`state.ts`) |
| 47 | + |
| 48 | +### API Endpoints Structure |
| 49 | + |
| 50 | +**OpenAI Compatible**: |
| 51 | +- `/v1/chat/completions` - Chat completions |
| 52 | +- `/v1/models` - Available models |
| 53 | +- `/v1/embeddings` - Text embeddings |
| 54 | + |
| 55 | +**Anthropic Compatible**: |
| 56 | +- `/v1/messages` - Message completions (translates to/from OpenAI format) |
| 57 | +- `/v1/messages/count_tokens` - Token counting for Anthropic format |
| 58 | + |
| 59 | +**Gemini Compatible**: |
| 60 | +- `/v1beta/models/{model}:generateContent` - Standard generation |
| 61 | +- `/v1beta/models/{model}:streamGenerateContent` - Streaming generation |
| 62 | +- `/v1beta/models/{model}:countTokens` - Token counting |
| 63 | + |
| 64 | +**Monitoring**: |
| 65 | +- `/usage` - GitHub Copilot usage dashboard |
| 66 | +- `/token` - Current Copilot token info |
| 67 | + |
| 68 | +### Key Implementation Details |
| 69 | + |
| 70 | +**Anthropic Token Counting**: |
| 71 | +The `getTokenCount()` function in `src/lib/tokenizer.ts` implements token counting specifically for Anthropic compatibility: |
| 72 | +- Converts multipart content to text-only for counting |
| 73 | +- Splits messages into input (all except last assistant) and output (last assistant message only) |
| 74 | +- Uses GPT-4o tokenizer as the underlying counting mechanism |
| 75 | +- Returns `{input: number, output: number}` format |
| 76 | + |
| 77 | +**Message Translation**: |
| 78 | +- OpenAI → Anthropic: Converts chat completion responses to Anthropic message format |
| 79 | +- Anthropic → OpenAI: Converts Anthropic message requests to OpenAI chat completion format |
| 80 | +- OpenAI → Gemini: Converts chat completion responses to Gemini response format |
| 81 | +- Gemini → OpenAI: Converts Gemini requests to OpenAI chat completion format |
| 82 | +- Handles tool calls, system messages, and content blocks appropriately for all formats |
| 83 | + |
| 84 | +**Streaming Translation**: |
| 85 | +Real-time conversion of OpenAI SSE chunks to both Anthropic streaming events and Gemini streaming responses, maintaining state for proper message reconstruction. |
| 86 | + |
| 87 | +**Gemini API Implementation**: |
| 88 | +The Gemini integration (`src/routes/messages/gemini-*`) provides: |
| 89 | +- Full compatibility with Google's Gemini API specification |
| 90 | +- Comprehensive request/response translation between Gemini and OpenAI formats |
| 91 | +- Support for function calling, multimodal content (text + images), and streaming |
| 92 | +- Extensive debug logging with file-based logs in `logs/` directory |
| 93 | +- Error handling with appropriate HTTP status codes and Gemini-formatted error responses |
| 94 | +- Support for generation configuration (temperature, max tokens, top-p, stop sequences) |
| 95 | + |
| 96 | +**Critical Gemini Translation Details**: |
| 97 | +- Gemini CLI sends function responses as **nested arrays** in contents, requiring special handling |
| 98 | +- `parametersJsonSchema` field takes precedence over `parameters` in function declarations |
| 99 | +- Tool call ID mapping must be maintained between assistant tool calls and user tool responses |
| 100 | +- Function response arrays need extraction with `processFunctionResponseArray()` helper |
| 101 | +- Debug logs in `logs/gemini-*.log` files are essential for troubleshooting translation issues |
| 102 | + |
| 103 | +## Code Style & Conventions |
| 104 | + |
| 105 | +- **TypeScript**: Strict mode enabled, avoid `any` types |
| 106 | +- **Imports**: Use `~/*` path aliases for `src/*` imports |
| 107 | +- **Error Handling**: Use explicit error classes from `src/lib/error.ts` |
| 108 | +- **Testing**: Place tests in `tests/` directory with `*.test.ts` naming |
| 109 | +- **Formatting**: Prettier with package.json plugin |
| 110 | +- **Linting**: @echristian/eslint-config with strict rules |
| 111 | + |
| 112 | +## Important Notes |
| 113 | + |
| 114 | +- Server uses GitHub Copilot as the underlying LLM provider |
| 115 | +- Rate limiting and manual approval features help avoid GitHub abuse detection |
| 116 | +- Token counting uses GPT-4o tokenizer regardless of the actual model being proxied |
| 117 | +- All API translations maintain compatibility with OpenAI, Anthropic, and Gemini client libraries |
| 118 | +- Gemini API debugging logs are written to `logs/` directory for troubleshooting translation issues |
| 119 | + |
| 120 | +## Debugging & Troubleshooting |
| 121 | + |
| 122 | +**Common Gemini API Issues**: |
| 123 | +- **Function calls fail while text prompts work**: Check `logs/gemini-translation.log` for missing `parameters` in translated tools |
| 124 | +- **Tool response mapping errors**: Verify tool_call_id consistency between assistant tool calls and user tool responses |
| 125 | +- **Nested array handling**: Gemini CLI sends function responses as nested arrays requiring `processFunctionResponseArray()` extraction |
| 126 | +- **HTTPError from create-chat-completions**: Usually indicates parameter validation failure in OpenAI translation layer |
| 127 | + |
| 128 | +**Key Log Files**: |
| 129 | +- `logs/gemini-errors.log`: HTTP errors and stack traces |
| 130 | +- `logs/gemini-debug.log`: Request/response flow with full JSON payloads |
| 131 | +- `logs/gemini-translation.log`: Translation pipeline details showing input/output transformations |
| 132 | + |
| 133 | +**Debugging Commands**: |
| 134 | +- `bun run lint && bun run typecheck && bun run build`: Full validation pipeline |
| 135 | +- Check error reports in `C:\Users\39764\AppData\Local\Temp\gemini-client-error-*.json` for client-side failures |
0 commit comments