ngpt 2.4.0__tar.gz → 2.5.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.
- {ngpt-2.4.0 → ngpt-2.5.1}/PKG-INFO +16 -1
- {ngpt-2.4.0 → ngpt-2.5.1}/README.md +13 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/api/client.md +49 -24
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/installation.md +16 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/overview.md +2 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/usage/cli_usage.md +51 -2
- {ngpt-2.4.0 → ngpt-2.5.1}/ngpt/cli.py +262 -17
- {ngpt-2.4.0 → ngpt-2.5.1}/ngpt/client.py +22 -3
- {ngpt-2.4.0 → ngpt-2.5.1}/pyproject.toml +6 -1
- {ngpt-2.4.0 → ngpt-2.5.1}/uv.lock +61 -1
- {ngpt-2.4.0 → ngpt-2.5.1}/.github/workflows/python-publish.yml +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/.gitignore +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/.python-version +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/COMMIT_GUIDELINES.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/CONTRIBUTING.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/LICENSE +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/CONTRIBUTING.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/LICENSE.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/README.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/_config.yml +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/api/README.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/api/config.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/assets/css/style.scss +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/configuration.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/examples/README.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/examples/advanced.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/examples/basic.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/examples/integrations.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/usage/README.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/docs/usage/library_usage.md +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/ngpt/__init__.py +0 -0
- {ngpt-2.4.0 → ngpt-2.5.1}/ngpt/config.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ngpt
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.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
|
@@ -30,6 +30,8 @@ Classifier: Topic :: Utilities
|
|
30
30
|
Requires-Python: >=3.8
|
31
31
|
Requires-Dist: prompt-toolkit>=3.0.0
|
32
32
|
Requires-Dist: requests>=2.31.0
|
33
|
+
Provides-Extra: prettify
|
34
|
+
Requires-Dist: rich>=10.0.0; extra == 'prettify'
|
33
35
|
Description-Content-Type: text/markdown
|
34
36
|
|
35
37
|
# nGPT
|
@@ -76,9 +78,18 @@ ngpt -n "Tell me about quantum computing"
|
|
76
78
|
# Generate code
|
77
79
|
ngpt --code "function to calculate the Fibonacci sequence"
|
78
80
|
|
81
|
+
# Generate code with syntax highlighting
|
82
|
+
ngpt --code --prettify "function to calculate the Fibonacci sequence"
|
83
|
+
|
79
84
|
# Generate and execute shell commands
|
80
85
|
ngpt --shell "list all files in the current directory"
|
81
86
|
|
87
|
+
# Display markdown responses with beautiful formatting
|
88
|
+
ngpt --prettify "Explain markdown syntax with examples"
|
89
|
+
|
90
|
+
# Use a specific markdown renderer
|
91
|
+
ngpt --prettify --renderer=rich "Create a markdown table"
|
92
|
+
|
82
93
|
# Use multiline editor for complex prompts
|
83
94
|
ngpt --text
|
84
95
|
|
@@ -99,6 +110,7 @@ For more examples and detailed usage, visit the [CLI Usage Guide](https://nazdri
|
|
99
110
|
- 💬 **Interactive Chat**: Continuous conversation with memory in modern UI
|
100
111
|
- 📊 **Streaming Responses**: Real-time output for better user experience
|
101
112
|
- 🔍 **Web Search**: Integrated with compatible API endpoints
|
113
|
+
- 🎨 **Markdown Rendering**: Beautiful formatting of markdown and code with syntax highlighting
|
102
114
|
- ⚙️ **Multiple Configurations**: Cross-platform config system supporting different profiles
|
103
115
|
- 💻 **Shell Command Generation**: OS-aware command execution
|
104
116
|
- 🧩 **Clean Code Generation**: Output code without markdown or explanations
|
@@ -267,6 +279,9 @@ You can configure the client using the following options:
|
|
267
279
|
| `--max_tokens` | Set maximum response length in tokens |
|
268
280
|
| `--preprompt` | Set custom system prompt to control AI behavior |
|
269
281
|
| `--log` | Set filepath to log conversation to (for interactive modes) |
|
282
|
+
| `--prettify` | Render markdown responses and code with syntax highlighting |
|
283
|
+
| `--renderer` | Select which markdown renderer to use with --prettify (auto, rich, or glow) |
|
284
|
+
| `--list-renderers` | Show available markdown renderers for use with --prettify |
|
270
285
|
| `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
|
271
286
|
| `--config-index` | Index of the configuration to use (default: 0) |
|
272
287
|
| `--provider` | Provider name to identify the configuration to use (alternative to --config-index) |
|
@@ -42,9 +42,18 @@ ngpt -n "Tell me about quantum computing"
|
|
42
42
|
# Generate code
|
43
43
|
ngpt --code "function to calculate the Fibonacci sequence"
|
44
44
|
|
45
|
+
# Generate code with syntax highlighting
|
46
|
+
ngpt --code --prettify "function to calculate the Fibonacci sequence"
|
47
|
+
|
45
48
|
# Generate and execute shell commands
|
46
49
|
ngpt --shell "list all files in the current directory"
|
47
50
|
|
51
|
+
# Display markdown responses with beautiful formatting
|
52
|
+
ngpt --prettify "Explain markdown syntax with examples"
|
53
|
+
|
54
|
+
# Use a specific markdown renderer
|
55
|
+
ngpt --prettify --renderer=rich "Create a markdown table"
|
56
|
+
|
48
57
|
# Use multiline editor for complex prompts
|
49
58
|
ngpt --text
|
50
59
|
|
@@ -65,6 +74,7 @@ For more examples and detailed usage, visit the [CLI Usage Guide](https://nazdri
|
|
65
74
|
- 💬 **Interactive Chat**: Continuous conversation with memory in modern UI
|
66
75
|
- 📊 **Streaming Responses**: Real-time output for better user experience
|
67
76
|
- 🔍 **Web Search**: Integrated with compatible API endpoints
|
77
|
+
- 🎨 **Markdown Rendering**: Beautiful formatting of markdown and code with syntax highlighting
|
68
78
|
- ⚙️ **Multiple Configurations**: Cross-platform config system supporting different profiles
|
69
79
|
- 💻 **Shell Command Generation**: OS-aware command execution
|
70
80
|
- 🧩 **Clean Code Generation**: Output code without markdown or explanations
|
@@ -233,6 +243,9 @@ You can configure the client using the following options:
|
|
233
243
|
| `--max_tokens` | Set maximum response length in tokens |
|
234
244
|
| `--preprompt` | Set custom system prompt to control AI behavior |
|
235
245
|
| `--log` | Set filepath to log conversation to (for interactive modes) |
|
246
|
+
| `--prettify` | Render markdown responses and code with syntax highlighting |
|
247
|
+
| `--renderer` | Select which markdown renderer to use with --prettify (auto, rich, or glow) |
|
248
|
+
| `--list-renderers` | Show available markdown renderers for use with --prettify |
|
236
249
|
| `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
|
237
250
|
| `--config-index` | Index of the configuration to use (default: 0) |
|
238
251
|
| `--provider` | Provider name to identify the configuration to use (alternative to --config-index) |
|
@@ -49,7 +49,7 @@ client = NGPTClient(
|
|
49
49
|
|
50
50
|
## Chat Method
|
51
51
|
|
52
|
-
The
|
52
|
+
The main method for interacting with the AI model.
|
53
53
|
|
54
54
|
```python
|
55
55
|
response = client.chat(
|
@@ -57,8 +57,10 @@ response = client.chat(
|
|
57
57
|
stream: bool = True,
|
58
58
|
temperature: float = 0.7,
|
59
59
|
max_tokens: Optional[int] = None,
|
60
|
+
top_p: float = 1.0,
|
60
61
|
messages: Optional[List[Dict[str, str]]] = None,
|
61
62
|
web_search: bool = False,
|
63
|
+
markdown_format: bool = False,
|
62
64
|
**kwargs
|
63
65
|
) -> str
|
64
66
|
```
|
@@ -69,49 +71,55 @@ response = client.chat(
|
|
69
71
|
|-----------|------|---------|-------------|
|
70
72
|
| `prompt` | `str` | Required | The user's message |
|
71
73
|
| `stream` | `bool` | `True` | Whether to stream the response |
|
72
|
-
| `temperature` | `float` | `0.7` | Controls randomness in the response
|
74
|
+
| `temperature` | `float` | `0.7` | Controls randomness in the response |
|
73
75
|
| `max_tokens` | `Optional[int]` | `None` | Maximum number of tokens to generate |
|
74
|
-
| `
|
76
|
+
| `top_p` | `float` | `1.0` | Controls diversity via nucleus sampling |
|
77
|
+
| `messages` | `Optional[List[Dict[str, str]]]` | `None` | Optional list of message objects to override default behavior |
|
75
78
|
| `web_search` | `bool` | `False` | Whether to enable web search capability |
|
76
|
-
|
|
79
|
+
| `markdown_format` | `bool` | `False` | If True, allows markdown formatting in responses |
|
80
|
+
| `**kwargs` | `Any` | `{}` | Additional arguments to pass to the API |
|
77
81
|
|
78
82
|
### Returns
|
79
83
|
|
80
|
-
|
81
|
-
|
84
|
+
If `stream=True`, returns chunks of the response as they are generated.
|
85
|
+
If `stream=False`, returns the complete response as a string.
|
82
86
|
|
83
87
|
### Examples
|
84
88
|
|
85
89
|
```python
|
86
|
-
# Basic
|
87
|
-
|
88
|
-
|
89
|
-
print() # Final newline
|
90
|
+
# Basic usage
|
91
|
+
response = client.chat("Tell me about quantum computing")
|
92
|
+
print(response)
|
90
93
|
|
91
94
|
# Without streaming
|
92
95
|
response = client.chat("Tell me about quantum computing", stream=False)
|
93
96
|
print(response)
|
94
97
|
|
98
|
+
# With custom temperature (higher = more creative, lower = more deterministic)
|
99
|
+
response = client.chat("Write a poem about nature", temperature=0.9)
|
100
|
+
print(response)
|
101
|
+
|
102
|
+
# With token limit
|
103
|
+
response = client.chat("Explain the history of AI", max_tokens=100)
|
104
|
+
print(response)
|
105
|
+
|
95
106
|
# With conversation history
|
96
107
|
messages = [
|
97
108
|
{"role": "system", "content": "You are a helpful assistant."},
|
98
109
|
{"role": "user", "content": "Hello, who are you?"},
|
99
|
-
{"role": "assistant", "content": "I'm an AI assistant
|
100
|
-
{"role": "user", "content": "Tell me about yourself"}
|
110
|
+
{"role": "assistant", "content": "I'm an AI assistant created to help answer questions and provide information."},
|
111
|
+
{"role": "user", "content": "Tell me more about yourself"}
|
101
112
|
]
|
102
113
|
response = client.chat("", messages=messages)
|
103
114
|
print(response)
|
104
115
|
|
105
|
-
#
|
106
|
-
response = client.chat("What
|
116
|
+
# Enable web search capability (if API supports it)
|
117
|
+
response = client.chat("What are the latest developments in quantum computing?", web_search=True)
|
107
118
|
print(response)
|
108
119
|
|
109
|
-
#
|
110
|
-
response = client.chat("
|
111
|
-
response
|
112
|
-
|
113
|
-
# With token limit
|
114
|
-
response = client.chat("Summarize this concept", max_tokens=100)
|
120
|
+
# Enable markdown formatting for rich text responses
|
121
|
+
response = client.chat("Create a table comparing programming languages", markdown_format=True)
|
122
|
+
print(response) # Response will contain markdown formatting like tables, code blocks, etc.
|
115
123
|
```
|
116
124
|
|
117
125
|
## Generate Shell Command
|
@@ -157,13 +165,17 @@ command = client.generate_shell_command(
|
|
157
165
|
|
158
166
|
## Generate Code
|
159
167
|
|
160
|
-
Generates
|
168
|
+
Generates code based on the prompt.
|
161
169
|
|
162
170
|
```python
|
163
171
|
code = client.generate_code(
|
164
172
|
prompt: str,
|
165
173
|
language: str = "python",
|
166
|
-
web_search: bool = False
|
174
|
+
web_search: bool = False,
|
175
|
+
temperature: float = 0.4,
|
176
|
+
top_p: float = 0.95,
|
177
|
+
max_tokens: Optional[int] = None,
|
178
|
+
markdown_format: bool = False
|
167
179
|
) -> str
|
168
180
|
```
|
169
181
|
|
@@ -174,15 +186,19 @@ code = client.generate_code(
|
|
174
186
|
| `prompt` | `str` | Required | Description of the code to generate |
|
175
187
|
| `language` | `str` | `"python"` | Programming language to generate code in |
|
176
188
|
| `web_search` | `bool` | `False` | Whether to enable web search capability |
|
189
|
+
| `temperature` | `float` | `0.4` | Controls randomness in the response |
|
190
|
+
| `top_p` | `float` | `0.95` | Controls diversity via nucleus sampling |
|
191
|
+
| `max_tokens` | `Optional[int]` | `None` | Maximum number of tokens to generate |
|
192
|
+
| `markdown_format` | `bool` | `False` | If True, returns code with markdown formatting including syntax highlighting |
|
177
193
|
|
178
194
|
### Returns
|
179
195
|
|
180
|
-
A string containing the generated code
|
196
|
+
A string containing the generated code. If `markdown_format` is `False`, returns plain text code. If `markdown_format` is `True`, returns code formatted in markdown with appropriate syntax highlighting.
|
181
197
|
|
182
198
|
### Examples
|
183
199
|
|
184
200
|
```python
|
185
|
-
# Generate Python code (default)
|
201
|
+
# Generate Python code (default, plain text)
|
186
202
|
python_code = client.generate_code("function to calculate fibonacci numbers")
|
187
203
|
print(python_code)
|
188
204
|
|
@@ -193,6 +209,15 @@ js_code = client.generate_code(
|
|
193
209
|
)
|
194
210
|
print(js_code)
|
195
211
|
|
212
|
+
# Generate code with markdown formatting for documentation or display
|
213
|
+
markdown_code = client.generate_code(
|
214
|
+
"class that implements a binary search tree",
|
215
|
+
language="python",
|
216
|
+
markdown_format=True
|
217
|
+
)
|
218
|
+
# This will output code wrapped in markdown code blocks with syntax highlighting
|
219
|
+
print(markdown_code)
|
220
|
+
|
196
221
|
# Generate code with web search for latest best practices
|
197
222
|
react_code = client.generate_code(
|
198
223
|
"create a React component that fetches and displays data from an API",
|
@@ -8,6 +8,10 @@ There are several ways to install nGPT depending on your needs and environment.
|
|
8
8
|
- `requests` library (automatically installed as a dependency)
|
9
9
|
- `prompt_toolkit` library (automatically installed as a dependency)
|
10
10
|
|
11
|
+
## Optional Dependencies
|
12
|
+
|
13
|
+
- `rich` library - For enhanced markdown rendering with syntax highlighting
|
14
|
+
|
11
15
|
## Installing from PyPI (Recommended)
|
12
16
|
|
13
17
|
The simplest way to install nGPT is through the Python Package Index (PyPI):
|
@@ -18,6 +22,18 @@ pip install ngpt
|
|
18
22
|
|
19
23
|
This will install the latest stable release of nGPT and all its dependencies.
|
20
24
|
|
25
|
+
For markdown rendering capabilities, install with the prettify extra:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
pip install ngpt[prettify]
|
29
|
+
```
|
30
|
+
|
31
|
+
Alternatively, you can install the optional dependency separately:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
pip install rich
|
35
|
+
```
|
36
|
+
|
21
37
|
## Installing in a Virtual Environment
|
22
38
|
|
23
39
|
It's often good practice to install Python packages in a virtual environment to avoid conflicts:
|
@@ -18,6 +18,8 @@ nGPT is a lightweight Python library and command-line interface (CLI) tool desig
|
|
18
18
|
|
19
19
|
- **Web Search Integration**: Works with compatible API endpoints that support web search capabilities.
|
20
20
|
|
21
|
+
- **Markdown Rendering**: Beautiful formatting of markdown responses and syntax highlighting for code.
|
22
|
+
|
21
23
|
- **Multiple Configuration Support**: Maintain different API configurations for various services or models.
|
22
24
|
|
23
25
|
- **Shell Command Generation**: Generate OS-aware commands that work on your specific platform.
|
@@ -48,6 +48,9 @@ Here are the most commonly used options:
|
|
48
48
|
| `--temperature` | Set temperature (controls randomness, default: 0.7) |
|
49
49
|
| `--top_p` | Set top_p (controls diversity, default: 1.0) |
|
50
50
|
| `--max_tokens` | Set maximum response length in tokens |
|
51
|
+
| `--prettify` | Render markdown responses and code with syntax highlighting |
|
52
|
+
| `--renderer` | Select which markdown renderer to use (auto, rich, or glow) |
|
53
|
+
| `--list-renderers` | Show available markdown renderers on your system |
|
51
54
|
| `--config-index` | Index of the configuration to use (default: 0) |
|
52
55
|
| `--provider` | Provider name to identify the configuration to use (alternative to --config-index) |
|
53
56
|
|
@@ -140,6 +143,46 @@ This opens an editor where you can:
|
|
140
143
|
- Press Ctrl+D or F10 to submit the text
|
141
144
|
- Press Esc to cancel
|
142
145
|
|
146
|
+
### Markdown Rendering
|
147
|
+
|
148
|
+
Display markdown responses with beautiful formatting and syntax highlighting:
|
149
|
+
|
150
|
+
```bash
|
151
|
+
ngpt --prettify "Explain markdown syntax with examples"
|
152
|
+
```
|
153
|
+
|
154
|
+
This instructs the AI to generate properly formatted markdown responses, which are then rendered with appropriate formatting, including:
|
155
|
+
- Syntax highlighting for code blocks
|
156
|
+
- Proper rendering of tables
|
157
|
+
- Formatted headers, lists, and other markdown elements
|
158
|
+
|
159
|
+
You can specify which markdown renderer to use:
|
160
|
+
|
161
|
+
```bash
|
162
|
+
# Use Rich (Python library) renderer
|
163
|
+
ngpt --prettify --renderer=rich "Create a markdown table comparing programming languages"
|
164
|
+
|
165
|
+
# Use Glow (terminal-based) renderer
|
166
|
+
ngpt --prettify --renderer=glow "Write documentation with code examples"
|
167
|
+
|
168
|
+
# Use automatic selection (default is Rich if available)
|
169
|
+
ngpt --prettify --renderer=auto "Explain blockchain with code examples"
|
170
|
+
```
|
171
|
+
|
172
|
+
Combine with code generation for syntax-highlighted code:
|
173
|
+
|
174
|
+
```bash
|
175
|
+
ngpt -c --prettify "function to calculate the Fibonacci sequence"
|
176
|
+
```
|
177
|
+
|
178
|
+
When using `--prettify` with code generation, the AI will output code in markdown format with proper syntax highlighting based on the language.
|
179
|
+
|
180
|
+
See available renderers on your system:
|
181
|
+
|
182
|
+
```bash
|
183
|
+
ngpt --list-renderers
|
184
|
+
```
|
185
|
+
|
143
186
|
### Using Web Search
|
144
187
|
|
145
188
|
Enable web search capability (if your API endpoint supports it):
|
@@ -248,8 +291,14 @@ ngpt --model gpt-4o-mini -n "Explain quantum entanglement"
|
|
248
291
|
# Interactive session with custom prompt and logging
|
249
292
|
ngpt -i --preprompt "You are a data science tutor" --log datasci_tutoring.txt
|
250
293
|
|
251
|
-
#
|
252
|
-
ngpt --
|
294
|
+
# Generate code with syntax highlighting
|
295
|
+
ngpt -c --prettify "create a sorting algorithm"
|
296
|
+
|
297
|
+
# Render markdown with web search for up-to-date information
|
298
|
+
ngpt --prettify --web-search "Create a markdown table of recent SpaceX launches"
|
299
|
+
|
300
|
+
# Interactive session with markdown rendering
|
301
|
+
ngpt -i --prettify --renderer=rich
|
253
302
|
```
|
254
303
|
|
255
304
|
### Using a Custom Configuration File
|
@@ -5,6 +5,23 @@ 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
|
+
# Try to import markdown rendering libraries
|
9
|
+
try:
|
10
|
+
import rich
|
11
|
+
from rich.markdown import Markdown
|
12
|
+
from rich.console import Console
|
13
|
+
HAS_RICH = True
|
14
|
+
except ImportError:
|
15
|
+
HAS_RICH = False
|
16
|
+
|
17
|
+
# Try to import the glow command if available
|
18
|
+
def has_glow_installed():
|
19
|
+
"""Check if glow is installed in the system."""
|
20
|
+
import shutil
|
21
|
+
return shutil.which("glow") is not None
|
22
|
+
|
23
|
+
HAS_GLOW = has_glow_installed()
|
24
|
+
|
8
25
|
# ANSI color codes for terminal output
|
9
26
|
COLORS = {
|
10
27
|
"reset": "\033[0m",
|
@@ -68,6 +85,162 @@ if not HAS_COLOR:
|
|
68
85
|
for key in COLORS:
|
69
86
|
COLORS[key] = ""
|
70
87
|
|
88
|
+
def has_markdown_renderer(renderer='auto'):
|
89
|
+
"""Check if the specified markdown renderer is available.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
renderer (str): Which renderer to check: 'auto', 'rich', or 'glow'
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
bool: True if the renderer is available, False otherwise
|
96
|
+
"""
|
97
|
+
if renderer == 'auto':
|
98
|
+
return HAS_RICH or HAS_GLOW
|
99
|
+
elif renderer == 'rich':
|
100
|
+
return HAS_RICH
|
101
|
+
elif renderer == 'glow':
|
102
|
+
return HAS_GLOW
|
103
|
+
else:
|
104
|
+
return False
|
105
|
+
|
106
|
+
def show_available_renderers():
|
107
|
+
"""Show which markdown renderers are available and their status."""
|
108
|
+
print(f"\n{COLORS['cyan']}{COLORS['bold']}Available Markdown Renderers:{COLORS['reset']}")
|
109
|
+
|
110
|
+
if HAS_GLOW:
|
111
|
+
print(f" {COLORS['green']}✓ Glow{COLORS['reset']} - Terminal-based Markdown renderer")
|
112
|
+
else:
|
113
|
+
print(f" {COLORS['yellow']}✗ Glow{COLORS['reset']} - Not installed (https://github.com/charmbracelet/glow)")
|
114
|
+
|
115
|
+
if HAS_RICH:
|
116
|
+
print(f" {COLORS['green']}✓ Rich{COLORS['reset']} - Python library for terminal formatting (Recommended)")
|
117
|
+
else:
|
118
|
+
print(f" {COLORS['yellow']}✗ Rich{COLORS['reset']} - Not installed (pip install rich)")
|
119
|
+
|
120
|
+
if not HAS_GLOW and not HAS_RICH:
|
121
|
+
print(f"\n{COLORS['yellow']}To enable prettified markdown output, install one of the above renderers.{COLORS['reset']}")
|
122
|
+
else:
|
123
|
+
renderers = []
|
124
|
+
if HAS_RICH:
|
125
|
+
renderers.append("rich")
|
126
|
+
if HAS_GLOW:
|
127
|
+
renderers.append("glow")
|
128
|
+
print(f"\n{COLORS['green']}Usage examples:{COLORS['reset']}")
|
129
|
+
print(f" ngpt --prettify \"Your prompt here\" {COLORS['gray']}# Beautify markdown responses{COLORS['reset']}")
|
130
|
+
print(f" ngpt -c --prettify \"Write a sort function\" {COLORS['gray']}# Syntax highlight generated code{COLORS['reset']}")
|
131
|
+
if renderers:
|
132
|
+
renderer = renderers[0]
|
133
|
+
print(f" ngpt --prettify --renderer={renderer} \"Your prompt\" {COLORS['gray']}# Specify renderer{COLORS['reset']}")
|
134
|
+
|
135
|
+
print("")
|
136
|
+
|
137
|
+
def warn_if_no_markdown_renderer(renderer='auto'):
|
138
|
+
"""Warn the user if the specified markdown renderer is not available.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
renderer (str): Which renderer to check: 'auto', 'rich', or 'glow'
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
bool: True if the renderer is available, False otherwise
|
145
|
+
"""
|
146
|
+
if has_markdown_renderer(renderer):
|
147
|
+
return True
|
148
|
+
|
149
|
+
if renderer == 'auto':
|
150
|
+
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']}Or install 'glow' from https://github.com/charmbracelet/glow{COLORS['reset']}")
|
153
|
+
elif renderer == 'rich':
|
154
|
+
print(f"{COLORS['yellow']}Warning: Rich is not available.{COLORS['reset']}")
|
155
|
+
print(f"{COLORS['yellow']}Install with: pip install rich{COLORS['reset']}")
|
156
|
+
elif renderer == 'glow':
|
157
|
+
print(f"{COLORS['yellow']}Warning: Glow is not available.{COLORS['reset']}")
|
158
|
+
print(f"{COLORS['yellow']}Install from https://github.com/charmbracelet/glow{COLORS['reset']}")
|
159
|
+
else:
|
160
|
+
print(f"{COLORS['yellow']}Error: Invalid renderer '{renderer}'. Use 'auto', 'rich', or 'glow'.{COLORS['reset']}")
|
161
|
+
|
162
|
+
return False
|
163
|
+
|
164
|
+
def prettify_markdown(text, renderer='auto'):
|
165
|
+
"""Render markdown text with beautiful formatting using either Rich or Glow.
|
166
|
+
|
167
|
+
The function handles both general markdown and code blocks with syntax highlighting.
|
168
|
+
For code generation mode, it automatically wraps the code in markdown code blocks.
|
169
|
+
|
170
|
+
Args:
|
171
|
+
text (str): Markdown text to render
|
172
|
+
renderer (str): Which renderer to use: 'auto', 'rich', or 'glow'
|
173
|
+
|
174
|
+
Returns:
|
175
|
+
bool: True if rendering was successful, False otherwise
|
176
|
+
"""
|
177
|
+
# For 'auto', prefer rich if available, otherwise use glow
|
178
|
+
if renderer == 'auto':
|
179
|
+
if HAS_RICH:
|
180
|
+
return prettify_markdown(text, 'rich')
|
181
|
+
elif HAS_GLOW:
|
182
|
+
return prettify_markdown(text, 'glow')
|
183
|
+
else:
|
184
|
+
return False
|
185
|
+
|
186
|
+
# Use glow for rendering
|
187
|
+
elif renderer == 'glow':
|
188
|
+
if not HAS_GLOW:
|
189
|
+
print(f"{COLORS['yellow']}Warning: Glow is not available. Install from https://github.com/charmbracelet/glow{COLORS['reset']}")
|
190
|
+
# Fall back to rich if available
|
191
|
+
if HAS_RICH:
|
192
|
+
print(f"{COLORS['yellow']}Falling back to Rich renderer.{COLORS['reset']}")
|
193
|
+
return prettify_markdown(text, 'rich')
|
194
|
+
return False
|
195
|
+
|
196
|
+
# Use glow
|
197
|
+
import tempfile
|
198
|
+
import subprocess
|
199
|
+
|
200
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as temp:
|
201
|
+
temp_filename = temp.name
|
202
|
+
temp.write(text)
|
203
|
+
|
204
|
+
try:
|
205
|
+
# Execute glow on the temporary file
|
206
|
+
subprocess.run(["glow", temp_filename], check=True)
|
207
|
+
os.unlink(temp_filename)
|
208
|
+
return True
|
209
|
+
except Exception as e:
|
210
|
+
print(f"{COLORS['yellow']}Error using glow: {str(e)}{COLORS['reset']}")
|
211
|
+
os.unlink(temp_filename)
|
212
|
+
|
213
|
+
# Fall back to rich if available
|
214
|
+
if HAS_RICH:
|
215
|
+
print(f"{COLORS['yellow']}Falling back to Rich renderer.{COLORS['reset']}")
|
216
|
+
return prettify_markdown(text, 'rich')
|
217
|
+
return False
|
218
|
+
|
219
|
+
# Use rich for rendering
|
220
|
+
elif renderer == 'rich':
|
221
|
+
if not HAS_RICH:
|
222
|
+
print(f"{COLORS['yellow']}Warning: Rich is not available. Install with: pip install rich{COLORS['reset']}")
|
223
|
+
# Fall back to glow if available
|
224
|
+
if HAS_GLOW:
|
225
|
+
print(f"{COLORS['yellow']}Falling back to Glow renderer.{COLORS['reset']}")
|
226
|
+
return prettify_markdown(text, 'glow')
|
227
|
+
return False
|
228
|
+
|
229
|
+
# Use rich
|
230
|
+
try:
|
231
|
+
console = Console()
|
232
|
+
md = Markdown(text)
|
233
|
+
console.print(md)
|
234
|
+
return True
|
235
|
+
except Exception as e:
|
236
|
+
print(f"{COLORS['yellow']}Error using rich for markdown: {str(e)}{COLORS['reset']}")
|
237
|
+
return False
|
238
|
+
|
239
|
+
# Invalid renderer specified
|
240
|
+
else:
|
241
|
+
print(f"{COLORS['yellow']}Error: Invalid renderer '{renderer}'. Use 'auto', 'rich', or 'glow'.{COLORS['reset']}")
|
242
|
+
return False
|
243
|
+
|
71
244
|
# Custom help formatter with color support
|
72
245
|
class ColoredHelpFormatter(argparse.HelpFormatter):
|
73
246
|
"""Help formatter that properly handles ANSI color codes without breaking alignment."""
|
@@ -332,7 +505,7 @@ def check_config(config):
|
|
332
505
|
|
333
506
|
return True
|
334
507
|
|
335
|
-
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):
|
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'):
|
336
509
|
"""Run an interactive chat session with conversation history."""
|
337
510
|
# Get terminal width for better formatting
|
338
511
|
try:
|
@@ -380,6 +553,14 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
380
553
|
|
381
554
|
# Initialize conversation history
|
382
555
|
system_prompt = preprompt if preprompt else "You are a helpful assistant."
|
556
|
+
|
557
|
+
# Add markdown formatting instruction to system prompt if prettify is enabled
|
558
|
+
if prettify:
|
559
|
+
if system_prompt:
|
560
|
+
system_prompt += " You can use markdown formatting in your responses where appropriate."
|
561
|
+
else:
|
562
|
+
system_prompt = "You are a helpful assistant. You can use markdown formatting in your responses where appropriate."
|
563
|
+
|
383
564
|
conversation = []
|
384
565
|
system_message = {"role": "system", "content": system_prompt}
|
385
566
|
conversation.append(system_message)
|
@@ -492,15 +673,24 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
492
673
|
else:
|
493
674
|
print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
|
494
675
|
|
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:
|
681
|
+
print(f"\n{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
|
682
|
+
print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
|
683
|
+
|
495
684
|
# Get AI response with conversation history
|
496
685
|
response = client.chat(
|
497
686
|
prompt=user_input,
|
498
687
|
messages=conversation,
|
499
|
-
stream=
|
688
|
+
stream=should_stream,
|
500
689
|
web_search=web_search,
|
501
690
|
temperature=temperature,
|
502
691
|
top_p=top_p,
|
503
|
-
max_tokens=max_tokens
|
692
|
+
max_tokens=max_tokens,
|
693
|
+
markdown_format=prettify
|
504
694
|
)
|
505
695
|
|
506
696
|
# Add AI response to conversation history
|
@@ -508,9 +698,12 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
508
698
|
assistant_message = {"role": "assistant", "content": response}
|
509
699
|
conversation.append(assistant_message)
|
510
700
|
|
511
|
-
# Print response if not streamed
|
512
|
-
if no_stream:
|
513
|
-
|
701
|
+
# Print response if not streamed (either due to no_stream or prettify)
|
702
|
+
if no_stream or prettify:
|
703
|
+
if prettify:
|
704
|
+
prettify_markdown(response, renderer)
|
705
|
+
else:
|
706
|
+
print(response)
|
514
707
|
|
515
708
|
# Log assistant response if logging is enabled
|
516
709
|
if log_handle:
|
@@ -567,6 +760,7 @@ def main():
|
|
567
760
|
config_group.add_argument('--show-config', action='store_true', help='Show the current configuration(s) and exit')
|
568
761
|
config_group.add_argument('--all', action='store_true', help='Show details for all configurations (requires --show-config)')
|
569
762
|
config_group.add_argument('--list-models', action='store_true', help='List all available models for the current configuration and exit')
|
763
|
+
config_group.add_argument('--list-renderers', action='store_true', help='Show available markdown renderers for use with --prettify')
|
570
764
|
|
571
765
|
# Global options
|
572
766
|
global_group = parser.add_argument_group('Global Options')
|
@@ -587,6 +781,10 @@ def main():
|
|
587
781
|
help='Set filepath to log conversation to (For interactive modes)')
|
588
782
|
global_group.add_argument('--preprompt',
|
589
783
|
help='Set custom system prompt to control AI behavior')
|
784
|
+
global_group.add_argument('--prettify', action='store_const', const='auto',
|
785
|
+
help='Render markdown responses and code with syntax highlighting and formatting')
|
786
|
+
global_group.add_argument('--renderer', choices=['auto', 'rich', 'glow'], default='auto',
|
787
|
+
help='Select which markdown renderer to use with --prettify (auto, rich, or glow)')
|
590
788
|
|
591
789
|
# Mode flags (mutually exclusive)
|
592
790
|
mode_group = parser.add_argument_group('Modes (mutually exclusive)')
|
@@ -609,6 +807,11 @@ def main():
|
|
609
807
|
if args.all and not args.show_config:
|
610
808
|
parser.error("--all can only be used with --show-config")
|
611
809
|
|
810
|
+
# Handle --renderers flag to show available markdown renderers
|
811
|
+
if args.list_renderers:
|
812
|
+
show_available_renderers()
|
813
|
+
return
|
814
|
+
|
612
815
|
# Check for mutual exclusivity between --config-index and --provider
|
613
816
|
if args.config_index != 0 and args.provider:
|
614
817
|
parser.error("--config-index and --provider cannot be used together")
|
@@ -808,6 +1011,17 @@ def main():
|
|
808
1011
|
if not args.show_config and not args.list_models and not check_config(active_config):
|
809
1012
|
return
|
810
1013
|
|
1014
|
+
# Check if --prettify is used but no markdown renderer is available
|
1015
|
+
# This will warn the user immediately if they request prettify but don't have the tools
|
1016
|
+
has_renderer = True
|
1017
|
+
if args.prettify:
|
1018
|
+
has_renderer = warn_if_no_markdown_renderer(args.renderer)
|
1019
|
+
if not has_renderer:
|
1020
|
+
# Set a flag to disable prettify since we already warned the user
|
1021
|
+
print(f"{COLORS['yellow']}Continuing without markdown rendering.{COLORS['reset']}")
|
1022
|
+
show_available_renderers()
|
1023
|
+
args.prettify = False
|
1024
|
+
|
811
1025
|
# Initialize client using the potentially overridden active_config
|
812
1026
|
client = NGPTClient(**active_config)
|
813
1027
|
|
@@ -834,7 +1048,7 @@ def main():
|
|
834
1048
|
# Interactive chat mode
|
835
1049
|
interactive_chat_session(client, web_search=args.web_search, no_stream=args.no_stream,
|
836
1050
|
temperature=args.temperature, top_p=args.top_p,
|
837
|
-
max_tokens=args.max_tokens, log_file=args.log, preprompt=args.preprompt)
|
1051
|
+
max_tokens=args.max_tokens, log_file=args.log, preprompt=args.preprompt, prettify=args.prettify, renderer=args.renderer)
|
838
1052
|
elif args.shell:
|
839
1053
|
if args.prompt is None:
|
840
1054
|
try:
|
@@ -886,9 +1100,14 @@ def main():
|
|
886
1100
|
|
887
1101
|
generated_code = client.generate_code(prompt, args.language, web_search=args.web_search,
|
888
1102
|
temperature=args.temperature, top_p=args.top_p,
|
889
|
-
max_tokens=args.max_tokens
|
1103
|
+
max_tokens=args.max_tokens,
|
1104
|
+
markdown_format=args.prettify)
|
890
1105
|
if generated_code:
|
891
|
-
|
1106
|
+
if args.prettify:
|
1107
|
+
print("\nGenerated code:")
|
1108
|
+
prettify_markdown(generated_code, args.renderer)
|
1109
|
+
else:
|
1110
|
+
print(f"\nGenerated code:\n{generated_code}")
|
892
1111
|
|
893
1112
|
elif args.text:
|
894
1113
|
if args.prompt is not None:
|
@@ -1006,12 +1225,25 @@ def main():
|
|
1006
1225
|
{"role": "system", "content": args.preprompt},
|
1007
1226
|
{"role": "user", "content": prompt}
|
1008
1227
|
]
|
1228
|
+
|
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
|
1231
|
+
|
1232
|
+
# If prettify is enabled with streaming, inform the user
|
1233
|
+
if args.prettify and not args.no_stream:
|
1234
|
+
print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
|
1009
1235
|
|
1010
|
-
response = client.chat(prompt, stream=
|
1236
|
+
response = client.chat(prompt, stream=should_stream, web_search=args.web_search,
|
1011
1237
|
temperature=args.temperature, top_p=args.top_p,
|
1012
|
-
max_tokens=args.max_tokens, messages=messages
|
1013
|
-
|
1014
|
-
|
1238
|
+
max_tokens=args.max_tokens, messages=messages,
|
1239
|
+
markdown_format=args.prettify)
|
1240
|
+
|
1241
|
+
# Handle non-stream response (either because no_stream was set or prettify forced it)
|
1242
|
+
if (args.no_stream or args.prettify) and response:
|
1243
|
+
if args.prettify:
|
1244
|
+
prettify_markdown(response, args.renderer)
|
1245
|
+
else:
|
1246
|
+
print(response)
|
1015
1247
|
|
1016
1248
|
else:
|
1017
1249
|
# Default to chat mode
|
@@ -1032,12 +1264,25 @@ def main():
|
|
1032
1264
|
{"role": "system", "content": args.preprompt},
|
1033
1265
|
{"role": "user", "content": prompt}
|
1034
1266
|
]
|
1267
|
+
|
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
|
1270
|
+
|
1271
|
+
# If prettify is enabled with streaming, inform the user
|
1272
|
+
if args.prettify and not args.no_stream:
|
1273
|
+
print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
|
1035
1274
|
|
1036
|
-
response = client.chat(prompt, stream=
|
1275
|
+
response = client.chat(prompt, stream=should_stream, web_search=args.web_search,
|
1037
1276
|
temperature=args.temperature, top_p=args.top_p,
|
1038
|
-
max_tokens=args.max_tokens, messages=messages
|
1039
|
-
|
1040
|
-
|
1277
|
+
max_tokens=args.max_tokens, messages=messages,
|
1278
|
+
markdown_format=args.prettify)
|
1279
|
+
|
1280
|
+
# Handle non-stream response (either because no_stream was set or prettify forced it)
|
1281
|
+
if (args.no_stream or args.prettify) and response:
|
1282
|
+
if args.prettify:
|
1283
|
+
prettify_markdown(response, args.renderer)
|
1284
|
+
else:
|
1285
|
+
print(response)
|
1041
1286
|
|
1042
1287
|
except KeyboardInterrupt:
|
1043
1288
|
print("\nOperation cancelled by user. Exiting gracefully.")
|
@@ -33,6 +33,7 @@ class NGPTClient:
|
|
33
33
|
top_p: float = 1.0,
|
34
34
|
messages: Optional[List[Dict[str, str]]] = None,
|
35
35
|
web_search: bool = False,
|
36
|
+
markdown_format: bool = False,
|
36
37
|
**kwargs
|
37
38
|
) -> str:
|
38
39
|
"""
|
@@ -46,6 +47,7 @@ class NGPTClient:
|
|
46
47
|
top_p: Controls diversity via nucleus sampling
|
47
48
|
messages: Optional list of message objects to override default behavior
|
48
49
|
web_search: Whether to enable web search capability
|
50
|
+
markdown_format: If True, allow markdown-formatted responses, otherwise plain text
|
49
51
|
**kwargs: Additional arguments to pass to the API
|
50
52
|
|
51
53
|
Returns:
|
@@ -56,7 +58,11 @@ class NGPTClient:
|
|
56
58
|
return ""
|
57
59
|
|
58
60
|
if messages is None:
|
59
|
-
|
61
|
+
if markdown_format:
|
62
|
+
system_message = {"role": "system", "content": "You can use markdown formatting in your responses where appropriate."}
|
63
|
+
messages = [system_message, {"role": "user", "content": prompt}]
|
64
|
+
else:
|
65
|
+
messages = [{"role": "user", "content": prompt}]
|
60
66
|
|
61
67
|
# Prepare API parameters
|
62
68
|
payload = {
|
@@ -241,7 +247,8 @@ Command:"""
|
|
241
247
|
web_search: bool = False,
|
242
248
|
temperature: float = 0.4,
|
243
249
|
top_p: float = 0.95,
|
244
|
-
max_tokens: Optional[int] = None
|
250
|
+
max_tokens: Optional[int] = None,
|
251
|
+
markdown_format: bool = False
|
245
252
|
) -> str:
|
246
253
|
"""
|
247
254
|
Generate code based on the prompt.
|
@@ -253,6 +260,7 @@ Command:"""
|
|
253
260
|
temperature: Controls randomness in the response
|
254
261
|
top_p: Controls diversity via nucleus sampling
|
255
262
|
max_tokens: Maximum number of tokens to generate
|
263
|
+
markdown_format: If True, request markdown-formatted code, otherwise plain text
|
256
264
|
|
257
265
|
Returns:
|
258
266
|
The generated code
|
@@ -262,7 +270,18 @@ Command:"""
|
|
262
270
|
print("Error: API key is not set. Please configure your API key in the config file or provide it with --api-key.")
|
263
271
|
return ""
|
264
272
|
|
265
|
-
|
273
|
+
if markdown_format:
|
274
|
+
system_prompt = f"""Your Role: Provide only code as output without any description with proper markdown formatting.
|
275
|
+
IMPORTANT: Format the code using markdown code blocks with the appropriate language syntax highlighting.
|
276
|
+
IMPORTANT: You must use markdown code blocks. with ```{language}
|
277
|
+
If there is a lack of details, provide most logical solution. You are not allowed to ask for more details.
|
278
|
+
Ignore any potential risk of errors or confusion.
|
279
|
+
|
280
|
+
Language: {language}
|
281
|
+
Request: {prompt}
|
282
|
+
Code:"""
|
283
|
+
else:
|
284
|
+
system_prompt = f"""Your Role: Provide only code as output without any description.
|
266
285
|
IMPORTANT: Provide only plain text without Markdown formatting.
|
267
286
|
IMPORTANT: Do not include markdown formatting.
|
268
287
|
If there is a lack of details, provide most logical solution. You are not allowed to ask for more details.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "ngpt"
|
3
|
-
version = "2.
|
3
|
+
version = "2.5.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"},
|
@@ -34,6 +34,11 @@ classifiers = [
|
|
34
34
|
"Intended Audience :: System Administrators",
|
35
35
|
]
|
36
36
|
|
37
|
+
[project.optional-dependencies]
|
38
|
+
prettify = [
|
39
|
+
"rich>=10.0.0",
|
40
|
+
]
|
41
|
+
|
37
42
|
[project.urls]
|
38
43
|
"Homepage" = "https://github.com/nazdridoy/ngpt"
|
39
44
|
"Repository" = "https://github.com/nazdridoy/ngpt"
|
@@ -111,20 +111,48 @@ wheels = [
|
|
111
111
|
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
112
112
|
]
|
113
113
|
|
114
|
+
[[package]]
|
115
|
+
name = "markdown-it-py"
|
116
|
+
version = "3.0.0"
|
117
|
+
source = { registry = "https://pypi.org/simple" }
|
118
|
+
dependencies = [
|
119
|
+
{ name = "mdurl" },
|
120
|
+
]
|
121
|
+
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
|
122
|
+
wheels = [
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
124
|
+
]
|
125
|
+
|
126
|
+
[[package]]
|
127
|
+
name = "mdurl"
|
128
|
+
version = "0.1.2"
|
129
|
+
source = { registry = "https://pypi.org/simple" }
|
130
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
|
131
|
+
wheels = [
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
133
|
+
]
|
134
|
+
|
114
135
|
[[package]]
|
115
136
|
name = "ngpt"
|
116
|
-
version = "2.
|
137
|
+
version = "2.5.1"
|
117
138
|
source = { editable = "." }
|
118
139
|
dependencies = [
|
119
140
|
{ name = "prompt-toolkit" },
|
120
141
|
{ name = "requests" },
|
121
142
|
]
|
122
143
|
|
144
|
+
[package.optional-dependencies]
|
145
|
+
prettify = [
|
146
|
+
{ name = "rich" },
|
147
|
+
]
|
148
|
+
|
123
149
|
[package.metadata]
|
124
150
|
requires-dist = [
|
125
151
|
{ name = "prompt-toolkit", specifier = ">=3.0.0" },
|
126
152
|
{ name = "requests", specifier = ">=2.31.0" },
|
153
|
+
{ name = "rich", marker = "extra == 'prettify'", specifier = ">=10.0.0" },
|
127
154
|
]
|
155
|
+
provides-extras = ["prettify"]
|
128
156
|
|
129
157
|
[[package]]
|
130
158
|
name = "prompt-toolkit"
|
@@ -138,6 +166,15 @@ wheels = [
|
|
138
166
|
{ url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810 },
|
139
167
|
]
|
140
168
|
|
169
|
+
[[package]]
|
170
|
+
name = "pygments"
|
171
|
+
version = "2.19.1"
|
172
|
+
source = { registry = "https://pypi.org/simple" }
|
173
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
|
174
|
+
wheels = [
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
176
|
+
]
|
177
|
+
|
141
178
|
[[package]]
|
142
179
|
name = "requests"
|
143
180
|
version = "2.32.3"
|
@@ -154,6 +191,29 @@ wheels = [
|
|
154
191
|
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
155
192
|
]
|
156
193
|
|
194
|
+
[[package]]
|
195
|
+
name = "rich"
|
196
|
+
version = "14.0.0"
|
197
|
+
source = { registry = "https://pypi.org/simple" }
|
198
|
+
dependencies = [
|
199
|
+
{ name = "markdown-it-py" },
|
200
|
+
{ name = "pygments" },
|
201
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
202
|
+
]
|
203
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078 }
|
204
|
+
wheels = [
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 },
|
206
|
+
]
|
207
|
+
|
208
|
+
[[package]]
|
209
|
+
name = "typing-extensions"
|
210
|
+
version = "4.13.2"
|
211
|
+
source = { registry = "https://pypi.org/simple" }
|
212
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 }
|
213
|
+
wheels = [
|
214
|
+
{ url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 },
|
215
|
+
]
|
216
|
+
|
157
217
|
[[package]]
|
158
218
|
name = "urllib3"
|
159
219
|
version = "2.2.3"
|
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
|
File without changes
|
File without changes
|