@@ -6,6 +6,7 @@ import { createGoogleGenerativeAI } from "@ai-sdk/google";
6
6
import { createOpenAI } from "@ai-sdk/openai" ;
7
7
import { createXai } from "@ai-sdk/xai" ;
8
8
import { spawn } from "child_process" ;
9
+ import { randomUUID } from "crypto" ;
9
10
import {
10
11
createAnthropicProxy ,
11
12
type CreateAnthropicProxyOptions ,
@@ -42,28 +43,60 @@ if (process.env.ANTHROPIC_API_KEY) {
42
43
} ) ;
43
44
}
44
45
45
- const proxyURL = createAnthropicProxy ( {
46
- providers,
47
- } ) ;
46
+ // Authentication token for the proxy. If the user already provided an
47
+ // ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY, reuse it so Claude sends it as
48
+ // Authorization: Bearer / X-Api-Key. Otherwise generate an ephemeral token and
49
+ // inject it only into the spawned Claude process.
50
+ const proxyAuthToken =
51
+ process . env . ANTHROPIC_AUTH_TOKEN ??
52
+ process . env . ANTHROPIC_API_KEY ??
53
+ randomUUID ( ) ;
54
+
55
+ const proxyAuthHeaderName = process . env . ANYCLAUDE_AUTH_HEADER ?? "X-AnyClaude-Token" ;
56
+
57
+ // Allow overriding host/port via environment variables for flexibility. If
58
+ // port is not provided, we bind to an ephemeral random port for parallel safety.
59
+ const proxyHost = process . env . ANYCLAUDE_HOST || "127.0.0.1" ;
60
+ const proxyPort = process . env . ANYCLAUDE_PORT
61
+ ? Number ( process . env . ANYCLAUDE_PORT )
62
+ : undefined ;
63
+
64
+ ( async ( ) => {
65
+ const proxyURL = await createAnthropicProxy ( {
66
+ providers,
67
+ host : proxyHost ,
68
+ port : proxyPort ,
69
+ authToken : proxyAuthToken ,
70
+ authHeaderName : proxyAuthHeaderName ,
71
+ } ) ;
72
+
73
+ if ( process . env . PROXY_ONLY === "true" ) {
74
+ console . log ( "Proxy only mode: " + proxyURL ) ;
75
+ return ;
76
+ }
48
77
49
- if ( process . env . PROXY_ONLY === "true" ) {
50
- console . log ( "Proxy only mode: " + proxyURL ) ;
51
- } else {
52
78
const claudeArgs = process . argv . slice ( 2 ) ;
53
79
const proc = spawn ( "claude" , claudeArgs , {
54
80
env : {
55
81
...process . env ,
56
82
ANTHROPIC_BASE_URL : proxyURL ,
83
+ // Ensure the Claude CLI includes our custom header via ANTHROPIC_CUSTOM_HEADERS
84
+ ANTHROPIC_CUSTOM_HEADERS : ( ( ) => {
85
+ const existing = process . env . ANTHROPIC_CUSTOM_HEADERS ;
86
+ const line = `${ proxyAuthHeaderName } : ${ proxyAuthToken } ` ;
87
+ return existing ? `${ existing } \n${ line } ` : line ;
88
+ } ) ( ) ,
57
89
} ,
58
90
stdio : "inherit" ,
59
91
} ) ;
60
92
proc . on ( "exit" , ( code ) => {
61
93
if ( claudeArgs [ 0 ] === "-h" || claudeArgs [ 0 ] === "--help" ) {
62
- console . log ( "\nCustom Models:" )
63
- console . log ( " --model <provider>/<model> e.g. openai/o3 " ) ;
94
+ console . log ( "\nCustom Models:" ) ;
95
+ console . log ( " --model <provider>/<model> e.g. openai/gpt-5-mini " ) ;
64
96
}
65
-
66
- process . exit ( code ) ;
97
+ process . exit ( code ?? 0 ) ;
67
98
} ) ;
68
- }
69
-
99
+ } ) ( ) . catch ( ( err ) => {
100
+ console . error ( err ) ;
101
+ process . exit ( 1 ) ;
102
+ } ) ;
0 commit comments