11import {
2+ BailianError ,
3+ ExitCode ,
24 chatEndpoint ,
35 defineCommand ,
46 getConfigPath ,
@@ -16,18 +18,58 @@ import { promptConfirm } from "../../output/prompt.ts";
1618import { printCurrentCommandHelp } from "../../utils/command-help.ts" ;
1719import { resolveConsoleOrigin , runConsoleLogin } from "./login-console.ts" ;
1820
21+ const RETRY_DELAY_BASE_MS = 500 ;
22+
23+ function canRetry ( err : unknown ) : boolean {
24+ if ( err instanceof BailianError ) {
25+ if ( err . exitCode === ExitCode . NETWORK || err . exitCode === ExitCode . TIMEOUT ) {
26+ return true ;
27+ }
28+ const status = err . api ?. httpStatus ;
29+ return status === 401 || ( status !== undefined && status >= 500 ) ;
30+ }
31+ if ( err instanceof Error ) {
32+ return (
33+ err . name === "AbortError" ||
34+ err . name === "TimeoutError" ||
35+ err . message . includes ( "timed out" ) ||
36+ err . message === "fetch failed"
37+ ) ;
38+ }
39+ return false ;
40+ }
41+
1942async function validateKeyAndPersist ( config : Config , key : string ) : Promise < void > {
2043 process . stderr . write ( "Testing key... " ) ;
2144 const testConfig = { ...config , apiKey : key } ;
22- await requestJson < unknown > ( testConfig , {
45+ const requestOpts = {
2346 url : chatEndpoint ( testConfig . baseUrl ) ,
2447 method : "POST" ,
48+ timeout : Math . min ( config . timeout , 30 ) ,
2549 body : {
2650 model : "qwen3.7-max" ,
2751 messages : [ { role : "user" , content : "hi" } ] ,
2852 max_tokens : 1 ,
2953 } ,
30- } ) ;
54+ } ;
55+
56+ for ( let attempt = 1 ; attempt <= 3 ; attempt ++ ) {
57+ try {
58+ await requestJson < unknown > ( testConfig , requestOpts ) ;
59+ break ;
60+ } catch ( err ) {
61+ if ( attempt >= 3 || ! canRetry ( err ) ) {
62+ process . stderr . write ( "\n" ) ;
63+ throw new BailianError ( "API key validation failed" , ExitCode . AUTH , "Invalid API key." , {
64+ cause : err ,
65+ } ) ;
66+ }
67+ // retry delay: 500ms, 1000ms, 2000ms
68+ const delayMs = RETRY_DELAY_BASE_MS * 2 ** ( attempt - 1 ) ;
69+ await new Promise ( ( resolve ) => setTimeout ( resolve , delayMs ) ) ;
70+ }
71+ }
72+
3173 process . stderr . write ( "Valid\n" ) ;
3274
3375 const existing = readConfigFile ( ) as Record < string , unknown > ;
0 commit comments