ngpt 2.5.1__tar.gz → 2.7.1__tar.gz

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.
Files changed (32) hide show
  1. {ngpt-2.5.1 → ngpt-2.7.1}/PKG-INFO +23 -4
  2. {ngpt-2.5.1 → ngpt-2.7.1}/README.md +19 -0
  3. {ngpt-2.5.1 → ngpt-2.7.1}/docs/examples/advanced.md +22 -0
  4. {ngpt-2.5.1 → ngpt-2.7.1}/docs/examples/basic.md +12 -0
  5. {ngpt-2.5.1 → ngpt-2.7.1}/docs/installation.md +20 -6
  6. {ngpt-2.5.1 → ngpt-2.7.1}/docs/overview.md +2 -0
  7. {ngpt-2.5.1 → ngpt-2.7.1}/docs/usage/cli_usage.md +31 -0
  8. {ngpt-2.5.1 → ngpt-2.7.1}/ngpt/cli.py +253 -35
  9. {ngpt-2.5.1 → ngpt-2.7.1}/ngpt/client.py +21 -6
  10. {ngpt-2.5.1 → ngpt-2.7.1}/pyproject.toml +3 -3
  11. {ngpt-2.5.1 → ngpt-2.7.1}/uv.lock +6 -6
  12. {ngpt-2.5.1 → ngpt-2.7.1}/.github/workflows/python-publish.yml +0 -0
  13. {ngpt-2.5.1 → ngpt-2.7.1}/.gitignore +0 -0
  14. {ngpt-2.5.1 → ngpt-2.7.1}/.python-version +0 -0
  15. {ngpt-2.5.1 → ngpt-2.7.1}/COMMIT_GUIDELINES.md +0 -0
  16. {ngpt-2.5.1 → ngpt-2.7.1}/CONTRIBUTING.md +0 -0
  17. {ngpt-2.5.1 → ngpt-2.7.1}/LICENSE +0 -0
  18. {ngpt-2.5.1 → ngpt-2.7.1}/docs/CONTRIBUTING.md +0 -0
  19. {ngpt-2.5.1 → ngpt-2.7.1}/docs/LICENSE.md +0 -0
  20. {ngpt-2.5.1 → ngpt-2.7.1}/docs/README.md +0 -0
  21. {ngpt-2.5.1 → ngpt-2.7.1}/docs/_config.yml +0 -0
  22. {ngpt-2.5.1 → ngpt-2.7.1}/docs/api/README.md +0 -0
  23. {ngpt-2.5.1 → ngpt-2.7.1}/docs/api/client.md +0 -0
  24. {ngpt-2.5.1 → ngpt-2.7.1}/docs/api/config.md +0 -0
  25. {ngpt-2.5.1 → ngpt-2.7.1}/docs/assets/css/style.scss +0 -0
  26. {ngpt-2.5.1 → ngpt-2.7.1}/docs/configuration.md +0 -0
  27. {ngpt-2.5.1 → ngpt-2.7.1}/docs/examples/README.md +0 -0
  28. {ngpt-2.5.1 → ngpt-2.7.1}/docs/examples/integrations.md +0 -0
  29. {ngpt-2.5.1 → ngpt-2.7.1}/docs/usage/README.md +0 -0
  30. {ngpt-2.5.1 → ngpt-2.7.1}/docs/usage/library_usage.md +0 -0
  31. {ngpt-2.5.1 → ngpt-2.7.1}/ngpt/__init__.py +0 -0
  32. {ngpt-2.5.1 → ngpt-2.7.1}/ngpt/config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 2.5.1
3
+ Version: 2.7.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,10 +28,10 @@ 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
32
31
  Requires-Dist: requests>=2.31.0
33
- Provides-Extra: prettify
34
- Requires-Dist: rich>=10.0.0; extra == 'prettify'
32
+ Provides-Extra: full
33
+ Requires-Dist: prompt-toolkit>=3.0.0; extra == 'full'
34
+ Requires-Dist: rich>=10.0.0; extra == 'full'
35
35
  Description-Content-Type: text/markdown
36
36
 
37
37
  # nGPT
@@ -66,6 +66,9 @@ A lightweight Python CLI and library for interacting with OpenAI-compatible APIs
66
66
  # Install
67
67
  pip install ngpt
68
68
 
69
+ # Install with additional features
70
+ pip install "ngpt[full]"
71
+
69
72
  # Chat with default settings
70
73
  ngpt "Tell me about quantum computing"
71
74
 
@@ -81,12 +84,18 @@ ngpt --code "function to calculate the Fibonacci sequence"
81
84
  # Generate code with syntax highlighting
82
85
  ngpt --code --prettify "function to calculate the Fibonacci sequence"
83
86
 
87
+ # Generate code with real-time syntax highlighting
88
+ ngpt --code --stream-prettify "function to calculate the Fibonacci sequence"
89
+
84
90
  # Generate and execute shell commands
85
91
  ngpt --shell "list all files in the current directory"
86
92
 
87
93
  # Display markdown responses with beautiful formatting
88
94
  ngpt --prettify "Explain markdown syntax with examples"
89
95
 
96
+ # Display markdown responses with real-time formatting
97
+ ngpt --stream-prettify "Explain markdown syntax with examples"
98
+
90
99
  # Use a specific markdown renderer
91
100
  ngpt --prettify --renderer=rich "Create a markdown table"
92
101
 
@@ -111,6 +120,7 @@ For more examples and detailed usage, visit the [CLI Usage Guide](https://nazdri
111
120
  - 📊 **Streaming Responses**: Real-time output for better user experience
112
121
  - 🔍 **Web Search**: Integrated with compatible API endpoints
113
122
  - 🎨 **Markdown Rendering**: Beautiful formatting of markdown and code with syntax highlighting
123
+ - ⚡ **Real-time Markdown**: Stream responses with live updating syntax highlighting and formatting
114
124
  - ⚙️ **Multiple Configurations**: Cross-platform config system supporting different profiles
115
125
  - 💻 **Shell Command Generation**: OS-aware command execution
116
126
  - 🧩 **Clean Code Generation**: Output code without markdown or explanations
@@ -136,11 +146,19 @@ Key documentation sections:
136
146
  ## Installation
137
147
 
138
148
  ```bash
149
+ # Basic installation (minimal dependencies)
139
150
  pip install ngpt
151
+
152
+ # Full installation with all features (recommended)
153
+ pip install "ngpt[full]"
140
154
  ```
141
155
 
142
156
  Requires Python 3.8 or newer.
143
157
 
158
+ The full installation includes:
159
+ - Enhanced markdown rendering with syntax highlighting
160
+ - Improved interactive input experience with multiline editing
161
+
144
162
  For detailed installation instructions, see the [Installation Guide](https://nazdridoy.github.io/ngpt/installation.html).
145
163
 
146
164
  ## Usage
@@ -280,6 +298,7 @@ You can configure the client using the following options:
280
298
  | `--preprompt` | Set custom system prompt to control AI behavior |
281
299
  | `--log` | Set filepath to log conversation to (for interactive modes) |
282
300
  | `--prettify` | Render markdown responses and code with syntax highlighting |
301
+ | `--stream-prettify` | Enable real-time markdown rendering with syntax highlighting while streaming |
283
302
  | `--renderer` | Select which markdown renderer to use with --prettify (auto, rich, or glow) |
284
303
  | `--list-renderers` | Show available markdown renderers for use with --prettify |
285
304
  | `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
@@ -30,6 +30,9 @@ A lightweight Python CLI and library for interacting with OpenAI-compatible APIs
30
30
  # Install
31
31
  pip install ngpt
32
32
 
33
+ # Install with additional features
34
+ pip install "ngpt[full]"
35
+
33
36
  # Chat with default settings
34
37
  ngpt "Tell me about quantum computing"
35
38
 
@@ -45,12 +48,18 @@ ngpt --code "function to calculate the Fibonacci sequence"
45
48
  # Generate code with syntax highlighting
46
49
  ngpt --code --prettify "function to calculate the Fibonacci sequence"
47
50
 
51
+ # Generate code with real-time syntax highlighting
52
+ ngpt --code --stream-prettify "function to calculate the Fibonacci sequence"
53
+
48
54
  # Generate and execute shell commands
49
55
  ngpt --shell "list all files in the current directory"
50
56
 
51
57
  # Display markdown responses with beautiful formatting
52
58
  ngpt --prettify "Explain markdown syntax with examples"
53
59
 
60
+ # Display markdown responses with real-time formatting
61
+ ngpt --stream-prettify "Explain markdown syntax with examples"
62
+
54
63
  # Use a specific markdown renderer
55
64
  ngpt --prettify --renderer=rich "Create a markdown table"
56
65
 
@@ -75,6 +84,7 @@ For more examples and detailed usage, visit the [CLI Usage Guide](https://nazdri
75
84
  - 📊 **Streaming Responses**: Real-time output for better user experience
76
85
  - 🔍 **Web Search**: Integrated with compatible API endpoints
77
86
  - 🎨 **Markdown Rendering**: Beautiful formatting of markdown and code with syntax highlighting
87
+ - ⚡ **Real-time Markdown**: Stream responses with live updating syntax highlighting and formatting
78
88
  - ⚙️ **Multiple Configurations**: Cross-platform config system supporting different profiles
79
89
  - 💻 **Shell Command Generation**: OS-aware command execution
80
90
  - 🧩 **Clean Code Generation**: Output code without markdown or explanations
@@ -100,11 +110,19 @@ Key documentation sections:
100
110
  ## Installation
101
111
 
102
112
  ```bash
113
+ # Basic installation (minimal dependencies)
103
114
  pip install ngpt
115
+
116
+ # Full installation with all features (recommended)
117
+ pip install "ngpt[full]"
104
118
  ```
105
119
 
106
120
  Requires Python 3.8 or newer.
107
121
 
122
+ The full installation includes:
123
+ - Enhanced markdown rendering with syntax highlighting
124
+ - Improved interactive input experience with multiline editing
125
+
108
126
  For detailed installation instructions, see the [Installation Guide](https://nazdridoy.github.io/ngpt/installation.html).
109
127
 
110
128
  ## Usage
@@ -244,6 +262,7 @@ You can configure the client using the following options:
244
262
  | `--preprompt` | Set custom system prompt to control AI behavior |
245
263
  | `--log` | Set filepath to log conversation to (for interactive modes) |
246
264
  | `--prettify` | Render markdown responses and code with syntax highlighting |
265
+ | `--stream-prettify` | Enable real-time markdown rendering with syntax highlighting while streaming |
247
266
  | `--renderer` | Select which markdown renderer to use with --prettify (auto, rich, or glow) |
248
267
  | `--list-renderers` | Show available markdown renderers for use with --prettify |
249
268
  | `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
@@ -316,6 +316,28 @@ print(response_high)
316
316
 
317
317
  ## Advanced CLI Usage
318
318
 
319
+ ### Working with Real-time Markdown Rendering
320
+
321
+ Use the stream-prettify feature for an enhanced user experience with formatted markdown in real-time:
322
+
323
+ ```bash
324
+ # Basic streaming markdown
325
+ ngpt --stream-prettify "Compare and contrast different sorting algorithms with examples"
326
+
327
+ # Real-time code generation with syntax highlighting
328
+ ngpt -c --stream-prettify --language typescript "implement a React hook for managing form state"
329
+
330
+ # Interactive session with real-time markdown rendering
331
+ ngpt -i --stream-prettify
332
+ ```
333
+
334
+ Combining stream-prettify with web search for up-to-date formatted information:
335
+
336
+ ```bash
337
+ # Get latest news with beautified formatting in real-time
338
+ ngpt --stream-prettify --web-search "What are the latest developments in AI research?"
339
+ ```
340
+
319
341
  ### Custom Script with argparse
320
342
 
321
343
  Create a custom script that uses nGPT with argparse for a better CLI experience:
@@ -129,6 +129,12 @@ ngpt "Tell me about quantum computing"
129
129
 
130
130
  # No streaming (wait for full response)
131
131
  ngpt -n "Explain the theory of relativity"
132
+
133
+ # Prettify markdown output
134
+ ngpt --prettify "Create a markdown table comparing different programming languages"
135
+
136
+ # Real-time markdown formatting with streaming
137
+ ngpt --stream-prettify "Explain machine learning algorithms with examples"
132
138
  ```
133
139
 
134
140
  ### Code Generation
@@ -139,6 +145,12 @@ ngpt -c "function to calculate prime numbers"
139
145
 
140
146
  # Generate specific language code
141
147
  ngpt -c "create a React component that displays a counter" --language jsx
148
+
149
+ # Generate code with syntax highlighting
150
+ ngpt -c --prettify "implement a binary search tree"
151
+
152
+ # Generate code with real-time syntax highlighting
153
+ ngpt -c --stream-prettify "write a function to sort an array using quicksort"
142
154
  ```
143
155
 
144
156
  ### Shell Commands
@@ -6,11 +6,11 @@ There are several ways to install nGPT depending on your needs and environment.
6
6
 
7
7
  - Python 3.8 or newer
8
8
  - `requests` library (automatically installed as a dependency)
9
- - `prompt_toolkit` library (automatically installed as a dependency)
10
9
 
11
10
  ## Optional Dependencies
12
11
 
13
12
  - `rich` library - For enhanced markdown rendering with syntax highlighting
13
+ - `prompt_toolkit` library - For improved interactive input experience with multiline editing
14
14
 
15
15
  ## Installing from PyPI (Recommended)
16
16
 
@@ -20,18 +20,20 @@ The simplest way to install nGPT is through the Python Package Index (PyPI):
20
20
  pip install ngpt
21
21
  ```
22
22
 
23
- This will install the latest stable release of nGPT and all its dependencies.
23
+ This will install the latest stable release of nGPT with basic functionality.
24
24
 
25
- For markdown rendering capabilities, install with the prettify extra:
25
+ For additional capabilities like markdown rendering, syntax highlighting, and enhanced interactive input experience, install with the full extras:
26
26
 
27
27
  ```bash
28
- pip install ngpt[prettify]
28
+ pip install "ngpt[full]"
29
29
  ```
30
30
 
31
- Alternatively, you can install the optional dependency separately:
31
+ Note that quotes around the package name are required due to the square brackets.
32
+
33
+ Alternatively, you can install the optional dependencies separately:
32
34
 
33
35
  ```bash
34
- pip install rich
36
+ pip install rich prompt_toolkit
35
37
  ```
36
38
 
37
39
  ## Installing in a Virtual Environment
@@ -52,6 +54,9 @@ source ngpt-env/bin/activate
52
54
 
53
55
  # Install nGPT
54
56
  pip install ngpt
57
+
58
+ # Or with all features
59
+ pip install "ngpt[full]"
55
60
  ```
56
61
 
57
62
  ### Using conda
@@ -65,6 +70,9 @@ conda activate ngpt-env
65
70
 
66
71
  # Install nGPT
67
72
  pip install ngpt
73
+
74
+ # Or with all features
75
+ pip install "ngpt[full]"
68
76
  ```
69
77
 
70
78
  ## Installing from Source
@@ -80,6 +88,9 @@ cd ngpt
80
88
 
81
89
  # Install the package in development mode
82
90
  pip install -e .
91
+
92
+ # Or with all features
93
+ pip install -e ".[full]"
83
94
  ```
84
95
 
85
96
  ## Upgrading
@@ -88,6 +99,9 @@ To upgrade to the latest version:
88
99
 
89
100
  ```bash
90
101
  pip install --upgrade ngpt
102
+
103
+ # Or with all features
104
+ pip install --upgrade "ngpt[full]"
91
105
  ```
92
106
 
93
107
  ## Verifying the Installation
@@ -20,6 +20,8 @@ nGPT is a lightweight Python library and command-line interface (CLI) tool desig
20
20
 
21
21
  - **Markdown Rendering**: Beautiful formatting of markdown responses and syntax highlighting for code.
22
22
 
23
+ - **Real-time Markdown Rendering**: Stream responses with live updating syntax highlighting and formatting using the `--stream-prettify` option.
24
+
23
25
  - **Multiple Configuration Support**: Maintain different API configurations for various services or models.
24
26
 
25
27
  - **Shell Command Generation**: Generate OS-aware commands that work on your specific platform.
@@ -49,6 +49,7 @@ Here are the most commonly used options:
49
49
  | `--top_p` | Set top_p (controls diversity, default: 1.0) |
50
50
  | `--max_tokens` | Set maximum response length in tokens |
51
51
  | `--prettify` | Render markdown responses and code with syntax highlighting |
52
+ | `--stream-prettify` | Enable real-time markdown rendering with syntax highlighting while streaming |
52
53
  | `--renderer` | Select which markdown renderer to use (auto, rich, or glow) |
53
54
  | `--list-renderers` | Show available markdown renderers on your system |
54
55
  | `--config-index` | Index of the configuration to use (default: 0) |
@@ -177,6 +178,30 @@ ngpt -c --prettify "function to calculate the Fibonacci sequence"
177
178
 
178
179
  When using `--prettify` with code generation, the AI will output code in markdown format with proper syntax highlighting based on the language.
179
180
 
181
+ ### Real-time Markdown Rendering
182
+
183
+ Display markdown responses with real-time formatting and syntax highlighting while streaming:
184
+
185
+ ```bash
186
+ ngpt --stream-prettify "Explain quantum computing with code examples"
187
+ ```
188
+
189
+ This provides an enhanced experience by rendering markdown in real-time as content arrives, offering both the benefits of streaming and formatted output simultaneously. This feature uses Rich for live updates and beautiful formatting.
190
+
191
+ You can also combine this with code generation:
192
+
193
+ ```bash
194
+ ngpt -c --stream-prettify "write a function to implement merge sort in Python"
195
+ ```
196
+
197
+ This is particularly useful for longer code generation tasks, as you can see the code being formatted with syntax highlighting in real-time.
198
+
199
+ Notes on `--stream-prettify`:
200
+ - Requires Rich to be installed (`pip install "ngpt[full]"` or `pip install rich`)
201
+ - Only works with the Rich renderer (even if you specify another renderer)
202
+ - Works in both regular and interactive modes
203
+ - Creates a more dynamic and responsive UI experience
204
+
180
205
  See available renderers on your system:
181
206
 
182
207
  ```bash
@@ -294,11 +319,17 @@ ngpt -i --preprompt "You are a data science tutor" --log datasci_tutoring.txt
294
319
  # Generate code with syntax highlighting
295
320
  ngpt -c --prettify "create a sorting algorithm"
296
321
 
322
+ # Generate code with real-time syntax highlighting
323
+ ngpt -c --stream-prettify "implement a binary search tree in JavaScript"
324
+
297
325
  # Render markdown with web search for up-to-date information
298
326
  ngpt --prettify --web-search "Create a markdown table of recent SpaceX launches"
299
327
 
300
328
  # Interactive session with markdown rendering
301
329
  ngpt -i --prettify --renderer=rich
330
+
331
+ # Interactive session with real-time markdown rendering
332
+ ngpt -i --stream-prettify
302
333
  ```
303
334
 
304
335
  ### Using a Custom Configuration File
@@ -115,10 +115,11 @@ def show_available_renderers():
115
115
  if HAS_RICH:
116
116
  print(f" {COLORS['green']}✓ Rich{COLORS['reset']} - Python library for terminal formatting (Recommended)")
117
117
  else:
118
- print(f" {COLORS['yellow']}✗ Rich{COLORS['reset']} - Not installed (pip install rich)")
118
+ print(f" {COLORS['yellow']}✗ Rich{COLORS['reset']} - Not installed (pip install \"ngpt[full]\" or pip install rich)")
119
119
 
120
120
  if not HAS_GLOW and not HAS_RICH:
121
121
  print(f"\n{COLORS['yellow']}To enable prettified markdown output, install one of the above renderers.{COLORS['reset']}")
122
+ print(f"{COLORS['yellow']}For Rich: pip install \"ngpt[full]\" or pip install rich{COLORS['reset']}")
122
123
  else:
123
124
  renderers = []
124
125
  if HAS_RICH:
@@ -148,11 +149,11 @@ def warn_if_no_markdown_renderer(renderer='auto'):
148
149
 
149
150
  if renderer == 'auto':
150
151
  print(f"{COLORS['yellow']}Warning: No markdown rendering library available.{COLORS['reset']}")
151
- print(f"{COLORS['yellow']}Install 'rich' package with: pip install rich{COLORS['reset']}")
152
+ print(f"{COLORS['yellow']}Install with: pip install \"ngpt[full]\"{COLORS['reset']}")
152
153
  print(f"{COLORS['yellow']}Or install 'glow' from https://github.com/charmbracelet/glow{COLORS['reset']}")
153
154
  elif renderer == 'rich':
154
155
  print(f"{COLORS['yellow']}Warning: Rich is not available.{COLORS['reset']}")
155
- print(f"{COLORS['yellow']}Install with: pip install rich{COLORS['reset']}")
156
+ print(f"{COLORS['yellow']}Install with: pip install \"ngpt[full]\" or pip install rich{COLORS['reset']}")
156
157
  elif renderer == 'glow':
157
158
  print(f"{COLORS['yellow']}Warning: Glow is not available.{COLORS['reset']}")
158
159
  print(f"{COLORS['yellow']}Install from https://github.com/charmbracelet/glow{COLORS['reset']}")
@@ -219,7 +220,8 @@ def prettify_markdown(text, renderer='auto'):
219
220
  # Use rich for rendering
220
221
  elif renderer == 'rich':
221
222
  if not HAS_RICH:
222
- print(f"{COLORS['yellow']}Warning: Rich is not available. Install with: pip install rich{COLORS['reset']}")
223
+ print(f"{COLORS['yellow']}Warning: Rich is not available.{COLORS['reset']}")
224
+ print(f"{COLORS['yellow']}Install with: pip install \"ngpt[full]\" or pip install rich{COLORS['reset']}")
223
225
  # Fall back to glow if available
224
226
  if HAS_GLOW:
225
227
  print(f"{COLORS['yellow']}Falling back to Glow renderer.{COLORS['reset']}")
@@ -505,8 +507,22 @@ def check_config(config):
505
507
 
506
508
  return True
507
509
 
508
- def interactive_chat_session(client, web_search=False, no_stream=False, temperature=0.7, top_p=1.0, max_tokens=None, log_file=None, preprompt=None, prettify=False, renderer='auto'):
509
- """Run an interactive chat session with conversation history."""
510
+ def interactive_chat_session(client, web_search=False, no_stream=False, temperature=0.7, top_p=1.0, max_tokens=None, log_file=None, preprompt=None, prettify=False, renderer='auto', stream_prettify=False):
511
+ """Start an interactive chat session with the AI.
512
+
513
+ Args:
514
+ client: The NGPTClient instance
515
+ web_search: Whether to enable web search capability
516
+ no_stream: Whether to disable streaming
517
+ temperature: Controls randomness in the response
518
+ top_p: Controls diversity via nucleus sampling
519
+ max_tokens: Maximum number of tokens to generate in each response
520
+ log_file: Optional filepath to log conversation to
521
+ preprompt: Custom system prompt to control AI behavior
522
+ prettify: Whether to enable markdown rendering
523
+ renderer: Which markdown renderer to use
524
+ stream_prettify: Whether to enable streaming with prettify
525
+ """
510
526
  # Get terminal width for better formatting
511
527
  try:
512
528
  term_width = shutil.get_terminal_size().columns
@@ -668,18 +684,38 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
668
684
  log_handle.flush()
669
685
 
670
686
  # Print assistant indicator with formatting
671
- if not no_stream:
687
+ if not no_stream and not stream_prettify:
672
688
  print(f"\n{ngpt_header()}: {COLORS['reset']}", end="", flush=True)
673
- else:
689
+ elif not stream_prettify:
674
690
  print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
675
691
 
676
- # If prettify is enabled, we need to disable streaming to collect the full response
677
- should_stream = not no_stream and not prettify
678
-
679
- # If prettify is enabled with streaming, inform the user
680
- if prettify and not no_stream:
692
+ # If prettify is enabled with regular streaming
693
+ if prettify and not no_stream and not stream_prettify:
681
694
  print(f"\n{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
682
695
  print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
696
+ should_stream = False
697
+ else:
698
+ # Regular behavior with stream-prettify taking precedence
699
+ should_stream = not no_stream
700
+
701
+ # Setup for stream-prettify
702
+ stream_callback = None
703
+ live_display = None
704
+
705
+ if stream_prettify and should_stream:
706
+ # Get the correct header for interactive mode
707
+ header = ngpt_header()
708
+ live_display, stream_callback = prettify_streaming_markdown(renderer, is_interactive=True, header_text=header)
709
+ if not live_display:
710
+ # Fallback to normal prettify if live display setup failed
711
+ prettify = True
712
+ stream_prettify = False
713
+ should_stream = False
714
+ print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
715
+
716
+ # Start live display if using stream-prettify
717
+ if stream_prettify and live_display:
718
+ live_display.start()
683
719
 
684
720
  # Get AI response with conversation history
685
721
  response = client.chat(
@@ -690,9 +726,14 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
690
726
  temperature=temperature,
691
727
  top_p=top_p,
692
728
  max_tokens=max_tokens,
693
- markdown_format=prettify
729
+ markdown_format=prettify or stream_prettify,
730
+ stream_callback=stream_callback
694
731
  )
695
732
 
733
+ # Stop live display if using stream-prettify
734
+ if stream_prettify and live_display:
735
+ live_display.stop()
736
+
696
737
  # Add AI response to conversation history
697
738
  if response:
698
739
  assistant_message = {"role": "assistant", "content": response}
@@ -726,6 +767,83 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
726
767
  log_handle.write(f"\n--- End of Session ---\n")
727
768
  log_handle.close()
728
769
 
770
+ def prettify_streaming_markdown(renderer='rich', is_interactive=False, header_text=None):
771
+ """Set up streaming markdown rendering.
772
+
773
+ This function creates a live display context for rendering markdown
774
+ that can be updated in real-time as streaming content arrives.
775
+
776
+ Args:
777
+ renderer (str): Which renderer to use (currently only 'rich' is supported for streaming)
778
+ is_interactive (bool): Whether this is being used in interactive mode
779
+ header_text (str): Header text to include at the top (for interactive mode)
780
+
781
+ Returns:
782
+ tuple: (live_display, update_function) if successful, (None, None) otherwise
783
+ """
784
+ # Only warn if explicitly specifying a renderer other than 'rich' or 'auto'
785
+ if renderer != 'rich' and renderer != 'auto':
786
+ print(f"{COLORS['yellow']}Warning: Streaming prettify only supports 'rich' renderer currently.{COLORS['reset']}")
787
+ print(f"{COLORS['yellow']}Falling back to Rich renderer.{COLORS['reset']}")
788
+
789
+ # Always use rich for streaming prettify
790
+ renderer = 'rich'
791
+
792
+ if not HAS_RICH:
793
+ print(f"{COLORS['yellow']}Warning: Rich is not available for streaming prettify.{COLORS['reset']}")
794
+ print(f"{COLORS['yellow']}Install with: pip install \"ngpt[full]\" or pip install rich{COLORS['reset']}")
795
+ return None, None
796
+
797
+ try:
798
+ from rich.live import Live
799
+ from rich.markdown import Markdown
800
+ from rich.console import Console
801
+ from rich.text import Text
802
+ from rich.panel import Panel
803
+ import rich.box
804
+
805
+ console = Console()
806
+
807
+ # Create an empty markdown object to start with
808
+ if is_interactive and header_text:
809
+ # For interactive mode, include header in a panel
810
+ # Clean up the header text to avoid duplication - use just "🤖 nGPT" instead of "╭─ 🤖 nGPT"
811
+ clean_header = "🤖 nGPT"
812
+ panel_title = Text(clean_header, style="cyan bold")
813
+
814
+ # Create a nicer, more compact panel
815
+ padding = (1, 1) # Less horizontal padding (left, right)
816
+ md_obj = Panel(
817
+ Markdown(""),
818
+ title=panel_title,
819
+ title_align="left",
820
+ border_style="cyan",
821
+ padding=padding,
822
+ width=console.width - 4, # Make panel slightly narrower than console
823
+ box=rich.box.ROUNDED
824
+ )
825
+ else:
826
+ md_obj = Markdown("")
827
+
828
+ # Initialize the Live display with an empty markdown
829
+ live = Live(md_obj, console=console, refresh_per_second=10)
830
+
831
+ # Define an update function that will be called with new content
832
+ def update_content(content):
833
+ nonlocal md_obj
834
+ if is_interactive and header_text:
835
+ # Update the panel content
836
+ md_obj.renderable = Markdown(content)
837
+ live.update(md_obj)
838
+ else:
839
+ md_obj = Markdown(content)
840
+ live.update(md_obj)
841
+
842
+ return live, update_content
843
+ except Exception as e:
844
+ print(f"{COLORS['yellow']}Error setting up Rich streaming display: {str(e)}{COLORS['reset']}")
845
+ return None, None
846
+
729
847
  def main():
730
848
  # Colorize description - use a shorter description to avoid line wrapping issues
731
849
  description = f"{COLORS['cyan']}{COLORS['bold']}nGPT{COLORS['reset']} - Interact with AI language models via OpenAI-compatible APIs"
@@ -783,6 +901,8 @@ def main():
783
901
  help='Set custom system prompt to control AI behavior')
784
902
  global_group.add_argument('--prettify', action='store_const', const='auto',
785
903
  help='Render markdown responses and code with syntax highlighting and formatting')
904
+ global_group.add_argument('--stream-prettify', action='store_true',
905
+ help='Enable streaming with markdown rendering (automatically uses Rich renderer)')
786
906
  global_group.add_argument('--renderer', choices=['auto', 'rich', 'glow'], default='auto',
787
907
  help='Select which markdown renderer to use with --prettify (auto, rich, or glow)')
788
908
 
@@ -1022,6 +1142,14 @@ def main():
1022
1142
  show_available_renderers()
1023
1143
  args.prettify = False
1024
1144
 
1145
+ # Check if --prettify is used with --stream-prettify (conflict)
1146
+ if args.prettify and args.stream_prettify:
1147
+ parser.error("--prettify and --stream-prettify cannot be used together. Choose one option.")
1148
+
1149
+ # Check if --stream-prettify is used but Rich is not available
1150
+ if args.stream_prettify and not has_markdown_renderer('rich'):
1151
+ parser.error("--stream-prettify requires Rich to be installed. Install with: pip install \"ngpt[full]\" or pip install rich")
1152
+
1025
1153
  # Initialize client using the potentially overridden active_config
1026
1154
  client = NGPTClient(**active_config)
1027
1155
 
@@ -1046,9 +1174,19 @@ def main():
1046
1174
  # Handle modes
1047
1175
  if args.interactive:
1048
1176
  # Interactive chat mode
1049
- interactive_chat_session(client, web_search=args.web_search, no_stream=args.no_stream,
1050
- temperature=args.temperature, top_p=args.top_p,
1051
- max_tokens=args.max_tokens, log_file=args.log, preprompt=args.preprompt, prettify=args.prettify, renderer=args.renderer)
1177
+ interactive_chat_session(
1178
+ client,
1179
+ web_search=args.web_search,
1180
+ no_stream=args.no_stream,
1181
+ temperature=args.temperature,
1182
+ top_p=args.top_p,
1183
+ max_tokens=args.max_tokens,
1184
+ log_file=args.log,
1185
+ preprompt=args.preprompt,
1186
+ prettify=args.prettify,
1187
+ renderer=args.renderer,
1188
+ stream_prettify=args.stream_prettify
1189
+ )
1052
1190
  elif args.shell:
1053
1191
  if args.prompt is None:
1054
1192
  try:
@@ -1097,12 +1235,50 @@ def main():
1097
1235
  sys.exit(130)
1098
1236
  else:
1099
1237
  prompt = args.prompt
1238
+
1239
+ # Setup for stream-prettify with code generation
1240
+ stream_callback = None
1241
+ live_display = None
1242
+ should_stream = False
1243
+
1244
+ if args.stream_prettify:
1245
+ should_stream = True # Enable streaming
1246
+ # This is the code generation mode, not interactive
1247
+ live_display, stream_callback = prettify_streaming_markdown(args.renderer)
1248
+ if not live_display:
1249
+ # Fallback to normal prettify if live display setup failed
1250
+ args.prettify = True
1251
+ args.stream_prettify = False
1252
+ should_stream = False
1253
+ print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
1254
+
1255
+ # If regular prettify is enabled with streaming, inform the user
1256
+ if args.prettify and not args.no_stream:
1257
+ print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
1258
+
1259
+ print("\nGenerating code...")
1260
+
1261
+ # Start live display if using stream-prettify
1262
+ if args.stream_prettify and live_display:
1263
+ live_display.start()
1264
+
1265
+ generated_code = client.generate_code(
1266
+ prompt=prompt,
1267
+ language=args.language,
1268
+ web_search=args.web_search,
1269
+ temperature=args.temperature,
1270
+ top_p=args.top_p,
1271
+ max_tokens=args.max_tokens,
1272
+ markdown_format=args.prettify or args.stream_prettify,
1273
+ stream=should_stream,
1274
+ stream_callback=stream_callback
1275
+ )
1276
+
1277
+ # Stop live display if using stream-prettify
1278
+ if args.stream_prettify and live_display:
1279
+ live_display.stop()
1100
1280
 
1101
- generated_code = client.generate_code(prompt, args.language, web_search=args.web_search,
1102
- temperature=args.temperature, top_p=args.top_p,
1103
- max_tokens=args.max_tokens,
1104
- markdown_format=args.prettify)
1105
- if generated_code:
1281
+ if generated_code and not args.stream_prettify:
1106
1282
  if args.prettify:
1107
1283
  print("\nGenerated code:")
1108
1284
  prettify_markdown(generated_code, args.renderer)
@@ -1226,25 +1402,46 @@ def main():
1226
1402
  {"role": "user", "content": prompt}
1227
1403
  ]
1228
1404
 
1229
- # If prettify is enabled, we need to disable streaming to collect the full response
1230
- should_stream = not args.no_stream and not args.prettify
1405
+ # If stream-prettify is enabled
1406
+ stream_callback = None
1407
+ live_display = None
1231
1408
 
1232
- # If prettify is enabled with streaming, inform the user
1409
+ if args.stream_prettify:
1410
+ should_stream = True # Enable streaming
1411
+ # This is the standard mode, not interactive
1412
+ live_display, stream_callback = prettify_streaming_markdown(args.renderer)
1413
+ if not live_display:
1414
+ # Fallback to normal prettify if live display setup failed
1415
+ args.prettify = True
1416
+ args.stream_prettify = False
1417
+ should_stream = False
1418
+ print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
1419
+
1420
+ # If regular prettify is enabled with streaming, inform the user
1233
1421
  if args.prettify and not args.no_stream:
1234
1422
  print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
1235
-
1423
+
1424
+ # Start live display if using stream-prettify
1425
+ if args.stream_prettify and live_display:
1426
+ live_display.start()
1427
+
1236
1428
  response = client.chat(prompt, stream=should_stream, web_search=args.web_search,
1237
1429
  temperature=args.temperature, top_p=args.top_p,
1238
1430
  max_tokens=args.max_tokens, messages=messages,
1239
- markdown_format=args.prettify)
1431
+ markdown_format=args.prettify or args.stream_prettify,
1432
+ stream_callback=stream_callback)
1240
1433
 
1241
- # Handle non-stream response (either because no_stream was set or prettify forced it)
1434
+ # Stop live display if using stream-prettify
1435
+ if args.stream_prettify and live_display:
1436
+ live_display.stop()
1437
+
1438
+ # Handle non-stream response or regular prettify
1242
1439
  if (args.no_stream or args.prettify) and response:
1243
1440
  if args.prettify:
1244
1441
  prettify_markdown(response, args.renderer)
1245
1442
  else:
1246
1443
  print(response)
1247
-
1444
+
1248
1445
  else:
1249
1446
  # Default to chat mode
1250
1447
  if args.prompt is None:
@@ -1265,19 +1462,40 @@ def main():
1265
1462
  {"role": "user", "content": prompt}
1266
1463
  ]
1267
1464
 
1268
- # If prettify is enabled, we need to disable streaming to collect the full response
1269
- should_stream = not args.no_stream and not args.prettify
1465
+ # If stream-prettify is enabled
1466
+ stream_callback = None
1467
+ live_display = None
1270
1468
 
1271
- # If prettify is enabled with streaming, inform the user
1469
+ if args.stream_prettify:
1470
+ should_stream = True # Enable streaming
1471
+ # This is the standard mode, not interactive
1472
+ live_display, stream_callback = prettify_streaming_markdown(args.renderer)
1473
+ if not live_display:
1474
+ # Fallback to normal prettify if live display setup failed
1475
+ args.prettify = True
1476
+ args.stream_prettify = False
1477
+ should_stream = False
1478
+ print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
1479
+
1480
+ # If regular prettify is enabled with streaming, inform the user
1272
1481
  if args.prettify and not args.no_stream:
1273
1482
  print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
1274
-
1483
+
1484
+ # Start live display if using stream-prettify
1485
+ if args.stream_prettify and live_display:
1486
+ live_display.start()
1487
+
1275
1488
  response = client.chat(prompt, stream=should_stream, web_search=args.web_search,
1276
1489
  temperature=args.temperature, top_p=args.top_p,
1277
1490
  max_tokens=args.max_tokens, messages=messages,
1278
- markdown_format=args.prettify)
1491
+ markdown_format=args.prettify or args.stream_prettify,
1492
+ stream_callback=stream_callback)
1279
1493
 
1280
- # Handle non-stream response (either because no_stream was set or prettify forced it)
1494
+ # Stop live display if using stream-prettify
1495
+ if args.stream_prettify and live_display:
1496
+ live_display.stop()
1497
+
1498
+ # Handle non-stream response or regular prettify
1281
1499
  if (args.no_stream or args.prettify) and response:
1282
1500
  if args.prettify:
1283
1501
  prettify_markdown(response, args.renderer)
@@ -34,6 +34,7 @@ class NGPTClient:
34
34
  messages: Optional[List[Dict[str, str]]] = None,
35
35
  web_search: bool = False,
36
36
  markdown_format: bool = False,
37
+ stream_callback: Optional[callable] = None,
37
38
  **kwargs
38
39
  ) -> str:
39
40
  """
@@ -48,6 +49,7 @@ class NGPTClient:
48
49
  messages: Optional list of message objects to override default behavior
49
50
  web_search: Whether to enable web search capability
50
51
  markdown_format: If True, allow markdown-formatted responses, otherwise plain text
52
+ stream_callback: Optional callback function for streaming mode updates
51
53
  **kwargs: Additional arguments to pass to the API
52
54
 
53
55
  Returns:
@@ -129,15 +131,23 @@ class NGPTClient:
129
131
  delta = chunk["choices"][0].get("delta", {})
130
132
  content = delta.get("content", "")
131
133
  if content:
132
- print(content, end="", flush=True)
133
- collected_content += content
134
+ if stream_callback:
135
+ # If we have a callback, use it and don't print here
136
+ collected_content += content
137
+ stream_callback(collected_content)
138
+ else:
139
+ # Default behavior: print to console
140
+ print(content, end="", flush=True)
141
+ collected_content += content
134
142
  except json.JSONDecodeError:
135
143
  pass # Skip invalid JSON
136
144
  except KeyboardInterrupt:
137
145
  print("\nGeneration cancelled by user.")
138
146
  return collected_content
139
147
 
140
- print() # Add a final newline
148
+ # Only print a newline if we're not using a callback
149
+ if not stream_callback:
150
+ print() # Add a final newline
141
151
  return collected_content
142
152
 
143
153
  except requests.exceptions.HTTPError as e:
@@ -248,7 +258,9 @@ Command:"""
248
258
  temperature: float = 0.4,
249
259
  top_p: float = 0.95,
250
260
  max_tokens: Optional[int] = None,
251
- markdown_format: bool = False
261
+ markdown_format: bool = False,
262
+ stream: bool = False,
263
+ stream_callback: Optional[callable] = None
252
264
  ) -> str:
253
265
  """
254
266
  Generate code based on the prompt.
@@ -261,6 +273,8 @@ Command:"""
261
273
  top_p: Controls diversity via nucleus sampling
262
274
  max_tokens: Maximum number of tokens to generate
263
275
  markdown_format: If True, request markdown-formatted code, otherwise plain text
276
+ stream: Whether to stream the response
277
+ stream_callback: Optional callback function for streaming mode updates
264
278
 
265
279
  Returns:
266
280
  The generated code
@@ -299,12 +313,13 @@ Code:"""
299
313
  try:
300
314
  return self.chat(
301
315
  prompt=prompt,
302
- stream=False,
316
+ stream=stream,
303
317
  messages=messages,
304
318
  web_search=web_search,
305
319
  temperature=temperature,
306
320
  top_p=top_p,
307
- max_tokens=max_tokens
321
+ max_tokens=max_tokens,
322
+ stream_callback=stream_callback
308
323
  )
309
324
  except Exception as e:
310
325
  print(f"Error generating code: {e}")
@@ -1,13 +1,12 @@
1
1
  [project]
2
2
  name = "ngpt"
3
- version = "2.5.1"
3
+ version = "2.7.1"
4
4
  description = "A lightweight Python CLI and library for interacting with OpenAI-compatible APIs, supporting both official and self-hosted LLM endpoints."
5
5
  authors = [
6
6
  {name = "nazDridoy", email = "nazdridoy399@gmail.com"},
7
7
  ]
8
8
  dependencies = [
9
9
  "requests>=2.31.0",
10
- "prompt_toolkit>=3.0.0",
11
10
  ]
12
11
  requires-python = ">=3.8"
13
12
  readme = "README.md"
@@ -35,8 +34,9 @@ classifiers = [
35
34
  ]
36
35
 
37
36
  [project.optional-dependencies]
38
- prettify = [
37
+ full = [
39
38
  "rich>=10.0.0",
39
+ "prompt_toolkit>=3.0.0",
40
40
  ]
41
41
 
42
42
  [project.urls]
@@ -134,25 +134,25 @@ wheels = [
134
134
 
135
135
  [[package]]
136
136
  name = "ngpt"
137
- version = "2.5.1"
137
+ version = "2.7.1"
138
138
  source = { editable = "." }
139
139
  dependencies = [
140
- { name = "prompt-toolkit" },
141
140
  { name = "requests" },
142
141
  ]
143
142
 
144
143
  [package.optional-dependencies]
145
- prettify = [
144
+ full = [
145
+ { name = "prompt-toolkit" },
146
146
  { name = "rich" },
147
147
  ]
148
148
 
149
149
  [package.metadata]
150
150
  requires-dist = [
151
- { name = "prompt-toolkit", specifier = ">=3.0.0" },
151
+ { name = "prompt-toolkit", marker = "extra == 'full'", specifier = ">=3.0.0" },
152
152
  { name = "requests", specifier = ">=2.31.0" },
153
- { name = "rich", marker = "extra == 'prettify'", specifier = ">=10.0.0" },
153
+ { name = "rich", marker = "extra == 'full'", specifier = ">=10.0.0" },
154
154
  ]
155
- provides-extras = ["prettify"]
155
+ provides-extras = ["full"]
156
156
 
157
157
  [[package]]
158
158
  name = "prompt-toolkit"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes