Coverage for aipyapp/llm/client_oauth2.py: 29%
34 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
4import time
5import httpx
6from typing import Optional, Dict
7from .base_openai import OpenAIBaseClient
9class OAuth2Client(OpenAIBaseClient):
10 """
11 OAuth2-based OpenAI LLM client that:
12 1. First gets token using client_id/client_secret
13 2. Then uses the token to make LLM API calls
14 """
15 def __init__(self, config: Dict):
16 super().__init__(config)
17 self._token_url = config.get("token_url")
18 self._client_id = config.get("client_id")
19 self._client_secret = config.get("client_secret")
20 self._access_token: Optional[str] = None
21 self._token_expires = 0
23 def usable(self) -> bool:
24 return all([
25 self._token_url,
26 self._client_id,
27 self._client_secret,
28 self._base_url
29 ])
31 def _get_client(self):
32 self._api_key = self._get_access_token()
33 return super()._get_client()
35 def _get_access_token(self) -> str:
36 """Get OAuth2 access token using client credentials"""
37 current_time = time.time()
39 # Return existing token if it's still valid (with 300 seconds buffer)
40 if self._access_token and current_time < (self._token_expires - 300):
41 return self._access_token
43 auth_data = {
44 'client_id': self._client_id,
45 'client_secret': self._client_secret,
46 'grant_type': 'client_credentials'
47 }
49 with httpx.Client(timeout=self._timeout, verify=self._tls_verify) as client:
50 response = client.post(
51 self._token_url,
52 data=auth_data
53 )
54 response.raise_for_status()
55 token_data = response.json()
56 self._access_token = token_data['access_token']
58 # Calculate expiration time (default to 5 mins if not provided)
59 expires_in = token_data.get("expires_in", 300)
60 self._token_expires = current_time + expires_in
62 return self._access_token
64 def get_completion(self, messages):
65 response = super().get_completion(messages)
66 self._client = None
68 return response