ngpt 3.0.5__py3-none-any.whl → 3.1.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/cli/interactive.py CHANGED
@@ -218,7 +218,7 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
218
218
  # Create a wrapper for the stream callback that handles spinner and live display
219
219
  original_callback = stream_callback
220
220
 
221
- def spinner_handling_callback(content):
221
+ def spinner_handling_callback(content, **kwargs):
222
222
  nonlocal first_content_received
223
223
 
224
224
  # On first content, stop the spinner and start the live display
@@ -239,7 +239,7 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
239
239
 
240
240
  # Call the original callback to update content
241
241
  if original_callback:
242
- original_callback(content)
242
+ original_callback(content, **kwargs)
243
243
 
244
244
  # Use our wrapper callback
245
245
  stream_callback = spinner_handling_callback
@@ -269,7 +269,9 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
269
269
 
270
270
  # Stop live display if using stream-prettify
271
271
  if stream_prettify and live_display and first_content_received:
272
- live_display.stop()
272
+ # Before stopping the live display, update with complete=True to show final formatted content
273
+ if stream_callback and response:
274
+ stream_callback(response, complete=True)
273
275
 
274
276
  # Add AI response to conversation history
275
277
  if response:
ngpt/cli/modes/chat.py CHANGED
@@ -103,7 +103,7 @@ def chat_mode(client, args, logger=None):
103
103
  original_callback = stream_callback
104
104
  first_content_received = False
105
105
 
106
- def spinner_handling_callback(content):
106
+ def spinner_handling_callback(content, **kwargs):
107
107
  nonlocal first_content_received
108
108
 
109
109
  # On first content, stop the spinner
@@ -117,7 +117,7 @@ def chat_mode(client, args, logger=None):
117
117
 
118
118
  # Call the original callback to update the display
119
119
  if original_callback:
120
- original_callback(content)
120
+ original_callback(content, **kwargs)
121
121
 
122
122
  # Use our wrapper callback
123
123
  if args.stream_prettify and live_display:
@@ -135,7 +135,9 @@ def chat_mode(client, args, logger=None):
135
135
 
136
136
  # Stop live display if using stream-prettify
137
137
  if args.stream_prettify and live_display:
138
- live_display.stop()
138
+ # Before stopping the live display, update with complete=True to show final formatted content
139
+ if stream_callback and response:
140
+ stream_callback(response, complete=True)
139
141
 
140
142
  # Log the AI response if logging is enabled
141
143
  if logger and response:
ngpt/cli/modes/code.py CHANGED
@@ -88,7 +88,7 @@ def code_mode(client, args, logger=None):
88
88
  original_callback = stream_callback
89
89
  first_content_received = False
90
90
 
91
- def spinner_handling_callback(content):
91
+ def spinner_handling_callback(content, **kwargs):
92
92
  nonlocal first_content_received
93
93
 
94
94
  # On first content, stop the spinner
@@ -102,7 +102,7 @@ def code_mode(client, args, logger=None):
102
102
 
103
103
  # Call the original callback to update the display
104
104
  if original_callback:
105
- original_callback(content)
105
+ original_callback(content, **kwargs)
106
106
 
107
107
  # Use our wrapper callback
108
108
  if use_stream_prettify and live_display:
@@ -127,7 +127,9 @@ def code_mode(client, args, logger=None):
127
127
 
128
128
  # Stop live display if using stream-prettify
129
129
  if use_stream_prettify and live_display:
130
- live_display.stop()
130
+ # Before stopping the live display, update with complete=True to show final formatted content
131
+ if stream_callback and generated_code:
132
+ stream_callback(generated_code, complete=True)
131
133
 
132
134
  # Log the generated code if logging is enabled
133
135
  if logger and generated_code:
ngpt/cli/modes/rewrite.py CHANGED
@@ -172,7 +172,7 @@ def rewrite_mode(client, args, logger=None):
172
172
  original_callback = stream_callback
173
173
  first_content_received = False
174
174
 
175
- def spinner_handling_callback(content):
175
+ def spinner_handling_callback(content, **kwargs):
176
176
  nonlocal first_content_received
177
177
 
178
178
  # On first content, stop the spinner
@@ -186,7 +186,7 @@ def rewrite_mode(client, args, logger=None):
186
186
 
187
187
  # Call the original callback to update the display
188
188
  if original_callback:
189
- original_callback(content)
189
+ original_callback(content, **kwargs)
190
190
 
191
191
  # Use our wrapper callback
192
192
  if args.stream_prettify and live_display:
@@ -210,7 +210,10 @@ def rewrite_mode(client, args, logger=None):
210
210
 
211
211
  # Stop live display if using stream-prettify
212
212
  if args.stream_prettify and live_display:
213
- live_display.stop()
213
+ # Before stopping the live display, update with complete=True to show final formatted content
214
+ if stream_callback and response:
215
+ stream_callback(response, complete=True)
216
+ # No need for else clause - the complete=True will handle stopping the live display
214
217
  # Add a small delay to ensure terminal stability
215
218
  time.sleep(0.2)
216
219
 
ngpt/cli/modes/text.py CHANGED
@@ -74,7 +74,7 @@ def text_mode(client, args, logger=None):
74
74
  original_callback = stream_callback
75
75
  first_content_received = False
76
76
 
77
- def spinner_handling_callback(content):
77
+ def spinner_handling_callback(content, **kwargs):
78
78
  nonlocal first_content_received
79
79
 
80
80
  # On first content, stop the spinner
@@ -88,7 +88,7 @@ def text_mode(client, args, logger=None):
88
88
 
89
89
  # Call the original callback to update the display
90
90
  if original_callback:
91
- original_callback(content)
91
+ original_callback(content, **kwargs)
92
92
 
93
93
  # Use our wrapper callback
94
94
  if args.stream_prettify and live_display:
@@ -106,7 +106,9 @@ def text_mode(client, args, logger=None):
106
106
 
107
107
  # Stop live display if using stream-prettify
108
108
  if args.stream_prettify and live_display:
109
- live_display.stop()
109
+ # Before stopping the live display, update with complete=True to show final formatted content
110
+ if stream_callback and response:
111
+ stream_callback(response, complete=True)
110
112
 
111
113
  # Log the AI response if logging is enabled
112
114
  if logger and response:
ngpt/cli/renderers.py CHANGED
@@ -239,13 +239,19 @@ 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 vertical overflow handling
242
+ # Get terminal dimensions for better display
243
+ term_width = shutil.get_terminal_size().columns
244
+ term_height = shutil.get_terminal_size().lines
245
+
246
+ # Use 2/3 of terminal height for content display (min 10 lines, max 30 lines)
247
+ display_height = max(10, min(30, int(term_height * 2/3)))
248
+
249
+ # Initialize the Live display (without height parameter)
243
250
  live = Live(
244
251
  md_obj,
245
252
  console=console,
246
253
  refresh_per_second=10,
247
- auto_refresh=False,
248
- vertical_overflow="visible" # Attempt to make overflow visible
254
+ auto_refresh=False
249
255
  )
250
256
 
251
257
  # Track if this is the first content update
@@ -253,9 +259,18 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
253
259
  stop_spinner_event = None
254
260
  spinner_thread = None
255
261
 
262
+ # Store the full content for final display
263
+ full_content = ""
264
+
256
265
  # Define an update function that will be called with new content
257
- def update_content(content):
258
- nonlocal md_obj, first_update
266
+ def update_content(content, **kwargs):
267
+ nonlocal md_obj, first_update, full_content, live, display_height
268
+
269
+ # Store the full content for final display
270
+ full_content = content
271
+
272
+ # Check if this is the final update (complete flag)
273
+ is_complete = kwargs.get('complete', False)
259
274
 
260
275
  # Start live display on first content
261
276
  if first_update:
@@ -267,16 +282,55 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
267
282
 
268
283
  # Update content in live display
269
284
  if is_interactive and header_text:
270
- # Update the panel content
271
- md_obj.renderable = Markdown(content)
285
+ # Update the panel content - for streaming, only show the last portion that fits in display_height
286
+ if not is_complete:
287
+ # Calculate approximate lines needed (rough estimation)
288
+ content_lines = content.count('\n') + 1
289
+ available_height = display_height - 4 # Account for panel borders and padding
290
+
291
+ if content_lines > available_height:
292
+ # If content is too big, show only the last part that fits
293
+ lines = content.split('\n')
294
+ truncated_content = '\n'.join(lines[-available_height:])
295
+ md_obj.renderable = Markdown(truncated_content)
296
+ else:
297
+ md_obj.renderable = Markdown(content)
298
+ else:
299
+ md_obj.renderable = Markdown(content)
300
+
272
301
  live.update(md_obj)
273
302
  else:
274
- md_obj = Markdown(content)
303
+ # Same logic for non-interactive mode
304
+ if not is_complete:
305
+ # Calculate approximate lines needed
306
+ content_lines = content.count('\n') + 1
307
+ available_height = display_height - 1 # Account for minimal overhead
308
+
309
+ if content_lines > available_height:
310
+ # If content is too big, show only the last part that fits
311
+ lines = content.split('\n')
312
+ truncated_content = '\n'.join(lines[-available_height:])
313
+ md_obj = Markdown(truncated_content)
314
+ else:
315
+ md_obj = Markdown(content)
316
+ else:
317
+ md_obj = Markdown(content)
318
+
275
319
  live.update(md_obj)
276
320
 
277
321
  # Ensure the display refreshes with new content
278
322
  live.refresh()
279
323
 
324
+ # If streaming is complete, stop the live display
325
+ if is_complete:
326
+ try:
327
+ # Just stop the live display when complete - no need to redisplay content
328
+ live.stop()
329
+ except Exception as e:
330
+ # Fallback if something goes wrong
331
+ sys.stderr.write(f"\nError stopping live display: {str(e)}\n")
332
+ sys.stderr.flush()
333
+
280
334
  # Define a function to set up and start the spinner
281
335
  def setup_spinner(stop_event, message="Waiting for AI response...", color=COLORS['cyan']):
282
336
  nonlocal stop_spinner_event, spinner_thread
@@ -298,6 +352,7 @@ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_te
298
352
  # Return a function that can be used to stop the spinner
299
353
  return lambda: stop_event.set() if stop_event else None
300
354
 
355
+ # Return the necessary components for streaming to work
301
356
  return live, update_content, setup_spinner
302
357
  except Exception as e:
303
358
  print(f"{COLORS['yellow']}Error setting up Rich streaming display: {str(e)}{COLORS['reset']}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 3.0.5
3
+ Version: 3.1.0
4
4
  Summary: Swiss army knife for LLMs: powerful CLI, interactive chatbot, and flexible Python library. Works with OpenAI, Ollama, Groq, Claude, Gemini, 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=XQvofZs_WkbgUto3Dbx7Yw-AmPAQHh8kdHUe3uWy8w4,11382
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=TiGiu85Bi7tFqRuhOPUdm8LjCEGr0WbZmCYzrx8cL9g,13037
8
+ ngpt/cli/interactive.py,sha256=Zep4yiGRFPVrJV1zp7xB5lXg7hVhXhbRlaVA4DgRBbQ,13241
9
9
  ngpt/cli/main.py,sha256=rIGbsr1wll4fJhAmPx8C9fCJYlhKijdHqal9e3NC2I8,28908
10
- ngpt/cli/renderers.py,sha256=yYt3b_cWUYckfgLQ1wkEiQCnq5v5m7hfn5PWxHJzR9Y,12422
10
+ ngpt/cli/renderers.py,sha256=ovV0IexZyrjCk8LK5ZGVvf5K7wCLco4jRhDv_tp6Kvw,15184
11
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=ULSIFach3Namb3FQBhgACxhHXME-fX7bLBDum9JQfks,5699
14
- ngpt/cli/modes/code.py,sha256=1EeiooyNe1jvTyNu6r0J9xY34QXb2uBQKPeNca-DrRI,5734
13
+ ngpt/cli/modes/chat.py,sha256=oibPaN4LAqrzIbWpw--ql0TwU0u_jlLCeNuxxyO7wPg,5887
14
+ ngpt/cli/modes/code.py,sha256=AEsQKdL8mh4ImcI5R7TXzwEq_JBTkmS-L0AA_-dpHm0,5934
15
15
  ngpt/cli/modes/gitcommsg.py,sha256=rsfMoeOupmNp-5p5fsMSPAf18BbzXWq-4PF2HjEz6SY,46991
16
- ngpt/cli/modes/rewrite.py,sha256=CEo8vzd_sIZbzZx52kPlMpXU0-rsoQg03KqG10h_0nU,10366
16
+ ngpt/cli/modes/rewrite.py,sha256=CrzUHxUoZc48D3ooVIvDbCjIIuERO1v-ddG3ajhETQs,10646
17
17
  ngpt/cli/modes/shell.py,sha256=QkprnOxMMTg2v5DIwcofDnnr3JPNfuk-YgSQaae5Xps,3311
18
- ngpt/cli/modes/text.py,sha256=z08xaW2r0XzyunUzBhwZKqnwPjyRol_CSazjLygmLRs,4514
18
+ ngpt/cli/modes/text.py,sha256=vCwZnVxIbsTCLE8YVJIPwZsGgk7VRs8v-eeaVwCOZqI,4702
19
19
  ngpt/utils/__init__.py,sha256=E46suk2-QgYBI0Qrs6WXOajOUOebF3ETAFY7ah8DTWs,942
20
20
  ngpt/utils/cli_config.py,sha256=IlHnOEEGpLoGZInynM778wgpxLVcJ_STKWxg2Ypvir4,11196
21
21
  ngpt/utils/config.py,sha256=WYOk_b1eiYjo6hpV3pfXr2RjqhOnmKqwZwKid1T41I4,10363
22
22
  ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
23
- ngpt-3.0.5.dist-info/METADATA,sha256=NAZUe2QY26o0pRoGL7VWUT34fBHiAZH-blpqdfViTog,28992
24
- ngpt-3.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- ngpt-3.0.5.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
- ngpt-3.0.5.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
- ngpt-3.0.5.dist-info/RECORD,,
23
+ ngpt-3.1.0.dist-info/METADATA,sha256=irJUzUn2P7MRjh8E-Dz0oQPOZ3PqKk7MRMf0TMkNZbM,28992
24
+ ngpt-3.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ ngpt-3.1.0.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
+ ngpt-3.1.0.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
+ ngpt-3.1.0.dist-info/RECORD,,
File without changes