ngpt 2.15.2__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.
@@ -4,6 +4,7 @@ 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
@@ -498,12 +499,27 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
498
499
  logger.log_template("DEBUG", "CHUNK", chunk_prompt)
499
500
 
500
501
  # Process chunk - use technical system prompt for analysis
501
- print(f"{COLORS['yellow']}Analyzing changes...{COLORS['reset']}")
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
+
502
511
  try:
503
512
  result = handle_api_call(client, chunk_prompt, technical_system_prompt, logger)
504
- partial_analyses.append(result)
513
+ # Stop the spinner
514
+ stop_spinner.set()
515
+ spinner_thread.join()
516
+ # Show success message
505
517
  print(f"{COLORS['green']}✓ Chunk {i+1} processed{COLORS['reset']}")
518
+ partial_analyses.append(result)
506
519
  except Exception as e:
520
+ # Stop the spinner
521
+ stop_spinner.set()
522
+ spinner_thread.join()
507
523
  print(f"{COLORS['red']}Error processing chunk {i+1}: {str(e)}{COLORS['reset']}")
508
524
  if logger:
509
525
  logger.error(f"Error processing chunk {i+1}: {str(e)}")
@@ -511,7 +527,7 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
511
527
 
512
528
  # Rate limit protection between chunks
513
529
  if i < chunk_count - 1:
514
- # Use the spinner function
530
+ # Use the spinner function with fixed duration
515
531
  spinner("Waiting to avoid rate limits...", 5, color=COLORS['yellow'])
516
532
 
517
533
  # Combine partial analyses
@@ -539,7 +555,16 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
539
555
  )
540
556
  else:
541
557
  # Combined analysis is under the chunk size limit, generate the commit message
542
- print(f"{COLORS['green']}Generating commit message from combined analysis...{COLORS['reset']}")
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
+
543
568
  combine_prompt = create_combine_prompt(partial_analyses)
544
569
 
545
570
  # Log combine template
@@ -550,6 +575,10 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
550
575
  # Use commit message system prompt for final generation
551
576
  commit_message = handle_api_call(client, combine_prompt, commit_system_prompt, logger)
552
577
 
578
+ # Stop the spinner
579
+ stop_spinner.set()
580
+ spinner_thread.join()
581
+
553
582
  # If the commit message is too long, we need to condense it
554
583
  if len(commit_message.splitlines()) > max_msg_lines:
555
584
  return condense_commit_message(
@@ -563,6 +592,10 @@ def process_with_chunking(client, diff_content, context, chunk_size=200, recursi
563
592
  )
564
593
  return commit_message
565
594
  except Exception as e:
595
+ # Stop the spinner
596
+ stop_spinner.set()
597
+ spinner_thread.join()
598
+
566
599
  print(f"{COLORS['red']}Error combining analyses: {str(e)}{COLORS['reset']}")
567
600
  if logger:
568
601
  logger.error(f"Error combining analyses: {str(e)}")
@@ -683,18 +716,33 @@ SECTION OF ANALYSIS TO CONDENSE:
683
716
  if logger:
684
717
  logger.log_template("DEBUG", f"CONDENSE_ANALYSIS_DEPTH_{current_depth}_CHUNK_{i+1}", condense_prompt)
685
718
 
686
- print(f"{COLORS['yellow']}Condensing analysis chunk {i+1}/{analysis_chunk_count}...{COLORS['reset']}")
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()
687
728
 
688
729
  # Condense this analysis chunk - use technical system prompt for condensing analysis
689
730
  try:
690
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']}")
691
737
  condensed_chunks.append(condensed_chunk)
692
738
 
693
739
  if logger:
694
740
  logger.log_content("DEBUG", f"CONDENSED_ANALYSIS_DEPTH_{current_depth}_CHUNK_{i+1}", condensed_chunk)
695
-
696
- print(f"{COLORS['green']}✓ Analysis chunk {i+1}/{analysis_chunk_count} condensed{COLORS['reset']}")
697
741
  except Exception as e:
742
+ # Stop the spinner
743
+ stop_spinner.set()
744
+ spinner_thread.join()
745
+
698
746
  print(f"{COLORS['red']}Error condensing analysis chunk {i+1}: {str(e)}{COLORS['reset']}")
699
747
  if logger:
700
748
  logger.error(f"Error condensing analysis chunk {i+1} at depth {current_depth}: {str(e)}")
@@ -702,7 +750,7 @@ SECTION OF ANALYSIS TO CONDENSE:
702
750
 
703
751
  # Rate limit protection between chunks
704
752
  if i < analysis_chunk_count - 1:
705
- # Use the spinner function
753
+ # Use the spinner function with fixed duration
706
754
  spinner("Waiting to avoid rate limits...", 5, color=COLORS['yellow'])
707
755
 
708
756
  # Combine condensed chunks
@@ -812,10 +860,21 @@ REQUIREMENTS:
812
860
  if logger:
813
861
  logger.log_template("DEBUG", f"CONDENSE_PROMPT_DEPTH_{current_depth}", condense_prompt)
814
862
 
815
- print(f"{COLORS['yellow']}Condensing commit message (depth {current_depth}/{max_recursion_depth})...{COLORS['reset']}")
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()
816
872
 
817
873
  try:
818
874
  condensed_result = handle_api_call(client, condense_prompt, system_prompt, logger)
875
+ # Stop the spinner
876
+ stop_spinner.set()
877
+ spinner_thread.join()
819
878
 
820
879
  if logger:
821
880
  logger.log_content("DEBUG", f"CONDENSED_RESULT_DEPTH_{current_depth}", condensed_result)
@@ -842,6 +901,10 @@ REQUIREMENTS:
842
901
  else:
843
902
  return condensed_result
844
903
  except Exception as e:
904
+ # Stop the spinner
905
+ stop_spinner.set()
906
+ spinner_thread.join()
907
+
845
908
  print(f"{COLORS['red']}Error condensing commit message: {str(e)}{COLORS['reset']}")
846
909
  if logger:
847
910
  logger.error(f"Error condensing commit message at depth {current_depth}: {str(e)}")
ngpt/cli/ui.py CHANGED
@@ -154,14 +154,16 @@ def get_multiline_input():
154
154
  print("\nInput cancelled by user. Exiting gracefully.")
155
155
  return None
156
156
 
157
- def spinner(message, duration=5, spinner_chars="⣾⣽⣻⢿⡿⣟⣯⣷", color=None):
157
+ def spinner(message, duration=5, spinner_chars="⣾⣽⣻⢿⡿⣟⣯⣷", color=None, stop_event=None):
158
158
  """Display a spinner animation with a message.
159
159
 
160
160
  Args:
161
161
  message: The message to display alongside the spinner
162
- duration: Duration in seconds to show the spinner
162
+ duration: Duration in seconds to show the spinner (used if stop_event is None)
163
163
  spinner_chars: Characters to use for the spinner animation
164
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
165
167
  """
166
168
  # Default color handling
167
169
  color_start = ""
@@ -172,16 +174,24 @@ def spinner(message, duration=5, spinner_chars="⣾⣽⣻⢿⡿⣟⣯⣷", color
172
174
 
173
175
  # Each character shows for 0.2 seconds
174
176
  char_duration = 0.2
175
- # Total number of characters to show (not iterations through the entire spinner sequence)
176
- total_chars = int(duration / char_duration)
177
177
 
178
- # Run the spinner
179
- for i in range(total_chars):
180
- # Get the appropriate character by cycling through the spinner characters
181
- char = spinner_chars[i % len(spinner_chars)]
182
- sys.stdout.write(f"\r{color_start}{message} {char}{color_end}")
183
- sys.stdout.flush()
184
- time.sleep(char_duration)
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)
185
195
 
186
196
  # Clear the line when done
187
197
  sys.stdout.write("\r" + " " * (len(message) + 10) + "\r")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 2.15.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=gTtxg2E1WJg4W9JQxrUaM83OYjKjv6pOFTOaWlfa6Mw,6548
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=dbT9_Y1RiahJxBXvrKC0IIEddzd7CXjMae7txauOK7Q,44840
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.15.2.dist-info/METADATA,sha256=ZUt1VWznWOfW3-kOB9EgIV8Xkw0x2LdoR8Q9BTMeOkg,23523
24
- ngpt-2.15.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- ngpt-2.15.2.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
26
- ngpt-2.15.2.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
27
- ngpt-2.15.2.dist-info/RECORD,,
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