ngpt 2.16.4__py3-none-any.whl → 2.16.5__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/interactive.py CHANGED
@@ -1,6 +1,8 @@
1
1
  import os
2
2
  import shutil
3
3
  import traceback
4
+ import threading
5
+ import sys
4
6
  from .formatters import COLORS
5
7
  from .renderers import prettify_markdown, prettify_streaming_markdown
6
8
 
@@ -197,21 +199,53 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
197
199
  # Setup for stream-prettify
198
200
  stream_callback = None
199
201
  live_display = None
202
+ stop_spinner_func = None
203
+ stop_spinner_event = None
204
+ first_content_received = False
200
205
 
201
206
  if stream_prettify and should_stream:
202
207
  # Get the correct header for interactive mode
203
208
  header = ngpt_header()
204
- live_display, stream_callback = prettify_streaming_markdown(renderer, is_interactive=True, header_text=header)
209
+ live_display, stream_callback, setup_spinner = prettify_streaming_markdown(renderer, is_interactive=True, header_text=header)
205
210
  if not live_display:
206
211
  # Fallback to normal prettify if live display setup failed
207
212
  prettify = True
208
213
  stream_prettify = False
209
214
  should_stream = False
210
215
  print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
211
-
212
- # Start live display if using stream-prettify
213
- if stream_prettify and live_display:
214
- live_display.start()
216
+ else:
217
+ # Create a wrapper for the stream callback that handles spinner and live display
218
+ original_callback = stream_callback
219
+
220
+ def spinner_handling_callback(content):
221
+ nonlocal first_content_received
222
+
223
+ # On first content, stop the spinner and start the live display
224
+ if not first_content_received:
225
+ first_content_received = True
226
+
227
+ # Stop the spinner if it's running
228
+ if stop_spinner_func:
229
+ stop_spinner_func()
230
+
231
+ # Clear the spinner line completely
232
+ sys.stdout.write("\r" + " " * 100 + "\r")
233
+ sys.stdout.flush()
234
+
235
+ # Now start the live display
236
+ if live_display:
237
+ live_display.start()
238
+
239
+ # Call the original callback to update content
240
+ if original_callback:
241
+ original_callback(content)
242
+
243
+ # Use our wrapper callback
244
+ stream_callback = spinner_handling_callback
245
+
246
+ # Set up and start the spinner
247
+ stop_spinner_event = threading.Event()
248
+ stop_spinner_func = setup_spinner(stop_spinner_event, "Waiting for response...", color=COLORS['green'])
215
249
 
216
250
  # Get AI response with conversation history
217
251
  response = client.chat(
@@ -226,8 +260,14 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
226
260
  stream_callback=stream_callback
227
261
  )
228
262
 
263
+ # Ensure spinner is stopped if no content was received
264
+ if stop_spinner_event and not first_content_received:
265
+ stop_spinner_event.set()
266
+ sys.stdout.write("\r" + " " * 100 + "\r")
267
+ sys.stdout.flush()
268
+
229
269
  # Stop live display if using stream-prettify
230
- if stream_prettify and live_display:
270
+ if stream_prettify and live_display and first_content_received:
231
271
  live_display.stop()
232
272
 
233
273
  # Add AI response to conversation history
ngpt/cli/modes/chat.py CHANGED
@@ -97,7 +97,7 @@ def chat_mode(client, args, logger=None):
97
97
  stop_spinner_event = None
98
98
  if args.stream_prettify and live_display:
99
99
  stop_spinner_event = threading.Event()
100
- stop_spinner_func = setup_spinner(stop_spinner_event)
100
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
101
101
 
102
102
  # Create a wrapper for the stream callback that will stop the spinner on first content
103
103
  original_callback = stream_callback
ngpt/cli/modes/code.py CHANGED
@@ -82,7 +82,7 @@ def code_mode(client, args, logger=None):
82
82
  stop_spinner_event = None
83
83
  if use_stream_prettify and live_display:
84
84
  stop_spinner_event = threading.Event()
85
- stop_spinner_func = setup_spinner(stop_spinner_event)
85
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
86
86
 
87
87
  # Create a wrapper for the stream callback that will stop the spinner on first content
88
88
  original_callback = stream_callback
ngpt/cli/modes/rewrite.py CHANGED
@@ -168,7 +168,7 @@ def rewrite_mode(client, args, logger=None):
168
168
  stop_spinner_event = None
169
169
  if args.stream_prettify and live_display:
170
170
  stop_spinner_event = threading.Event()
171
- stop_spinner_func = setup_spinner(stop_spinner_event)
171
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
172
172
 
173
173
  # Create a wrapper for the stream callback that will stop the spinner on first content
174
174
  original_callback = stream_callback
ngpt/cli/modes/shell.py CHANGED
@@ -31,7 +31,7 @@ def shell_mode(client, args, logger=None):
31
31
  spinner_thread = threading.Thread(
32
32
  target=spinner,
33
33
  args=("Generating command...",),
34
- kwargs={"stop_event": stop_spinner}
34
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
35
35
  )
36
36
  spinner_thread.daemon = True
37
37
  spinner_thread.start()
ngpt/cli/modes/text.py CHANGED
@@ -70,7 +70,7 @@ def text_mode(client, args, logger=None):
70
70
  stop_spinner_event = None
71
71
  if args.stream_prettify and live_display:
72
72
  stop_spinner_event = threading.Event()
73
- stop_spinner_func = setup_spinner(stop_spinner_event)
73
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
74
74
 
75
75
  # Create a wrapper for the stream callback that will stop the spinner on first content
76
76
  original_callback = stream_callback
ngpt/cli/renderers.py CHANGED
@@ -272,7 +272,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
272
272
  live.refresh()
273
273
 
274
274
  # Define a function to set up and start the spinner
275
- def setup_spinner(stop_event, message="Waiting for AI response..."):
275
+ def setup_spinner(stop_event, message="Waiting for AI response...", color=COLORS['cyan']):
276
276
  nonlocal stop_spinner_event, spinner_thread
277
277
  from .ui import spinner
278
278
  import threading
@@ -284,7 +284,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
284
284
  spinner_thread = threading.Thread(
285
285
  target=spinner,
286
286
  args=(message,),
287
- kwargs={"stop_event": stop_event}
287
+ kwargs={"stop_event": stop_event, "color": color}
288
288
  )
289
289
  spinner_thread.daemon = True
290
290
  spinner_thread.start()
ngpt/cli/ui.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import sys
2
2
  import time
3
3
  import shutil
4
+ from .formatters import COLORS
4
5
 
5
6
  # Optional imports for enhanced UI
6
7
  try:
@@ -167,18 +168,23 @@ def spinner(message, duration=5, spinner_chars="⣾⣽⣻⢿⡿⣟⣯⣷", color
167
168
  """
168
169
  char_duration = 0.2
169
170
 
171
+ # Apply color to message if provided
172
+ colored_message = message
173
+ if color:
174
+ colored_message = f"{color}{message}{COLORS['reset']}"
175
+
170
176
  if stop_event:
171
177
  i = 0
172
178
  while not stop_event.is_set():
173
179
  char = spinner_chars[i % len(spinner_chars)]
174
- print(f"\r{message} {char}", end="", flush=True)
180
+ print(f"\r{colored_message} {char}", end="", flush=True)
175
181
  i += 1
176
182
  time.sleep(char_duration)
177
183
  else:
178
184
  total_chars = int(duration / char_duration)
179
185
  for i in range(total_chars):
180
186
  char = spinner_chars[i % len(spinner_chars)]
181
- print(f"\r{message} {char}", end="", flush=True)
187
+ print(f"\r{colored_message} {char}", end="", flush=True)
182
188
  time.sleep(char_duration)
183
189
 
184
190
  # Clear the line when done
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 2.16.4
3
+ Version: 2.16.5
4
4
  Summary: Swiss army knife for LLMs: powerful CLI, interactive chatbot, and flexible Python library. Works with OpenAI, Ollama, Groq, Claude, and any OpenAI-compatible API.
5
5
  Project-URL: Homepage, https://github.com/nazdridoy/ngpt
6
6
  Project-URL: Repository, https://github.com/nazdridoy/ngpt
@@ -5,23 +5,23 @@ ngpt/cli/__init__.py,sha256=hebbDSMGiOd43YNnQP67uzr67Ue6rZPwm2czynr5iZY,43
5
5
  ngpt/cli/args.py,sha256=VJM6ySMnVrXgKaGb7Qb3AQPYxcQCv3FfCI4x8YkAsLQ,11534
6
6
  ngpt/cli/config_manager.py,sha256=NQQcWnjUppAAd0s0p9YAf8EyKS1ex5-0EB4DvKdB4dk,3662
7
7
  ngpt/cli/formatters.py,sha256=HBYGlx_7eoAKyzfy0Vq5L0yn8yVKjngqYBukMmXCcz0,9401
8
- ngpt/cli/interactive.py,sha256=DZFbExcXd7RylkpBiZBhiI6N8FBaT0m_lBes0Pvhi48,10894
8
+ ngpt/cli/interactive.py,sha256=oLflfYVSX_NdYb5D8BsEeYr2m_6yWw06Rw-BS5tLqkI,12923
9
9
  ngpt/cli/main.py,sha256=6GO4r9e9su7FFukj9JeVmJt1bJsqPOJBj6xo3iyMZXU,28911
10
- ngpt/cli/renderers.py,sha256=0ditb6F8uKIAX70jS8bnzcXUd9xttLv3zIYfDCBixgw,12221
11
- ngpt/cli/ui.py,sha256=B4dgipuJsH66gjpfKXfjJ0ANBveFciTkepmkZXtqJvg,6579
10
+ ngpt/cli/renderers.py,sha256=oTafec3HCLhthywiRhyTTG9YM9xNvlJBKu6DSy7Igu8,12259
11
+ ngpt/cli/ui.py,sha256=m8qtd4cCSHBGHPUlHVdBEfun1G1Se4vLKTSgnS7QOKE,6775
12
12
  ngpt/cli/modes/__init__.py,sha256=R3aO662RIzWEOvr3moTrEI8Tpg0zDDyMGGh1-OxiRgM,285
13
- ngpt/cli/modes/chat.py,sha256=XmRmPxHr2W_t8D_9JGTbEUWydnfm5BmGA5ODAu0u2oU,5679
14
- ngpt/cli/modes/code.py,sha256=On3JQZO79FOeUK5Tw89jsQF_lI8rAIHHe_zu2bHX99c,5712
13
+ ngpt/cli/modes/chat.py,sha256=-g8hMHkn9Dv3iGFZvbXXFQwG8KsXEgngr6Si9AUdQXE,5701
14
+ ngpt/cli/modes/code.py,sha256=1EeiooyNe1jvTyNu6r0J9xY34QXb2uBQKPeNca-DrRI,5734
15
15
  ngpt/cli/modes/gitcommsg.py,sha256=Bhgg9UArrfRUwosgVlNLUB7i1B8j-1ngpkmCm5iZBkM,46786
16
- ngpt/cli/modes/rewrite.py,sha256=8QDhjzAjWDnDAHEBXRWIGg7xx6fqRhIPse_GVHMBe4o,10157
17
- ngpt/cli/modes/shell.py,sha256=-uZ3CeWdZBidUnfStNGX0sr20WSovn5DSfwsMkBWaEo,3286
18
- ngpt/cli/modes/text.py,sha256=Q5vfBwDPyEtFubs8fPS_pPQBlyTxcDgOF-tCsz3oIH0,4559
16
+ ngpt/cli/modes/rewrite.py,sha256=vWgOWBCC2XppWGwYBpIHDcyAMAIzLl3jF6uzuH_G_dc,10179
17
+ ngpt/cli/modes/shell.py,sha256=QkprnOxMMTg2v5DIwcofDnnr3JPNfuk-YgSQaae5Xps,3311
18
+ ngpt/cli/modes/text.py,sha256=T65vfFqv5QoXroSAuzH7FaO1YTfq_A3WXu4Xy8lp4K8,4581
19
19
  ngpt/utils/__init__.py,sha256=E46suk2-QgYBI0Qrs6WXOajOUOebF3ETAFY7ah8DTWs,942
20
20
  ngpt/utils/cli_config.py,sha256=tQxR3a2iXyc5TfRBPQHSUXPInO2dv_zTPGn04eWfmoo,11285
21
21
  ngpt/utils/config.py,sha256=WYOk_b1eiYjo6hpV3pfXr2RjqhOnmKqwZwKid1T41I4,10363
22
22
  ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
23
- ngpt-2.16.4.dist-info/METADATA,sha256=LMstFvIe9EaUm9w1pbDxJJrTzquFGYzu_-6gRbBKBgs,24938
24
- ngpt-2.16.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- ngpt-2.16.4.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
- ngpt-2.16.4.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
- ngpt-2.16.4.dist-info/RECORD,,
23
+ ngpt-2.16.5.dist-info/METADATA,sha256=AZzcALgZ0ZiZaD7iMOxDhWa9g3CwKUi32ogVXvty4kI,24938
24
+ ngpt-2.16.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ ngpt-2.16.5.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
+ ngpt-2.16.5.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
+ ngpt-2.16.5.dist-info/RECORD,,
File without changes