ngpt 1.2.0__py3-none-any.whl → 1.4.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
@@ -5,6 +5,24 @@ from .client import NGPTClient
5
5
  from .config import load_config, get_config_path, load_configs, add_config_entry, remove_config_entry
6
6
  from . import __version__
7
7
 
8
+ # Optional imports for enhanced UI
9
+ try:
10
+ from prompt_toolkit import prompt as pt_prompt
11
+ from prompt_toolkit.styles import Style
12
+ from prompt_toolkit.key_binding import KeyBindings
13
+ from prompt_toolkit.formatted_text import HTML
14
+ from prompt_toolkit.layout.containers import HSplit, Window
15
+ from prompt_toolkit.layout.layout import Layout
16
+ from prompt_toolkit.layout.controls import FormattedTextControl
17
+ from prompt_toolkit.application import Application
18
+ from prompt_toolkit.widgets import TextArea
19
+ from prompt_toolkit.layout.margins import ScrollbarMargin
20
+ from prompt_toolkit.filters import to_filter
21
+ import shutil
22
+ HAS_PROMPT_TOOLKIT = True
23
+ except ImportError:
24
+ HAS_PROMPT_TOOLKIT = False
25
+
8
26
  def show_config_help():
9
27
  """Display help information about configuration."""
10
28
  print("\nConfiguration Help:")
@@ -85,12 +103,15 @@ def main():
85
103
  global_group.add_argument('--model', help='Model to use')
86
104
  global_group.add_argument('--web-search', action='store_true',
87
105
  help='Enable web search capability (Note: Your API endpoint must support this feature)')
106
+ global_group.add_argument('-n', '--no-stream', action='store_true',
107
+ help='Return the whole response without streaming')
88
108
 
89
109
  # Mode flags (mutually exclusive)
90
110
  mode_group = parser.add_argument_group('Modes (mutually exclusive)')
91
111
  mode_exclusive_group = mode_group.add_mutually_exclusive_group()
92
112
  mode_exclusive_group.add_argument('-s', '--shell', action='store_true', help='Generate and execute shell commands')
93
113
  mode_exclusive_group.add_argument('-c', '--code', action='store_true', help='Generate code')
114
+ mode_exclusive_group.add_argument('-t', '--text', action='store_true', help='Enter multi-line text input (submit with Ctrl+D)')
94
115
  # Note: --show-config is handled separately and implicitly acts as a mode
95
116
 
96
117
  # Language option for code mode
@@ -209,7 +230,7 @@ def main():
209
230
  return
210
231
 
211
232
  # Check if prompt is required but not provided
212
- if not args.prompt and not (args.shell or args.code):
233
+ if not args.prompt and not (args.shell or args.code or args.text):
213
234
  parser.print_help()
214
235
  return
215
236
 
@@ -273,6 +294,119 @@ def main():
273
294
  if generated_code:
274
295
  print(f"\nGenerated code:\n{generated_code}")
275
296
 
297
+ elif args.text:
298
+ # Multi-line text input mode
299
+ if args.prompt is not None:
300
+ prompt = args.prompt
301
+ else:
302
+ try:
303
+ if HAS_PROMPT_TOOLKIT:
304
+ print("\033[94m\033[1m" + "Multi-line Input Mode" + "\033[0m")
305
+ print("Press Ctrl+D to submit, Ctrl+C to exit")
306
+ print("Use arrow keys to navigate, Enter for new line")
307
+
308
+ # Create key bindings
309
+ kb = KeyBindings()
310
+
311
+ # Explicitly bind Ctrl+D to exit
312
+ @kb.add('c-d')
313
+ def _(event):
314
+ event.app.exit(result=event.app.current_buffer.text)
315
+
316
+ # Explicitly bind Ctrl+C to exit
317
+ @kb.add('c-c')
318
+ def _(event):
319
+ event.app.exit(result=None)
320
+ print("\nInput cancelled by user. Exiting gracefully.")
321
+ sys.exit(130)
322
+
323
+ # Get terminal dimensions
324
+ term_width, term_height = shutil.get_terminal_size()
325
+
326
+ # Create a styled TextArea
327
+ text_area = TextArea(
328
+ style="class:input-area",
329
+ multiline=True,
330
+ wrap_lines=True,
331
+ width=term_width - 4,
332
+ height=min(20, term_height - 8),
333
+ prompt=HTML("<ansicyan>>>> </ansicyan>"),
334
+ scrollbar=True,
335
+ focus_on_click=True,
336
+ lexer=None,
337
+ )
338
+ text_area.window.right_margins = [ScrollbarMargin(display_arrows=True)]
339
+
340
+ # Create a title bar
341
+ title_bar = FormattedTextControl(
342
+ HTML("<style bg='ansicyan' fg='ansiblack'><b> NGPT Multi-line Editor </b></style>")
343
+ )
344
+
345
+ # Create a status bar with key bindings info
346
+ status_bar = FormattedTextControl(
347
+ HTML("<ansiblue><b>Ctrl+D</b></ansiblue>: Submit | <ansiblue><b>Ctrl+C</b></ansiblue>: Cancel | <ansiblue><b>↑↓←→</b></ansiblue>: Navigate")
348
+ )
349
+
350
+ # Create the layout
351
+ layout = Layout(
352
+ HSplit([
353
+ Window(title_bar, height=1),
354
+ Window(height=1, char="-", style="class:separator"),
355
+ text_area,
356
+ Window(height=1, char="-", style="class:separator"),
357
+ Window(status_bar, height=1),
358
+ ])
359
+ )
360
+
361
+ # Create a style
362
+ style = Style.from_dict({
363
+ "separator": "ansigray",
364
+ "input-area": "bg:ansiblack fg:ansiwhite",
365
+ "cursor": "bg:ansiwhite fg:ansiblack",
366
+ })
367
+
368
+ # Create and run the application
369
+ app = Application(
370
+ layout=layout,
371
+ full_screen=False,
372
+ key_bindings=kb,
373
+ style=style,
374
+ mouse_support=True,
375
+ )
376
+
377
+ prompt = app.run()
378
+
379
+ if not prompt or not prompt.strip():
380
+ print("Empty prompt. Exiting.")
381
+ return
382
+ else:
383
+ # Fallback to standard input with a better implementation
384
+ print("Enter your multi-line prompt (press Ctrl+D to submit):")
385
+ print("Note: Install 'prompt_toolkit' package for an enhanced input experience")
386
+
387
+ # Use a more robust approach for multiline input without prompt_toolkit
388
+ lines = []
389
+ while True:
390
+ try:
391
+ line = input()
392
+ lines.append(line)
393
+ except EOFError: # Ctrl+D was pressed
394
+ break
395
+
396
+ prompt = "\n".join(lines)
397
+ if not prompt.strip():
398
+ print("Empty prompt. Exiting.")
399
+ return
400
+
401
+ except KeyboardInterrupt:
402
+ print("\nInput cancelled by user. Exiting gracefully.")
403
+ sys.exit(130)
404
+
405
+ print("\nSubmission successful. Waiting for response...")
406
+ response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search)
407
+ if args.no_stream and response:
408
+ print(response)
409
+
276
410
  else:
277
411
  # Default to chat mode
278
412
  if args.prompt is None:
@@ -284,7 +418,9 @@ def main():
284
418
  sys.exit(130)
285
419
  else:
286
420
  prompt = args.prompt
287
- client.chat(prompt, web_search=args.web_search)
421
+ response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search)
422
+ if args.no_stream and response:
423
+ print(response)
288
424
 
289
425
  except KeyboardInterrupt:
290
426
  print("\nOperation cancelled by user. Exiting gracefully.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 1.2.0
3
+ Version: 1.4.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
@@ -28,6 +28,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
28
28
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
29
  Classifier: Topic :: Utilities
30
30
  Requires-Python: >=3.8
31
+ Requires-Dist: prompt-toolkit>=3.0.0
31
32
  Requires-Dist: requests>=2.31.0
32
33
  Description-Content-Type: text/markdown
33
34
 
@@ -63,11 +64,17 @@ pip install ngpt
63
64
  # Chat with default settings
64
65
  ngpt "Tell me about quantum computing"
65
66
 
67
+ # Return response without streaming
68
+ ngpt -n "Tell me about quantum computing"
69
+
66
70
  # Generate code
67
71
  ngpt --code "function to calculate the Fibonacci sequence"
68
72
 
69
73
  # Generate and execute shell commands
70
74
  ngpt --shell "list all files in the current directory"
75
+
76
+ # Use multiline editor for complex prompts
77
+ ngpt --text
71
78
  ```
72
79
 
73
80
  ## Features
@@ -80,6 +87,7 @@ ngpt --shell "list all files in the current directory"
80
87
  - ⚙️ **Multiple Configurations**: Cross-platform config system supporting different profiles
81
88
  - 💻 **Shell Command Generation**: OS-aware command execution
82
89
  - 🧩 **Clean Code Generation**: Output code without markdown or explanations
90
+ - 📝 **Rich Multiline Editor**: Interactive multiline text input with syntax highlighting and intuitive controls
83
91
 
84
92
  ## Installation
85
93
 
@@ -121,6 +129,10 @@ ngpt -s "list all files in current directory"
121
129
  # Generate clean code (using -c or --code flag)
122
130
  # Returns only code without markdown formatting or explanations
123
131
  ngpt -c "create a python function that calculates fibonacci numbers"
132
+
133
+ # Use multiline text editor for complex prompts (using -t or --text flag)
134
+ # Opens an interactive editor with syntax highlighting and intuitive controls
135
+ ngpt -t
124
136
  ```
125
137
 
126
138
  ### As a Library
@@ -193,6 +205,7 @@ You can configure the client using the following options:
193
205
  | `--base-url` | Base URL for the API |
194
206
  | `--model` | Model to use |
195
207
  | `--web-search` | Enable web search capability |
208
+ | `-n, --no-stream` | Return the whole response without streaming |
196
209
  | `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
197
210
  | `--config-index` | Index of the configuration to use (default: 0) |
198
211
  | `--remove` | Remove the configuration at the specified index (requires --config and --config-index) |
@@ -200,6 +213,7 @@ You can configure the client using the following options:
200
213
  | `--all` | Used with `--show-config` to display all configurations |
201
214
  | `-s, --shell` | Generate and execute shell commands |
202
215
  | `-c, --code` | Generate clean code output |
216
+ | `-t, --text` | Open interactive multiline editor for complex prompts |
203
217
  | `-v, --version` | Show version information |
204
218
 
205
219
  ### Interactive Configuration
@@ -0,0 +1,9 @@
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,,
@@ -1,9 +0,0 @@
1
- ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
- ngpt/cli.py,sha256=tIKXjKfh4K19UcZ0uG8JqTVz-9Lxg-p16dkYTiOmp7o,13582
3
- ngpt/client.py,sha256=O0dPYeQCJlpWZWBBsroo-5UxeyBVwqC6o3Pm8lRnDiY,10329
4
- ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
- ngpt-1.2.0.dist-info/METADATA,sha256=o8iptGfiLJbibZZLKYFrg584Ppw6BMLkZuZQfvOzAFk,9497
6
- ngpt-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- ngpt-1.2.0.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
- ngpt-1.2.0.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
- ngpt-1.2.0.dist-info/RECORD,,
File without changes