11use anyhow:: { anyhow, Result } ;
2- use reqwest :: Client ;
3- use serde :: { Deserialize , Serialize } ;
2+ use serde :: Deserialize ;
3+ use serde_json :: json ;
44use std:: time:: Duration ;
55use tokio:: time:: { sleep, timeout} ;
66
77use crate :: config:: Config ;
8+ use crate :: providers:: api_client:: { ApiClient , AuthMethod } ;
89
9- /// Default model for NanoGPT configuration
10- pub const NANOGPT_DEFAULT_MODEL : & str = "openai/gpt-4.1-nano" ;
11-
12- const NANOGPT_START_URL : & str = "https://nano-gpt.com/api/cli-login/start" ;
13- const NANOGPT_POLL_URL : & str = "https://nano-gpt.com/api/cli-login/poll" ;
10+ const NANOGPT_CLI_LOGIN_HOST : & str = "https://nano-gpt.com/api/cli-login" ;
1411const AUTH_TIMEOUT : Duration = Duration :: from_secs ( 180 ) ; // 3 minutes
1512const POLL_INTERVAL : Duration = Duration :: from_secs ( 2 ) ;
1613
17- #[ derive( Debug , Serialize ) ]
18- struct StartRequest {
19- client_name : String ,
20- }
21-
2214#[ derive( Debug , Deserialize ) ]
2315struct StartResponse {
2416 device_code : String ,
2517 verification_uri_complete : String ,
2618}
2719
28- #[ derive( Debug , Serialize ) ]
29- struct PollRequest {
30- device_code : String ,
31- }
32-
3320#[ derive( Debug , Deserialize ) ]
3421struct PollResponse {
3522 key : String ,
3623}
3724
38- async fn poll_for_token ( device_code : & str ) -> Result < String > {
39- let client = Client :: new ( ) ;
25+ fn build_client ( ) -> Result < ApiClient > {
26+ ApiClient :: new ( NANOGPT_CLI_LOGIN_HOST . to_string ( ) , AuthMethod :: NoAuth ) ?
27+ . with_header ( "x-client" , "goose" )
28+ }
4029
30+ async fn poll_for_token ( client : & ApiClient , device_code : & str ) -> Result < String > {
4131 loop {
4232 sleep ( POLL_INTERVAL ) . await ;
4333
44- let body = PollRequest {
45- device_code : device_code. to_string ( ) ,
46- } ;
34+ let body = json ! ( { "device_code" : device_code } ) ;
4735
48- let response = client. post ( NANOGPT_POLL_URL ) . json ( & body) . send ( ) . await ?;
36+ let response = client. response_post ( None , "poll" , & body) . await ?;
4937 // https://docs.nano-gpt.com/integrations/cli-login#response-codes
5038 match response. status ( ) . as_u16 ( ) {
5139 200 => {
@@ -82,12 +70,10 @@ async fn poll_for_token(device_code: &str) -> Result<String> {
8270}
8371
8472pub async fn complete_nanogpt_auth ( ) -> Result < String > {
85- let client = Client :: new ( ) ;
86- let body = StartRequest {
87- client_name : "goose" . to_string ( ) ,
88- } ;
73+ let client = build_client ( ) ?;
74+ let body = json ! ( { "client_name" : "goose" } ) ;
8975
90- let response = client. post ( NANOGPT_START_URL ) . json ( & body) . send ( ) . await ?;
76+ let response = client. response_post ( None , "start" , & body) . await ?;
9177
9278 if !response. status ( ) . is_success ( ) {
9379 let status = response. status ( ) ;
@@ -113,7 +99,12 @@ pub async fn complete_nanogpt_auth() -> Result<String> {
11399
114100 println ! ( "Waiting for NanoGPT authorization..." ) ;
115101
116- match timeout ( AUTH_TIMEOUT , poll_for_token ( & start_resp. device_code ) ) . await {
102+ match timeout (
103+ AUTH_TIMEOUT ,
104+ poll_for_token ( & client, & start_resp. device_code ) ,
105+ )
106+ . await
107+ {
117108 Ok ( Ok ( api_key) ) => Ok ( api_key) ,
118109 Ok ( Err ( e) ) => Err ( e) ,
119110 Err ( _) => Err ( anyhow ! ( "Authentication timed out - please try again" ) ) ,
@@ -123,6 +114,5 @@ pub async fn complete_nanogpt_auth() -> Result<String> {
123114pub fn configure_nanogpt ( config : & Config , api_key : String ) -> Result < ( ) > {
124115 config. set_secret ( "NANOGPT_API_KEY" , & api_key) ?;
125116 config. set_goose_provider ( "nano-gpt" ) ?;
126- config. set_goose_model ( NANOGPT_DEFAULT_MODEL ) ?;
127117 Ok ( ( ) )
128118}
0 commit comments