ngpt 1.1.1__py3-none-any.whl → 1.1.2__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/cli.py +35 -11
- ngpt/client.py +38 -30
- ngpt/config.py +20 -16
- {ngpt-1.1.1.dist-info → ngpt-1.1.2.dist-info}/METADATA +1 -1
- ngpt-1.1.2.dist-info/RECORD +9 -0
- ngpt-1.1.1.dist-info/RECORD +0 -9
- {ngpt-1.1.1.dist-info → ngpt-1.1.2.dist-info}/WHEEL +0 -0
- {ngpt-1.1.1.dist-info → ngpt-1.1.2.dist-info}/entry_points.txt +0 -0
- {ngpt-1.1.1.dist-info → ngpt-1.1.2.dist-info}/licenses/LICENSE +0 -0
ngpt/cli.py
CHANGED
@@ -171,8 +171,12 @@ def main():
|
|
171
171
|
# Handle modes
|
172
172
|
if args.shell:
|
173
173
|
if args.prompt is None:
|
174
|
-
|
175
|
-
|
174
|
+
try:
|
175
|
+
print("Enter shell command description: ", end='')
|
176
|
+
prompt = input()
|
177
|
+
except KeyboardInterrupt:
|
178
|
+
print("\nInput cancelled by user. Exiting gracefully.")
|
179
|
+
sys.exit(130)
|
176
180
|
else:
|
177
181
|
prompt = args.prompt
|
178
182
|
|
@@ -182,20 +186,33 @@ def main():
|
|
182
186
|
|
183
187
|
print(f"\nGenerated command: {command}")
|
184
188
|
|
185
|
-
|
186
|
-
|
189
|
+
try:
|
190
|
+
print("Do you want to execute this command? [y/N] ", end='')
|
191
|
+
response = input().lower()
|
192
|
+
except KeyboardInterrupt:
|
193
|
+
print("\nCommand execution cancelled by user.")
|
194
|
+
return
|
195
|
+
|
187
196
|
if response == 'y' or response == 'yes':
|
188
197
|
import subprocess
|
189
198
|
try:
|
190
|
-
|
191
|
-
|
199
|
+
try:
|
200
|
+
print("\nExecuting command... (Press Ctrl+C to cancel)")
|
201
|
+
result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
|
202
|
+
print(f"\nOutput:\n{result.stdout}")
|
203
|
+
except KeyboardInterrupt:
|
204
|
+
print("\nCommand execution cancelled by user.")
|
192
205
|
except subprocess.CalledProcessError as e:
|
193
206
|
print(f"\nError:\n{e.stderr}")
|
194
207
|
|
195
208
|
elif args.code:
|
196
209
|
if args.prompt is None:
|
197
|
-
|
198
|
-
|
210
|
+
try:
|
211
|
+
print("Enter code description: ", end='')
|
212
|
+
prompt = input()
|
213
|
+
except KeyboardInterrupt:
|
214
|
+
print("\nInput cancelled by user. Exiting gracefully.")
|
215
|
+
sys.exit(130)
|
199
216
|
else:
|
200
217
|
prompt = args.prompt
|
201
218
|
|
@@ -206,16 +223,23 @@ def main():
|
|
206
223
|
else:
|
207
224
|
# Default to chat mode
|
208
225
|
if args.prompt is None:
|
209
|
-
|
210
|
-
|
226
|
+
try:
|
227
|
+
print("Enter your prompt: ", end='')
|
228
|
+
prompt = input()
|
229
|
+
except KeyboardInterrupt:
|
230
|
+
print("\nInput cancelled by user. Exiting gracefully.")
|
231
|
+
sys.exit(130)
|
211
232
|
else:
|
212
233
|
prompt = args.prompt
|
213
234
|
client.chat(prompt, web_search=args.web_search)
|
214
235
|
|
215
236
|
except KeyboardInterrupt:
|
216
|
-
print("\nOperation cancelled by user.")
|
237
|
+
print("\nOperation cancelled by user. Exiting gracefully.")
|
238
|
+
# Make sure we exit with a non-zero status code to indicate the operation was cancelled
|
239
|
+
sys.exit(130) # 130 is the standard exit code for SIGINT (Ctrl+C)
|
217
240
|
except Exception as e:
|
218
241
|
print(f"Error: {e}")
|
242
|
+
sys.exit(1) # Exit with error code
|
219
243
|
|
220
244
|
if __name__ == "__main__":
|
221
245
|
main()
|
ngpt/client.py
CHANGED
@@ -82,43 +82,51 @@ class NGPTClient:
|
|
82
82
|
try:
|
83
83
|
if not stream:
|
84
84
|
# Regular request
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
85
|
+
try:
|
86
|
+
response = requests.post(url, headers=self.headers, json=payload)
|
87
|
+
response.raise_for_status() # Raise exception for HTTP errors
|
88
|
+
result = response.json()
|
89
|
+
|
90
|
+
# Extract content from response
|
91
|
+
if "choices" in result and len(result["choices"]) > 0:
|
92
|
+
return result["choices"][0]["message"]["content"]
|
93
|
+
return ""
|
94
|
+
except KeyboardInterrupt:
|
95
|
+
print("\nRequest cancelled by user.")
|
96
|
+
return ""
|
93
97
|
else:
|
94
98
|
# Streaming request
|
95
99
|
collected_content = ""
|
96
100
|
with requests.post(url, headers=self.headers, json=payload, stream=True) as response:
|
97
101
|
response.raise_for_status() # Raise exception for HTTP errors
|
98
102
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
# Skip keep-alive lines
|
109
|
-
if line == "[DONE]":
|
110
|
-
break
|
103
|
+
try:
|
104
|
+
for line in response.iter_lines():
|
105
|
+
if not line:
|
106
|
+
continue
|
107
|
+
|
108
|
+
# Handle SSE format
|
109
|
+
line = line.decode('utf-8')
|
110
|
+
if line.startswith('data: '):
|
111
|
+
line = line[6:] # Remove 'data: ' prefix
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
113
|
+
# Skip keep-alive lines
|
114
|
+
if line == "[DONE]":
|
115
|
+
break
|
116
|
+
|
117
|
+
try:
|
118
|
+
chunk = json.loads(line)
|
119
|
+
if "choices" in chunk and len(chunk["choices"]) > 0:
|
120
|
+
delta = chunk["choices"][0].get("delta", {})
|
121
|
+
content = delta.get("content", "")
|
122
|
+
if content:
|
123
|
+
print(content, end="", flush=True)
|
124
|
+
collected_content += content
|
125
|
+
except json.JSONDecodeError:
|
126
|
+
pass # Skip invalid JSON
|
127
|
+
except KeyboardInterrupt:
|
128
|
+
print("\nGeneration cancelled by user.")
|
129
|
+
return collected_content
|
122
130
|
|
123
131
|
print() # Add a final newline
|
124
132
|
return collected_content
|
ngpt/config.py
CHANGED
@@ -56,22 +56,26 @@ def add_config_entry(config_path: Path, config_index: Optional[int] = None) -> N
|
|
56
56
|
|
57
57
|
# Interactive configuration
|
58
58
|
print("Enter configuration details (press Enter to use default values):")
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
59
|
+
try:
|
60
|
+
new_entry["api_key"] = input(f"API Key: ") or new_entry["api_key"]
|
61
|
+
new_entry["base_url"] = input(f"Base URL [{new_entry['base_url']}]: ") or new_entry["base_url"]
|
62
|
+
new_entry["provider"] = input(f"Provider [{new_entry['provider']}]: ") or new_entry["provider"]
|
63
|
+
new_entry["model"] = input(f"Model [{new_entry['model']}]: ") or new_entry["model"]
|
64
|
+
|
65
|
+
# Add or update the entry
|
66
|
+
if config_index is not None and config_index < len(configs):
|
67
|
+
configs[config_index] = new_entry
|
68
|
+
print(f"Updated configuration at index {config_index}")
|
69
|
+
else:
|
70
|
+
configs.append(new_entry)
|
71
|
+
print(f"Added new configuration at index {len(configs)-1}")
|
72
|
+
|
73
|
+
# Save the updated configs
|
74
|
+
with open(config_path, "w") as f:
|
75
|
+
json.dump(configs, f, indent=2)
|
76
|
+
except KeyboardInterrupt:
|
77
|
+
print("\nConfiguration cancelled by user. Exiting.")
|
78
|
+
sys.exit(130) # Exit with standard keyboard interrupt code
|
75
79
|
|
76
80
|
def load_configs(custom_path: Optional[str] = None) -> List[Dict[str, Any]]:
|
77
81
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ngpt
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.2
|
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
|
@@ -0,0 +1,9 @@
|
|
1
|
+
ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
|
2
|
+
ngpt/cli.py,sha256=LIXr3NWgdsrddbcYmOxRsWYbNeKNILJZWnIkO7iCSzc,10672
|
3
|
+
ngpt/client.py,sha256=j7UCX_nkFRQJ_15ynxdu0Tj3HxxsI7Ll4__HdTbD7zE,10400
|
4
|
+
ngpt/config.py,sha256=JWCEp1aMq96i8owi4z_poKigaA_s2UTfzY0fjBM5MoQ,5295
|
5
|
+
ngpt-1.1.2.dist-info/METADATA,sha256=GBuRNy3W9JGtdH4NMHriYVOQ2KClYlczYIjmyGcK0xM,6299
|
6
|
+
ngpt-1.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
7
|
+
ngpt-1.1.2.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
|
8
|
+
ngpt-1.1.2.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
|
9
|
+
ngpt-1.1.2.dist-info/RECORD,,
|
ngpt-1.1.1.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
|
2
|
-
ngpt/cli.py,sha256=HA85u1-ajsOBO7Zp-Hngyr4NbYxdktn-uM1VuCvy4CU,9495
|
3
|
-
ngpt/client.py,sha256=DfOjE2qQQZq3JF6wNa4YxEfUALq4B0ycP_3v9ZKw2ds,9940
|
4
|
-
ngpt/config.py,sha256=qkOd4pNk8pW191u4EzHORecPpRDX2yVPrMQkJ35UsNw,5063
|
5
|
-
ngpt-1.1.1.dist-info/METADATA,sha256=g7JncpCt4beu2lsc3-8x7LBnQxROCcD9hMvH5IYWk8w,6299
|
6
|
-
ngpt-1.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
7
|
-
ngpt-1.1.1.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
|
8
|
-
ngpt-1.1.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
|
9
|
-
ngpt-1.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|