added x-client header in the nanogpt api call (#8368)
This commit is contained in:
@@ -1,51 +1,39 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use reqwest::Client;
|
use serde::Deserialize;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde_json::json;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::time::{sleep, timeout};
|
use tokio::time::{sleep, timeout};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::providers::api_client::{ApiClient, AuthMethod};
|
||||||
|
|
||||||
/// Default model for NanoGPT configuration
|
const NANOGPT_CLI_LOGIN_HOST: &str = "https://nano-gpt.com/api/cli-login";
|
||||||
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 AUTH_TIMEOUT: Duration = Duration::from_secs(180); // 3 minutes
|
const AUTH_TIMEOUT: Duration = Duration::from_secs(180); // 3 minutes
|
||||||
const POLL_INTERVAL: Duration = Duration::from_secs(2);
|
const POLL_INTERVAL: Duration = Duration::from_secs(2);
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
struct StartRequest {
|
|
||||||
client_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct StartResponse {
|
struct StartResponse {
|
||||||
device_code: String,
|
device_code: String,
|
||||||
verification_uri_complete: String,
|
verification_uri_complete: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
struct PollRequest {
|
|
||||||
device_code: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct PollResponse {
|
struct PollResponse {
|
||||||
key: String,
|
key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn poll_for_token(device_code: &str) -> Result<String> {
|
fn build_client() -> Result<ApiClient> {
|
||||||
let client = Client::new();
|
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 {
|
loop {
|
||||||
sleep(POLL_INTERVAL).await;
|
sleep(POLL_INTERVAL).await;
|
||||||
|
|
||||||
let body = PollRequest {
|
let body = json!({ "device_code": device_code });
|
||||||
device_code: device_code.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
// https://docs.nano-gpt.com/integrations/cli-login#response-codes
|
||||||
match response.status().as_u16() {
|
match response.status().as_u16() {
|
||||||
200 => {
|
200 => {
|
||||||
@@ -82,12 +70,10 @@ async fn poll_for_token(device_code: &str) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn complete_nanogpt_auth() -> Result<String> {
|
pub async fn complete_nanogpt_auth() -> Result<String> {
|
||||||
let client = Client::new();
|
let client = build_client()?;
|
||||||
let body = StartRequest {
|
let body = json!({ "client_name": "goose" });
|
||||||
client_name: "goose".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
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() {
|
if !response.status().is_success() {
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
@@ -113,7 +99,12 @@ pub async fn complete_nanogpt_auth() -> Result<String> {
|
|||||||
|
|
||||||
println!("Waiting for NanoGPT authorization...");
|
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(Ok(api_key)) => Ok(api_key),
|
||||||
Ok(Err(e)) => Err(e),
|
Ok(Err(e)) => Err(e),
|
||||||
Err(_) => Err(anyhow!("Authentication timed out - please try again")),
|
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<()> {
|
pub fn configure_nanogpt(config: &Config, api_key: String) -> Result<()> {
|
||||||
config.set_secret("NANOGPT_API_KEY", &api_key)?;
|
config.set_secret("NANOGPT_API_KEY", &api_key)?;
|
||||||
config.set_goose_provider("nano-gpt")?;
|
config.set_goose_provider("nano-gpt")?;
|
||||||
config.set_goose_model(NANOGPT_DEFAULT_MODEL)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,16 @@ pub struct NanoGptProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NanoGptProvider {
|
impl NanoGptProvider {
|
||||||
async fn check_subscription(api_key: &str) -> bool {
|
fn build_client(host: &str, api_key: &str) -> Result<ApiClient> {
|
||||||
let client = match ApiClient::new(
|
ApiClient::new(
|
||||||
NANOGPT_SUBSCRIPTION_HOST.to_string(),
|
host.to_string(),
|
||||||
AuthMethod::BearerToken(api_key.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,
|
Ok(c) => c,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
@@ -62,7 +67,7 @@ impl NanoGptProvider {
|
|||||||
NANOGPT_API_HOST.to_string()
|
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 {
|
Ok(Self {
|
||||||
api_client,
|
api_client,
|
||||||
|
|||||||
Reference in New Issue
Block a user