11import type { SessionConfigOption , SessionConfigSelectOption } from "@agentclientprotocol/sdk" ;
22import { llm , Model } from "@codeworksh/aikit" ;
3+ import { JsonGitHubCopilotAuthStorage } from "@codeworksh/aikit/oauth/github/copilot" ;
4+ import { JsonOpenAICodexAuthStorage } from "@codeworksh/aikit/oauth/openai/codex" ;
35import { ModelCatalog } from "@codeworksh/harness/effect" ;
46import { Effect } from "effect" ;
57
@@ -22,6 +24,23 @@ export const formatThinkingLevel = (level: Model.ThinkingLevel): string => {
2224 }
2325} ;
2426
27+ export const parseModelValue = (
28+ value : string ,
29+ defaultProvider ?: string ,
30+ ) : { provider : string ; modelId : string } => {
31+ const slash = value . indexOf ( "/" ) ;
32+ if ( slash !== - 1 ) {
33+ return {
34+ provider : value . slice ( 0 , slash ) ,
35+ modelId : value . slice ( slash + 1 ) ,
36+ } ;
37+ }
38+ return {
39+ provider : defaultProvider ?? "openai" ,
40+ modelId : value ,
41+ } ;
42+ } ;
43+
2544export interface SessionConfigInput {
2645 readonly provider ?: string | undefined ;
2746 readonly model ?: string | undefined ;
@@ -37,12 +56,16 @@ export interface SessionConfigInput {
3756 */
3857export const resolveConfigOptions = ( input : SessionConfigInput ) : Effect . Effect < Array < SessionConfigOption > > =>
3958 Effect . gen ( function * ( ) {
40- let provider = input . provider ?? "openai" ;
41- let modelId = input . model ?? "gpt-5.6-luna" ;
42- if ( modelId . includes ( "/" ) ) {
43- const slash = modelId . indexOf ( "/" ) ;
44- provider = input . provider ?? modelId . slice ( 0 , slash ) ;
45- modelId = modelId . slice ( slash + 1 ) ;
59+ let provider : string ;
60+ let modelId : string ;
61+
62+ if ( input . provider !== undefined ) {
63+ provider = input . provider ;
64+ modelId = input . model ?? "gpt-5.6-luna" ;
65+ } else {
66+ const parsed = parseModelValue ( input . model ?? "openai/gpt-5.6-luna" ) ;
67+ provider = parsed . provider ;
68+ modelId = parsed . modelId ;
4669 }
4770
4871 const modelInfo = yield * Effect . tryPromise ( ( ) => llm . model ( provider , modelId ) ) . pipe (
@@ -59,21 +82,29 @@ export const resolveConfigOptions = (input: SessionConfigInput): Effect.Effect<A
5982
6083 if ( catalog ) {
6184 const activeProviders = new Set < string > ( ) ;
62- activeProviders . add ( provider ) ;
63- activeProviders . add ( "google" ) ;
64- activeProviders . add ( "openai" ) ;
65- activeProviders . add ( "anthropic" ) ;
85+ if ( provider ) {
86+ activeProviders . add ( provider ) ;
87+ }
88+
89+ // Check OAuth availability
90+ const codexStorage = new JsonOpenAICodexAuthStorage ( { } ) ;
91+ const copilotStorage = new JsonGitHubCopilotAuthStorage ( { } ) ;
92+ const [ hasCodex , hasCopilot ] = yield * Effect . tryPromise ( ( ) =>
93+ Promise . all ( [
94+ codexStorage . get ( ) . then ( ( token ) => Boolean ( token ?. access ) ) . catch ( ( ) => false ) ,
95+ copilotStorage . get ( ) . then ( ( token ) => Boolean ( token ?. access ) ) . catch ( ( ) => false ) ,
96+ ] ) ,
97+ ) . pipe ( Effect . orElseSucceed ( ( ) => [ false , false ] as const ) ) ;
98+
99+ if ( hasCodex ) activeProviders . add ( "openai-codex" ) ;
100+ if ( hasCopilot ) activeProviders . add ( "github-copilot" ) ;
66101
67102 for ( const [ pId , pModels ] of Object . entries ( catalog ) ) {
68103 if ( ! pModels ) continue ;
69104 const first = Object . values ( pModels ) [ 0 ] ;
70105 const envVars = first ?. provider ?. env ?? [ ] ;
71- const hasKey = envVars . some ( ( k ) => {
72- const proc = ( globalThis as Record < string , unknown > ) . process as
73- | { env ?: Record < string , string | undefined > }
74- | undefined ;
75- return Boolean ( proc ?. env ?. [ k ] ) ;
76- } ) ;
106+ // oxlint-disable-next-line effecttsgo/process-env
107+ const hasKey = envVars . some ( ( k ) => Boolean ( process . env [ k ] ) ) ;
77108 if ( hasKey ) {
78109 activeProviders . add ( pId ) ;
79110 }
@@ -91,17 +122,6 @@ export const resolveConfigOptions = (input: SessionConfigInput): Effect.Effect<A
91122 }
92123 }
93124
94- if ( modelOptions . length === 0 ) {
95- modelOptions . push (
96- { value : "google/gemini-2.5-pro" , name : "Google: Gemini 2.5 Pro" } ,
97- { value : "google/gemini-2.5-flash" , name : "Google: Gemini 2.5 Flash" } ,
98- { value : "google/gemini-3.8-flash" , name : "Google: Gemini 3.8 Flash" } ,
99- { value : "openai/gpt-5.6-luna" , name : "OpenAI: GPT-5.6 Luna" } ,
100- { value : "openai/gpt-4o" , name : "OpenAI: GPT-4o" } ,
101- { value : "anthropic/claude-3-7-sonnet" , name : "Anthropic: Claude 3.7 Sonnet" } ,
102- ) ;
103- }
104-
105125 if ( ! modelOptions . some ( ( o ) => o . value === currentModelValue ) ) {
106126 modelOptions . unshift ( {
107127 value : currentModelValue ,
0 commit comments