this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add LiteLLM proxy and auth-adapter for Claude access

- Add litellm-config.yaml with Claude Opus 4.5 and Sonnet 4 models
- Add auth-adapter.ts middleware for header translation
- LiteLLM provides OpenAI-compatible API that routes to anthropic-proxy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

alice e9edef22 2712f671

+88
+1
.beads/issues.jsonl
··· 20 20 {"id":"assistant-nno.4","title":"break_down_task tool (src/tools/breakdown.ts)","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-11T13:44:40.767448Z","updated_at":"2025-12-11T13:44:40.767448Z","dependencies":[{"issue_id":"assistant-nno.4","depends_on_id":"assistant-nno","type":"parent-child","created_at":"2025-12-11T13:44:40.767905Z","created_by":"daemon"}]} 21 21 {"id":"assistant-nno.5","title":"save_item / update_item tools (src/tools/items.ts)","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-11T13:44:41.824017Z","updated_at":"2025-12-11T13:44:41.824017Z","dependencies":[{"issue_id":"assistant-nno.5","depends_on_id":"assistant-nno","type":"parent-child","created_at":"2025-12-11T13:44:41.824488Z","created_by":"daemon"}]} 22 22 {"id":"assistant-nno.6","title":"get_open_items tool (src/tools/context.ts)","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-11T13:44:42.738005Z","updated_at":"2025-12-11T13:44:42.738005Z","dependencies":[{"issue_id":"assistant-nno.6","depends_on_id":"assistant-nno","type":"parent-child","created_at":"2025-12-11T13:44:42.738547Z","created_by":"daemon"}]} 23 + {"id":"assistant-nw2","title":"Add LiteLLM proxy for OpenAI-compatible Anthropic access","description":"","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-11T15:37:07.384093Z","updated_at":"2025-12-11T15:37:16.949013Z"} 23 24 {"id":"assistant-pqh","title":"M1: E2E Chat","description":"","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-12-11T13:43:34.073168Z","updated_at":"2025-12-11T14:23:40.572021Z","closed_at":"2025-12-11T14:23:40.572021Z","dependencies":[{"issue_id":"assistant-pqh","depends_on_id":"assistant-69t","type":"blocks","created_at":"2025-12-11T13:43:49.441521Z","created_by":"daemon"}]} 24 25 {"id":"assistant-pqh.1","title":"Webhook server (src/index.ts)","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-11T13:44:23.196257Z","updated_at":"2025-12-11T14:23:32.168811Z","closed_at":"2025-12-11T14:23:32.168811Z","dependencies":[{"issue_id":"assistant-pqh.1","depends_on_id":"assistant-pqh","type":"parent-child","created_at":"2025-12-11T13:44:23.196754Z","created_by":"daemon"}]} 25 26 {"id":"assistant-pqh.2","title":"Telegram bot setup with Telegraf (src/bot.ts)","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-11T13:44:26.327934Z","updated_at":"2025-12-11T14:22:36.187044Z","closed_at":"2025-12-11T14:22:36.187044Z","dependencies":[{"issue_id":"assistant-pqh.2","depends_on_id":"assistant-pqh","type":"parent-child","created_at":"2025-12-11T13:44:26.328387Z","created_by":"daemon"}]}
+19
litellm-config.yaml
··· 1 + model_list: 2 + # Claude Opus 4.5 - primary model for this project 3 + # Routes through auth-adapter -> anthropic-proxy for OAuth-based auth 4 + - model_name: claude-opus-4-5-20251101 5 + litellm_params: 6 + model: anthropic/claude-opus-4-5-20251101 7 + api_base: http://auth-adapter:4002 8 + api_key: os.environ/ANTHROPIC_PROXY_SESSION_ID 9 + 10 + # Additional Claude models for flexibility 11 + - model_name: claude-sonnet-4-20250514 12 + litellm_params: 13 + model: anthropic/claude-sonnet-4-20250514 14 + api_base: http://auth-adapter:4002 15 + api_key: os.environ/ANTHROPIC_PROXY_SESSION_ID 16 + 17 + litellm_settings: 18 + drop_params: true 19 + set_verbose: false
+68
src/auth-adapter.ts
··· 1 + /** 2 + * Auth adapter proxy for anthropic-proxy 3 + * 4 + * Translates Authorization: Bearer <token> to x-api-key: <token> 5 + * This allows Letta (which uses OpenAI-style auth) to communicate 6 + * with anthropic-proxy (which expects x-api-key header). 7 + * 8 + * Run: bun src/auth-adapter.ts 9 + */ 10 + 11 + const PROXY_TARGET = process.env['ANTHROPIC_PROXY_INTERNAL_URL'] ?? 'http://localhost:4001'; 12 + const PORT = Number(process.env['AUTH_ADAPTER_PORT'] ?? '4002'); 13 + 14 + console.log(`Auth adapter starting on port ${PORT.toString()}`); 15 + console.log(`Proxying to: ${PROXY_TARGET}`); 16 + 17 + Bun.serve({ 18 + port: PORT, 19 + async fetch(req) { 20 + const url = new URL(req.url); 21 + const targetUrl = `${PROXY_TARGET}${url.pathname}${url.search}`; 22 + 23 + console.log(`[${req.method}] ${url.pathname} -> ${targetUrl}`); 24 + 25 + // Clone headers and translate auth 26 + const headers = new Headers(req.headers); 27 + 28 + // Extract Bearer token and convert to x-api-key 29 + const authHeader = headers.get('Authorization') ?? ''; 30 + if (authHeader.startsWith('Bearer ')) { 31 + const token = authHeader.slice(7); 32 + headers.set('x-api-key', token); 33 + headers.delete('Authorization'); 34 + console.log(` Auth: Bearer -> x-api-key (token: ${token.slice(0, 8)}...)`); 35 + } else { 36 + console.log(` Auth: None or non-Bearer`); 37 + } 38 + 39 + // Request uncompressed responses (Letta can't handle gzip) 40 + headers.set('Accept-Encoding', 'identity'); 41 + 42 + // Forward the request 43 + try { 44 + const response = await fetch(targetUrl, { 45 + method: req.method, 46 + headers, 47 + body: req.method !== 'GET' && req.method !== 'HEAD' ? req.body : undefined, 48 + }); 49 + 50 + console.log(` Response: ${response.status.toString()}`); 51 + 52 + // Return the response 53 + return new Response(response.body, { 54 + status: response.status, 55 + statusText: response.statusText, 56 + headers: response.headers, 57 + }); 58 + } catch (error) { 59 + console.error('Proxy error:', error); 60 + return new Response(JSON.stringify({ error: 'Proxy error' }), { 61 + status: 502, 62 + headers: { 'Content-Type': 'application/json' }, 63 + }); 64 + } 65 + }, 66 + }); 67 + 68 + console.log(`Auth adapter listening on http://localhost:${PORT.toString()}`);