added x-client header in the nanogpt api call (#8368)

This commit is contained in:
Lifei Zhou
2026-04-07 22:51:03 +10:00
committed by GitHub
parent 7449a96664
commit c4aa7f56df
2 changed files with 30 additions and 35 deletions
+20 -30
View File
@@ -1,51 +1,39 @@
use anyhow::{anyhow, Result};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use serde_json::json;
use std::time::Duration;
use tokio::time::{sleep, timeout};
use crate::config::Config;
use crate::providers::api_client::{ApiClient, AuthMethod};
/// Default model for NanoGPT configuration
pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano";
const NANOGPT_START_URL: &str = "https://nano-gpt.com/api/cli-login/start";
const NANOGPT_POLL_URL: &str = "https://nano-gpt.com/api/cli-login/poll";
const NANOGPT_CLI_LOGIN_HOST: &str = "https://nano-gpt.com/api/cli-login";
const AUTH_TIMEOUT: Duration = Duration::from_secs(180); // 3 minutes
const POLL_INTERVAL: Duration = Duration::from_secs(2);
#[derive(Debug, Serialize)]
struct StartRequest {
client_name: String,
}
#[derive(Debug, Deserialize)]
struct StartResponse {
device_code: String,
verification_uri_complete: String,
}
#[derive(Debug, Serialize)]
struct PollRequest {
device_code: String,
}
#[derive(Debug, Deserialize)]
struct PollResponse {
key: String,
}
async fn poll_for_token(device_code: &str) -> Result<String> {
let client = Client::new();
fn build_client() -> Result<ApiClient> {
ApiClient::new(NANOGPT_CLI_LOGIN_HOST.to_string(), AuthMethod::NoAuth)?
.with_header("x-client", "goose")
}
async fn poll_for_token(client: &ApiClient, device_code: &str) -> Result<String> {
loop {
sleep(POLL_INTERVAL).await;
let body = PollRequest {
device_code: device_code.to_string(),
};
let body = json!({ "device_code": device_code });
let response = client.post(NANOGPT_POLL_URL).json(&body).send().await?;
let response = client.response_post(None, "poll", &body).await?;
// https://docs.nano-gpt.com/integrations/cli-login#response-codes
match response.status().as_u16() {
200 => {
@@ -82,12 +70,10 @@ async fn poll_for_token(device_code: &str) -> Result<String> {
}
pub async fn complete_nanogpt_auth() -> Result<String> {
let client = Client::new();
let body = StartRequest {
client_name: "goose".to_string(),
};
let client = build_client()?;
let body = json!({ "client_name": "goose" });
let response = client.post(NANOGPT_START_URL).json(&body).send().await?;
let response = client.response_post(None, "start", &body).await?;
if !response.status().is_success() {
let status = response.status();
@@ -113,7 +99,12 @@ pub async fn complete_nanogpt_auth() -> Result<String> {
println!("Waiting for NanoGPT authorization...");
match timeout(AUTH_TIMEOUT, poll_for_token(&start_resp.device_code)).await {
match timeout(
AUTH_TIMEOUT,
poll_for_token(&client, &start_resp.device_code),
)
.await
{
Ok(Ok(api_key)) => Ok(api_key),
Ok(Err(e)) => Err(e),
Err(_) => Err(anyhow!("Authentication timed out - please try again")),
@@ -123,6 +114,5 @@ pub async fn complete_nanogpt_auth() -> Result<String> {
pub fn configure_nanogpt(config: &Config, api_key: String) -> Result<()> {
config.set_secret("NANOGPT_API_KEY", &api_key)?;
config.set_goose_provider("nano-gpt")?;
config.set_goose_model(NANOGPT_DEFAULT_MODEL)?;
Ok(())
}
+10 -5
View File
@@ -29,11 +29,16 @@ pub struct NanoGptProvider {
}
impl NanoGptProvider {
async fn check_subscription(api_key: &str) -> bool {
let client = match ApiClient::new(
NANOGPT_SUBSCRIPTION_HOST.to_string(),
fn build_client(host: &str, api_key: &str) -> Result<ApiClient> {
ApiClient::new(
host.to_string(),
AuthMethod::BearerToken(api_key.to_string()),
) {
)?
.with_header("x-client", "goose")
}
async fn check_subscription(api_key: &str) -> bool {
let client = match Self::build_client(NANOGPT_SUBSCRIPTION_HOST, api_key) {
Ok(c) => c,
Err(_) => return false,
};
@@ -62,7 +67,7 @@ impl NanoGptProvider {
NANOGPT_API_HOST.to_string()
};
let api_client = ApiClient::new(host, AuthMethod::BearerToken(api_key))?;
let api_client = Self::build_client(&host, &api_key)?;
Ok(Self {
api_client,