ngpt 3.8.2__py3-none-any.whl → 3.8.3__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/modes/chat.py +18 -13
- ngpt/cli/modes/code.py +20 -15
- ngpt/cli/modes/interactive.py +53 -46
- ngpt/cli/modes/rewrite.py +18 -13
- ngpt/cli/modes/shell.py +15 -13
- ngpt/cli/modes/text.py +18 -13
- ngpt/cli/renderers.py +56 -50
- {ngpt-3.8.2.dist-info → ngpt-3.8.3.dist-info}/METADATA +1 -1
- {ngpt-3.8.2.dist-info → ngpt-3.8.3.dist-info}/RECORD +12 -12
- {ngpt-3.8.2.dist-info → ngpt-3.8.3.dist-info}/WHEEL +0 -0
- {ngpt-3.8.2.dist-info → ngpt-3.8.3.dist-info}/entry_points.txt +0 -0
- {ngpt-3.8.2.dist-info → ngpt-3.8.3.dist-info}/licenses/LICENSE +0 -0
ngpt/cli/modes/chat.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
2
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
3
3
|
from ..ui import spinner
|
4
4
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
5
5
|
import sys
|
@@ -53,9 +53,10 @@ def chat_mode(client, args, logger=None):
|
|
53
53
|
stop_spinner.set()
|
54
54
|
spinner_thread.join()
|
55
55
|
# Clear the spinner line completely
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
with TERMINAL_RENDER_LOCK:
|
57
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
58
|
+
sys.stdout.flush()
|
59
|
+
print("Enhanced input with web search results.")
|
59
60
|
except Exception as e:
|
60
61
|
# Stop the spinner before re-raising
|
61
62
|
stop_spinner.set()
|
@@ -129,11 +130,14 @@ def chat_mode(client, args, logger=None):
|
|
129
130
|
# On first content, stop the spinner
|
130
131
|
if not first_content_received and stop_spinner_func:
|
131
132
|
first_content_received = True
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
|
134
|
+
# Use lock to prevent terminal rendering conflicts
|
135
|
+
with TERMINAL_RENDER_LOCK:
|
136
|
+
# Stop the spinner
|
137
|
+
stop_spinner_func()
|
138
|
+
# Ensure spinner message is cleared with an extra blank line
|
139
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
140
|
+
sys.stdout.flush()
|
137
141
|
|
138
142
|
# Call the original callback to update the display
|
139
143
|
if original_callback:
|
@@ -165,7 +169,8 @@ def chat_mode(client, args, logger=None):
|
|
165
169
|
|
166
170
|
# Handle non-stream response or regular prettify
|
167
171
|
if (args.no_stream or args.prettify) and response:
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
+
with TERMINAL_RENDER_LOCK:
|
173
|
+
if args.prettify:
|
174
|
+
prettify_markdown(response, args.renderer)
|
175
|
+
else:
|
176
|
+
print(response)
|
ngpt/cli/modes/code.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown, has_markdown_renderer, show_available_renderers
|
2
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, has_markdown_renderer, show_available_renderers, TERMINAL_RENDER_LOCK
|
3
3
|
from ..ui import spinner, copy_to_clipboard
|
4
4
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
5
5
|
import sys
|
@@ -126,9 +126,10 @@ def code_mode(client, args, logger=None):
|
|
126
126
|
stop_spinner.set()
|
127
127
|
spinner_thread.join()
|
128
128
|
# Clear the spinner line completely
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
with TERMINAL_RENDER_LOCK:
|
130
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
131
|
+
sys.stdout.flush()
|
132
|
+
print("Enhanced input with web search results.")
|
132
133
|
except Exception as e:
|
133
134
|
# Stop the spinner before re-raising
|
134
135
|
stop_spinner.set()
|
@@ -211,11 +212,14 @@ def code_mode(client, args, logger=None):
|
|
211
212
|
# On first content, stop the spinner
|
212
213
|
if not first_content_received and stop_spinner_func:
|
213
214
|
first_content_received = True
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
215
|
+
|
216
|
+
# Use lock to prevent terminal rendering conflicts
|
217
|
+
with TERMINAL_RENDER_LOCK:
|
218
|
+
# Stop the spinner
|
219
|
+
stop_spinner_func()
|
220
|
+
# Ensure spinner message is cleared with an extra blank line
|
221
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
222
|
+
sys.stdout.flush()
|
219
223
|
|
220
224
|
# Call the original callback to update the display
|
221
225
|
if original_callback:
|
@@ -297,12 +301,13 @@ def code_mode(client, args, logger=None):
|
|
297
301
|
|
298
302
|
# Print non-streamed output if needed
|
299
303
|
if generated_code and not should_stream:
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
304
|
+
with TERMINAL_RENDER_LOCK:
|
305
|
+
if use_regular_prettify:
|
306
|
+
print("\nGenerated code:")
|
307
|
+
prettify_markdown(generated_code, args.renderer)
|
308
|
+
else:
|
309
|
+
# Should only happen if --no-stream was used without prettify
|
310
|
+
print(f"\nGenerated code:\n{generated_code}")
|
306
311
|
|
307
312
|
# Offer to copy to clipboard
|
308
313
|
if generated_code and not args.no_stream:
|
ngpt/cli/modes/interactive.py
CHANGED
@@ -5,7 +5,7 @@ import threading
|
|
5
5
|
import sys
|
6
6
|
import time
|
7
7
|
from ..formatters import COLORS
|
8
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
8
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
9
9
|
from ..ui import spinner
|
10
10
|
from ...utils import enhance_prompt_with_web_search
|
11
11
|
|
@@ -78,8 +78,9 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
78
78
|
def print_separator():
|
79
79
|
# Make sure there's exactly one newline before and after
|
80
80
|
# Use sys.stdout.write for direct control, avoiding any extra newlines
|
81
|
-
|
82
|
-
|
81
|
+
with TERMINAL_RENDER_LOCK:
|
82
|
+
sys.stdout.write(f"\n{separator}\n")
|
83
|
+
sys.stdout.flush()
|
83
84
|
|
84
85
|
# Initialize conversation history
|
85
86
|
system_prompt = preprompt if preprompt else "You are a helpful assistant."
|
@@ -111,35 +112,37 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
111
112
|
|
112
113
|
# Function to display conversation history
|
113
114
|
def display_history():
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
print(f"\n{COLORS['cyan']}{COLORS['bold']}Conversation History:{COLORS['reset']}")
|
119
|
-
print(separator)
|
120
|
-
|
121
|
-
# Skip system message
|
122
|
-
message_count = 0
|
123
|
-
for i, msg in enumerate(conversation):
|
124
|
-
if msg["role"] == "system":
|
125
|
-
continue
|
115
|
+
with TERMINAL_RENDER_LOCK:
|
116
|
+
if len(conversation) <= 1: # Only system message
|
117
|
+
print(f"\n{COLORS['yellow']}No conversation history yet.{COLORS['reset']}")
|
118
|
+
return
|
126
119
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
120
|
+
print(f"\n{COLORS['cyan']}{COLORS['bold']}Conversation History:{COLORS['reset']}")
|
121
|
+
print(separator)
|
122
|
+
|
123
|
+
# Skip system message
|
124
|
+
message_count = 0
|
125
|
+
for i, msg in enumerate(conversation):
|
126
|
+
if msg["role"] == "system":
|
127
|
+
continue
|
128
|
+
|
129
|
+
if msg["role"] == "user":
|
130
|
+
message_count += 1
|
131
|
+
print(f"\n{user_header()}")
|
132
|
+
print(f"{COLORS['cyan']}│ [{message_count}] {COLORS['reset']}{msg['content']}")
|
133
|
+
elif msg["role"] == "assistant":
|
134
|
+
print(f"\n{ngpt_header()}")
|
135
|
+
print(f"{COLORS['green']}│ {COLORS['reset']}{msg['content']}")
|
136
|
+
|
137
|
+
print(f"\n{separator}") # Consistent separator at the end
|
136
138
|
|
137
139
|
# Function to clear conversation history
|
138
140
|
def clear_history():
|
139
141
|
nonlocal conversation
|
140
142
|
conversation = [{"role": "system", "content": system_prompt}]
|
141
|
-
|
142
|
-
|
143
|
+
with TERMINAL_RENDER_LOCK:
|
144
|
+
print(f"\n{COLORS['yellow']}Conversation history cleared.{COLORS['reset']}")
|
145
|
+
print(separator) # Add separator for consistency
|
143
146
|
|
144
147
|
try:
|
145
148
|
while True:
|
@@ -249,10 +252,11 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
249
252
|
|
250
253
|
# Print the header if needed
|
251
254
|
if should_print_header:
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
255
|
+
with TERMINAL_RENDER_LOCK:
|
256
|
+
if not no_stream and not stream_prettify:
|
257
|
+
print(f"\n{ngpt_header()}: {COLORS['reset']}", end="", flush=True)
|
258
|
+
elif not stream_prettify:
|
259
|
+
print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
|
256
260
|
|
257
261
|
# Determine streaming behavior
|
258
262
|
if prettify and not no_stream and not stream_prettify:
|
@@ -294,18 +298,20 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
294
298
|
if not first_content_received:
|
295
299
|
first_content_received = True
|
296
300
|
|
297
|
-
#
|
298
|
-
|
299
|
-
|
301
|
+
# Use lock to prevent terminal rendering conflicts
|
302
|
+
with TERMINAL_RENDER_LOCK:
|
303
|
+
# Stop the spinner if it's running
|
304
|
+
if stop_spinner_func:
|
305
|
+
stop_spinner_func()
|
306
|
+
|
307
|
+
# Clear the spinner line completely without leaving extra newlines
|
308
|
+
# Use direct terminal control to ensure consistency
|
309
|
+
sys.stdout.write("\r" + " " * shutil.get_terminal_size().columns + "\r")
|
310
|
+
sys.stdout.flush()
|
300
311
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
sys.stdout.flush()
|
305
|
-
|
306
|
-
# Now start the live display
|
307
|
-
if live_display:
|
308
|
-
live_display.start()
|
312
|
+
# Now start the live display
|
313
|
+
if live_display:
|
314
|
+
live_display.start()
|
309
315
|
|
310
316
|
# Call the original callback to update content
|
311
317
|
if original_callback:
|
@@ -351,11 +357,12 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
351
357
|
|
352
358
|
# Print response if not streamed (either due to no_stream or prettify)
|
353
359
|
if no_stream or prettify:
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
360
|
+
with TERMINAL_RENDER_LOCK:
|
361
|
+
if prettify:
|
362
|
+
# For pretty formatting with rich, don't print any header text as the rich renderer already includes it
|
363
|
+
prettify_markdown(response, renderer)
|
364
|
+
else:
|
365
|
+
print(response)
|
359
366
|
|
360
367
|
# Log AI response if logging is enabled
|
361
368
|
if logger:
|
ngpt/cli/modes/rewrite.py
CHANGED
@@ -2,7 +2,7 @@ import sys
|
|
2
2
|
import threading
|
3
3
|
import time
|
4
4
|
from ..formatters import COLORS
|
5
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
5
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
6
6
|
from ..ui import get_multiline_input, spinner, copy_to_clipboard
|
7
7
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
8
8
|
|
@@ -127,9 +127,10 @@ def rewrite_mode(client, args, logger=None):
|
|
127
127
|
stop_spinner.set()
|
128
128
|
spinner_thread.join()
|
129
129
|
# Clear the spinner line completely
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
with TERMINAL_RENDER_LOCK:
|
131
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
132
|
+
sys.stdout.flush()
|
133
|
+
print("Enhanced input with web search results.")
|
133
134
|
except Exception as e:
|
134
135
|
# Stop the spinner before re-raising
|
135
136
|
stop_spinner.set()
|
@@ -197,11 +198,14 @@ def rewrite_mode(client, args, logger=None):
|
|
197
198
|
# On first content, stop the spinner
|
198
199
|
if not first_content_received and stop_spinner_func:
|
199
200
|
first_content_received = True
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
201
|
+
|
202
|
+
# Use lock to prevent terminal rendering conflicts
|
203
|
+
with TERMINAL_RENDER_LOCK:
|
204
|
+
# Stop the spinner
|
205
|
+
stop_spinner_func()
|
206
|
+
# Ensure spinner message is cleared with an extra blank line
|
207
|
+
sys.stdout.write("\r" + " " * 100 + "\r\n")
|
208
|
+
sys.stdout.flush()
|
205
209
|
|
206
210
|
# Call the original callback to update the display
|
207
211
|
if original_callback:
|
@@ -241,10 +245,11 @@ def rewrite_mode(client, args, logger=None):
|
|
241
245
|
|
242
246
|
# Handle non-stream response or regular prettify
|
243
247
|
if (args.no_stream or args.prettify) and response:
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
+
with TERMINAL_RENDER_LOCK:
|
249
|
+
if args.prettify:
|
250
|
+
prettify_markdown(response, args.renderer)
|
251
|
+
else:
|
252
|
+
print(response)
|
248
253
|
|
249
254
|
# Offer to copy to clipboard if not in a redirected output
|
250
255
|
if not args.no_stream and response:
|
ngpt/cli/modes/shell.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
2
|
from ..ui import spinner, copy_to_clipboard, get_terminal_input
|
3
|
-
from ..renderers import prettify_markdown, has_markdown_renderer, prettify_streaming_markdown, show_available_renderers
|
3
|
+
from ..renderers import prettify_markdown, has_markdown_renderer, prettify_streaming_markdown, show_available_renderers, TERMINAL_RENDER_LOCK
|
4
4
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
5
5
|
import subprocess
|
6
6
|
import sys
|
@@ -796,19 +796,21 @@ def shell_mode(client, args, logger=None):
|
|
796
796
|
]
|
797
797
|
prompt_text = f"\nWhat would you like to do? [{COLORS['cyan']}C{COLORS['reset']}/{COLORS['cyan']}E{COLORS['reset']}/{COLORS['cyan']}D{COLORS['reset']}/{COLORS['cyan']}A{COLORS['reset']}] "
|
798
798
|
|
799
|
-
#
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
799
|
+
# Make sure box rendering is complete before showing options
|
800
|
+
with TERMINAL_RENDER_LOCK:
|
801
|
+
# Add a small delay to ensure terminal rendering is complete,
|
802
|
+
# especially important for stream-prettify mode
|
803
|
+
if use_stream_prettify:
|
804
|
+
time.sleep(0.5)
|
805
|
+
|
806
|
+
# Print options with proper flushing to ensure display
|
807
|
+
print(options_text, flush=True)
|
808
|
+
for option in options:
|
809
|
+
print(option, flush=True)
|
808
810
|
|
809
|
-
|
810
|
-
|
811
|
-
|
811
|
+
# Print prompt and flush to ensure it appears
|
812
|
+
sys.stdout.write(prompt_text)
|
813
|
+
sys.stdout.flush()
|
812
814
|
|
813
815
|
try:
|
814
816
|
# Use get_terminal_input which opens /dev/tty directly rather than using stdin
|
ngpt/cli/modes/text.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
2
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
3
3
|
from ..ui import get_multiline_input, spinner
|
4
4
|
from ...utils import enhance_prompt_with_web_search
|
5
5
|
import threading
|
@@ -47,9 +47,10 @@ def text_mode(client, args, logger=None):
|
|
47
47
|
stop_spinner.set()
|
48
48
|
spinner_thread.join()
|
49
49
|
# Clear the spinner line completely
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
with TERMINAL_RENDER_LOCK:
|
51
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
52
|
+
sys.stdout.flush()
|
53
|
+
print("Enhanced input with web search results.")
|
53
54
|
except Exception as e:
|
54
55
|
# Stop the spinner before re-raising
|
55
56
|
stop_spinner.set()
|
@@ -119,11 +120,14 @@ def text_mode(client, args, logger=None):
|
|
119
120
|
# On first content, stop the spinner
|
120
121
|
if not first_content_received and stop_spinner_func:
|
121
122
|
first_content_received = True
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
123
|
+
|
124
|
+
# Use lock to prevent terminal rendering conflicts
|
125
|
+
with TERMINAL_RENDER_LOCK:
|
126
|
+
# Stop the spinner
|
127
|
+
stop_spinner_func()
|
128
|
+
# Ensure spinner message is cleared with an extra blank line
|
129
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
130
|
+
sys.stdout.flush()
|
127
131
|
|
128
132
|
# Call the original callback to update the display
|
129
133
|
if original_callback:
|
@@ -155,7 +159,8 @@ def text_mode(client, args, logger=None):
|
|
155
159
|
|
156
160
|
# Handle non-stream response or regular prettify
|
157
161
|
if (args.no_stream or args.prettify) and response:
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
+
with TERMINAL_RENDER_LOCK:
|
163
|
+
if args.prettify:
|
164
|
+
prettify_markdown(response, args.renderer)
|
165
|
+
else:
|
166
|
+
print(response)
|
ngpt/cli/renderers.py
CHANGED
@@ -3,8 +3,12 @@ import shutil
|
|
3
3
|
import subprocess
|
4
4
|
import tempfile
|
5
5
|
import sys
|
6
|
+
import threading
|
6
7
|
from .formatters import COLORS
|
7
8
|
|
9
|
+
# Global lock for terminal rendering to prevent race conditions
|
10
|
+
TERMINAL_RENDER_LOCK = threading.Lock()
|
11
|
+
|
8
12
|
# Try to import markdown rendering libraries
|
9
13
|
try:
|
10
14
|
import rich
|
@@ -308,63 +312,65 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
|
|
308
312
|
# Check if this is the final update (complete flag)
|
309
313
|
is_complete = kwargs.get('complete', False)
|
310
314
|
|
311
|
-
#
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
# Update
|
321
|
-
if
|
322
|
-
#
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
315
|
+
# Use lock to prevent terminal rendering conflicts
|
316
|
+
with TERMINAL_RENDER_LOCK:
|
317
|
+
# Start live display on first content
|
318
|
+
if first_update:
|
319
|
+
first_update = False
|
320
|
+
# Let the spinner's clean_exit handle the cleanup
|
321
|
+
# No additional cleanup needed here
|
322
|
+
live.start()
|
323
|
+
|
324
|
+
# Update content in live display
|
325
|
+
if is_interactive and header_text:
|
326
|
+
# Update the panel content - for streaming, only show the last portion that fits in display_height
|
327
|
+
if not is_complete:
|
328
|
+
# Calculate approximate lines needed (rough estimation)
|
329
|
+
content_lines = content.count('\n') + 1
|
330
|
+
available_height = display_height - 4 # Account for panel borders and padding
|
331
|
+
|
332
|
+
if content_lines > available_height:
|
333
|
+
# If content is too big, show only the last part that fits
|
334
|
+
lines = content.split('\n')
|
335
|
+
truncated_content = '\n'.join(lines[-available_height:])
|
336
|
+
md_obj.renderable = Markdown(truncated_content)
|
337
|
+
else:
|
338
|
+
md_obj.renderable = Markdown(content)
|
331
339
|
else:
|
332
340
|
md_obj.renderable = Markdown(content)
|
333
|
-
else:
|
334
|
-
md_obj.renderable = Markdown(content)
|
335
|
-
|
336
|
-
live.update(md_obj)
|
337
|
-
else:
|
338
|
-
# Same logic for non-interactive mode
|
339
|
-
if not is_complete:
|
340
|
-
# Calculate approximate lines needed
|
341
|
-
content_lines = content.count('\n') + 1
|
342
|
-
available_height = display_height - 4 # Account for panel borders and padding
|
343
341
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
342
|
+
live.update(md_obj)
|
343
|
+
else:
|
344
|
+
# Same logic for non-interactive mode
|
345
|
+
if not is_complete:
|
346
|
+
# Calculate approximate lines needed
|
347
|
+
content_lines = content.count('\n') + 1
|
348
|
+
available_height = display_height - 4 # Account for panel borders and padding
|
349
|
+
|
350
|
+
if content_lines > available_height:
|
351
|
+
# If content is too big, show only the last part that fits
|
352
|
+
lines = content.split('\n')
|
353
|
+
truncated_content = '\n'.join(lines[-available_height:])
|
354
|
+
md_obj.renderable = Markdown(truncated_content)
|
355
|
+
else:
|
356
|
+
md_obj.renderable = Markdown(content)
|
349
357
|
else:
|
350
358
|
md_obj.renderable = Markdown(content)
|
351
|
-
|
352
|
-
|
359
|
+
|
360
|
+
live.update(md_obj)
|
353
361
|
|
354
|
-
|
362
|
+
# Ensure the display refreshes with new content
|
363
|
+
live.refresh()
|
355
364
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
# Fallback if something goes wrong
|
366
|
-
sys.stderr.write(f"\nError stopping live display: {str(e)}\n")
|
367
|
-
sys.stderr.flush()
|
365
|
+
# If streaming is complete, stop the live display
|
366
|
+
if is_complete:
|
367
|
+
try:
|
368
|
+
# Just stop the live display when complete - no need to redisplay content
|
369
|
+
live.stop()
|
370
|
+
except Exception as e:
|
371
|
+
# Fallback if something goes wrong
|
372
|
+
sys.stderr.write(f"\nError stopping live display: {str(e)}\n")
|
373
|
+
sys.stderr.flush()
|
368
374
|
|
369
375
|
# Define a function to set up and start the spinner
|
370
376
|
def setup_spinner(stop_event, message="Waiting for AI response...", color=COLORS['cyan']):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ngpt
|
3
|
-
Version: 3.8.
|
3
|
+
Version: 3.8.3
|
4
4
|
Summary: Swiss army knife for LLMs: powerful CLI and interactive chatbot in one package. Seamlessly work with OpenAI, Ollama, Groq, Claude, Gemini, or any OpenAI-compatible API to generate code, craft git commits, rewrite text, and execute shell commands.
|
5
5
|
Project-URL: Homepage, https://github.com/nazdridoy/ngpt
|
6
6
|
Project-URL: Repository, https://github.com/nazdridoy/ngpt
|
@@ -6,24 +6,24 @@ ngpt/cli/args.py,sha256=HYCDHhqP-BI_tibL1qGQ9we4483h_kCa2ksh-QxOeiU,12694
|
|
6
6
|
ngpt/cli/config_manager.py,sha256=NQQcWnjUppAAd0s0p9YAf8EyKS1ex5-0EB4DvKdB4dk,3662
|
7
7
|
ngpt/cli/formatters.py,sha256=HBYGlx_7eoAKyzfy0Vq5L0yn8yVKjngqYBukMmXCcz0,9401
|
8
8
|
ngpt/cli/main.py,sha256=PVulo8Pm53-oQ2Pgc4G90YhwyPImt8j7HKmY38SJ7CM,28696
|
9
|
-
ngpt/cli/renderers.py,sha256=
|
9
|
+
ngpt/cli/renderers.py,sha256=vAoDkpvgG2Fl81zkJDk_-zM1Fsw8E4Uv6m1AI81Fawo,17049
|
10
10
|
ngpt/cli/ui.py,sha256=4RFxIf51di5EsytVr7OoyCWF_d40KJ0Mbom0VWgPlCc,10870
|
11
11
|
ngpt/cli/modes/__init__.py,sha256=KP7VR6Xw9k1p5Jcu0F38RDxSFvFIzH3j1ThDLNwznUI,363
|
12
|
-
ngpt/cli/modes/chat.py,sha256=
|
13
|
-
ngpt/cli/modes/code.py,sha256=
|
12
|
+
ngpt/cli/modes/chat.py,sha256=x1leClKq7UupA_CdW4tym0AivY2o_II123-I5IcAkxQ,7091
|
13
|
+
ngpt/cli/modes/code.py,sha256=Qj59xq6fZqgUDw7SbvmPKX_gdpc7DHJhNkn1sB5qgUU,12932
|
14
14
|
ngpt/cli/modes/gitcommsg.py,sha256=iTg3KlZwI0lGMcmUa62b0ashwLcxegdEEvT29PPtpBc,49595
|
15
|
-
ngpt/cli/modes/interactive.py,sha256=
|
16
|
-
ngpt/cli/modes/rewrite.py,sha256=
|
17
|
-
ngpt/cli/modes/shell.py,sha256=
|
18
|
-
ngpt/cli/modes/text.py,sha256=
|
15
|
+
ngpt/cli/modes/interactive.py,sha256=E0c38NA8xnuRKAce40F35uFYcohFDvaqSB8nf1ywS-4,17958
|
16
|
+
ngpt/cli/modes/rewrite.py,sha256=QQm453X9aoUQP9CAtmeghlMytMJPlsDZPKef9tGfj6g,11181
|
17
|
+
ngpt/cli/modes/shell.py,sha256=it1Brq1-LGeNfPKYBeVAwF-a78g9UP-KscofBZQkbr4,41589
|
18
|
+
ngpt/cli/modes/text.py,sha256=rUr7Byds7zkO9ZbMSZWOO_3fWfpeM40Tq1XJAgdapcs,6679
|
19
19
|
ngpt/utils/__init__.py,sha256=_92f8eGMMOtQQA3uwgSRVwUEl1EIRFjWPUjcfGgI-eI,1244
|
20
20
|
ngpt/utils/cli_config.py,sha256=Ug8cECBTIuzOwkBWidLTfs-OAdOsCMJ2bNa70pOADfw,11195
|
21
21
|
ngpt/utils/config.py,sha256=wsArA4osnh8fKqOvtsPqqBxAz3DpdjtaWUFaRtnUdyc,10452
|
22
22
|
ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
|
23
23
|
ngpt/utils/pipe.py,sha256=qRHF-Ma7bbU0cOcb1Yhe4S-kBavivtnnvLA3EYS4FY4,2162
|
24
24
|
ngpt/utils/web_search.py,sha256=w5ke4KJMRxq7r5jtbUXvspja6XhjoPZloVkZ0IvBXIE,30731
|
25
|
-
ngpt-3.8.
|
26
|
-
ngpt-3.8.
|
27
|
-
ngpt-3.8.
|
28
|
-
ngpt-3.8.
|
29
|
-
ngpt-3.8.
|
25
|
+
ngpt-3.8.3.dist-info/METADATA,sha256=GjMEbP2fAxk4J6LdsM7vN0N3vT6ikicEbTRoWRGlNQI,28919
|
26
|
+
ngpt-3.8.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
27
|
+
ngpt-3.8.3.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
|
28
|
+
ngpt-3.8.3.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
|
29
|
+
ngpt-3.8.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|