ngpt 1.4.1__py3-none-any.whl → 1.5.1__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 CHANGED
@@ -112,7 +112,7 @@ def main():
112
112
  mode_exclusive_group.add_argument('-s', '--shell', action='store_true', help='Generate and execute shell commands')
113
113
  mode_exclusive_group.add_argument('-c', '--code', action='store_true', help='Generate code')
114
114
  mode_exclusive_group.add_argument('-t', '--text', action='store_true', help='Enter multi-line text input (submit with Ctrl+D)')
115
- # Note: --show-config is handled separately and implicitly acts as a mode
115
+ mode_exclusive_group.add_argument('-i', '--interactive', action='store_true', help='Start an interactive chat session')
116
116
 
117
117
  # Language option for code mode
118
118
  parser.add_argument('--language', default="python", help='Programming language to generate code in (for code mode)')
@@ -230,7 +230,7 @@ def main():
230
230
  return
231
231
 
232
232
  # Check if prompt is required but not provided
233
- if not args.prompt and not (args.shell or args.code or args.text):
233
+ if not args.prompt and not (args.shell or args.code or args.text or args.interactive):
234
234
  parser.print_help()
235
235
  return
236
236
 
@@ -279,6 +279,139 @@ def main():
279
279
  except subprocess.CalledProcessError as e:
280
280
  print(f"\nError:\n{e.stderr}")
281
281
 
282
+ elif args.interactive:
283
+ # Interactive chat mode
284
+ conversation_history = []
285
+ print("\033[94m\033[1m" + "Interactive Chat Mode" + "\033[0m")
286
+ print("Type your messages and press Ctrl+D to send. Type 'exit', 'quit', or use Ctrl+C to exit.")
287
+ print("Type 'clear' to start a new conversation.")
288
+ if HAS_PROMPT_TOOLKIT:
289
+ print("Use arrow keys to navigate, Enter for new line in multi-line mode.")
290
+ print()
291
+
292
+ try:
293
+ while True:
294
+ try:
295
+ # Get user input with prompt_toolkit if available
296
+ if HAS_PROMPT_TOOLKIT:
297
+ # Create key bindings
298
+ kb = KeyBindings()
299
+
300
+ # Explicitly bind Ctrl+C to exit
301
+ @kb.add('c-c')
302
+ def _(event):
303
+ event.app.exit(result=None)
304
+ print("\nExiting interactive chat mode.")
305
+ sys.exit(130)
306
+
307
+ # Explicitly bind Ctrl+D to submit
308
+ @kb.add('c-d')
309
+ def _(event):
310
+ event.app.exit(result=event.app.current_buffer.text)
311
+
312
+ # Get terminal dimensions
313
+ term_width, term_height = shutil.get_terminal_size()
314
+
315
+ # Create a styled TextArea
316
+ text_area = TextArea(
317
+ style="class:input-area",
318
+ multiline=True,
319
+ wrap_lines=True,
320
+ width=term_width - 4,
321
+ height=min(10, term_height - 8),
322
+ prompt=HTML("<ansiblue>>>> </ansiblue>"),
323
+ scrollbar=True,
324
+ focus_on_click=True,
325
+ lexer=None,
326
+ )
327
+ text_area.window.right_margins = [ScrollbarMargin(display_arrows=True)]
328
+
329
+ # Create a title bar
330
+ title_bar = FormattedTextControl(
331
+ HTML("<style bg='ansiblue' fg='ansiwhite'><b> NGPT Interactive Chat </b></style>")
332
+ )
333
+
334
+ # Create a status bar with key bindings and commands info
335
+ status_bar = FormattedTextControl(
336
+ HTML("<ansiblue><b>Ctrl+D</b></ansiblue>: Submit | <ansiblue><b>Ctrl+C</b></ansiblue>: Exit | Type <ansiblue><b>clear</b></ansiblue> to start new conversation")
337
+ )
338
+
339
+ # Create the layout
340
+ layout = Layout(
341
+ HSplit([
342
+ Window(title_bar, height=1),
343
+ Window(height=1, char="-", style="class:separator"),
344
+ text_area,
345
+ Window(height=1, char="-", style="class:separator"),
346
+ Window(status_bar, height=1),
347
+ ])
348
+ )
349
+
350
+ # Create a style
351
+ style = Style.from_dict({
352
+ "separator": "ansigray",
353
+ "input-area": "bg:ansiblack fg:ansiwhite",
354
+ "cursor": "bg:ansiwhite fg:ansiblack",
355
+ })
356
+
357
+ # Create and run the application
358
+ app = Application(
359
+ layout=layout,
360
+ full_screen=False,
361
+ key_bindings=kb,
362
+ style=style,
363
+ mouse_support=True,
364
+ )
365
+
366
+ user_input = app.run()
367
+ if user_input is None:
368
+ break
369
+ else:
370
+ # Fallback to standard input
371
+ user_input = input("\033[1m\033[94m>>> \033[0m")
372
+
373
+ # Handle special commands
374
+ if user_input is None:
375
+ break
376
+ elif user_input.lower() in ['exit', 'quit', 'q']:
377
+ print("Exiting interactive chat mode.")
378
+ break
379
+ elif user_input.lower() == 'clear':
380
+ print("Starting a new conversation.")
381
+ conversation_history = []
382
+ continue
383
+ elif not user_input.strip():
384
+ continue
385
+
386
+ # Add user message to conversation history
387
+ conversation_history.append({"role": "user", "content": user_input})
388
+
389
+ # Get response from the model
390
+ print("\033[90m" + "AI is thinking..." + "\033[0m")
391
+ response = client.chat(
392
+ prompt=user_input,
393
+ stream=not args.no_stream,
394
+ messages=conversation_history,
395
+ web_search=args.web_search
396
+ )
397
+
398
+ # Add assistant message to conversation history
399
+ conversation_history.append({"role": "assistant", "content": response})
400
+
401
+ # If no streaming, print the response
402
+ if args.no_stream and response:
403
+ print("\033[92m" + response + "\033[0m")
404
+
405
+ print() # Add spacing between exchanges
406
+
407
+ except KeyboardInterrupt:
408
+ print("\nExiting interactive chat mode.")
409
+ break
410
+
411
+ except Exception as e:
412
+ print(f"\nError in interactive mode: {e}")
413
+ return
414
+
282
415
  elif args.code:
283
416
  if args.prompt is None:
284
417
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 1.4.1
3
+ Version: 1.5.1
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=ZMBmNJfKiKAO88MecT7CDHH1uyqpupeCqGSX4-5LC_g,27117
3
+ ngpt/client.py,sha256=O0dPYeQCJlpWZWBBsroo-5UxeyBVwqC6o3Pm8lRnDiY,10329
4
+ ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
+ ngpt-1.5.1.dist-info/METADATA,sha256=eHORtsw7QD5HwfIhqRzCojOTNtfBqZ6kXCFT_8VBRq8,10086
6
+ ngpt-1.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ ngpt-1.5.1.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
+ ngpt-1.5.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
+ ngpt-1.5.1.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
- ngpt/cli.py,sha256=0oOh0hmqBrITihyacTfTt7elMoVenmsgxtED6YDcQUc,20254
3
- ngpt/client.py,sha256=O0dPYeQCJlpWZWBBsroo-5UxeyBVwqC6o3Pm8lRnDiY,10329
4
- ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
- ngpt-1.4.1.dist-info/METADATA,sha256=NPF972cMmb088HjbEDfmsRMMnbZPJyji41o_Pt6arEQ,10086
6
- ngpt-1.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- ngpt-1.4.1.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
- ngpt-1.4.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
- ngpt-1.4.1.dist-info/RECORD,,
File without changes