ngpt 2.12.0__py3-none-any.whl → 2.14.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/args.py +17 -0
- ngpt/cli/formatters.py +1 -0
- ngpt/cli/main.py +28 -10
- ngpt/cli/modes/__init__.py +3 -1
- ngpt/cli/modes/gitcommsg.py +730 -0
- ngpt/cli/modes/rewrite.py +209 -0
- ngpt/utils/cli_config.py +6 -0
- ngpt/utils/log.py +305 -5
- {ngpt-2.12.0.dist-info → ngpt-2.14.0.dist-info}/METADATA +73 -28
- {ngpt-2.12.0.dist-info → ngpt-2.14.0.dist-info}/RECORD +13 -11
- {ngpt-2.12.0.dist-info → ngpt-2.14.0.dist-info}/WHEEL +0 -0
- {ngpt-2.12.0.dist-info → ngpt-2.14.0.dist-info}/entry_points.txt +0 -0
- {ngpt-2.12.0.dist-info → ngpt-2.14.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
import sys
|
2
|
+
import platform
|
3
|
+
from ..formatters import COLORS
|
4
|
+
from ..renderers import prettify_markdown, prettify_streaming_markdown
|
5
|
+
from ..ui import get_multiline_input
|
6
|
+
|
7
|
+
# System prompt for rewriting text
|
8
|
+
REWRITE_SYSTEM_PROMPT = """You are an expert text editor and rewriter. Your task is to rewrite the user's text to improve readability and flow while carefully preserving the original meaning, tone, and style.
|
9
|
+
|
10
|
+
PRIMARY GOAL:
|
11
|
+
Improve the quality and clarity of writing without changing the author's voice or intent.
|
12
|
+
|
13
|
+
PRESERVATION RULES (HIGHEST PRIORITY):
|
14
|
+
1. Preserve the exact meaning and information content
|
15
|
+
2. Maintain the original tone (formal/casual/technical/friendly/serious/rude)
|
16
|
+
3. Keep the author's perspective and point of view
|
17
|
+
4. Respect the style of expression when intentional
|
18
|
+
5. Retain technical terminology, jargon, and domain-specific language
|
19
|
+
6. Keep all facts, data points, quotes, and references exactly as provided
|
20
|
+
|
21
|
+
IMPROVEMENT FOCUS:
|
22
|
+
1. Fix grammar, spelling, and punctuation errors
|
23
|
+
2. Improve sentence structure and flow
|
24
|
+
3. Enhance clarity and readability
|
25
|
+
4. Make language more concise and precise
|
26
|
+
5. Replace awkward phrasings with more natural alternatives
|
27
|
+
6. Break up sentences longer than 25 words
|
28
|
+
7. Convert passive voice to active when appropriate
|
29
|
+
8. Remove redundancies, filler words, and unnecessary repetition
|
30
|
+
|
31
|
+
FORMAT PRESERVATION:
|
32
|
+
1. Maintain all paragraph breaks and section structures
|
33
|
+
2. Preserve formatting of lists, bullet points, and numbering
|
34
|
+
3. Keep code blocks (```) exactly as they appear with no changes to code
|
35
|
+
4. Respect all markdown formatting (bold, italic, headers, etc.)
|
36
|
+
5. Preserve URLs, email addresses, file paths, and variables exactly
|
37
|
+
6. Maintain the structure of tables and other special formats
|
38
|
+
|
39
|
+
CONTENT-SPECIFIC GUIDANCE:
|
40
|
+
- For technical content: Prioritize precision and clarity over stylistic changes
|
41
|
+
- For casual text: Maintain conversational flow and personality
|
42
|
+
- For formal writing: Preserve professionalism while improving structure
|
43
|
+
- For emotional content: Carefully maintain the emotional resonance and intensity
|
44
|
+
|
45
|
+
STRICTLY AVOID:
|
46
|
+
1. Adding new information not present in the original
|
47
|
+
2. Removing key points or substantive content
|
48
|
+
3. Significantly changing the formality level
|
49
|
+
4. Inserting your own opinions or commentary
|
50
|
+
5. Explaining what you changed (just provide the improved text)
|
51
|
+
6. Altering the meaning of any sentence, even slightly
|
52
|
+
7. Changing domain-specific terminology or jargon to general terms
|
53
|
+
|
54
|
+
OUTPUT INSTRUCTION:
|
55
|
+
Provide ONLY the rewritten text with no explanations, comments, or meta-text.
|
56
|
+
|
57
|
+
EXAMPLES:
|
58
|
+
|
59
|
+
ORIGINAL: "The implementation of the feature, which was delayed due to unforeseen technical complications, is now scheduled for next week's release."
|
60
|
+
BETTER: "We delayed the feature implementation due to unforeseen technical complications. It's now scheduled for next week's release."
|
61
|
+
|
62
|
+
ORIGINAL: "We was hoping you could help with this issue what we are having with the server."
|
63
|
+
BETTER: "We were hoping you could help with this issue we're having with the server."
|
64
|
+
|
65
|
+
ORIGINAL: "The user interface, which is built using React, Redux, and various other frontend technologies, needs to be redesigned to accommodate the new features that we want to add to the application."
|
66
|
+
BETTER: "The React/Redux user interface needs redesigning to accommodate our planned new features."
|
67
|
+
"""
|
68
|
+
|
69
|
+
def get_terminal_input():
|
70
|
+
"""Get input from terminal in a cross-platform way, even when stdin is redirected."""
|
71
|
+
if platform.system() == 'Windows':
|
72
|
+
# Windows-specific solution
|
73
|
+
try:
|
74
|
+
import msvcrt
|
75
|
+
print("Press Y/N...", end="")
|
76
|
+
sys.stdout.flush()
|
77
|
+
# Wait for a keypress
|
78
|
+
char = msvcrt.getch().decode('utf-8').lower()
|
79
|
+
print(char) # Echo the character
|
80
|
+
return char
|
81
|
+
except ImportError:
|
82
|
+
# Fallback if msvcrt is not available
|
83
|
+
return None
|
84
|
+
else:
|
85
|
+
# Unix-like systems (Linux, macOS)
|
86
|
+
try:
|
87
|
+
with open('/dev/tty', 'r') as tty:
|
88
|
+
return tty.readline().strip().lower()
|
89
|
+
except (IOError, OSError):
|
90
|
+
return None
|
91
|
+
|
92
|
+
def rewrite_mode(client, args, logger=None):
|
93
|
+
"""Handle the text rewriting mode.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
client: The NGPTClient instance
|
97
|
+
args: The parsed command-line arguments
|
98
|
+
logger: Optional logger instance
|
99
|
+
"""
|
100
|
+
# Determine the input source (stdin pipe, command-line argument, or multiline input)
|
101
|
+
if not sys.stdin.isatty():
|
102
|
+
# Read from stdin if data is piped
|
103
|
+
input_text = sys.stdin.read().strip()
|
104
|
+
|
105
|
+
# If stdin is empty but prompt is provided, use the prompt
|
106
|
+
if not input_text and args.prompt:
|
107
|
+
input_text = args.prompt
|
108
|
+
elif args.prompt:
|
109
|
+
# Use the command-line argument if provided
|
110
|
+
input_text = args.prompt
|
111
|
+
else:
|
112
|
+
# No pipe or prompt - use multiline input
|
113
|
+
print("Enter or paste text to rewrite (Ctrl+D or Ctrl+Z to submit):")
|
114
|
+
input_text = get_multiline_input()
|
115
|
+
if input_text is None:
|
116
|
+
# Input was cancelled or empty
|
117
|
+
print("Exiting.")
|
118
|
+
return
|
119
|
+
|
120
|
+
# Check if input is empty
|
121
|
+
if not input_text:
|
122
|
+
print(f"{COLORS['yellow']}Error: Empty input. Please provide text to rewrite.{COLORS['reset']}")
|
123
|
+
return
|
124
|
+
|
125
|
+
# Set up messages array with system prompt and user content
|
126
|
+
messages = [
|
127
|
+
{"role": "system", "content": REWRITE_SYSTEM_PROMPT},
|
128
|
+
{"role": "user", "content": input_text}
|
129
|
+
]
|
130
|
+
|
131
|
+
print("\nSubmission successful. Waiting for response...")
|
132
|
+
|
133
|
+
# Log the messages if logging is enabled
|
134
|
+
if logger:
|
135
|
+
logger.log("system", REWRITE_SYSTEM_PROMPT)
|
136
|
+
logger.log("user", input_text)
|
137
|
+
|
138
|
+
# Set default streaming behavior based on --no-stream and --prettify arguments
|
139
|
+
should_stream = not args.no_stream and not args.prettify
|
140
|
+
|
141
|
+
# If stream-prettify is enabled
|
142
|
+
stream_callback = None
|
143
|
+
live_display = None
|
144
|
+
|
145
|
+
if args.stream_prettify:
|
146
|
+
should_stream = True # Enable streaming
|
147
|
+
live_display, stream_callback = prettify_streaming_markdown(args.renderer)
|
148
|
+
if not live_display:
|
149
|
+
# Fallback to normal prettify if live display setup failed
|
150
|
+
args.prettify = True
|
151
|
+
args.stream_prettify = False
|
152
|
+
should_stream = False
|
153
|
+
print(f"{COLORS['yellow']}Falling back to regular prettify mode.{COLORS['reset']}")
|
154
|
+
|
155
|
+
# If regular prettify is enabled with streaming, inform the user
|
156
|
+
if args.prettify and not args.no_stream:
|
157
|
+
print(f"{COLORS['yellow']}Note: Streaming disabled to enable markdown rendering.{COLORS['reset']}")
|
158
|
+
|
159
|
+
# Start live display if using stream-prettify
|
160
|
+
if args.stream_prettify and live_display:
|
161
|
+
live_display.start()
|
162
|
+
|
163
|
+
response = client.chat(
|
164
|
+
prompt=None, # Not used when messages are provided
|
165
|
+
stream=should_stream,
|
166
|
+
web_search=args.web_search,
|
167
|
+
temperature=args.temperature,
|
168
|
+
top_p=args.top_p,
|
169
|
+
max_tokens=args.max_tokens,
|
170
|
+
markdown_format=args.prettify or args.stream_prettify,
|
171
|
+
stream_callback=stream_callback,
|
172
|
+
messages=messages # Use messages array instead of prompt
|
173
|
+
)
|
174
|
+
|
175
|
+
# Stop live display if using stream-prettify
|
176
|
+
if args.stream_prettify and live_display:
|
177
|
+
live_display.stop()
|
178
|
+
|
179
|
+
# Log the AI response if logging is enabled
|
180
|
+
if logger and response:
|
181
|
+
logger.log("assistant", response)
|
182
|
+
|
183
|
+
# Handle non-stream response or regular prettify
|
184
|
+
if (args.no_stream or args.prettify) and response:
|
185
|
+
if args.prettify:
|
186
|
+
prettify_markdown(response, args.renderer)
|
187
|
+
else:
|
188
|
+
print(response)
|
189
|
+
|
190
|
+
# Offer to copy to clipboard if not in a redirected output
|
191
|
+
if not args.no_stream and sys.stdout.isatty():
|
192
|
+
try:
|
193
|
+
# Make sure to flush output before asking for input
|
194
|
+
print("\nCopy to clipboard? (y/n) ", end="")
|
195
|
+
sys.stdout.flush()
|
196
|
+
|
197
|
+
# Cross-platform terminal input
|
198
|
+
answer = get_terminal_input()
|
199
|
+
|
200
|
+
if answer == 'y':
|
201
|
+
try:
|
202
|
+
import pyperclip
|
203
|
+
pyperclip.copy(response)
|
204
|
+
print("Copied to clipboard.")
|
205
|
+
except ImportError:
|
206
|
+
print(f"{COLORS['yellow']}pyperclip not installed. Try: pip install \"ngpt[clipboard]\" {COLORS['reset']}")
|
207
|
+
|
208
|
+
except (KeyboardInterrupt, EOFError):
|
209
|
+
pass
|
ngpt/utils/cli_config.py
CHANGED
@@ -19,6 +19,12 @@ CLI_CONFIG_OPTIONS = {
|
|
19
19
|
"renderer": {"type": "str", "default": "auto", "context": ["all"]},
|
20
20
|
"config-index": {"type": "int", "default": 0, "context": ["all"], "exclusive": ["provider"]},
|
21
21
|
"web-search": {"type": "bool", "default": False, "context": ["all"]},
|
22
|
+
# GitCommit message options
|
23
|
+
"message-context": {"type": "str", "default": None, "context": ["gitcommsg"]},
|
24
|
+
"recursive-chunk": {"type": "bool", "default": False, "context": ["gitcommsg"]},
|
25
|
+
"diff": {"type": "str", "default": None, "context": ["gitcommsg"]},
|
26
|
+
"chunk-size": {"type": "int", "default": 200, "context": ["gitcommsg"]},
|
27
|
+
"max-depth": {"type": "int", "default": 3, "context": ["gitcommsg"]},
|
22
28
|
}
|
23
29
|
|
24
30
|
def get_cli_config_dir() -> Path:
|
ngpt/utils/log.py
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
import os
|
2
2
|
import sys
|
3
3
|
import datetime
|
4
|
+
import logging
|
5
|
+
import tempfile
|
4
6
|
from pathlib import Path
|
5
|
-
from typing import Optional, TextIO, Dict, Any
|
7
|
+
from typing import Optional, TextIO, Dict, Any, Union
|
6
8
|
|
7
|
-
#
|
9
|
+
# Define colors locally to avoid circular imports
|
8
10
|
COLORS = {
|
9
|
-
"
|
11
|
+
"reset": "\033[0m",
|
12
|
+
"bold": "\033[1m",
|
13
|
+
"cyan": "\033[36m",
|
14
|
+
"green": "\033[32m",
|
10
15
|
"yellow": "\033[33m",
|
11
|
-
"
|
16
|
+
"red": "\033[31m",
|
17
|
+
"blue": "\033[34m",
|
18
|
+
"magenta": "\033[35m",
|
19
|
+
"gray": "\033[90m",
|
20
|
+
"bg_blue": "\033[44m",
|
21
|
+
"bg_cyan": "\033[46m"
|
12
22
|
}
|
13
23
|
|
14
24
|
class Logger:
|
@@ -165,6 +175,281 @@ class Logger:
|
|
165
175
|
"""
|
166
176
|
return self.is_temp
|
167
177
|
|
178
|
+
# Add standard logging methods to be compatible with gitcommsg mode
|
179
|
+
def info(self, message: str):
|
180
|
+
"""Log an info message."""
|
181
|
+
self.log("INFO", message)
|
182
|
+
|
183
|
+
def debug(self, message: str):
|
184
|
+
"""Log a debug message."""
|
185
|
+
self.log("DEBUG", message)
|
186
|
+
|
187
|
+
def warning(self, message: str):
|
188
|
+
"""Log a warning message."""
|
189
|
+
self.log("WARNING", message)
|
190
|
+
|
191
|
+
def error(self, message: str, exc_info=False):
|
192
|
+
"""Log an error message."""
|
193
|
+
if exc_info:
|
194
|
+
import traceback
|
195
|
+
message += "\n" + traceback.format_exc()
|
196
|
+
self.log("ERROR", message)
|
197
|
+
|
198
|
+
|
199
|
+
class GitCommsgLogger:
|
200
|
+
"""Specialized logger for gitcommsg mode with standard logging methods."""
|
201
|
+
|
202
|
+
def __init__(self, log_path: Optional[str] = None):
|
203
|
+
"""
|
204
|
+
Initialize the gitcommsg logger.
|
205
|
+
|
206
|
+
Args:
|
207
|
+
log_path: Optional path to the log file. If None, a temporary file will be created.
|
208
|
+
"""
|
209
|
+
self.log_path = log_path
|
210
|
+
self.logger = None
|
211
|
+
self.is_temp = False
|
212
|
+
self.command_args = sys.argv
|
213
|
+
|
214
|
+
# Create a temporary log file if no path provided
|
215
|
+
if self.log_path is True or self.log_path is None:
|
216
|
+
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
|
217
|
+
if sys.platform == "win32":
|
218
|
+
temp_dir = os.environ.get("TEMP", "")
|
219
|
+
self.log_path = os.path.join(temp_dir, f"ngpt_gitcommsg_{timestamp}.log")
|
220
|
+
else:
|
221
|
+
self.log_path = f"/tmp/ngpt_gitcommsg_{timestamp}.log"
|
222
|
+
self.is_temp = True
|
223
|
+
|
224
|
+
def setup(self):
|
225
|
+
"""Set up the logger."""
|
226
|
+
# Set up Python's standard logging module
|
227
|
+
self.logger = logging.getLogger("gitcommsg")
|
228
|
+
self.logger.setLevel(logging.DEBUG)
|
229
|
+
|
230
|
+
# Clear any existing handlers
|
231
|
+
if self.logger.handlers:
|
232
|
+
for handler in self.logger.handlers:
|
233
|
+
self.logger.removeHandler(handler)
|
234
|
+
|
235
|
+
# Create file handler
|
236
|
+
try:
|
237
|
+
# Ensure the directory exists
|
238
|
+
log_dir = os.path.dirname(self.log_path)
|
239
|
+
if log_dir and not os.path.exists(log_dir):
|
240
|
+
os.makedirs(log_dir, exist_ok=True)
|
241
|
+
|
242
|
+
file_handler = logging.FileHandler(self.log_path)
|
243
|
+
file_handler.setLevel(logging.DEBUG)
|
244
|
+
|
245
|
+
# Create formatter
|
246
|
+
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
|
247
|
+
file_handler.setFormatter(formatter)
|
248
|
+
|
249
|
+
# Add handler to logger
|
250
|
+
self.logger.addHandler(file_handler)
|
251
|
+
|
252
|
+
print(f"{COLORS['green']}Logging enabled. Log file: {self.log_path}{COLORS['reset']}")
|
253
|
+
self.logger.info("GitCommitMsg mode started")
|
254
|
+
self.logger.info(f"Command: {' '.join(self.command_args)}")
|
255
|
+
|
256
|
+
return True
|
257
|
+
except Exception as e:
|
258
|
+
print(f"{COLORS['yellow']}Error setting up logger: {str(e)}{COLORS['reset']}")
|
259
|
+
return False
|
260
|
+
|
261
|
+
def info(self, message: str):
|
262
|
+
"""Log an info message."""
|
263
|
+
if self.logger:
|
264
|
+
self.logger.info(message)
|
265
|
+
|
266
|
+
def debug(self, message: str):
|
267
|
+
"""Log a debug message."""
|
268
|
+
if self.logger:
|
269
|
+
self.logger.debug(message)
|
270
|
+
|
271
|
+
def warning(self, message: str):
|
272
|
+
"""Log a warning message."""
|
273
|
+
if self.logger:
|
274
|
+
self.logger.warning(message)
|
275
|
+
|
276
|
+
def error(self, message: str, exc_info=False):
|
277
|
+
"""Log an error message."""
|
278
|
+
if self.logger:
|
279
|
+
self.logger.error(message, exc_info=exc_info)
|
280
|
+
|
281
|
+
def get_log_path(self) -> str:
|
282
|
+
"""
|
283
|
+
Get the path to the log file.
|
284
|
+
|
285
|
+
Returns:
|
286
|
+
str: Path to the log file
|
287
|
+
"""
|
288
|
+
return self.log_path
|
289
|
+
|
290
|
+
def is_temporary(self) -> bool:
|
291
|
+
"""
|
292
|
+
Check if the log file is temporary.
|
293
|
+
|
294
|
+
Returns:
|
295
|
+
bool: True if the log file is temporary
|
296
|
+
"""
|
297
|
+
return self.is_temp
|
298
|
+
|
299
|
+
def log_file_contents(self, level: str, description: str, filepath: str):
|
300
|
+
"""
|
301
|
+
Log the contents of a file.
|
302
|
+
|
303
|
+
Args:
|
304
|
+
level: Log level (DEBUG, INFO, etc.)
|
305
|
+
description: Description of the file contents
|
306
|
+
filepath: Path to the file
|
307
|
+
"""
|
308
|
+
if not self.logger or not os.path.isfile(filepath):
|
309
|
+
return
|
310
|
+
|
311
|
+
try:
|
312
|
+
# Start marker with description
|
313
|
+
self.logger.log(
|
314
|
+
getattr(logging, level.upper()),
|
315
|
+
f"===== BEGIN {description}: {filepath} ====="
|
316
|
+
)
|
317
|
+
|
318
|
+
# Read and log file contents
|
319
|
+
with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
|
320
|
+
content = f.read()
|
321
|
+
for line in content.split('\n'):
|
322
|
+
self.logger.log(
|
323
|
+
getattr(logging, level.upper()),
|
324
|
+
line
|
325
|
+
)
|
326
|
+
|
327
|
+
# End marker
|
328
|
+
self.logger.log(
|
329
|
+
getattr(logging, level.upper()),
|
330
|
+
f"===== END {description}: {filepath} ====="
|
331
|
+
)
|
332
|
+
except Exception as e:
|
333
|
+
self.logger.error(f"Error logging file contents: {str(e)}")
|
334
|
+
|
335
|
+
def log_content(self, level: str, description: str, content: str):
|
336
|
+
"""
|
337
|
+
Log the provided content.
|
338
|
+
|
339
|
+
Args:
|
340
|
+
level: Log level (DEBUG, INFO, etc.)
|
341
|
+
description: Description of the content
|
342
|
+
content: The content to log
|
343
|
+
"""
|
344
|
+
if not self.logger:
|
345
|
+
return
|
346
|
+
|
347
|
+
try:
|
348
|
+
# Create a temporary file for the content
|
349
|
+
fd, temp_path = tempfile.mkstemp(prefix="ngpt_log_", suffix=".txt")
|
350
|
+
with os.fdopen(fd, 'w', encoding='utf-8') as f:
|
351
|
+
f.write(content)
|
352
|
+
|
353
|
+
# Log the content from the file
|
354
|
+
self.log_file_contents(level, description, temp_path)
|
355
|
+
|
356
|
+
# Clean up the temporary file
|
357
|
+
try:
|
358
|
+
os.unlink(temp_path)
|
359
|
+
except Exception:
|
360
|
+
pass
|
361
|
+
except Exception as e:
|
362
|
+
if self.logger:
|
363
|
+
self.logger.error(f"Error logging content: {str(e)}")
|
364
|
+
|
365
|
+
def log_prompt(self, level: str, system_prompt: Optional[str], user_prompt: str):
|
366
|
+
"""
|
367
|
+
Log AI prompt information with detailed content.
|
368
|
+
|
369
|
+
Args:
|
370
|
+
level: Log level (DEBUG, INFO, etc.)
|
371
|
+
system_prompt: Optional system prompt
|
372
|
+
user_prompt: User prompt
|
373
|
+
"""
|
374
|
+
if not self.logger:
|
375
|
+
return
|
376
|
+
|
377
|
+
# Log summary
|
378
|
+
self.logger.log(
|
379
|
+
getattr(logging, level.upper()),
|
380
|
+
"AI Request:"
|
381
|
+
)
|
382
|
+
|
383
|
+
# Log system prompt if provided
|
384
|
+
if system_prompt:
|
385
|
+
self.log_content(level, "SYSTEM_PROMPT", system_prompt)
|
386
|
+
|
387
|
+
# Log user prompt
|
388
|
+
self.log_content(level, "USER_PROMPT", user_prompt)
|
389
|
+
|
390
|
+
def log_response(self, level: str, response: str):
|
391
|
+
"""
|
392
|
+
Log AI response with full content.
|
393
|
+
|
394
|
+
Args:
|
395
|
+
level: Log level (DEBUG, INFO, etc.)
|
396
|
+
response: The AI response
|
397
|
+
"""
|
398
|
+
if not self.logger:
|
399
|
+
return
|
400
|
+
|
401
|
+
# Log response
|
402
|
+
self.log_content(level, "AI_RESPONSE", response)
|
403
|
+
|
404
|
+
def log_diff(self, level: str, diff_content: str):
|
405
|
+
"""
|
406
|
+
Log git diff content.
|
407
|
+
|
408
|
+
Args:
|
409
|
+
level: Log level (DEBUG, INFO, etc.)
|
410
|
+
diff_content: The git diff content
|
411
|
+
"""
|
412
|
+
if not self.logger:
|
413
|
+
return
|
414
|
+
|
415
|
+
# Log diff content
|
416
|
+
self.log_content(level, "GIT_DIFF", diff_content)
|
417
|
+
|
418
|
+
def log_chunks(self, level: str, chunk_number: int, total_chunks: int, chunk_content: str):
|
419
|
+
"""
|
420
|
+
Log chunk content for processing.
|
421
|
+
|
422
|
+
Args:
|
423
|
+
level: Log level (DEBUG, INFO, etc.)
|
424
|
+
chunk_number: Current chunk number
|
425
|
+
total_chunks: Total number of chunks
|
426
|
+
chunk_content: Content of the chunk
|
427
|
+
"""
|
428
|
+
if not self.logger:
|
429
|
+
return
|
430
|
+
|
431
|
+
# Log chunk content
|
432
|
+
self.log_content(
|
433
|
+
level,
|
434
|
+
f"CHUNK_{chunk_number}_OF_{total_chunks}",
|
435
|
+
chunk_content
|
436
|
+
)
|
437
|
+
|
438
|
+
def log_template(self, level: str, template_type: str, template: str):
|
439
|
+
"""
|
440
|
+
Log prompt template.
|
441
|
+
|
442
|
+
Args:
|
443
|
+
level: Log level (DEBUG, INFO, etc.)
|
444
|
+
template_type: Type of template (INITIAL, CHUNK, COMBINE, etc.)
|
445
|
+
template: Template content
|
446
|
+
"""
|
447
|
+
if not self.logger:
|
448
|
+
return
|
449
|
+
|
450
|
+
# Log template
|
451
|
+
self.log_content(level, f"{template_type}_TEMPLATE", template)
|
452
|
+
|
168
453
|
|
169
454
|
def create_logger(log_path: Optional[str] = None) -> Logger:
|
170
455
|
"""
|
@@ -176,4 +461,19 @@ def create_logger(log_path: Optional[str] = None) -> Logger:
|
|
176
461
|
Returns:
|
177
462
|
Logger: Logger instance
|
178
463
|
"""
|
179
|
-
return Logger(log_path)
|
464
|
+
return Logger(log_path)
|
465
|
+
|
466
|
+
|
467
|
+
def create_gitcommsg_logger(log_path: Optional[str] = None) -> GitCommsgLogger:
|
468
|
+
"""
|
469
|
+
Create a gitcommsg logger instance.
|
470
|
+
|
471
|
+
Args:
|
472
|
+
log_path: Optional path to the log file
|
473
|
+
|
474
|
+
Returns:
|
475
|
+
GitCommsgLogger: GitCommsgLogger instance
|
476
|
+
"""
|
477
|
+
logger = GitCommsgLogger(log_path)
|
478
|
+
logger.setup()
|
479
|
+
return logger
|