ngpt 2.15.1__py3-none-any.whl → 2.16.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ngpt/cli/modes/gitcommsg.py +77 -20
- ngpt/cli/ui.py +45 -1
- {ngpt-2.15.1.dist-info → ngpt-2.16.0.dist-info}/METADATA +1 -1
- {ngpt-2.15.1.dist-info → ngpt-2.16.0.dist-info}/RECORD +7 -7
- {ngpt-2.15.1.dist-info → ngpt-2.16.0.dist-info}/WHEEL +0 -0
- {ngpt-2.15.1.dist-info → ngpt-2.16.0.dist-info}/entry_points.txt +0 -0
- {ngpt-2.15.1.dist-info → ngpt-2.16.0.dist-info}/licenses/LICENSE +0 -0
ngpt/cli/modes/gitcommsg.py
CHANGED
@@ -4,9 +4,11 @@ import sys
|
|
4
4
|
import tempfile
|
5
5
|
import time
|
6
6
|
import subprocess
|
7
|
+
import threading
|
7
8
|
from datetime import datetime
|
8
9
|
import logging
|
9
10
|
from ..formatters import COLORS
|
11
|
+
from ..ui import spinner
|
10
12
|
from ...utils.log import create_gitcommsg_logger
|
11
13
|
from ...utils.cli_config import get_cli_config_option
|
12
14
|
|
@@ -436,15 +438,8 @@ def handle_api_call(client, prompt, system_prompt=None, logger=None, max_retries
|
|
436
438
|
print(f"{COLORS['yellow']}{error_msg}{COLORS['reset']}")
|
437
439
|
print(f"{COLORS['yellow']}Retrying in {wait_seconds} seconds...{COLORS['reset']}")
|
438
440
|
|
439
|
-
#
|
440
|
-
spinner
|
441
|
-
for _ in range(wait_seconds * 5):
|
442
|
-
for char in spinner:
|
443
|
-
sys.stdout.write(f"\r{COLORS['yellow']}Waiting... {char}{COLORS['reset']}")
|
444
|
-
sys.stdout.flush()
|
445
|
-
time.sleep(0.2)
|
446
|
-
|
447
|
-
print("\r" + " " * 20 + "\r", end="")
|
441
|
+
# Use the spinner function
|
442
|
+
spinner(f"Retrying in {wait_seconds} seconds...", wait_seconds, color=COLORS['yellow'])
|
448
443
|
|
449
444
|
# Exponential backoff
|
450
445
|
wait_seconds *= 2
|
@@ -504,12 +499,27 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
|
|
504
499
|
logger.log_template("DEBUG", "CHUNK", chunk_prompt)
|
505
500
|
|
506
501
|
# Process chunk - use technical system prompt for analysis
|
507
|
-
|
502
|
+
stop_spinner = threading.Event()
|
503
|
+
spinner_thread = threading.Thread(
|
504
|
+
target=spinner,
|
505
|
+
args=("Analyzing changes...",),
|
506
|
+
kwargs={"stop_event": stop_spinner, "color": COLORS['yellow']}
|
507
|
+
)
|
508
|
+
spinner_thread.daemon = True
|
509
|
+
spinner_thread.start()
|
510
|
+
|
508
511
|
try:
|
509
512
|
result = handle_api_call(client, chunk_prompt, technical_system_prompt, logger)
|
510
|
-
|
513
|
+
# Stop the spinner
|
514
|
+
stop_spinner.set()
|
515
|
+
spinner_thread.join()
|
516
|
+
# Show success message
|
511
517
|
print(f"{COLORS['green']}✓ Chunk {i+1} processed{COLORS['reset']}")
|
518
|
+
partial_analyses.append(result)
|
512
519
|
except Exception as e:
|
520
|
+
# Stop the spinner
|
521
|
+
stop_spinner.set()
|
522
|
+
spinner_thread.join()
|
513
523
|
print(f"{COLORS['red']}Error processing chunk {i+1}: {str(e)}{COLORS['reset']}")
|
514
524
|
if logger:
|
515
525
|
logger.error(f"Error processing chunk {i+1}: {str(e)}")
|
@@ -517,8 +527,8 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
|
|
517
527
|
|
518
528
|
# Rate limit protection between chunks
|
519
529
|
if i < chunk_count - 1:
|
520
|
-
|
521
|
-
|
530
|
+
# Use the spinner function with fixed duration
|
531
|
+
spinner("Waiting to avoid rate limits...", 5, color=COLORS['yellow'])
|
522
532
|
|
523
533
|
# Combine partial analyses
|
524
534
|
print(f"\n{COLORS['cyan']}Combining analyses from {len(partial_analyses)} chunks...{COLORS['reset']}")
|
@@ -545,7 +555,16 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
|
|
545
555
|
)
|
546
556
|
else:
|
547
557
|
# Combined analysis is under the chunk size limit, generate the commit message
|
548
|
-
|
558
|
+
# Start spinner for generating commit message
|
559
|
+
stop_spinner = threading.Event()
|
560
|
+
spinner_thread = threading.Thread(
|
561
|
+
target=spinner,
|
562
|
+
args=("Generating commit message from combined analysis...",),
|
563
|
+
kwargs={"stop_event": stop_spinner, "color": COLORS['green']}
|
564
|
+
)
|
565
|
+
spinner_thread.daemon = True
|
566
|
+
spinner_thread.start()
|
567
|
+
|
549
568
|
combine_prompt = create_combine_prompt(partial_analyses)
|
550
569
|
|
551
570
|
# Log combine template
|
@@ -556,6 +575,10 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
|
|
556
575
|
# Use commit message system prompt for final generation
|
557
576
|
commit_message = handle_api_call(client, combine_prompt, commit_system_prompt, logger)
|
558
577
|
|
578
|
+
# Stop the spinner
|
579
|
+
stop_spinner.set()
|
580
|
+
spinner_thread.join()
|
581
|
+
|
559
582
|
# If the commit message is too long, we need to condense it
|
560
583
|
if len(commit_message.splitlines()) > max_msg_lines:
|
561
584
|
return condense_commit_message(
|
@@ -569,6 +592,10 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
|
|
569
592
|
)
|
570
593
|
return commit_message
|
571
594
|
except Exception as e:
|
595
|
+
# Stop the spinner
|
596
|
+
stop_spinner.set()
|
597
|
+
spinner_thread.join()
|
598
|
+
|
572
599
|
print(f"{COLORS['red']}Error combining analyses: {str(e)}{COLORS['reset']}")
|
573
600
|
if logger:
|
574
601
|
logger.error(f"Error combining analyses: {str(e)}")
|
@@ -689,18 +716,33 @@ SECTION OF ANALYSIS TO CONDENSE:
|
|
689
716
|
if logger:
|
690
717
|
logger.log_template("DEBUG", f"CONDENSE_ANALYSIS_DEPTH_{current_depth}_CHUNK_{i+1}", condense_prompt)
|
691
718
|
|
692
|
-
|
719
|
+
# Start spinner for analysis
|
720
|
+
stop_spinner = threading.Event()
|
721
|
+
spinner_thread = threading.Thread(
|
722
|
+
target=spinner,
|
723
|
+
args=(f"Condensing analysis chunk {i+1}/{analysis_chunk_count}...",),
|
724
|
+
kwargs={"stop_event": stop_spinner, "color": COLORS['yellow']}
|
725
|
+
)
|
726
|
+
spinner_thread.daemon = True
|
727
|
+
spinner_thread.start()
|
693
728
|
|
694
729
|
# Condense this analysis chunk - use technical system prompt for condensing analysis
|
695
730
|
try:
|
696
731
|
condensed_chunk = handle_api_call(client, condense_prompt, technical_system_prompt, logger)
|
732
|
+
# Stop the spinner
|
733
|
+
stop_spinner.set()
|
734
|
+
spinner_thread.join()
|
735
|
+
|
736
|
+
print(f"{COLORS['green']}✓ Analysis chunk {i+1}/{analysis_chunk_count} condensed{COLORS['reset']}")
|
697
737
|
condensed_chunks.append(condensed_chunk)
|
698
738
|
|
699
739
|
if logger:
|
700
740
|
logger.log_content("DEBUG", f"CONDENSED_ANALYSIS_DEPTH_{current_depth}_CHUNK_{i+1}", condensed_chunk)
|
701
|
-
|
702
|
-
print(f"{COLORS['green']}✓ Analysis chunk {i+1}/{analysis_chunk_count} condensed{COLORS['reset']}")
|
703
741
|
except Exception as e:
|
742
|
+
# Stop the spinner
|
743
|
+
stop_spinner.set()
|
744
|
+
spinner_thread.join()
|
745
|
+
|
704
746
|
print(f"{COLORS['red']}Error condensing analysis chunk {i+1}: {str(e)}{COLORS['reset']}")
|
705
747
|
if logger:
|
706
748
|
logger.error(f"Error condensing analysis chunk {i+1} at depth {current_depth}: {str(e)}")
|
@@ -708,8 +750,8 @@ SECTION OF ANALYSIS TO CONDENSE:
|
|
708
750
|
|
709
751
|
# Rate limit protection between chunks
|
710
752
|
if i < analysis_chunk_count - 1:
|
711
|
-
|
712
|
-
|
753
|
+
# Use the spinner function with fixed duration
|
754
|
+
spinner("Waiting to avoid rate limits...", 5, color=COLORS['yellow'])
|
713
755
|
|
714
756
|
# Combine condensed chunks
|
715
757
|
combined_condensed = "\n\n".join(condensed_chunks)
|
@@ -818,10 +860,21 @@ REQUIREMENTS:
|
|
818
860
|
if logger:
|
819
861
|
logger.log_template("DEBUG", f"CONDENSE_PROMPT_DEPTH_{current_depth}", condense_prompt)
|
820
862
|
|
821
|
-
|
863
|
+
# Start spinner for condensing
|
864
|
+
stop_spinner = threading.Event()
|
865
|
+
spinner_thread = threading.Thread(
|
866
|
+
target=spinner,
|
867
|
+
args=(f"Condensing commit message (depth {current_depth}/{max_recursion_depth})...",),
|
868
|
+
kwargs={"stop_event": stop_spinner, "color": COLORS['yellow']}
|
869
|
+
)
|
870
|
+
spinner_thread.daemon = True
|
871
|
+
spinner_thread.start()
|
822
872
|
|
823
873
|
try:
|
824
874
|
condensed_result = handle_api_call(client, condense_prompt, system_prompt, logger)
|
875
|
+
# Stop the spinner
|
876
|
+
stop_spinner.set()
|
877
|
+
spinner_thread.join()
|
825
878
|
|
826
879
|
if logger:
|
827
880
|
logger.log_content("DEBUG", f"CONDENSED_RESULT_DEPTH_{current_depth}", condensed_result)
|
@@ -848,6 +901,10 @@ REQUIREMENTS:
|
|
848
901
|
else:
|
849
902
|
return condensed_result
|
850
903
|
except Exception as e:
|
904
|
+
# Stop the spinner
|
905
|
+
stop_spinner.set()
|
906
|
+
spinner_thread.join()
|
907
|
+
|
851
908
|
print(f"{COLORS['red']}Error condensing commit message: {str(e)}{COLORS['reset']}")
|
852
909
|
if logger:
|
853
910
|
logger.error(f"Error condensing commit message at depth {current_depth}: {str(e)}")
|
ngpt/cli/ui.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import sys
|
2
|
+
import time
|
2
3
|
import shutil
|
3
4
|
|
4
5
|
# Optional imports for enhanced UI
|
@@ -151,4 +152,47 @@ def get_multiline_input():
|
|
151
152
|
|
152
153
|
except KeyboardInterrupt:
|
153
154
|
print("\nInput cancelled by user. Exiting gracefully.")
|
154
|
-
return None
|
155
|
+
return None
|
156
|
+
|
157
|
+
def spinner(message, duration=5, spinner_chars="⣾⣽⣻⢿⡿⣟⣯⣷", color=None, stop_event=None):
|
158
|
+
"""Display a spinner animation with a message.
|
159
|
+
|
160
|
+
Args:
|
161
|
+
message: The message to display alongside the spinner
|
162
|
+
duration: Duration in seconds to show the spinner (used if stop_event is None)
|
163
|
+
spinner_chars: Characters to use for the spinner animation
|
164
|
+
color: Optional color from COLORS dict to use for the message
|
165
|
+
stop_event: Optional threading.Event to signal when to stop the spinner
|
166
|
+
If provided, duration is ignored and spinner runs until event is set
|
167
|
+
"""
|
168
|
+
# Default color handling
|
169
|
+
color_start = ""
|
170
|
+
color_end = ""
|
171
|
+
if color:
|
172
|
+
color_start = color
|
173
|
+
color_end = "\033[0m" # Reset
|
174
|
+
|
175
|
+
# Each character shows for 0.2 seconds
|
176
|
+
char_duration = 0.2
|
177
|
+
|
178
|
+
if stop_event:
|
179
|
+
# Run until stop_event is set
|
180
|
+
i = 0
|
181
|
+
while not stop_event.is_set():
|
182
|
+
char = spinner_chars[i % len(spinner_chars)]
|
183
|
+
sys.stdout.write(f"\r{color_start}{message} {char}{color_end}")
|
184
|
+
sys.stdout.flush()
|
185
|
+
i += 1
|
186
|
+
time.sleep(char_duration)
|
187
|
+
else:
|
188
|
+
# Run for fixed duration
|
189
|
+
total_chars = int(duration / char_duration)
|
190
|
+
for i in range(total_chars):
|
191
|
+
char = spinner_chars[i % len(spinner_chars)]
|
192
|
+
sys.stdout.write(f"\r{color_start}{message} {char}{color_end}")
|
193
|
+
sys.stdout.flush()
|
194
|
+
time.sleep(char_duration)
|
195
|
+
|
196
|
+
# Clear the line when done
|
197
|
+
sys.stdout.write("\r" + " " * (len(message) + 10) + "\r")
|
198
|
+
sys.stdout.flush()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ngpt
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.16.0
|
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
|
@@ -8,11 +8,11 @@ ngpt/cli/formatters.py,sha256=HBYGlx_7eoAKyzfy0Vq5L0yn8yVKjngqYBukMmXCcz0,9401
|
|
8
8
|
ngpt/cli/interactive.py,sha256=DZFbExcXd7RylkpBiZBhiI6N8FBaT0m_lBes0Pvhi48,10894
|
9
9
|
ngpt/cli/main.py,sha256=6GO4r9e9su7FFukj9JeVmJt1bJsqPOJBj6xo3iyMZXU,28911
|
10
10
|
ngpt/cli/renderers.py,sha256=gJ3WdVvCGkNxrLEkLCh6gk9HBFMK8y7an6CsEkqt2Z8,10535
|
11
|
-
ngpt/cli/ui.py,sha256=
|
11
|
+
ngpt/cli/ui.py,sha256=j3i1Zyv5Yop8zpl1EqP03VmzEmbu4LamCxCsDlnvc58,6962
|
12
12
|
ngpt/cli/modes/__init__.py,sha256=R3aO662RIzWEOvr3moTrEI8Tpg0zDDyMGGh1-OxiRgM,285
|
13
13
|
ngpt/cli/modes/chat.py,sha256=4a5EgM_5A1zCSrLrjgQMDnBwIHd1Rnu5_BjSKSm7p24,4255
|
14
14
|
ngpt/cli/modes/code.py,sha256=RjOAj7BDO5vLUdIPkUfPtyIkI_W6qEHsZvYh-sIdVaM,4293
|
15
|
-
ngpt/cli/modes/gitcommsg.py,sha256=
|
15
|
+
ngpt/cli/modes/gitcommsg.py,sha256=Bhgg9UArrfRUwosgVlNLUB7i1B8j-1ngpkmCm5iZBkM,46786
|
16
16
|
ngpt/cli/modes/rewrite.py,sha256=Zb0PFvWRKXs4xJCF3GEdYc-LSmy6qRszz8-QJuldHc0,8595
|
17
17
|
ngpt/cli/modes/shell.py,sha256=lF9f7w-0bl_FdZl-WJnZuV736BKrWQtrwoKr3ejPXFE,2682
|
18
18
|
ngpt/cli/modes/text.py,sha256=ncYnfLFMdTPuHiOvAaHNiOWhox6GF6S-2fTwMIrAz-g,3140
|
@@ -20,8 +20,8 @@ ngpt/utils/__init__.py,sha256=E46suk2-QgYBI0Qrs6WXOajOUOebF3ETAFY7ah8DTWs,942
|
|
20
20
|
ngpt/utils/cli_config.py,sha256=tQxR3a2iXyc5TfRBPQHSUXPInO2dv_zTPGn04eWfmoo,11285
|
21
21
|
ngpt/utils/config.py,sha256=WYOk_b1eiYjo6hpV3pfXr2RjqhOnmKqwZwKid1T41I4,10363
|
22
22
|
ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
|
23
|
-
ngpt-2.
|
24
|
-
ngpt-2.
|
25
|
-
ngpt-2.
|
26
|
-
ngpt-2.
|
27
|
-
ngpt-2.
|
23
|
+
ngpt-2.16.0.dist-info/METADATA,sha256=T5OEQ8AtdLDyct1rLRKElBBUCZgehw1iesLMhZrcnKA,23523
|
24
|
+
ngpt-2.16.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
25
|
+
ngpt-2.16.0.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
|
26
|
+
ngpt-2.16.0.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
|
27
|
+
ngpt-2.16.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|