ngpt 3.5.1__py3-none-any.whl → 3.5.3__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/chat.py CHANGED
@@ -59,8 +59,31 @@ def chat_mode(client, args, logger=None):
59
59
  if args.web_search:
60
60
  try:
61
61
  original_prompt = prompt
62
- prompt = enhance_prompt_with_web_search(prompt, logger=logger)
63
- print("Enhanced input with web search results.")
62
+
63
+ # Start spinner for web search
64
+ stop_spinner = threading.Event()
65
+ spinner_thread = threading.Thread(
66
+ target=spinner,
67
+ args=("Searching the web for information...",),
68
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
69
+ )
70
+ spinner_thread.daemon = True
71
+ spinner_thread.start()
72
+
73
+ try:
74
+ prompt = enhance_prompt_with_web_search(prompt, logger=logger)
75
+ # Stop the spinner
76
+ stop_spinner.set()
77
+ spinner_thread.join()
78
+ # Clear the spinner line completely
79
+ sys.stdout.write("\r" + " " * 100 + "\r")
80
+ sys.stdout.flush()
81
+ print("Enhanced input with web search results.")
82
+ except Exception as e:
83
+ # Stop the spinner before re-raising
84
+ stop_spinner.set()
85
+ spinner_thread.join()
86
+ raise e
64
87
 
65
88
  # Log the enhanced prompt if logging is enabled
66
89
  if logger:
ngpt/cli/modes/code.py CHANGED
@@ -4,6 +4,29 @@ from ..ui import spinner
4
4
  from ...utils import enhance_prompt_with_web_search
5
5
  import sys
6
6
  import threading
7
+ import platform
8
+
9
+ def get_terminal_input():
10
+ """Get input from terminal in a cross-platform way, even when stdin is redirected."""
11
+ if platform.system() == 'Windows':
12
+ # Windows-specific solution
13
+ try:
14
+ import msvcrt
15
+ sys.stdout.flush()
16
+ # Wait for a keypress
17
+ char = msvcrt.getch().decode('utf-8').lower()
18
+ print(char) # Echo the character
19
+ return char
20
+ except ImportError:
21
+ # Fallback if msvcrt is not available
22
+ return None
23
+ else:
24
+ # Unix-like systems (Linux, macOS)
25
+ try:
26
+ with open('/dev/tty', 'r') as tty:
27
+ return tty.readline().strip().lower()
28
+ except (IOError, OSError):
29
+ return None
7
30
 
8
31
  # System prompt for code generation with markdown formatting
9
32
  CODE_SYSTEM_PROMPT_MARKDOWN = """Your Role: Provide only code as output without any description with proper markdown formatting.
@@ -105,8 +128,31 @@ def code_mode(client, args, logger=None):
105
128
  if args.web_search:
106
129
  try:
107
130
  original_prompt = prompt
108
- prompt = enhance_prompt_with_web_search(prompt, logger=logger, disable_citations=True)
109
- print("Enhanced input with web search results.")
131
+
132
+ # Start spinner for web search
133
+ stop_spinner = threading.Event()
134
+ spinner_thread = threading.Thread(
135
+ target=spinner,
136
+ args=("Searching the web for information...",),
137
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
138
+ )
139
+ spinner_thread.daemon = True
140
+ spinner_thread.start()
141
+
142
+ try:
143
+ prompt = enhance_prompt_with_web_search(prompt, logger=logger, disable_citations=True)
144
+ # Stop the spinner
145
+ stop_spinner.set()
146
+ spinner_thread.join()
147
+ # Clear the spinner line completely
148
+ sys.stdout.write("\r" + " " * 100 + "\r")
149
+ sys.stdout.flush()
150
+ print("Enhanced input with web search results.")
151
+ except Exception as e:
152
+ # Stop the spinner before re-raising
153
+ stop_spinner.set()
154
+ spinner_thread.join()
155
+ raise e
110
156
 
111
157
  # Log the enhanced prompt if logging is enabled
112
158
  if logger:
@@ -275,4 +321,27 @@ def code_mode(client, args, logger=None):
275
321
  prettify_markdown(generated_code, args.renderer)
276
322
  else:
277
323
  # Should only happen if --no-stream was used without prettify
278
- print(f"\nGenerated code:\n{generated_code}")
324
+ print(f"\nGenerated code:\n{generated_code}")
325
+
326
+ # Offer to copy to clipboard if not in a redirected output
327
+ if generated_code and not args.no_stream and sys.stdout.isatty():
328
+ try:
329
+ # Make sure to flush output before asking for input
330
+ # Make the prompt more visible with colors and formatting
331
+ clipboard_prompt = f"{COLORS['cyan']}{COLORS['bold']}Copy to clipboard? (y/n){COLORS['reset']} "
332
+ print(clipboard_prompt, end="")
333
+ sys.stdout.flush()
334
+
335
+ # Cross-platform terminal input
336
+ answer = get_terminal_input()
337
+
338
+ if answer == 'y':
339
+ try:
340
+ import pyperclip
341
+ pyperclip.copy(generated_code)
342
+ print(f"{COLORS['green']}Copied to clipboard.{COLORS['reset']}")
343
+ except ImportError:
344
+ print(f"{COLORS['yellow']}pyperclip not installed. Try: pip install \"ngpt[clipboard]\" {COLORS['reset']}")
345
+
346
+ except (KeyboardInterrupt, EOFError):
347
+ pass
@@ -6,6 +6,7 @@ import sys
6
6
  import time
7
7
  from ..formatters import COLORS
8
8
  from ..renderers import prettify_markdown, prettify_streaming_markdown
9
+ from ..ui import spinner
9
10
  from ...utils import enhance_prompt_with_web_search
10
11
 
11
12
  # Optional imports for enhanced UI
@@ -198,9 +199,30 @@ def interactive_chat_session(client, web_search=False, no_stream=False, temperat
198
199
  enhanced_prompt = user_input
199
200
  if web_search:
200
201
  try:
201
- print(f"{COLORS['cyan']}Searching the web...{COLORS['reset']}")
202
- enhanced_prompt = enhance_prompt_with_web_search(user_input, logger=logger)
203
- print(f"{COLORS['green']}Enhanced input with web search results.{COLORS['reset']}")
202
+ # Start spinner for web search
203
+ stop_spinner = threading.Event()
204
+ spinner_thread = threading.Thread(
205
+ target=spinner,
206
+ args=("Searching the web for information...",),
207
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
208
+ )
209
+ spinner_thread.daemon = True
210
+ spinner_thread.start()
211
+
212
+ try:
213
+ enhanced_prompt = enhance_prompt_with_web_search(user_input, logger=logger)
214
+ # Stop the spinner
215
+ stop_spinner.set()
216
+ spinner_thread.join()
217
+ # Clear the spinner line completely
218
+ sys.stdout.write("\r" + " " * shutil.get_terminal_size().columns + "\r")
219
+ sys.stdout.flush()
220
+ print(f"{COLORS['green']}Enhanced input with web search results.{COLORS['reset']}")
221
+ except Exception as e:
222
+ # Stop the spinner before re-raising
223
+ stop_spinner.set()
224
+ spinner_thread.join()
225
+ raise e
204
226
 
205
227
  # Update the user message in conversation with enhanced prompt
206
228
  for i in range(len(conversation) - 1, -1, -1):
ngpt/cli/modes/rewrite.py CHANGED
@@ -130,8 +130,31 @@ def rewrite_mode(client, args, logger=None):
130
130
  if args.web_search:
131
131
  try:
132
132
  original_text = input_text
133
- input_text = enhance_prompt_with_web_search(input_text, logger=logger)
134
- print("Enhanced input with web search results.")
133
+
134
+ # Start spinner for web search
135
+ stop_spinner = threading.Event()
136
+ spinner_thread = threading.Thread(
137
+ target=spinner,
138
+ args=("Searching the web for information...",),
139
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
140
+ )
141
+ spinner_thread.daemon = True
142
+ spinner_thread.start()
143
+
144
+ try:
145
+ input_text = enhance_prompt_with_web_search(input_text, logger=logger)
146
+ # Stop the spinner
147
+ stop_spinner.set()
148
+ spinner_thread.join()
149
+ # Clear the spinner line completely
150
+ sys.stdout.write("\r" + " " * 100 + "\r")
151
+ sys.stdout.flush()
152
+ print("Enhanced input with web search results.")
153
+ except Exception as e:
154
+ # Stop the spinner before re-raising
155
+ stop_spinner.set()
156
+ spinner_thread.join()
157
+ raise e
135
158
 
136
159
  # Log the enhanced input if logging is enabled
137
160
  if logger:
ngpt/cli/modes/shell.py CHANGED
@@ -60,8 +60,31 @@ def shell_mode(client, args, logger=None):
60
60
  if args.web_search:
61
61
  try:
62
62
  original_prompt = prompt
63
- prompt = enhance_prompt_with_web_search(prompt, logger=logger, disable_citations=True)
64
- print("Enhanced input with web search results.")
63
+
64
+ # Start spinner for web search
65
+ stop_spinner = threading.Event()
66
+ spinner_thread = threading.Thread(
67
+ target=spinner,
68
+ args=("Searching the web for information...",),
69
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
70
+ )
71
+ spinner_thread.daemon = True
72
+ spinner_thread.start()
73
+
74
+ try:
75
+ prompt = enhance_prompt_with_web_search(prompt, logger=logger, disable_citations=True)
76
+ # Stop the spinner
77
+ stop_spinner.set()
78
+ spinner_thread.join()
79
+ # Clear the spinner line completely
80
+ sys.stdout.write("\r" + " " * 100 + "\r")
81
+ sys.stdout.flush()
82
+ print("Enhanced input with web search results.")
83
+ except Exception as e:
84
+ # Stop the spinner before re-raising
85
+ stop_spinner.set()
86
+ spinner_thread.join()
87
+ raise e
65
88
 
66
89
  # Log the enhanced prompt if logging is enabled
67
90
  if logger:
ngpt/cli/modes/text.py CHANGED
@@ -30,8 +30,31 @@ def text_mode(client, args, logger=None):
30
30
  if args.web_search:
31
31
  try:
32
32
  original_prompt = prompt
33
- prompt = enhance_prompt_with_web_search(prompt, logger=logger)
34
- print("Enhanced input with web search results.")
33
+
34
+ # Start spinner for web search
35
+ stop_spinner = threading.Event()
36
+ spinner_thread = threading.Thread(
37
+ target=spinner,
38
+ args=("Searching the web for information...",),
39
+ kwargs={"stop_event": stop_spinner, "color": COLORS['cyan']}
40
+ )
41
+ spinner_thread.daemon = True
42
+ spinner_thread.start()
43
+
44
+ try:
45
+ prompt = enhance_prompt_with_web_search(prompt, logger=logger)
46
+ # Stop the spinner
47
+ stop_spinner.set()
48
+ spinner_thread.join()
49
+ # Clear the spinner line completely
50
+ sys.stdout.write("\r" + " " * 100 + "\r")
51
+ sys.stdout.flush()
52
+ print("Enhanced input with web search results.")
53
+ except Exception as e:
54
+ # Stop the spinner before re-raising
55
+ stop_spinner.set()
56
+ spinner_thread.join()
57
+ raise e
35
58
 
36
59
  # Log the enhanced prompt if logging is enabled
37
60
  if logger:
ngpt/utils/web_search.py CHANGED
@@ -31,10 +31,10 @@ def get_logger():
31
31
  if _logger is not None:
32
32
  return _logger
33
33
  else:
34
- # Default logging to stderr if no logger provided, but only for errors
34
+ # Default logging behavior - suppress all messages to console
35
35
  class DefaultLogger:
36
36
  def info(self, msg): pass # Suppress INFO messages
37
- def error(self, msg): print(f"ERROR: {msg}", file=sys.stderr)
37
+ def error(self, msg): pass # Suppress ERROR messages instead of printing to stderr
38
38
  def warning(self, msg): pass # Suppress WARNING messages
39
39
  def debug(self, msg): pass
40
40
  return DefaultLogger()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 3.5.1
3
+ Version: 3.5.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
@@ -45,16 +45,16 @@ Description-Content-Type: text/markdown
45
45
  </p>
46
46
 
47
47
  <p align="center">
48
- <a href="https://nazdridoy.github.io/ngpt/installation/"><img src="https://img.shields.io/badge/Linux-support-blue?logo=linux" alt="Linux"></a>
49
- <a href="https://nazdridoy.github.io/ngpt/installation/"><img src="https://img.shields.io/badge/Windows-support-blue?logo=windows" alt="Windows"></a>
50
- <a href="https://nazdridoy.github.io/ngpt/installation/"><img src="https://img.shields.io/badge/macOS-support-blue?logo=apple" alt="macOS"></a>
51
- <a href="https://nazdridoy.github.io/ngpt/installation/"><img src="https://img.shields.io/badge/Android-Termux-blue?logo=android" alt="Android"></a>
48
+ <a href="https://nazdridoy.github.io/ngpt/installation/#linuxmacos"><img src="https://img.shields.io/badge/Linux-support-blue?logo=linux" alt="Linux"></a>
49
+ <a href="https://nazdridoy.github.io/ngpt/installation/#windows"><img src="https://img.shields.io/badge/Windows-support-blue?logo=windows" alt="Windows"></a>
50
+ <a href="https://nazdridoy.github.io/ngpt/installation/#linuxmacos"><img src="https://img.shields.io/badge/macOS-support-blue?logo=apple" alt="macOS"></a>
51
+ <a href="https://nazdridoy.github.io/ngpt/installation/#android-termux"><img src="https://img.shields.io/badge/Android-Termux-blue?logo=android" alt="Android"></a>
52
52
  </p>
53
53
 
54
54
  🤖 nGPT: A 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. Fast, lightweight, and designed for both casual users and developers.
55
55
 
56
56
 
57
- ![2025-04-23_16-18-01](https://github.com/user-attachments/assets/b8e58926-5165-4352-b48b-9f4a982da86e)
57
+ ![ngpt-i](https://raw.githubusercontent.com/nazdridoy/ngpt/main/previews/ngpt-i.png)
58
58
 
59
59
 
60
60
  ## Features
@@ -9,20 +9,20 @@ ngpt/cli/main.py,sha256=oKX7ryTIrsvQRJHVnH2a763pGyNZthq81wkrRILwHLw,28932
9
9
  ngpt/cli/renderers.py,sha256=m71BeUXKynpKKGXFzwRSW1XngvyKiZ_xEsdujUbU0MA,16597
10
10
  ngpt/cli/ui.py,sha256=HoHDFpLiwMBP5wtMb8YYo244FMiqiPFRoBNcNGp6N0A,7310
11
11
  ngpt/cli/modes/__init__.py,sha256=KP7VR6Xw9k1p5Jcu0F38RDxSFvFIzH3j1ThDLNwznUI,363
12
- ngpt/cli/modes/chat.py,sha256=pv8Ec1l3XsHnW1o3iukxmKg3pK4UJeODl8mC73MH0qg,6927
13
- ngpt/cli/modes/code.py,sha256=ounayP8exu8Bb8QFL4TcyF2d3QI_QlsG5tf6v1FktxE,11470
12
+ ngpt/cli/modes/chat.py,sha256=jfKkrtSkx1gKPsKXDMxZ7BiJiMsCtFHyZCGIdmNQ0fk,7816
13
+ ngpt/cli/modes/code.py,sha256=RvVojJIm0jQnwzJ4tlKd4j4CFZuJOGc_YJ3RDjUNXOs,14181
14
14
  ngpt/cli/modes/gitcommsg.py,sha256=rsfMoeOupmNp-5p5fsMSPAf18BbzXWq-4PF2HjEz6SY,46991
15
- ngpt/cli/modes/interactive.py,sha256=COJABbSgfyVC98lvFD1K2yqKPqyH20vbVrYYh8oiPUk,16395
16
- ngpt/cli/modes/rewrite.py,sha256=ftD-6M9iQ7g4rLdlKyyLTRiJWYtbz64LIG4PIByxmOk,11472
17
- ngpt/cli/modes/shell.py,sha256=9oaOvzKc0VZ0Hjervbzo_kryMlYVZH0IXhc0MaBTYVk,8008
18
- ngpt/cli/modes/text.py,sha256=gdn4opioZ6G3nvfrTkp-dpoD-Of_ZvjVVRggVd6edkg,5528
15
+ ngpt/cli/modes/interactive.py,sha256=TtBrZUX45CVfKOPvkb1ya7dIQhXLILtn7ajmfM9ohso,17419
16
+ ngpt/cli/modes/rewrite.py,sha256=9o37-o5Q8SGfJ91-8pD4h7d5RsJeu85OEdv3nXKzQiA,12361
17
+ ngpt/cli/modes/shell.py,sha256=FaFOzxTxPJCpYsiQJIttS69fZg-asV4LVA5TLaGVN0Y,8897
18
+ ngpt/cli/modes/text.py,sha256=7t5WWXMFxGkBM5HMP4irbN9aQwxE2YgywjiVPep710k,6417
19
19
  ngpt/utils/__init__.py,sha256=qu_66I1Vtav2f1LDiPn5J3DUsbK7o1CSScMcTkYqxoM,1179
20
20
  ngpt/utils/cli_config.py,sha256=Ug8cECBTIuzOwkBWidLTfs-OAdOsCMJ2bNa70pOADfw,11195
21
21
  ngpt/utils/config.py,sha256=wsArA4osnh8fKqOvtsPqqBxAz3DpdjtaWUFaRtnUdyc,10452
22
22
  ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
23
- ngpt/utils/web_search.py,sha256=TK_c2U8MYM86f9J_oEzi0UZ46JohvyxdjfonHZZZqfY,30718
24
- ngpt-3.5.1.dist-info/METADATA,sha256=djECxREmLWeO-ugYuco3gi2xEJqaGuFpjJopqa3veLI,23886
25
- ngpt-3.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- ngpt-3.5.1.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
27
- ngpt-3.5.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
28
- ngpt-3.5.1.dist-info/RECORD,,
23
+ ngpt/utils/web_search.py,sha256=w5ke4KJMRxq7r5jtbUXvspja6XhjoPZloVkZ0IvBXIE,30731
24
+ ngpt-3.5.3.dist-info/METADATA,sha256=_Z2B2bvNXf-h03702SQ85UFPWLJUTFqcfXBJRtr2fTE,23912
25
+ ngpt-3.5.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
+ ngpt-3.5.3.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
27
+ ngpt-3.5.3.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
28
+ ngpt-3.5.3.dist-info/RECORD,,
File without changes