11import { Resource } from "@opencode-ai/console-resource"
2- import { Database , eq } from "@opencode-ai/console-core/drizzle/index.js"
2+ import { and , Database , eq , isNull , sql } from "@opencode-ai/console-core/drizzle/index.js"
33import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
4+ import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
45import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js"
56
67const paths : Record < string , string | undefined > = {
7- "GET /zen/v1/models" : "/v1/models" ,
88 "POST /zen/v1/chat/completions" : "/openai/v1/chat/completions" ,
99 "POST /zen/v1/responses" : "/openai/v1/responses" ,
1010 "POST /zen/v1/messages" : "/anthropic/v1/messages" ,
1111}
1212
13- export async function proxyInference ( request : Request , clientIP ?: string ) : Promise < Response | undefined > {
13+ export async function proxyInference (
14+ request : Request ,
15+ generation : {
16+ provider ?: "openai" | "anthropic" | "google"
17+ /** The provider's native model ID, not the public Zen alias. */
18+ model ?: string
19+ body : ( model ?: string ) => ReadableStream < Uint8Array >
20+ } ,
21+ ) : Promise < Response | undefined > {
1422 const url = new URL ( request . url )
1523 const path =
1624 paths [ `${ request . method } ${ url . pathname } ` ] ??
@@ -30,23 +38,52 @@ export async function proxyInference(request: Request, clientIP?: string): Promi
3038 // Routing only; the destination owns authentication and revocation after cutover.
3139 const workspace = await Database . use ( ( tx ) =>
3240 tx
33- . select ( { migratedAt : WorkspaceTable . migrated_at } )
41+ . select ( {
42+ id : WorkspaceTable . id ,
43+ migratedAt : WorkspaceTable . migrated_at ,
44+ provider : ProviderTable . provider ,
45+ } )
3446 . from ( KeyTable )
3547 . innerJoin ( WorkspaceTable , eq ( WorkspaceTable . id , KeyTable . workspaceID ) )
48+ . leftJoin (
49+ ProviderTable ,
50+ generation . provider
51+ ? and (
52+ eq ( ProviderTable . workspaceID , KeyTable . workspaceID ) ,
53+ eq ( ProviderTable . provider , generation . provider ) ,
54+ isNull ( ProviderTable . timeDeleted ) ,
55+ sql `length(${ ProviderTable . credentials } ) > 0` ,
56+ )
57+ : sql `false` ,
58+ )
3659 . where ( eq ( KeyTable . key , key ) )
3760 . limit ( 1 )
3861 . then ( ( rows ) => rows [ 0 ] ) ,
3962 )
4063 if ( ! workspace ?. migratedAt ) return undefined
64+ const model = workspace . provider ? generation . model : undefined
65+ if ( workspace . provider && ! model ) throw new Error ( "Legacy BYOK model mapping is unavailable" )
4166
4267 const destination = new URL ( Resource . ConsoleMigration . inferenceUrl )
43- destination . pathname = `${ destination . pathname . replace ( / \/ $ / , "" ) } ${ path } `
68+ // Imported connections must use this same workspace/provider-derived ID.
69+ const target = model
70+ ? `/custom/conn_${ workspace . id . slice ( 4 ) } _${ workspace . provider } ${
71+ path . startsWith ( "/google/" )
72+ ? `/models/${ encodeURIComponent ( model ) } ${ url . pathname . slice ( url . pathname . lastIndexOf ( ":" ) ) } `
73+ : url . pathname . slice ( "/zen/v1" . length )
74+ } `
75+ : path
76+ destination . pathname = `${ destination . pathname . replace ( / \/ $ / , "" ) } ${ target } `
4477 destination . search = url . search
4578 destination . hash = ""
4679
47- const forwarded = new Request ( destination , request )
80+ // Model extraction has already read part of the body; forward its replay stream.
81+ const forwarded = new Request (
82+ destination ,
83+ new Request ( request , { method : request . method , body : generation . body ( model ) } ) ,
84+ )
4885 forwarded . headers . set ( "authorization" , `Bearer ${ key } ` )
49- const ip = request . headers . get ( "cf-connecting-ip" ) ?? clientIP
86+ const ip = request . headers . get ( "cf-connecting-ip" )
5087 if ( ip ) forwarded . headers . set ( "x-real-ip" , ip )
5188 const requestID = request . headers . get ( "x-opencode-request-id" ) ?? request . headers . get ( "x-opencode-request" )
5289 if ( requestID ) forwarded . headers . set ( "x-opencode-request-id" , requestID )
0 commit comments