ngpt 3.8.1__tar.gz → 3.8.3__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-3.8.1 → ngpt-3.8.3}/PKG-INFO +143 -1
- {ngpt-3.8.1 → ngpt-3.8.3}/README.md +142 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/chat.py +18 -13
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/code.py +20 -15
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/interactive.py +53 -46
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/rewrite.py +18 -13
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/shell.py +346 -63
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/text.py +18 -13
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/renderers.py +56 -50
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/ui.py +33 -4
- {ngpt-3.8.1 → ngpt-3.8.3}/pyproject.toml +1 -1
- {ngpt-3.8.1 → ngpt-3.8.3}/uv.lock +1 -1
- {ngpt-3.8.1 → ngpt-3.8.3}/.github/workflows/aur-publish.yml +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/.github/workflows/python-publish.yml +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/.gitignore +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/.python-version +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/COMMIT_GUIDELINES.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/CONTRIBUTING.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/LICENSE +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/PKGBUILD +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/CONTRIBUTING.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/LICENSE.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/_config.yml +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/_sass/custom/custom.scss +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/configuration.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/examples/advanced.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/examples/basic.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/examples.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/index.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/installation.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/overview.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/usage/cli_config.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/usage/cli_usage.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/usage/gitcommsg.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/usage/web_search.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/docs/usage.md +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/__init__.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/__main__.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/__init__.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/args.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/config_manager.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/formatters.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/main.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/__init__.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/cli/modes/gitcommsg.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/client.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/__init__.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/cli_config.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/config.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/log.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/pipe.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/ngpt/utils/web_search.py +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-g.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-i.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-s-c.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-sh-c-a.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-w-self.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/previews/ngpt-w.png +0 -0
- {ngpt-3.8.1 → ngpt-3.8.3}/wiki.md +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ngpt
|
3
|
-
Version: 3.8.
|
3
|
+
Version: 3.8.3
|
4
4
|
Summary: Swiss army knife for LLMs: powerful CLI and interactive chatbot in one package. Seamlessly work with OpenAI, Ollama, Groq, Claude, Gemini, or any OpenAI-compatible API to generate code, craft git commits, rewrite text, and execute shell commands.
|
5
5
|
Project-URL: Homepage, https://github.com/nazdridoy/ngpt
|
6
6
|
Project-URL: Repository, https://github.com/nazdridoy/ngpt
|
@@ -493,6 +493,8 @@ In interactive mode:
|
|
493
493
|
- For security, your API key is not displayed when editing configurations
|
494
494
|
- When removing a configuration, you'll be asked to confirm before deletion
|
495
495
|
|
496
|
+

|
497
|
+
|
496
498
|
For more details on configuring nGPT, see the [Configuration Guide](https://nazdridoy.github.io/ngpt/configuration/).
|
497
499
|
|
498
500
|
### Configuration File
|
@@ -541,6 +543,146 @@ nGPT determines configuration values in the following order (highest priority fi
|
|
541
543
|
4. Main configuration file `ngpt.conf` or `custom-config-file`
|
542
544
|
5. Default values
|
543
545
|
|
546
|
+
### Real-World Demonstrations with nGPT
|
547
|
+
|
548
|
+
Let's see nGPT in action! Here are some practical ways you can use it every day:
|
549
|
+
|
550
|
+
#### Quick Q&A and Coding
|
551
|
+
|
552
|
+
```bash
|
553
|
+
# Get a quick explanation
|
554
|
+
ngpt "Explain the difference between threads and processes in Python"
|
555
|
+
|
556
|
+
# Generate code with real-time syntax highlighting
|
557
|
+
ngpt --code --stream-prettify "Write a Python function to reverse a linked list"
|
558
|
+
```
|
559
|
+
|
560
|
+
With the `--code` flag, nGPT gives you clean code without explanations or markdown, just what you need to copy and paste into your project. The `--stream-prettify` option shows real-time syntax highlighting as the code comes in.
|
561
|
+
|
562
|
+
#### Shell Command Generation (OS-Aware)
|
563
|
+
|
564
|
+
```bash
|
565
|
+
# Let nGPT generate the correct command for your OS
|
566
|
+
ngpt --shell "list all files in the current directory including hidden ones"
|
567
|
+
# On Linux/macOS: ls -la
|
568
|
+
# On Windows: dir /a
|
569
|
+
```
|
570
|
+
|
571
|
+
One of my favorite features! No more Googling obscure command flags, nGPT generates the right command for your operating system. It'll even execute it for you if you approve.
|
572
|
+
|
573
|
+

|
574
|
+
|
575
|
+
#### Text Rewriting and Summarization
|
576
|
+
|
577
|
+
```bash
|
578
|
+
# Pipe text to rewrite it (e.g., improve clarity)
|
579
|
+
echo "This is a rough draft of my email." | ngpt -r
|
580
|
+
|
581
|
+
# Summarize a file using the pipe placeholder
|
582
|
+
cat long-article.txt | ngpt --pipe "Summarize this document concisely: {}"
|
583
|
+
```
|
584
|
+
|
585
|
+
The text rewriting feature is perfect for quickly improving documentation, emails, or reports. And with pipe placeholders, you can feed in content from files or other commands.
|
586
|
+
|
587
|
+
#### Git Commit Message Generation
|
588
|
+
|
589
|
+
```bash
|
590
|
+
# Stage your changes
|
591
|
+
git add .
|
592
|
+
|
593
|
+
# Let nGPT generate a conventional commit message based on the diff
|
594
|
+
ngpt -g
|
595
|
+
|
596
|
+
# Generate git commit message from a diff file
|
597
|
+
ngpt -g --diff changes.diff
|
598
|
+
```
|
599
|
+
|
600
|
+
This is a huge time-saver. nGPT analyzes your git diff and generates a properly formatted conventional commit message that actually describes what you changed. No more staring at the blank commit message prompt!
|
601
|
+
|
602
|
+

|
603
|
+
|
604
|
+
#### Web Search Integration
|
605
|
+
|
606
|
+
```bash
|
607
|
+
# Ask questions that require up-to-date information
|
608
|
+
ngpt --web-search "What's the latest news about AI regulation?"
|
609
|
+
```
|
610
|
+
|
611
|
+
The `--web-search` flag lets nGPT consult the web for recent information, making it useful for questions about current events or topics that might have changed since the AI's training data cutoff.
|
612
|
+
|
613
|
+

|
614
|
+
|
615
|
+
### Real-World Integration Examples
|
616
|
+
|
617
|
+
Let's look at how nGPT can fit into your everyday workflow with some practical examples:
|
618
|
+
|
619
|
+
#### Developer Workflow
|
620
|
+
|
621
|
+
As a developer, I use nGPT throughout my day:
|
622
|
+
|
623
|
+
**Morning code review**:
|
624
|
+
```bash
|
625
|
+
# Get explanations of complex code
|
626
|
+
git show | ngpt --pipe "Explain what this code change does and any potential issues: {}"
|
627
|
+
```
|
628
|
+
|
629
|
+
**Debugging help**:
|
630
|
+
```bash
|
631
|
+
# Help understand a cryptic error message
|
632
|
+
npm run build 2>&1 | grep Error | ngpt --pipe "What does this error mean and how can I fix it: {}"
|
633
|
+
```
|
634
|
+
|
635
|
+
**Documentation generation**:
|
636
|
+
```bash
|
637
|
+
# Generate JSDoc comments for functions
|
638
|
+
cat src/utils.js | ngpt --pipe "Write proper JSDoc comments for these functions: {}"
|
639
|
+
```
|
640
|
+
|
641
|
+
**Commit messages**:
|
642
|
+
```bash
|
643
|
+
# After finishing a feature
|
644
|
+
git add .
|
645
|
+
ngpt -g
|
646
|
+
```
|
647
|
+
|
648
|
+
#### Writer's Assistant
|
649
|
+
|
650
|
+
For content creators and writers:
|
651
|
+
|
652
|
+
**Overcoming writer's block**:
|
653
|
+
```bash
|
654
|
+
ngpt "Give me 5 different angles to approach an article about sustainable technology"
|
655
|
+
```
|
656
|
+
|
657
|
+
**Editing assistance**:
|
658
|
+
```bash
|
659
|
+
cat draft.md | ngpt -r
|
660
|
+
```
|
661
|
+
|
662
|
+
**Research summaries**:
|
663
|
+
```bash
|
664
|
+
curl -s https://example.com/research-paper.html | ngpt --pipe "Summarize the key findings from this research: {}"
|
665
|
+
```
|
666
|
+
|
667
|
+
#### System Administrator
|
668
|
+
|
669
|
+
For sysadmins and DevOps folks:
|
670
|
+
|
671
|
+
**Generating complex commands**:
|
672
|
+
```bash
|
673
|
+
ngpt -s "find all log files larger than 100MB that haven't been modified in the last 30 days"
|
674
|
+
```
|
675
|
+
|
676
|
+
*Creating configuration files**:
|
677
|
+
```bash
|
678
|
+
ngpt --code "Create a Docker Compose file for a Redis, PostgreSQL, and Node.js application"
|
679
|
+
```
|
680
|
+
|
681
|
+
**Troubleshooting systems**:
|
682
|
+
```bash
|
683
|
+
dmesg | tail -50 | ngpt --pipe "Explain what might be causing the issues based on these system logs: {}"
|
684
|
+
```
|
685
|
+
|
544
686
|
## Contributing
|
545
687
|
|
546
688
|
We welcome contributions to nGPT! Whether it's bug fixes, feature additions, or documentation improvements, your help is appreciated.
|
@@ -456,6 +456,8 @@ In interactive mode:
|
|
456
456
|
- For security, your API key is not displayed when editing configurations
|
457
457
|
- When removing a configuration, you'll be asked to confirm before deletion
|
458
458
|
|
459
|
+

|
460
|
+
|
459
461
|
For more details on configuring nGPT, see the [Configuration Guide](https://nazdridoy.github.io/ngpt/configuration/).
|
460
462
|
|
461
463
|
### Configuration File
|
@@ -504,6 +506,146 @@ nGPT determines configuration values in the following order (highest priority fi
|
|
504
506
|
4. Main configuration file `ngpt.conf` or `custom-config-file`
|
505
507
|
5. Default values
|
506
508
|
|
509
|
+
### Real-World Demonstrations with nGPT
|
510
|
+
|
511
|
+
Let's see nGPT in action! Here are some practical ways you can use it every day:
|
512
|
+
|
513
|
+
#### Quick Q&A and Coding
|
514
|
+
|
515
|
+
```bash
|
516
|
+
# Get a quick explanation
|
517
|
+
ngpt "Explain the difference between threads and processes in Python"
|
518
|
+
|
519
|
+
# Generate code with real-time syntax highlighting
|
520
|
+
ngpt --code --stream-prettify "Write a Python function to reverse a linked list"
|
521
|
+
```
|
522
|
+
|
523
|
+
With the `--code` flag, nGPT gives you clean code without explanations or markdown, just what you need to copy and paste into your project. The `--stream-prettify` option shows real-time syntax highlighting as the code comes in.
|
524
|
+
|
525
|
+
#### Shell Command Generation (OS-Aware)
|
526
|
+
|
527
|
+
```bash
|
528
|
+
# Let nGPT generate the correct command for your OS
|
529
|
+
ngpt --shell "list all files in the current directory including hidden ones"
|
530
|
+
# On Linux/macOS: ls -la
|
531
|
+
# On Windows: dir /a
|
532
|
+
```
|
533
|
+
|
534
|
+
One of my favorite features! No more Googling obscure command flags, nGPT generates the right command for your operating system. It'll even execute it for you if you approve.
|
535
|
+
|
536
|
+

|
537
|
+
|
538
|
+
#### Text Rewriting and Summarization
|
539
|
+
|
540
|
+
```bash
|
541
|
+
# Pipe text to rewrite it (e.g., improve clarity)
|
542
|
+
echo "This is a rough draft of my email." | ngpt -r
|
543
|
+
|
544
|
+
# Summarize a file using the pipe placeholder
|
545
|
+
cat long-article.txt | ngpt --pipe "Summarize this document concisely: {}"
|
546
|
+
```
|
547
|
+
|
548
|
+
The text rewriting feature is perfect for quickly improving documentation, emails, or reports. And with pipe placeholders, you can feed in content from files or other commands.
|
549
|
+
|
550
|
+
#### Git Commit Message Generation
|
551
|
+
|
552
|
+
```bash
|
553
|
+
# Stage your changes
|
554
|
+
git add .
|
555
|
+
|
556
|
+
# Let nGPT generate a conventional commit message based on the diff
|
557
|
+
ngpt -g
|
558
|
+
|
559
|
+
# Generate git commit message from a diff file
|
560
|
+
ngpt -g --diff changes.diff
|
561
|
+
```
|
562
|
+
|
563
|
+
This is a huge time-saver. nGPT analyzes your git diff and generates a properly formatted conventional commit message that actually describes what you changed. No more staring at the blank commit message prompt!
|
564
|
+
|
565
|
+

|
566
|
+
|
567
|
+
#### Web Search Integration
|
568
|
+
|
569
|
+
```bash
|
570
|
+
# Ask questions that require up-to-date information
|
571
|
+
ngpt --web-search "What's the latest news about AI regulation?"
|
572
|
+
```
|
573
|
+
|
574
|
+
The `--web-search` flag lets nGPT consult the web for recent information, making it useful for questions about current events or topics that might have changed since the AI's training data cutoff.
|
575
|
+
|
576
|
+

|
577
|
+
|
578
|
+
### Real-World Integration Examples
|
579
|
+
|
580
|
+
Let's look at how nGPT can fit into your everyday workflow with some practical examples:
|
581
|
+
|
582
|
+
#### Developer Workflow
|
583
|
+
|
584
|
+
As a developer, I use nGPT throughout my day:
|
585
|
+
|
586
|
+
**Morning code review**:
|
587
|
+
```bash
|
588
|
+
# Get explanations of complex code
|
589
|
+
git show | ngpt --pipe "Explain what this code change does and any potential issues: {}"
|
590
|
+
```
|
591
|
+
|
592
|
+
**Debugging help**:
|
593
|
+
```bash
|
594
|
+
# Help understand a cryptic error message
|
595
|
+
npm run build 2>&1 | grep Error | ngpt --pipe "What does this error mean and how can I fix it: {}"
|
596
|
+
```
|
597
|
+
|
598
|
+
**Documentation generation**:
|
599
|
+
```bash
|
600
|
+
# Generate JSDoc comments for functions
|
601
|
+
cat src/utils.js | ngpt --pipe "Write proper JSDoc comments for these functions: {}"
|
602
|
+
```
|
603
|
+
|
604
|
+
**Commit messages**:
|
605
|
+
```bash
|
606
|
+
# After finishing a feature
|
607
|
+
git add .
|
608
|
+
ngpt -g
|
609
|
+
```
|
610
|
+
|
611
|
+
#### Writer's Assistant
|
612
|
+
|
613
|
+
For content creators and writers:
|
614
|
+
|
615
|
+
**Overcoming writer's block**:
|
616
|
+
```bash
|
617
|
+
ngpt "Give me 5 different angles to approach an article about sustainable technology"
|
618
|
+
```
|
619
|
+
|
620
|
+
**Editing assistance**:
|
621
|
+
```bash
|
622
|
+
cat draft.md | ngpt -r
|
623
|
+
```
|
624
|
+
|
625
|
+
**Research summaries**:
|
626
|
+
```bash
|
627
|
+
curl -s https://example.com/research-paper.html | ngpt --pipe "Summarize the key findings from this research: {}"
|
628
|
+
```
|
629
|
+
|
630
|
+
#### System Administrator
|
631
|
+
|
632
|
+
For sysadmins and DevOps folks:
|
633
|
+
|
634
|
+
**Generating complex commands**:
|
635
|
+
```bash
|
636
|
+
ngpt -s "find all log files larger than 100MB that haven't been modified in the last 30 days"
|
637
|
+
```
|
638
|
+
|
639
|
+
*Creating configuration files**:
|
640
|
+
```bash
|
641
|
+
ngpt --code "Create a Docker Compose file for a Redis, PostgreSQL, and Node.js application"
|
642
|
+
```
|
643
|
+
|
644
|
+
**Troubleshooting systems**:
|
645
|
+
```bash
|
646
|
+
dmesg | tail -50 | ngpt --pipe "Explain what might be causing the issues based on these system logs: {}"
|
647
|
+
```
|
648
|
+
|
507
649
|
## Contributing
|
508
650
|
|
509
651
|
We welcome contributions to nGPT! Whether it's bug fixes, feature additions, or documentation improvements, your help is appreciated.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
2
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
3
3
|
from ..ui import spinner
|
4
4
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
5
5
|
import sys
|
@@ -53,9 +53,10 @@ def chat_mode(client, args, logger=None):
|
|
53
53
|
stop_spinner.set()
|
54
54
|
spinner_thread.join()
|
55
55
|
# Clear the spinner line completely
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
with TERMINAL_RENDER_LOCK:
|
57
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
58
|
+
sys.stdout.flush()
|
59
|
+
print("Enhanced input with web search results.")
|
59
60
|
except Exception as e:
|
60
61
|
# Stop the spinner before re-raising
|
61
62
|
stop_spinner.set()
|
@@ -129,11 +130,14 @@ def chat_mode(client, args, logger=None):
|
|
129
130
|
# On first content, stop the spinner
|
130
131
|
if not first_content_received and stop_spinner_func:
|
131
132
|
first_content_received = True
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
|
134
|
+
# Use lock to prevent terminal rendering conflicts
|
135
|
+
with TERMINAL_RENDER_LOCK:
|
136
|
+
# Stop the spinner
|
137
|
+
stop_spinner_func()
|
138
|
+
# Ensure spinner message is cleared with an extra blank line
|
139
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
140
|
+
sys.stdout.flush()
|
137
141
|
|
138
142
|
# Call the original callback to update the display
|
139
143
|
if original_callback:
|
@@ -165,7 +169,8 @@ def chat_mode(client, args, logger=None):
|
|
165
169
|
|
166
170
|
# Handle non-stream response or regular prettify
|
167
171
|
if (args.no_stream or args.prettify) and response:
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
+
with TERMINAL_RENDER_LOCK:
|
173
|
+
if args.prettify:
|
174
|
+
prettify_markdown(response, args.renderer)
|
175
|
+
else:
|
176
|
+
print(response)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from ..formatters import COLORS
|
2
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown, has_markdown_renderer, show_available_renderers
|
2
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, has_markdown_renderer, show_available_renderers, TERMINAL_RENDER_LOCK
|
3
3
|
from ..ui import spinner, copy_to_clipboard
|
4
4
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
5
5
|
import sys
|
@@ -126,9 +126,10 @@ def code_mode(client, args, logger=None):
|
|
126
126
|
stop_spinner.set()
|
127
127
|
spinner_thread.join()
|
128
128
|
# Clear the spinner line completely
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
with TERMINAL_RENDER_LOCK:
|
130
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
131
|
+
sys.stdout.flush()
|
132
|
+
print("Enhanced input with web search results.")
|
132
133
|
except Exception as e:
|
133
134
|
# Stop the spinner before re-raising
|
134
135
|
stop_spinner.set()
|
@@ -211,11 +212,14 @@ def code_mode(client, args, logger=None):
|
|
211
212
|
# On first content, stop the spinner
|
212
213
|
if not first_content_received and stop_spinner_func:
|
213
214
|
first_content_received = True
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
215
|
+
|
216
|
+
# Use lock to prevent terminal rendering conflicts
|
217
|
+
with TERMINAL_RENDER_LOCK:
|
218
|
+
# Stop the spinner
|
219
|
+
stop_spinner_func()
|
220
|
+
# Ensure spinner message is cleared with an extra blank line
|
221
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
222
|
+
sys.stdout.flush()
|
219
223
|
|
220
224
|
# Call the original callback to update the display
|
221
225
|
if original_callback:
|
@@ -297,12 +301,13 @@ def code_mode(client, args, logger=None):
|
|
297
301
|
|
298
302
|
# Print non-streamed output if needed
|
299
303
|
if generated_code and not should_stream:
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
304
|
+
with TERMINAL_RENDER_LOCK:
|
305
|
+
if use_regular_prettify:
|
306
|
+
print("\nGenerated code:")
|
307
|
+
prettify_markdown(generated_code, args.renderer)
|
308
|
+
else:
|
309
|
+
# Should only happen if --no-stream was used without prettify
|
310
|
+
print(f"\nGenerated code:\n{generated_code}")
|
306
311
|
|
307
312
|
# Offer to copy to clipboard
|
308
313
|
if generated_code and not args.no_stream:
|
@@ -5,7 +5,7 @@ import threading
|
|
5
5
|
import sys
|
6
6
|
import time
|
7
7
|
from ..formatters import COLORS
|
8
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
8
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
9
9
|
from ..ui import spinner
|
10
10
|
from ...utils import enhance_prompt_with_web_search
|
11
11
|
|
@@ -78,8 +78,9 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
78
78
|
def print_separator():
|
79
79
|
# Make sure there's exactly one newline before and after
|
80
80
|
# Use sys.stdout.write for direct control, avoiding any extra newlines
|
81
|
-
|
82
|
-
|
81
|
+
with TERMINAL_RENDER_LOCK:
|
82
|
+
sys.stdout.write(f"\n{separator}\n")
|
83
|
+
sys.stdout.flush()
|
83
84
|
|
84
85
|
# Initialize conversation history
|
85
86
|
system_prompt = preprompt if preprompt else "You are a helpful assistant."
|
@@ -111,35 +112,37 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
111
112
|
|
112
113
|
# Function to display conversation history
|
113
114
|
def display_history():
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
print(f"\n{COLORS['cyan']}{COLORS['bold']}Conversation History:{COLORS['reset']}")
|
119
|
-
print(separator)
|
120
|
-
|
121
|
-
# Skip system message
|
122
|
-
message_count = 0
|
123
|
-
for i, msg in enumerate(conversation):
|
124
|
-
if msg["role"] == "system":
|
125
|
-
continue
|
115
|
+
with TERMINAL_RENDER_LOCK:
|
116
|
+
if len(conversation) <= 1: # Only system message
|
117
|
+
print(f"\n{COLORS['yellow']}No conversation history yet.{COLORS['reset']}")
|
118
|
+
return
|
126
119
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
120
|
+
print(f"\n{COLORS['cyan']}{COLORS['bold']}Conversation History:{COLORS['reset']}")
|
121
|
+
print(separator)
|
122
|
+
|
123
|
+
# Skip system message
|
124
|
+
message_count = 0
|
125
|
+
for i, msg in enumerate(conversation):
|
126
|
+
if msg["role"] == "system":
|
127
|
+
continue
|
128
|
+
|
129
|
+
if msg["role"] == "user":
|
130
|
+
message_count += 1
|
131
|
+
print(f"\n{user_header()}")
|
132
|
+
print(f"{COLORS['cyan']}│ [{message_count}] {COLORS['reset']}{msg['content']}")
|
133
|
+
elif msg["role"] == "assistant":
|
134
|
+
print(f"\n{ngpt_header()}")
|
135
|
+
print(f"{COLORS['green']}│ {COLORS['reset']}{msg['content']}")
|
136
|
+
|
137
|
+
print(f"\n{separator}") # Consistent separator at the end
|
136
138
|
|
137
139
|
# Function to clear conversation history
|
138
140
|
def clear_history():
|
139
141
|
nonlocal conversation
|
140
142
|
conversation = [{"role": "system", "content": system_prompt}]
|
141
|
-
|
142
|
-
|
143
|
+
with TERMINAL_RENDER_LOCK:
|
144
|
+
print(f"\n{COLORS['yellow']}Conversation history cleared.{COLORS['reset']}")
|
145
|
+
print(separator) # Add separator for consistency
|
143
146
|
|
144
147
|
try:
|
145
148
|
while True:
|
@@ -249,10 +252,11 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
249
252
|
|
250
253
|
# Print the header if needed
|
251
254
|
if should_print_header:
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
255
|
+
with TERMINAL_RENDER_LOCK:
|
256
|
+
if not no_stream and not stream_prettify:
|
257
|
+
print(f"\n{ngpt_header()}: {COLORS['reset']}", end="", flush=True)
|
258
|
+
elif not stream_prettify:
|
259
|
+
print(f"\n{ngpt_header()}: {COLORS['reset']}", flush=True)
|
256
260
|
|
257
261
|
# Determine streaming behavior
|
258
262
|
if prettify and not no_stream and not stream_prettify:
|
@@ -294,18 +298,20 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
294
298
|
if not first_content_received:
|
295
299
|
first_content_received = True
|
296
300
|
|
297
|
-
#
|
298
|
-
|
299
|
-
|
301
|
+
# Use lock to prevent terminal rendering conflicts
|
302
|
+
with TERMINAL_RENDER_LOCK:
|
303
|
+
# Stop the spinner if it's running
|
304
|
+
if stop_spinner_func:
|
305
|
+
stop_spinner_func()
|
306
|
+
|
307
|
+
# Clear the spinner line completely without leaving extra newlines
|
308
|
+
# Use direct terminal control to ensure consistency
|
309
|
+
sys.stdout.write("\r" + " " * shutil.get_terminal_size().columns + "\r")
|
310
|
+
sys.stdout.flush()
|
300
311
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
sys.stdout.flush()
|
305
|
-
|
306
|
-
# Now start the live display
|
307
|
-
if live_display:
|
308
|
-
live_display.start()
|
312
|
+
# Now start the live display
|
313
|
+
if live_display:
|
314
|
+
live_display.start()
|
309
315
|
|
310
316
|
# Call the original callback to update content
|
311
317
|
if original_callback:
|
@@ -351,11 +357,12 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
|
|
351
357
|
|
352
358
|
# Print response if not streamed (either due to no_stream or prettify)
|
353
359
|
if no_stream or prettify:
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
360
|
+
with TERMINAL_RENDER_LOCK:
|
361
|
+
if prettify:
|
362
|
+
# For pretty formatting with rich, don't print any header text as the rich renderer already includes it
|
363
|
+
prettify_markdown(response, renderer)
|
364
|
+
else:
|
365
|
+
print(response)
|
359
366
|
|
360
367
|
# Log AI response if logging is enabled
|
361
368
|
if logger:
|
@@ -2,7 +2,7 @@ import sys
|
|
2
2
|
import threading
|
3
3
|
import time
|
4
4
|
from ..formatters import COLORS
|
5
|
-
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
5
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown, TERMINAL_RENDER_LOCK
|
6
6
|
from ..ui import get_multiline_input, spinner, copy_to_clipboard
|
7
7
|
from ...utils import enhance_prompt_with_web_search, process_piped_input
|
8
8
|
|
@@ -127,9 +127,10 @@ def rewrite_mode(client, args, logger=None):
|
|
127
127
|
stop_spinner.set()
|
128
128
|
spinner_thread.join()
|
129
129
|
# Clear the spinner line completely
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
with TERMINAL_RENDER_LOCK:
|
131
|
+
sys.stdout.write("\r" + " " * 100 + "\r")
|
132
|
+
sys.stdout.flush()
|
133
|
+
print("Enhanced input with web search results.")
|
133
134
|
except Exception as e:
|
134
135
|
# Stop the spinner before re-raising
|
135
136
|
stop_spinner.set()
|
@@ -197,11 +198,14 @@ def rewrite_mode(client, args, logger=None):
|
|
197
198
|
# On first content, stop the spinner
|
198
199
|
if not first_content_received and stop_spinner_func:
|
199
200
|
first_content_received = True
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
201
|
+
|
202
|
+
# Use lock to prevent terminal rendering conflicts
|
203
|
+
with TERMINAL_RENDER_LOCK:
|
204
|
+
# Stop the spinner
|
205
|
+
stop_spinner_func()
|
206
|
+
# Ensure spinner message is cleared with an extra blank line
|
207
|
+
sys.stdout.write("\r" + " " * 100 + "\r\n")
|
208
|
+
sys.stdout.flush()
|
205
209
|
|
206
210
|
# Call the original callback to update the display
|
207
211
|
if original_callback:
|
@@ -241,10 +245,11 @@ def rewrite_mode(client, args, logger=None):
|
|
241
245
|
|
242
246
|
# Handle non-stream response or regular prettify
|
243
247
|
if (args.no_stream or args.prettify) and response:
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
+
with TERMINAL_RENDER_LOCK:
|
249
|
+
if args.prettify:
|
250
|
+
prettify_markdown(response, args.renderer)
|
251
|
+
else:
|
252
|
+
print(response)
|
248
253
|
|
249
254
|
# Offer to copy to clipboard if not in a redirected output
|
250
255
|
if not args.no_stream and response:
|