ngpt 1.7.1__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ngpt/client.py CHANGED
@@ -18,65 +18,12 @@ class NGPTClient:
18
18
  self.base_url = base_url if base_url.endswith('/') else base_url + '/'
19
19
  self.model = model
20
20
 
21
- # Detect provider based on base_url domain first
22
- detected_provider = self._detect_provider_from_url(self.base_url)
23
- self.provider = detected_provider if detected_provider else provider
24
-
25
21
  # Default headers
26
22
  self.headers = {
27
23
  "Content-Type": "application/json",
28
24
  "Authorization": f"Bearer {self.api_key}"
29
25
  }
30
26
 
31
- def _detect_provider_from_url(self, url: str) -> str:
32
- """
33
- Detect the API provider based on the base URL domain.
34
-
35
- Args:
36
- url: The base URL to analyze
37
-
38
- Returns:
39
- Detected provider name or empty string if not detected
40
- """
41
- import re
42
- from urllib.parse import urlparse
43
-
44
- # Extract domain from URL
45
- try:
46
- parsed_url = urlparse(url)
47
- domain = parsed_url.netloc.lower()
48
-
49
- # Check for known API provider domains
50
- if 'openai.com' in domain:
51
- return 'OpenAI'
52
- elif 'anthropic.com' in domain:
53
- return 'Anthropic'
54
- elif 'generativelanguage.googleapis.com' in domain:
55
- return 'Gemini'
56
- elif 'groq.com' in domain:
57
- return 'Groq'
58
- elif 'cohere.com' in domain or 'cohere.ai' in domain:
59
- return 'Cohere'
60
- elif 'mistral.ai' in domain:
61
- return 'Mistral'
62
- elif 'claude.ai' in domain:
63
- return 'Claude'
64
- elif re.match(r'(127\.0\.0\.1|localhost)', domain):
65
- # Local APIs, check path components for clues
66
- path = parsed_url.path.lower()
67
- if '/ollama' in path:
68
- return 'Ollama'
69
- elif '/llama' in path:
70
- return 'Llama'
71
- # Default to the explicitly provided provider for local APIs
72
- return ''
73
-
74
- # Return empty string if no match found, will fall back to provided provider
75
- return ''
76
- except Exception:
77
- # In case of any parsing error, fall back to provided provider
78
- return ''
79
-
80
27
  def chat(
81
28
  self,
82
29
  prompt: str,
@@ -132,26 +79,11 @@ class NGPTClient:
132
79
  endpoint = "chat/completions"
133
80
  url = f"{self.base_url}{endpoint}"
134
81
 
135
- # Set headers based on provider
136
- headers = self.headers.copy()
137
- provider = self.provider.lower() if hasattr(self, 'provider') else ""
138
-
139
- # Provider-specific customizations
140
- if 'gemini' in provider:
141
- # Gemini uses X-Goog-Api-Key instead of Bearer token
142
- headers = {
143
- "Content-Type": "application/json",
144
- "X-Goog-Api-Key": self.api_key
145
- }
146
-
147
- # Gemini may require a different endpoint or payload structure
148
- # This is a simplistic approach - may need further customization
149
-
150
82
  try:
151
83
  if not stream:
152
84
  # Regular request
153
85
  try:
154
- response = requests.post(url, headers=headers, json=payload)
86
+ response = requests.post(url, headers=self.headers, json=payload)
155
87
  response.raise_for_status() # Raise exception for HTTP errors
156
88
  result = response.json()
157
89
 
@@ -165,7 +97,7 @@ class NGPTClient:
165
97
  else:
166
98
  # Streaming request
167
99
  collected_content = ""
168
- with requests.post(url, headers=headers, json=payload, stream=True) as response:
100
+ with requests.post(url, headers=self.headers, json=payload, stream=True) as response:
169
101
  response.raise_for_status() # Raise exception for HTTP errors
170
102
 
171
103
  try:
@@ -339,77 +271,36 @@ Code:"""
339
271
  if not self.api_key:
340
272
  print("Error: API key is not set. Please configure your API key in the config file or provide it with --api-key.")
341
273
  return []
342
-
343
- provider = getattr(self, 'provider', '').lower()
344
-
345
- # Handle provider-specific API differences
346
- if 'gemini' in provider:
347
- # Gemini API specific handling
348
- # Base URL typically ends with /v1beta or similar - we want to add /models
349
- base_url = self.base_url.rstrip('/')
350
- if base_url.endswith('/v1beta'):
351
- url = f"{base_url}/models"
352
- else:
353
- url = f"{base_url}/models"
354
274
 
355
- # Gemini uses X-Goog-Api-Key instead of Bearer token
356
- headers = {
357
- "Content-Type": "application/json",
358
- "X-Goog-Api-Key": self.api_key
359
- }
275
+ # Endpoint for models
276
+ url = f"{self.base_url}models"
277
+
278
+ try:
279
+ response = requests.get(url, headers=self.headers)
280
+ response.raise_for_status() # Raise exception for HTTP errors
281
+ result = response.json()
360
282
 
361
- try:
362
- response = requests.get(url, headers=headers)
363
- response.raise_for_status()
364
- result = response.json()
365
-
366
- # Gemini API returns models in a different format
367
- if "models" in result:
368
- # Transform to match our expected format
369
- return [{"id": model.get("name", "").split("/")[-1],
370
- "owned_by": "Google"}
371
- for model in result["models"]]
372
- else:
373
- print("Error: Unexpected response format when retrieving Gemini models.")
374
- return []
375
-
376
- except requests.exceptions.HTTPError as e:
377
- print(f"HTTP Error with Gemini API: {e}")
283
+ if "data" in result:
284
+ return result["data"]
285
+ else:
286
+ print("Error: Unexpected response format when retrieving models.")
378
287
  return []
379
288
 
380
- except Exception as e:
381
- print(f"Error retrieving Gemini models: {e}")
382
- return []
383
- else:
384
- # Standard OpenAI-compatible endpoint
385
- url = f"{self.base_url}models"
289
+ except requests.exceptions.HTTPError as e:
290
+ if e.response.status_code == 401:
291
+ print("Error: Authentication failed. Please check your API key.")
292
+ elif e.response.status_code == 404:
293
+ print(f"Error: Models endpoint not found at {url}")
294
+ elif e.response.status_code == 429:
295
+ print("Error: Rate limit exceeded. Please try again later.")
296
+ else:
297
+ print(f"HTTP Error: {e}")
298
+ return []
386
299
 
387
- try:
388
- response = requests.get(url, headers=self.headers)
389
- response.raise_for_status() # Raise exception for HTTP errors
390
- result = response.json()
391
-
392
- if "data" in result:
393
- return result["data"]
394
- else:
395
- print("Error: Unexpected response format when retrieving models.")
396
- return []
397
-
398
- except requests.exceptions.HTTPError as e:
399
- if e.response.status_code == 401:
400
- print("Error: Authentication failed. Please check your API key.")
401
- elif e.response.status_code == 404:
402
- print(f"Error: Models endpoint not found at {url}")
403
- elif e.response.status_code == 429:
404
- print("Error: Rate limit exceeded. Please try again later.")
405
- else:
406
- print(f"HTTP Error: {e}")
407
- return []
408
-
409
- except requests.exceptions.ConnectionError:
410
- print(f"Error: Could not connect to {self.base_url}. Please check your internet connection and base URL.")
411
- return []
412
-
413
- except Exception as e:
414
- print(f"Error: An unexpected error occurred while retrieving models: {e}")
415
- return []
300
+ except requests.exceptions.ConnectionError:
301
+ print(f"Error: Could not connect to {self.base_url}. Please check your internet connection and base URL.")
302
+ return []
303
+
304
+ except Exception as e:
305
+ print(f"Error: An unexpected error occurred while retrieving models: {e}")
306
+ return []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 1.7.1
3
+ Version: 2.0.0
4
4
  Summary: A lightweight Python CLI and library for interacting with OpenAI-compatible APIs, supporting both official and self-hosted LLM endpoints.
5
5
  Project-URL: Homepage, https://github.com/nazdridoy/ngpt
6
6
  Project-URL: Repository, https://github.com/nazdridoy/ngpt
@@ -121,9 +121,12 @@ ngpt --show-config
121
121
  # Show all configurations
122
122
  ngpt --show-config --all
123
123
 
124
- # List available models for the current configuration
124
+ # List available models for the active configuration
125
125
  ngpt --list-models
126
126
 
127
+ # List models for a specific configuration
128
+ ngpt --list-models --config-index 1
129
+
127
130
  # With custom options
128
131
  ngpt --api-key your-key --base-url http://your-endpoint --model your-model "Hello"
129
132
 
@@ -214,7 +217,7 @@ You can configure the client using the following options:
214
217
  | `--api-key` | API key for the service |
215
218
  | `--base-url` | Base URL for the API |
216
219
  | `--model` | Model to use |
217
- | `--list-models` | List all available models for the current configuration |
220
+ | `--list-models` | List all available models for the selected configuration (can be combined with --config-index) |
218
221
  | `--web-search` | Enable web search capability |
219
222
  | `-n, --no-stream` | Return the whole response without streaming |
220
223
  | `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
@@ -0,0 +1,9 @@
1
+ ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
+ ngpt/cli.py,sha256=AyIraZFq7icPot0moqPVJer72iqbtJxKBhy6VH-dwAA,28746
3
+ ngpt/client.py,sha256=ygtY2xuu-PAFPrz1CUJxcj3hyWw7q2kRG85ClDGClCw,12089
4
+ ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
+ ngpt-2.0.0.dist-info/METADATA,sha256=goeEJKkrJeTSrluucsXpuyinzJXbpyTSB5_s6fb4gV8,10686
6
+ ngpt-2.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ ngpt-2.0.0.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
+ ngpt-2.0.0.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
+ ngpt-2.0.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
- ngpt/cli.py,sha256=AyIraZFq7icPot0moqPVJer72iqbtJxKBhy6VH-dwAA,28746
3
- ngpt/client.py,sha256=qwAmBHSJvadbsvK5YPbY0By1M4bBvxd7j8piP5UdTgE,16553
4
- ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
- ngpt-1.7.1.dist-info/METADATA,sha256=ffoVoKaC58f-SKImuqxLfGOv9Umlpmou82aCFWpsfIM,10568
6
- ngpt-1.7.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- ngpt-1.7.1.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
- ngpt-1.7.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
- ngpt-1.7.1.dist-info/RECORD,,
File without changes