@@ -51,6 +51,8 @@ export interface ResolvedConfig {
5151 model : Model < string > ;
5252 apiKey : string ;
5353 source : "explicit" | "auto" | "proxy" | "byok" ;
54+ /** Header contract for Codebase proxy credentials. OAuth uses Bearer; issued keys use X-API-Key. */
55+ proxyAuth ?: "bearer" | "api-key" ;
5456}
5557
5658export class ConfigError extends Error { }
@@ -102,7 +104,12 @@ export function resolveConfig(envOrOpts: NodeJS.ProcessEnv | ResolveConfigOption
102104 const byok = buildByokConfig ( creds . provider as KnownProvider , creds . accessToken , override ) ;
103105 if ( byok ) return byok ;
104106 } else if ( useProxy ) {
105- const proxied = buildProxiedConfig ( env , creds . accessToken , override ) ;
107+ const proxied = buildProxiedConfig (
108+ env ,
109+ creds . accessToken ,
110+ creds . source === "manual" ? "api-key" : "bearer" ,
111+ override ,
112+ ) ;
106113 if ( proxied ) return proxied ;
107114 }
108115 }
@@ -202,6 +209,7 @@ export function resolveConfig(envOrOpts: NodeJS.ProcessEnv | ResolveConfigOption
202209function buildProxiedConfig (
203210 env : NodeJS . ProcessEnv ,
204211 accessToken : string ,
212+ authMode : "bearer" | "api-key" ,
205213 override ?: { provider ?: string ; modelId : string } ,
206214) : ResolvedConfig | null {
207215 // Runtime override (set via /model) wins over env vars wins over the default.
@@ -220,35 +228,39 @@ function buildProxiedConfig(
220228 const template = getModel ( "groq" , "llama-3.3-70b-versatile" ) as Model < string > | undefined ;
221229 if ( ! template ) return null ;
222230 const isDefault = ! explicitModel ;
223- const model : Model < string > = {
224- ...template ,
225- // "Codebase Auto" — backend renamed this slot from MiniMax-M2.7
226- // to d4f (DeepSeek V4 Flash) when the underlying SGLang server
227- // was repointed. Keep this in sync with web/backend/providers/
228- // registry.js DEFAULT_MODEL.
229- id : explicitModel ?? "d4f" ,
230- name : isDefault ? "Codebase Auto" : ( explicitModel ?? "Codebase Auto" ) ,
231- baseUrl : proxyBase ,
232- // Override provider so the status bar and /model don't lie about
233- // where this is served from. pi-ai uses `provider` mainly for
234- // display + a few baseUrl heuristics; the request body sends
235- // `model.id` only, so this cast is safe.
236- provider : "codebase" as Model < string > [ "provider" ] ,
237- cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
238- // Keep this in sync with web/backend/providers/registry.js. The
239- // Groq llama template's context window is only a synthesis
240- // scaffold; compaction must budget against the actual d4f backend.
241- contextWindow : 131_072 ,
242- } ;
243- return { model, apiKey : accessToken , source : "proxy" } ;
231+ const model = withProxyAuthHeaders (
232+ {
233+ ...template ,
234+ // "Codebase Auto" — backend renamed this slot from MiniMax-M2.7
235+ // to d4f (DeepSeek V4 Flash) when the underlying SGLang server
236+ // was repointed. Keep this in sync with web/backend/providers/
237+ // registry.js DEFAULT_MODEL.
238+ id : explicitModel ?? "d4f" ,
239+ name : isDefault ? "Codebase Auto" : ( explicitModel ?? "Codebase Auto" ) ,
240+ baseUrl : proxyBase ,
241+ // Override provider so the status bar and /model don't lie about
242+ // where this is served from. pi-ai uses `provider` mainly for
243+ // display + a few baseUrl heuristics; the request body sends
244+ // `model.id` only, so this cast is safe.
245+ provider : "codebase" as Model < string > [ "provider" ] ,
246+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
247+ // Keep this in sync with web/backend/providers/registry.js. The
248+ // Groq llama template's context window is only a synthesis
249+ // scaffold; compaction must budget against the actual d4f backend.
250+ contextWindow : 131_072 ,
251+ } ,
252+ accessToken ,
253+ authMode ,
254+ ) ;
255+ return { model, apiKey : accessToken , source : "proxy" , proxyAuth : authMode } ;
244256 }
245257
246258 const modelId = explicitModel ?? DEFAULT_MODELS [ explicitProvider ] ;
247259 if ( ! modelId ) return null ;
248260 const baseModel = getModel ( explicitProvider , modelId as never ) as Model < string > | undefined ;
249261 if ( baseModel ) {
250- const proxiedModel : Model < string > = { ...baseModel , baseUrl : proxyBase } ;
251- return { model : proxiedModel , apiKey : accessToken , source : "proxy" } ;
262+ const proxiedModel = withProxyAuthHeaders ( { ...baseModel , baseUrl : proxyBase } , accessToken , authMode ) ;
263+ return { model : proxiedModel , apiKey : accessToken , source : "proxy" , proxyAuth : authMode } ;
252264 }
253265 // pi-ai's registry doesn't know this provider+modelId combo (common for
254266 // backend-only models the proxy exposes, e.g. "codebase:MiniMax-M2.7"
@@ -260,20 +272,39 @@ function buildProxiedConfig(
260272 // didn't have native cost / context-window data for.
261273 const template = getModel ( "groq" , "llama-3.3-70b-versatile" ) as Model < string > | undefined ;
262274 if ( ! template ) return null ;
263- const synthesized : Model < string > = {
264- ...template ,
265- id : modelId ,
266- name : modelId ,
267- baseUrl : proxyBase ,
268- provider : explicitProvider as Model < string > [ "provider" ] ,
269- cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
270- // Same reasoning as Codebase Auto: synthesized proxy models point
271- // at large-context backends. Without overriding contextWindow the
272- // Groq llama template's 128k leaks through and the compaction
273- // engine triggers ~30% earlier than it should.
274- contextWindow : guessContextWindow ( modelId , 200_000 ) ,
275+ const synthesized = withProxyAuthHeaders (
276+ {
277+ ...template ,
278+ id : modelId ,
279+ name : modelId ,
280+ baseUrl : proxyBase ,
281+ provider : explicitProvider as Model < string > [ "provider" ] ,
282+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
283+ // Same reasoning as Codebase Auto: synthesized proxy models point
284+ // at large-context backends. Without overriding contextWindow the
285+ // Groq llama template's 128k leaks through and the compaction
286+ // engine triggers ~30% earlier than it should.
287+ contextWindow : guessContextWindow ( modelId , 200_000 ) ,
288+ } ,
289+ accessToken ,
290+ authMode ,
291+ ) ;
292+ return { model : synthesized , apiKey : accessToken , source : "proxy" , proxyAuth : authMode } ;
293+ }
294+
295+ function withProxyAuthHeaders (
296+ model : Model < string > ,
297+ accessToken : string ,
298+ authMode : "bearer" | "api-key" ,
299+ ) : Model < string > {
300+ if ( authMode === "bearer" ) return model ;
301+ return {
302+ ...model ,
303+ headers : {
304+ ...model . headers ,
305+ "X-API-Key" : accessToken ,
306+ } ,
275307 } ;
276- return { model : synthesized , apiKey : accessToken , source : "proxy" } ;
277308}
278309
279310/**
0 commit comments