claude-gateway 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/LICENSE +21 -0
  3. package/README.md +272 -0
  4. package/dist/cli.d.ts +13 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +409 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/client.d.ts +30 -0
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +106 -0
  11. package/dist/client.js.map +1 -0
  12. package/dist/oauth.d.ts +44 -0
  13. package/dist/oauth.d.ts.map +1 -0
  14. package/dist/oauth.js +135 -0
  15. package/dist/oauth.js.map +1 -0
  16. package/dist/router/logger.d.ts +19 -0
  17. package/dist/router/logger.d.ts.map +1 -0
  18. package/dist/router/logger.js +104 -0
  19. package/dist/router/logger.js.map +1 -0
  20. package/dist/router/middleware.d.ts +9 -0
  21. package/dist/router/middleware.d.ts.map +1 -0
  22. package/dist/router/middleware.js +46 -0
  23. package/dist/router/middleware.js.map +1 -0
  24. package/dist/router/models.d.ts +11 -0
  25. package/dist/router/models.d.ts.map +1 -0
  26. package/dist/router/models.js +61 -0
  27. package/dist/router/models.js.map +1 -0
  28. package/dist/router/server.d.ts +14 -0
  29. package/dist/router/server.d.ts.map +1 -0
  30. package/dist/router/server.js +423 -0
  31. package/dist/router/server.js.map +1 -0
  32. package/dist/router/translator.d.ts +33 -0
  33. package/dist/router/translator.d.ts.map +1 -0
  34. package/dist/router/translator.js +302 -0
  35. package/dist/router/translator.js.map +1 -0
  36. package/dist/token-manager.d.ts +32 -0
  37. package/dist/token-manager.d.ts.map +1 -0
  38. package/dist/token-manager.js +79 -0
  39. package/dist/token-manager.js.map +1 -0
  40. package/dist/types.d.ts +247 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +12 -0
  43. package/dist/types.js.map +1 -0
  44. package/package.json +75 -0
package/dist/oauth.js ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * EDUCATIONAL AND ENTERTAINMENT PURPOSES ONLY
3
+ *
4
+ * This software is provided for educational, research, and entertainment purposes only.
5
+ * It is not affiliated with, endorsed by, or sponsored by Anthropic PBC.
6
+ * Use at your own risk. No warranties provided. Users are solely responsible for
7
+ * ensuring compliance with Anthropic's Terms of Service and all applicable laws.
8
+ *
9
+ * Copyright (c) 2025 - Licensed under MIT License
10
+ */
11
+ /**
12
+ * OAuth utilities for Anthropic MAX plan authentication
13
+ */
14
+ import crypto from 'crypto';
15
+ import { URL } from 'url';
16
+ export const OAUTH_CONFIG = {
17
+ client_id: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
18
+ authorize_url: 'https://claude.ai/oauth/authorize', // MAX mode
19
+ token_url: 'https://console.anthropic.com/v1/oauth/token',
20
+ redirect_uri: 'https://console.anthropic.com/oauth/code/callback',
21
+ scope: 'org:create_api_key user:profile user:inference',
22
+ };
23
+ /**
24
+ * Generate PKCE code verifier and challenge
25
+ */
26
+ export function generatePKCE() {
27
+ const verifier = crypto.randomBytes(32).toString('base64url');
28
+ const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
29
+ return { verifier, challenge };
30
+ }
31
+ /**
32
+ * Generate random state for CSRF protection
33
+ */
34
+ export function generateState() {
35
+ return crypto.randomBytes(32).toString('base64url');
36
+ }
37
+ /**
38
+ * Build authorization URL for OAuth flow
39
+ */
40
+ export function getAuthorizationUrl(codeChallenge, state) {
41
+ const url = new URL(OAUTH_CONFIG.authorize_url);
42
+ url.searchParams.set('code', 'true'); // Tell it to return code
43
+ url.searchParams.set('client_id', OAUTH_CONFIG.client_id);
44
+ url.searchParams.set('redirect_uri', OAUTH_CONFIG.redirect_uri);
45
+ url.searchParams.set('response_type', 'code');
46
+ url.searchParams.set('scope', OAUTH_CONFIG.scope);
47
+ url.searchParams.set('code_challenge', codeChallenge);
48
+ url.searchParams.set('code_challenge_method', 'S256');
49
+ url.searchParams.set('state', state);
50
+ return url.toString();
51
+ }
52
+ /**
53
+ * Exchange authorization code for tokens
54
+ */
55
+ export async function exchangeCodeForTokens(code, codeVerifier, state) {
56
+ // Anthropic uses JSON format (not standard OAuth form-urlencoded)
57
+ const requestBody = {
58
+ code,
59
+ state,
60
+ grant_type: 'authorization_code',
61
+ client_id: OAUTH_CONFIG.client_id,
62
+ redirect_uri: OAUTH_CONFIG.redirect_uri,
63
+ code_verifier: codeVerifier,
64
+ };
65
+ const response = await fetch(OAUTH_CONFIG.token_url, {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': 'application/json' },
68
+ body: JSON.stringify(requestBody),
69
+ });
70
+ if (!response.ok) {
71
+ const error = await response.text();
72
+ throw new Error(`Token exchange failed: ${error}`);
73
+ }
74
+ const tokens = (await response.json());
75
+ // Add expiration timestamp
76
+ tokens.expires_at = Date.now() + tokens.expires_in * 1000;
77
+ tokens.created_at = new Date().toISOString();
78
+ return tokens;
79
+ }
80
+ /**
81
+ * Refresh access token using refresh token
82
+ */
83
+ export async function refreshAccessToken(refreshToken) {
84
+ // Anthropic uses JSON format
85
+ const requestBody = {
86
+ grant_type: 'refresh_token',
87
+ client_id: OAUTH_CONFIG.client_id,
88
+ refresh_token: refreshToken,
89
+ };
90
+ const response = await fetch(OAUTH_CONFIG.token_url, {
91
+ method: 'POST',
92
+ headers: { 'Content-Type': 'application/json' },
93
+ body: JSON.stringify(requestBody),
94
+ });
95
+ if (!response.ok) {
96
+ const error = await response.text();
97
+ throw new Error(`Token refresh failed: ${error}`);
98
+ }
99
+ const tokens = (await response.json());
100
+ // Add expiration timestamp
101
+ tokens.expires_at = Date.now() + tokens.expires_in * 1000;
102
+ tokens.created_at = new Date().toISOString();
103
+ return tokens;
104
+ }
105
+ /**
106
+ * Start OAuth flow - user manually copies code from redirect
107
+ */
108
+ export async function startOAuthFlow(askQuestion) {
109
+ const { verifier, challenge } = generatePKCE();
110
+ const state = generateState();
111
+ const authUrl = getAuthorizationUrl(challenge, state);
112
+ console.log('\n🔐 Starting OAuth flow...\n');
113
+ console.log('Please visit this URL to authorize:\n');
114
+ console.log(authUrl);
115
+ console.log('\n' + '='.repeat(70));
116
+ console.log('After authorizing, the page will show a code and state.');
117
+ console.log('Copy them and paste in this format: code#state');
118
+ console.log('Example: abc123xyz...#def456uvw...');
119
+ console.log('='.repeat(70) + '\n');
120
+ const input = await askQuestion('Paste code#state here: ');
121
+ const trimmed = input.trim();
122
+ if (!trimmed || !trimmed.includes('#')) {
123
+ throw new Error('Invalid format. Expected: code#state');
124
+ }
125
+ const [code, returnedState] = trimmed.split('#');
126
+ if (!code || !returnedState) {
127
+ throw new Error('Missing code or state');
128
+ }
129
+ if (returnedState !== state) {
130
+ throw new Error('State mismatch - possible CSRF attack');
131
+ }
132
+ console.log('\n✅ Authorization code received!\n');
133
+ return { code, verifier, state: returnedState };
134
+ }
135
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { AnthropicRequest, AnthropicResponse } from '../types.js';
2
+ export type LogLevel = 'quiet' | 'minimal' | 'medium' | 'maximum';
3
+ export declare class Logger {
4
+ private level;
5
+ constructor(level?: LogLevel);
6
+ setLevel(level: LogLevel): void;
7
+ startup(message: string): void;
8
+ logRequest(requestId: string, timestamp: string, request: AnthropicRequest, hadSystemPrompt: boolean, response?: {
9
+ status: number;
10
+ data?: AnthropicResponse;
11
+ }, error?: Error): void;
12
+ private logMinimal;
13
+ private logMedium;
14
+ private logMaximum;
15
+ info(message: string): void;
16
+ error(message: string, error?: unknown): void;
17
+ }
18
+ export declare const logger: Logger;
19
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/router/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElE,qBAAa,MAAM;IACL,OAAO,CAAC,KAAK;gBAAL,KAAK,GAAE,QAAmB;IAE9C,QAAQ,CAAC,KAAK,EAAE,QAAQ;IAIxB,OAAO,CAAC,OAAO,EAAE,MAAM;IAOvB,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,EACzB,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;KAAE,EACvD,KAAK,CAAC,EAAE,KAAK;IAef,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,SAAS;IAsCjB,OAAO,CAAC,UAAU;IAsClB,IAAI,CAAC,OAAO,EAAE,MAAM;IAMpB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAIvC;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -0,0 +1,104 @@
1
+ export class Logger {
2
+ level;
3
+ constructor(level = 'medium') {
4
+ this.level = level;
5
+ }
6
+ setLevel(level) {
7
+ this.level = level;
8
+ }
9
+ startup(message) {
10
+ // Always show startup messages unless quiet
11
+ if (this.level !== 'quiet') {
12
+ console.log(message);
13
+ }
14
+ }
15
+ logRequest(requestId, timestamp, request, hadSystemPrompt, response, error) {
16
+ if (this.level === 'quiet') {
17
+ return;
18
+ }
19
+ if (this.level === 'minimal') {
20
+ this.logMinimal(requestId, timestamp, request, response, error);
21
+ }
22
+ else if (this.level === 'medium') {
23
+ this.logMedium(requestId, timestamp, request, hadSystemPrompt, response, error);
24
+ }
25
+ else if (this.level === 'maximum') {
26
+ this.logMaximum(requestId, timestamp, request, hadSystemPrompt, response, error);
27
+ }
28
+ }
29
+ logMinimal(requestId, timestamp, request, response, error) {
30
+ const status = error ? '✗ ERROR' : response ? `✓ ${response.status}` : '...';
31
+ const tokens = response?.data?.usage
32
+ ? `(in:${response.data.usage.input_tokens} out:${response.data.usage.output_tokens})`
33
+ : '';
34
+ console.log(`[${timestamp.substring(11, 19)}] ${status} ${request.model} ${tokens}`);
35
+ }
36
+ logMedium(requestId, timestamp, request, hadSystemPrompt, response, error) {
37
+ console.log(`\n[${timestamp}] [${requestId}] Incoming request`);
38
+ console.log(` Model: ${request.model}`);
39
+ console.log(` Max tokens: ${request.max_tokens}`);
40
+ console.log(` ✓ Translated OpenAI → Anthropic format`);
41
+ if (!hadSystemPrompt) {
42
+ console.log(` ✓ Injected required system prompt`);
43
+ }
44
+ else {
45
+ console.log(` ✓ System prompt already present`);
46
+ }
47
+ console.log(` ✓ OAuth token validated`);
48
+ if (error) {
49
+ console.log(` ✗ Error: ${error.message}`);
50
+ }
51
+ else if (response) {
52
+ console.log(` → Forwarding to Anthropic API...`);
53
+ if (response.status >= 200 && response.status < 300) {
54
+ console.log(` ✓ Success (${response.status})`);
55
+ if (response.data?.usage) {
56
+ console.log(` Tokens: input=${response.data.usage.input_tokens}, output=${response.data.usage.output_tokens}`);
57
+ }
58
+ }
59
+ else {
60
+ console.log(` ✗ Error (${response.status})`);
61
+ }
62
+ }
63
+ }
64
+ logMaximum(requestId, timestamp, request, hadSystemPrompt, response, error) {
65
+ console.log('\n' + '='.repeat(80));
66
+ console.log(`[${timestamp}] [${requestId}] REQUEST`);
67
+ console.log('='.repeat(80));
68
+ console.log('Request Body (Anthropic format):');
69
+ console.log(JSON.stringify(request, null, 2));
70
+ console.log('\n✓ Translated OpenAI → Anthropic format');
71
+ if (!hadSystemPrompt) {
72
+ console.log('\n✓ Injected required system prompt');
73
+ }
74
+ else {
75
+ console.log('\n✓ System prompt already present');
76
+ }
77
+ console.log('✓ OAuth token validated');
78
+ console.log('→ Forwarding to Anthropic API...\n');
79
+ if (error) {
80
+ console.log('='.repeat(80));
81
+ console.log('ERROR');
82
+ console.log('='.repeat(80));
83
+ console.log(error);
84
+ }
85
+ else if (response) {
86
+ console.log('='.repeat(80));
87
+ console.log(`RESPONSE (${response.status})`);
88
+ console.log('='.repeat(80));
89
+ console.log(JSON.stringify(response.data, null, 2));
90
+ }
91
+ console.log('='.repeat(80) + '\n');
92
+ }
93
+ info(message) {
94
+ if (this.level !== 'quiet') {
95
+ console.log(message);
96
+ }
97
+ }
98
+ error(message, error) {
99
+ // Always show errors
100
+ console.error(message, error || '');
101
+ }
102
+ }
103
+ export const logger = new Logger();
104
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/router/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { AnthropicRequest, SystemMessage } from '../types.js';
2
+ export declare const REQUIRED_SYSTEM_PROMPT: SystemMessage;
3
+ /**
4
+ * Ensures the required system prompt is present as the first element
5
+ * If it's already there, returns the request unchanged
6
+ * If not, prepends the required prompt
7
+ */
8
+ export declare function ensureRequiredSystemPrompt(request: AnthropicRequest): AnthropicRequest;
9
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/router/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AA6BF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAYtF"}
@@ -0,0 +1,46 @@
1
+ export const REQUIRED_SYSTEM_PROMPT = {
2
+ type: 'text',
3
+ text: "You are Claude Code, Anthropic's official CLI for Claude.",
4
+ };
5
+ /**
6
+ * Normalizes system prompt to SystemMessage[] format
7
+ * Handles both string and array inputs
8
+ */
9
+ function normalizeSystemPrompt(system) {
10
+ if (!system) {
11
+ return [];
12
+ }
13
+ if (typeof system === 'string') {
14
+ return [{ type: 'text', text: system }];
15
+ }
16
+ return system;
17
+ }
18
+ /**
19
+ * Checks if the first system message matches the required Claude Code prompt
20
+ */
21
+ function hasRequiredSystemPrompt(system) {
22
+ const normalizedSystem = normalizeSystemPrompt(system);
23
+ if (normalizedSystem.length === 0) {
24
+ return false;
25
+ }
26
+ const firstMessage = normalizedSystem[0];
27
+ return firstMessage.type === 'text' && firstMessage.text === REQUIRED_SYSTEM_PROMPT.text;
28
+ }
29
+ /**
30
+ * Ensures the required system prompt is present as the first element
31
+ * If it's already there, returns the request unchanged
32
+ * If not, prepends the required prompt
33
+ */
34
+ export function ensureRequiredSystemPrompt(request) {
35
+ // If the required prompt is already first, return as-is
36
+ if (hasRequiredSystemPrompt(request.system)) {
37
+ return request;
38
+ }
39
+ // Otherwise, prepend the required normalized prompt
40
+ const existingSystem = normalizeSystemPrompt(request.system);
41
+ return {
42
+ ...request,
43
+ system: [REQUIRED_SYSTEM_PROMPT, ...existingSystem],
44
+ };
45
+ }
46
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/router/middleware.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,2DAA2D;CAClE,CAAC;AAEF;;;GAGG;AACH,SAAS,qBAAqB,CAAC,MAAiC;IAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,MAAiC;IAChE,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,YAAY,CAAC,IAAI,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,KAAK,sBAAsB,CAAC,IAAI,CAAC;AAC3F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAyB;IAClE,wDAAwD;IACxD,IAAI,uBAAuB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,oDAAoD;IACpD,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,CAAC,sBAAsB,EAAE,GAAG,cAAc,CAAC;KACpD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Anthropic Models pulled from Anthropic API as of January 2026 and converted to OpenAI format for compatibility.
3
+ * Source: https://api.anthropic.com/v1/models
4
+ */
5
+ export declare const ANTHROPIC_MODELS: {
6
+ type: string;
7
+ id: string;
8
+ name: string;
9
+ created: number;
10
+ }[];
11
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/router/models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;GAuD5B,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Anthropic Models pulled from Anthropic API as of January 2026 and converted to OpenAI format for compatibility.
3
+ * Source: https://api.anthropic.com/v1/models
4
+ */
5
+ export const ANTHROPIC_MODELS = [
6
+ {
7
+ type: 'model',
8
+ id: 'claude-opus-4-5-20251101',
9
+ name: 'Claude Opus 4.5',
10
+ created: 1763942400,
11
+ },
12
+ {
13
+ type: 'model',
14
+ id: 'claude-haiku-4-5-20251001',
15
+ name: 'Claude Haiku 4.5',
16
+ created: 1760486400,
17
+ },
18
+ {
19
+ type: 'model',
20
+ id: 'claude-sonnet-4-5-20250929',
21
+ name: 'Claude Sonnet 4.5',
22
+ created: 1759104000,
23
+ },
24
+ {
25
+ type: 'model',
26
+ id: 'claude-opus-4-1-20250805',
27
+ name: 'Claude Opus 4.1',
28
+ created: 1754352000,
29
+ },
30
+ {
31
+ type: 'model',
32
+ id: 'claude-opus-4-20250514',
33
+ name: 'Claude Opus 4',
34
+ created: 1747872000,
35
+ },
36
+ {
37
+ type: 'model',
38
+ id: 'claude-sonnet-4-20250514',
39
+ name: 'Claude Sonnet 4',
40
+ created: 1747872000,
41
+ },
42
+ {
43
+ type: 'model',
44
+ id: 'claude-3-7-sonnet-20250219',
45
+ name: 'Claude Sonnet 3.7',
46
+ created: 1740355200,
47
+ },
48
+ {
49
+ type: 'model',
50
+ id: 'claude-3-5-haiku-20241022',
51
+ name: 'Claude Haiku 3.5',
52
+ created: 1729555200,
53
+ },
54
+ {
55
+ type: 'model',
56
+ id: 'claude-3-haiku-20240307',
57
+ name: 'Claude Haiku 3',
58
+ created: 1709769600,
59
+ },
60
+ ];
61
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/router/models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,0BAA0B;QAC9B,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,2BAA2B;QAC/B,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,4BAA4B;QAChC,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,0BAA0B;QAC9B,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,wBAAwB;QAC5B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,0BAA0B;QAC9B,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,4BAA4B;QAChC,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,2BAA2B;QAC/B,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,UAAU;KACpB;IACD;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,yBAAyB;QAC7B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,UAAU;KACpB;CACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Claude Gateway Server - OpenAI-compatible proxy for Claude Code
3
+ *
4
+ * Exports a startServer function that can be called programmatically
5
+ * or from the CLI entry point.
6
+ */
7
+ /**
8
+ * Start the router server
9
+ * @param port Port to listen on
10
+ * @param askQuestion Function to ask user questions (for OAuth flow)
11
+ * @param onReadyCallback Optional callback when server is ready and no longer needs user input
12
+ */
13
+ export declare function startServer(port: number, askQuestion: (prompt: string) => Promise<string>, onReadyCallback?: () => void): Promise<void>;
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/router/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,EAChD,eAAe,CAAC,EAAE,MAAM,IAAI,iBA+b7B"}