diff --git a/docs/api-proxy-sidecar.md b/docs/api-proxy-sidecar.md index 16aa7b9a..af3e94f3 100644 --- a/docs/api-proxy-sidecar.md +++ b/docs/api-proxy-sidecar.md @@ -33,7 +33,7 @@ When enabled, the API proxy sidecar: │ │ │ Agent Container │ │ │ │ │ 172.30.0.20 │ │ │ │ │ OPENAI_BASE_URL= │ │ -│ │ │ http://172.30.0.30:10000/v1│────┘ +│ │ │ http://172.30.0.30:10000 │────┘ │ │ │ ANTHROPIC_BASE_URL= │ │ │ │ http://172.30.0.30:10001 │ │ │ └──────────────────────────────┘ @@ -76,7 +76,7 @@ sudo awf --enable-api-proxy \ -- npx @openai/codex -p "write a hello world function" ``` -The agent container automatically uses `http://172.30.0.30:10000/v1` as the OpenAI base URL. +The agent container automatically uses `http://172.30.0.30:10000` as the OpenAI base URL. ### Claude Code example @@ -138,7 +138,7 @@ The agent container receives **redacted placeholders** and proxy URLs: | Variable | Value | When set | Description | |----------|-------|----------|-------------| -| `OPENAI_BASE_URL` | `http://172.30.0.30:10000/v1` | `OPENAI_API_KEY` provided to host | Redirects OpenAI SDK to proxy | +| `OPENAI_BASE_URL` | `http://172.30.0.30:10000` | `OPENAI_API_KEY` provided to host | Redirects OpenAI SDK to proxy | | `ANTHROPIC_BASE_URL` | `http://172.30.0.30:10001` | `ANTHROPIC_API_KEY` provided to host | Redirects Anthropic SDK to proxy | | `ANTHROPIC_AUTH_TOKEN` | `placeholder-token-for-credential-isolation` | `ANTHROPIC_API_KEY` provided to host | Placeholder token (real auth via BASE_URL) | | `CLAUDE_CODE_API_KEY_HELPER` | `/usr/local/bin/get-claude-key.sh` | `ANTHROPIC_API_KEY` provided to host | Helper script for Claude Code CLI | @@ -231,7 +231,7 @@ When you pass `--enable-api-proxy`: ``` Agent Code - ↓ (HTTP request to 172.30.0.30:10000/v1) + ↓ (HTTP request to 172.30.0.30:10000) Node.js API Proxy ↓ (strips client auth headers) ↓ (injects Authorization: Bearer $OPENAI_API_KEY) diff --git a/docs/authentication-architecture.md b/docs/authentication-architecture.md index 72dcf8b3..2d6cf1e7 100644 --- a/docs/authentication-architecture.md +++ b/docs/authentication-architecture.md @@ -41,7 +41,7 @@ AWF uses a **3-container architecture** when API proxy mode is enabled: │ ✓ HTTP_PROXY=172.30.0.10:3128 │ │ ✓ ANTHROPIC_BASE_URL= │ │ ✓ HTTPS_PROXY=172.30.0.10:3128 │ │ http://172.30.0.30:10001 │ │ │ │ ✓ OPENAI_BASE_URL= │ -│ Ports: │ │ http://172.30.0.30:10000/v1 │ +│ Ports: │ │ http://172.30.0.30:10000 │ │ - 10000 (OpenAI proxy) │◄──────│ ✓ GITHUB_TOKEN=ghp_... │ │ - 10001 (Anthropic proxy) │ │ (protected by one-shot-token) │ │ │ │ │ @@ -113,7 +113,7 @@ agent: environment: # NO API KEYS - only base URLs pointing to api-proxy - ANTHROPIC_BASE_URL=http://172.30.0.30:10001 - - OPENAI_BASE_URL=http://172.30.0.30:10000/v1 + - OPENAI_BASE_URL=http://172.30.0.30:10000 # GitHub token for MCP servers (protected separately) - GITHUB_TOKEN=ghp_... networks: @@ -174,7 +174,7 @@ The agent container sees these environment variables: ```bash ANTHROPIC_BASE_URL=http://172.30.0.30:10001 -OPENAI_BASE_URL=http://172.30.0.30:10000/v1 +OPENAI_BASE_URL=http://172.30.0.30:10000 ``` These are standard environment variables recognized by the official SDKs: @@ -209,7 +209,7 @@ import openai client = openai.OpenAI() # SDK reads OPENAI_BASE_URL from environment -# Sends request to http://172.30.0.30:10000/v1 instead of api.openai.com +# Sends request to http://172.30.0.30:10000 instead of api.openai.com response = client.chat.completions.create( model="gpt-4", @@ -250,7 +250,7 @@ Without the NAT `RETURN` rule, traffic to `172.30.0.30` would be redirected to S **Traffic flow for OpenAI/Codex:** -1. Agent SDK makes HTTP request to `172.30.0.30:10000/v1` +1. Agent SDK makes HTTP request to `172.30.0.30:10000` 2. iptables allows direct TCP connection (NAT `RETURN` rule) 3. API proxy receives request on port 10000 4. API proxy injects `Authorization: Bearer sk-...` header diff --git a/src/docker-manager.test.ts b/src/docker-manager.test.ts index 3b00279f..2b1bbb7d 100644 --- a/src/docker-manager.test.ts +++ b/src/docker-manager.test.ts @@ -2345,7 +2345,7 @@ describe('docker-manager', () => { const result = generateDockerCompose(configWithProxy, mockNetworkConfigWithProxy); const agent = result.services.agent; const env = agent.environment as Record; - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); }); it('should configure HTTP_PROXY and HTTPS_PROXY in api-proxy to route through Squid', () => { @@ -2372,7 +2372,7 @@ describe('docker-manager', () => { const result = generateDockerCompose(configWithProxy, mockNetworkConfigWithProxy); const agent = result.services.agent; const env = agent.environment as Record; - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); expect(env.ANTHROPIC_BASE_URL).toBe('http://172.30.0.30:10001'); expect(env.ANTHROPIC_AUTH_TOKEN).toBe('sk-ant-placeholder-key-for-credential-isolation'); expect(env.CLAUDE_CODE_API_KEY_HELPER).toBe('/usr/local/bin/get-claude-key.sh'); @@ -2395,7 +2395,7 @@ describe('docker-manager', () => { const agent = result.services.agent; const env = agent.environment as Record; expect(env.ANTHROPIC_BASE_URL).toBeUndefined(); - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); }); it('should set AWF_API_PROXY_IP in agent environment', () => { @@ -2467,7 +2467,7 @@ describe('docker-manager', () => { // Agent should NOT have the raw API key — only the sidecar gets it expect(env.OPENAI_API_KEY).toBeUndefined(); // Agent should have OPENAI_BASE_URL to proxy through sidecar - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); } finally { if (origKey !== undefined) { process.env.OPENAI_API_KEY = origKey; @@ -2490,7 +2490,7 @@ describe('docker-manager', () => { // CODEX_API_KEY should NOT be passed to agent when api-proxy is enabled expect(env.CODEX_API_KEY).toBeUndefined(); // OPENAI_BASE_URL should be set when api-proxy is enabled with openaiApiKey - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); } finally { if (origKey !== undefined) { process.env.CODEX_API_KEY = origKey; @@ -2512,7 +2512,7 @@ describe('docker-manager', () => { // Even with envAll, agent should NOT have OPENAI_API_KEY when api-proxy is enabled expect(env.OPENAI_API_KEY).toBeUndefined(); // Agent should have OPENAI_BASE_URL to proxy through sidecar - expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1'); + expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000'); } finally { if (origKey !== undefined) { process.env.OPENAI_API_KEY = origKey; diff --git a/src/docker-manager.ts b/src/docker-manager.ts index ff00583b..3fefd8f8 100644 --- a/src/docker-manager.ts +++ b/src/docker-manager.ts @@ -1802,8 +1802,8 @@ export function generateDockerCompose( // container names in chroot mode environment.AWF_API_PROXY_IP = networkConfig.proxyIp; if (config.openaiApiKey) { - environment.OPENAI_BASE_URL = `http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}/v1`; - logger.debug(`OpenAI API will be proxied through sidecar at http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}/v1`); + environment.OPENAI_BASE_URL = `http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}`; + logger.debug(`OpenAI API will be proxied through sidecar at http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}`); if (config.openaiApiTarget) { logger.debug(`OpenAI API target overridden to: ${config.openaiApiTarget}`); } diff --git a/src/types.ts b/src/types.ts index 47d914a0..ee094d96 100644 --- a/src/types.ts +++ b/src/types.ts @@ -615,7 +615,7 @@ export interface WrapperConfig { * * When the corresponding API key is provided, the following environment * variables are set in the agent container: - * - OPENAI_BASE_URL=http://api-proxy:10000/v1 (set when OPENAI_API_KEY is provided) + * - OPENAI_BASE_URL=http://api-proxy:10000 (set when OPENAI_API_KEY is provided) * - ANTHROPIC_BASE_URL=http://api-proxy:10001 (set when ANTHROPIC_API_KEY is provided) * - COPILOT_API_URL=http://api-proxy:10002 (set when COPILOT_GITHUB_TOKEN or COPILOT_API_KEY is provided) * - CLAUDE_CODE_API_KEY_HELPER=/usr/local/bin/get-claude-key.sh (set when ANTHROPIC_API_KEY is provided)