ngpt 2.16.4__py3-none-any.whl → 2.16.6__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
@@ -131,8 +131,6 @@ def rewrite_mode(client, args, logger=None):
131
131
  {"role": "user", "content": input_text}
132
132
  ]
133
133
 
134
- print("\nSubmission successful. Waiting for response...")
135
-
136
134
  # Log the messages if logging is enabled
137
135
  if logger:
138
136
  logger.log("system", REWRITE_SYSTEM_PROMPT)
@@ -168,7 +166,7 @@ def rewrite_mode(client, args, logger=None):
168
166
  stop_spinner_event = None
169
167
  if args.stream_prettify and live_display:
170
168
  stop_spinner_event = threading.Event()
171
- stop_spinner_func = setup_spinner(stop_spinner_event)
169
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
172
170
 
173
171
  # Create a wrapper for the stream callback that will stop the spinner on first content
174
172
  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
@@ -21,8 +21,6 @@ def text_mode(client, args, logger=None):
21
21
  print("Exiting.")
22
22
  return
23
23
 
24
- print("\nSubmission successful. Waiting for response...")
25
-
26
24
  # Log the user message if logging is enabled
27
25
  if logger:
28
26
  logger.log("user", prompt)
@@ -70,7 +68,7 @@ def text_mode(client, args, logger=None):
70
68
  stop_spinner_event = None
71
69
  if args.stream_prettify and live_display:
72
70
  stop_spinner_event = threading.Event()
73
- stop_spinner_func = setup_spinner(stop_spinner_event)
71
+ stop_spinner_func = setup_spinner(stop_spinner_event, color=COLORS['cyan'])
74
72
 
75
73
  # Create a wrapper for the stream callback that will stop the spinner on first content
76
74
  original_callback = stream_callback
ngpt/cli/renderers.py CHANGED
@@ -239,8 +239,14 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
239
239
  else:
240
240
  md_obj = Markdown("")
241
241
 
242
- # Initialize the Live display with an empty markdown
243
- live = Live(md_obj, console=console, refresh_per_second=10, auto_refresh=False)
242
+ # Initialize the Live display with vertical overflow handling
243
+ live = Live(
244
+ md_obj,
245
+ console=console,
246
+ refresh_per_second=10,
247
+ auto_refresh=False,
248
+ vertical_overflow="visible" # Attempt to make overflow visible
249
+ )
244
250
 
245
251
  # Track if this is the first content update
246
252
  first_update = True
@@ -259,7 +265,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
259
265
  sys.stdout.flush()
260
266
  live.start()
261
267
 
262
- # Update content
268
+ # Update content in live display
263
269
  if is_interactive and header_text:
264
270
  # Update the panel content
265
271
  md_obj.renderable = Markdown(content)
@@ -272,7 +278,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
272
278
  live.refresh()
273
279
 
274
280
  # Define a function to set up and start the spinner
275
- def setup_spinner(stop_event, message="Waiting for AI response..."):
281
+ def setup_spinner(stop_event, message="Waiting for AI response...", color=COLORS['cyan']):
276
282
  nonlocal stop_spinner_event, spinner_thread
277
283
  from .ui import spinner
278
284
  import threading
@@ -284,7 +290,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
284
290
  spinner_thread = threading.Thread(
285
291
  target=spinner,
286
292
  args=(message,),
287
- kwargs={"stop_event": stop_event}
293
+ kwargs={"stop_event": stop_event, "color": color}
288
294
  )
289
295
  spinner_thread.daemon = True
290
296
  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.6
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=yYt3b_cWUYckfgLQ1wkEiQCnq5v5m7hfn5PWxHJzR9Y,12422
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=iEMn6i6cuaxOiKq886Lsh961riCmPj5K1mXVQeT2Z7k,10112
17
+ ngpt/cli/modes/shell.py,sha256=QkprnOxMMTg2v5DIwcofDnnr3JPNfuk-YgSQaae5Xps,3311
18
+ ngpt/cli/modes/text.py,sha256=z08xaW2r0XzyunUzBhwZKqnwPjyRol_CSazjLygmLRs,4514
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.6.dist-info/METADATA,sha256=DayL8rMlMWdplumfhcy9agLbWwXVQxGQv0kjOhGu14k,24938
24
+ ngpt-2.16.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ ngpt-2.16.6.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
+ ngpt-2.16.6.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
+ ngpt-2.16.6.dist-info/RECORD,,
File without changes