@@ -20,10 +20,19 @@ type PluginAuth = NonNullable<Hooks["auth"]>
2020 * Handle plugin-based authentication flow.
2121 * Returns true if auth was handled, false if it should fall through to default handling.
2222 */
23- async function handlePluginAuth ( plugin : { auth : PluginAuth } , provider : string ) : Promise < boolean > {
23+ async function handlePluginAuth ( plugin : { auth : PluginAuth } , provider : string , methodName ?: string ) : Promise < boolean > {
2424 let index = 0
25- if ( plugin . auth . methods . length > 1 ) {
26- const method = await prompts . select ( {
25+ if ( methodName ) {
26+ const match = plugin . auth . methods . findIndex ( ( x ) => x . label . toLowerCase ( ) === methodName . toLowerCase ( ) )
27+ if ( match === - 1 ) {
28+ prompts . log . error (
29+ `Unknown method "${ methodName } " for ${ provider } . Available: ${ plugin . auth . methods . map ( ( x ) => x . label ) . join ( ", " ) } ` ,
30+ )
31+ process . exit ( 1 )
32+ }
33+ index = match
34+ } else if ( plugin . auth . methods . length > 1 ) {
35+ const selected = await prompts . select ( {
2736 message : "Login method" ,
2837 options : [
2938 ...plugin . auth . methods . map ( ( x , index ) => ( {
@@ -32,8 +41,8 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string):
3241 } ) ) ,
3342 ] ,
3443 } )
35- if ( prompts . isCancel ( method ) ) throw new UI . CancelledError ( )
36- index = parseInt ( method )
44+ if ( prompts . isCancel ( selected ) ) throw new UI . CancelledError ( )
45+ index = parseInt ( selected )
3746 }
3847 const method = plugin . auth . methods [ index ]
3948
@@ -252,10 +261,21 @@ export const AuthLoginCommand = cmd({
252261 command : "login [url]" ,
253262 describe : "log in to a provider" ,
254263 builder : ( yargs ) =>
255- yargs . positional ( "url" , {
256- describe : "opencode auth provider" ,
257- type : "string" ,
258- } ) ,
264+ yargs
265+ . positional ( "url" , {
266+ describe : "opencode auth provider" ,
267+ type : "string" ,
268+ } )
269+ . option ( "provider" , {
270+ alias : [ "p" ] ,
271+ describe : "provider id or name to log in to (skips provider selection)" ,
272+ type : "string" ,
273+ } )
274+ . option ( "method" , {
275+ alias : [ "m" ] ,
276+ describe : "login method label (skips method selection)" ,
277+ type : "string" ,
278+ } ) ,
259279 async handler ( args ) {
260280 await Instance . provide ( {
261281 directory : process . cwd ( ) ,
@@ -322,60 +342,76 @@ export const AuthLoginCommand = cmd({
322342 enabled,
323343 providerNames : Object . fromEntries ( Object . entries ( config . provider ?? { } ) . map ( ( [ id , p ] ) => [ id , p . name ] ) ) ,
324344 } )
325- let provider = await prompts . autocomplete ( {
326- message : "Select provider" ,
327- maxItems : 8 ,
328- options : [
329- ...pipe (
330- providers ,
331- values ( ) ,
332- sortBy (
333- ( x ) => priority [ x . id ] ?? 99 ,
334- ( x ) => x . name ?? x . id ,
335- ) ,
336- map ( ( x ) => ( {
337- label : x . name ,
338- value : x . id ,
339- hint : {
340- opencode : "recommended" ,
341- anthropic : "Claude Max or API key" ,
342- openai : "ChatGPT Plus/Pro or API key" ,
343- } [ x . id ] ,
344- } ) ) ,
345+ const options = [
346+ ...pipe (
347+ providers ,
348+ values ( ) ,
349+ sortBy (
350+ ( x ) => priority [ x . id ] ?? 99 ,
351+ ( x ) => x . name ?? x . id ,
345352 ) ,
346- ... pluginProviders . map ( ( x ) => ( {
353+ map ( ( x ) => ( {
347354 label : x . name ,
348355 value : x . id ,
349- hint : "plugin" ,
356+ hint : {
357+ opencode : "recommended" ,
358+ anthropic : "Claude Max or API key" ,
359+ openai : "ChatGPT Plus/Pro or API key" ,
360+ } [ x . id ] ,
350361 } ) ) ,
351- {
352- value : "other" ,
353- label : "Other" ,
354- } ,
355- ] ,
356- } )
357-
358- if ( prompts . isCancel ( provider ) ) throw new UI . CancelledError ( )
362+ ) ,
363+ ...pluginProviders . map ( ( x ) => ( {
364+ label : x . name ,
365+ value : x . id ,
366+ hint : "plugin" ,
367+ } ) ) ,
368+ ]
369+
370+ let provider : string
371+ if ( args . provider ) {
372+ const input = args . provider
373+ const byID = options . find ( ( x ) => x . value === input )
374+ const byName = options . find ( ( x ) => x . label . toLowerCase ( ) === input . toLowerCase ( ) )
375+ const match = byID ?? byName
376+ if ( ! match ) {
377+ prompts . log . error ( `Unknown provider "${ input } "` )
378+ process . exit ( 1 )
379+ }
380+ provider = match . value
381+ } else {
382+ const selected = await prompts . autocomplete ( {
383+ message : "Select provider" ,
384+ maxItems : 8 ,
385+ options : [
386+ ...options ,
387+ {
388+ value : "other" ,
389+ label : "Other" ,
390+ } ,
391+ ] ,
392+ } )
393+ if ( prompts . isCancel ( selected ) ) throw new UI . CancelledError ( )
394+ provider = selected as string
395+ }
359396
360397 const plugin = await Plugin . list ( ) . then ( ( x ) => x . findLast ( ( x ) => x . auth ?. provider === provider ) )
361398 if ( plugin && plugin . auth ) {
362- const handled = await handlePluginAuth ( { auth : plugin . auth } , provider )
399+ const handled = await handlePluginAuth ( { auth : plugin . auth } , provider , args . method )
363400 if ( handled ) return
364401 }
365402
366403 if ( provider === "other" ) {
367- provider = await prompts . text ( {
404+ const custom = await prompts . text ( {
368405 message : "Enter provider id" ,
369406 validate : ( x ) => ( x && x . match ( / ^ [ 0 - 9 a - z - ] + $ / ) ? undefined : "a-z, 0-9 and hyphens only" ) ,
370407 } )
371- if ( prompts . isCancel ( provider ) ) throw new UI . CancelledError ( )
372- provider = provider . replace ( / ^ @ a i - s d k \/ / , "" )
373- if ( prompts . isCancel ( provider ) ) throw new UI . CancelledError ( )
408+ if ( prompts . isCancel ( custom ) ) throw new UI . CancelledError ( )
409+ provider = custom . replace ( / ^ @ a i - s d k \/ / , "" )
374410
375411 // Check if a plugin provides auth for this custom provider
376412 const customPlugin = await Plugin . list ( ) . then ( ( x ) => x . findLast ( ( x ) => x . auth ?. provider === provider ) )
377413 if ( customPlugin && customPlugin . auth ) {
378- const handled = await handlePluginAuth ( { auth : customPlugin . auth } , provider )
414+ const handled = await handlePluginAuth ( { auth : customPlugin . auth } , provider , args . method )
379415 if ( handled ) return
380416 }
381417
0 commit comments