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 +135 -2
- {ngpt-1.4.1.dist-info → ngpt-1.5.1.dist-info}/METADATA +1 -1
- ngpt-1.5.1.dist-info/RECORD +9 -0
- ngpt-1.4.1.dist-info/RECORD +0 -9
- {ngpt-1.4.1.dist-info → ngpt-1.5.1.dist-info}/WHEEL +0 -0
- {ngpt-1.4.1.dist-info → ngpt-1.5.1.dist-info}/entry_points.txt +0 -0
- {ngpt-1.4.1.dist-info → ngpt-1.5.1.dist-info}/licenses/LICENSE +0 -0
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
|
-
|
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.
|
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,,
|
ngpt-1.4.1.dist-info/RECORD
DELETED
@@ -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
|
File without changes
|
File without changes
|