gptdiff 0.1.8__py3-none-any.whl → 0.1.9__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.
- gptdiff/gptdiff.py +50 -8
- {gptdiff-0.1.8.dist-info → gptdiff-0.1.9.dist-info}/METADATA +1 -1
- gptdiff-0.1.9.dist-info/RECORD +8 -0
- gptdiff-0.1.8.dist-info/RECORD +0 -8
- {gptdiff-0.1.8.dist-info → gptdiff-0.1.9.dist-info}/LICENSE.txt +0 -0
- {gptdiff-0.1.8.dist-info → gptdiff-0.1.9.dist-info}/WHEEL +0 -0
- {gptdiff-0.1.8.dist-info → gptdiff-0.1.9.dist-info}/entry_points.txt +0 -0
- {gptdiff-0.1.8.dist-info → gptdiff-0.1.9.dist-info}/top_level.txt +0 -0
gptdiff/gptdiff.py
CHANGED
@@ -67,6 +67,25 @@ def create_think_toolbox():
|
|
67
67
|
)
|
68
68
|
return toolbox
|
69
69
|
|
70
|
+
def color_code_diff(diff_text: str) -> str:
|
71
|
+
"""
|
72
|
+
Color code lines in a diff. Lines beginning with '-' in red, and
|
73
|
+
lines beginning with '+' in green.
|
74
|
+
"""
|
75
|
+
red = "\033[31m"
|
76
|
+
green = "\033[32m"
|
77
|
+
reset = "\033[0m"
|
78
|
+
|
79
|
+
colorized_lines = []
|
80
|
+
for line in diff_text.split('\n'):
|
81
|
+
if line.startswith('-'):
|
82
|
+
colorized_lines.append(f"{red}{line}{reset}")
|
83
|
+
elif line.startswith('+'):
|
84
|
+
colorized_lines.append(f"{green}{line}{reset}")
|
85
|
+
else:
|
86
|
+
colorized_lines.append(line)
|
87
|
+
|
88
|
+
return '\n'.join(colorized_lines)
|
70
89
|
|
71
90
|
def load_gitignore_patterns(gitignore_path):
|
72
91
|
with open(gitignore_path, 'r') as f:
|
@@ -308,8 +327,16 @@ def smartapply(diff_text, files, model=None, api_key=None, base_url=None):
|
|
308
327
|
updated = call_llm_for_apply_with_think_tool_available(path, original, patch, model, api_key=api_key, base_url=base_url)
|
309
328
|
files[path] = updated.strip()
|
310
329
|
|
330
|
+
threads = []
|
331
|
+
|
311
332
|
for path, patch in parsed_diffs:
|
312
|
-
process_file(path, patch)
|
333
|
+
thread = threading.Thread(target=process_file, args=(path, patch))
|
334
|
+
thread.start()
|
335
|
+
threads.append(thread)
|
336
|
+
|
337
|
+
# Wait for all threads to complete
|
338
|
+
for thread in threads:
|
339
|
+
thread.join()
|
313
340
|
|
314
341
|
return files
|
315
342
|
|
@@ -339,6 +366,7 @@ def parse_arguments():
|
|
339
366
|
parser.add_argument('--temperature', type=float, default=0.7, help='Temperature parameter for model creativity (0.0 to 2.0)')
|
340
367
|
parser.add_argument('--max_tokens', type=int, default=30000, help='Temperature parameter for model creativity (0.0 to 2.0)')
|
341
368
|
parser.add_argument('--model', type=str, default=None, help='Model to use for the API call.')
|
369
|
+
parser.add_argument('--applymodel', type=str, default=None, help='Model to use for applying the diff. Defaults to the value of --model if not specified.')
|
342
370
|
|
343
371
|
parser.add_argument('--nowarn', action='store_true', help='Disable large token warning')
|
344
372
|
|
@@ -404,11 +432,11 @@ def parse_diff_per_file(diff_text):
|
|
404
432
|
|
405
433
|
return diffs
|
406
434
|
|
407
|
-
def call_llm_for_apply_with_think_tool_available(file_path, original_content, file_diff, model, api_key=None, base_url=None):
|
435
|
+
def call_llm_for_apply_with_think_tool_available(file_path, original_content, file_diff, model, api_key=None, base_url=None, extra_prompt=None, max_tokens=30000):
|
408
436
|
parser = FlatXMLParser("think")
|
409
437
|
formatter = FlatXMLPromptFormatter(tag="think")
|
410
438
|
toolbox = create_think_toolbox()
|
411
|
-
full_response = call_llm_for_apply(file_path, original_content, file_diff, model, api_key=
|
439
|
+
full_response = call_llm_for_apply(file_path, original_content, file_diff, model, api_key=api_key, base_url=base_url, extra_prompt=extra_prompt, max_tokens=max_tokens)
|
412
440
|
notool_response = ""
|
413
441
|
events = parser.parse(full_response)
|
414
442
|
is_in_tool = False
|
@@ -424,7 +452,7 @@ def call_llm_for_apply_with_think_tool_available(file_path, original_content, fi
|
|
424
452
|
|
425
453
|
return notool_response
|
426
454
|
|
427
|
-
def call_llm_for_apply(file_path, original_content, file_diff, model, api_key=None, base_url=None):
|
455
|
+
def call_llm_for_apply(file_path, original_content, file_diff, model, api_key=None, base_url=None, extra_prompt=None, max_tokens=30000):
|
428
456
|
"""AI-powered diff application with conflict resolution.
|
429
457
|
|
430
458
|
Internal workhorse for smartapply that handles individual file patches.
|
@@ -474,6 +502,8 @@ Diff to apply:
|
|
474
502
|
{file_diff}
|
475
503
|
</diff>"""
|
476
504
|
|
505
|
+
if extra_prompt:
|
506
|
+
user_prompt += f"\n\n{extra_prompt}"
|
477
507
|
if model == "gemini-2.0-flash-thinking-exp-01-21":
|
478
508
|
user_prompt = system_prompt+"\n"+user_prompt
|
479
509
|
messages = [
|
@@ -490,7 +520,7 @@ Diff to apply:
|
|
490
520
|
response = client.chat.completions.create(model=model,
|
491
521
|
messages=messages,
|
492
522
|
temperature=0.0,
|
493
|
-
max_tokens=
|
523
|
+
max_tokens=max_tokens)
|
494
524
|
full_response = response.choices[0].message.content
|
495
525
|
|
496
526
|
elapsed = time.time() - start_time
|
@@ -590,12 +620,21 @@ def main():
|
|
590
620
|
if confirmation != 'y':
|
591
621
|
print("Request canceled")
|
592
622
|
sys.exit(0)
|
593
|
-
|
623
|
+
try:
|
624
|
+
full_text, diff_text, prompt_tokens, completion_tokens, total_tokens, cost = call_llm_for_diff(system_prompt, user_prompt, files_content, args.model,
|
594
625
|
temperature=args.temperature,
|
595
626
|
api_key=os.getenv('GPTDIFF_LLM_API_KEY'),
|
596
627
|
base_url=os.getenv('GPTDIFF_LLM_BASE_URL', "https://nano-gpt.com/api/v1/"),
|
597
628
|
max_tokens=args.max_tokens
|
598
629
|
)
|
630
|
+
except Exception as e:
|
631
|
+
full_text = f"{e}"
|
632
|
+
diff_text = ""
|
633
|
+
prompt_tokens = 0
|
634
|
+
completion_tokens = 0
|
635
|
+
total_tokens = 0
|
636
|
+
cost = 0
|
637
|
+
print(f"Error in LLM response {e}")
|
599
638
|
|
600
639
|
if(diff_text.strip() == ""):
|
601
640
|
print(f"\033[1;33mThere was no data in this diff. The LLM may have returned something invalid.\033[0m")
|
@@ -608,7 +647,7 @@ def main():
|
|
608
647
|
elif args.apply:
|
609
648
|
print("\nAttempting apply with the following diff:")
|
610
649
|
print("\n<diff>")
|
611
|
-
print(diff_text)
|
650
|
+
print(color_code_diff(diff_text))
|
612
651
|
print("\n</diff>")
|
613
652
|
print("Saved to patch.diff")
|
614
653
|
if apply_diff(project_dir, diff_text):
|
@@ -651,8 +690,11 @@ def main():
|
|
651
690
|
print("SMARTAPPLY")
|
652
691
|
print(file_diff)
|
653
692
|
print("-" * 40)
|
693
|
+
if args.applymodel is None:
|
694
|
+
args.applymodel = args.model
|
695
|
+
|
654
696
|
try:
|
655
|
-
updated_content = call_llm_for_apply_with_think_tool_available(file_path, original_content, file_diff, args.
|
697
|
+
updated_content = call_llm_for_apply_with_think_tool_available(file_path, original_content, file_diff, args.applymodel, extra_prompt=f"This changeset is from the following instructions:\n{user_prompt}", max_tokens=args.max_tokens)
|
656
698
|
|
657
699
|
if updated_content.strip() == "":
|
658
700
|
print("Cowardly refusing to write empty file to", file_path, "merge failed")
|
@@ -0,0 +1,8 @@
|
|
1
|
+
gptdiff/__init__.py,sha256=yGjgwv7tNvH1ZLPsQyoo1CxpTOl1iCAwwDBp-_17ksQ,89
|
2
|
+
gptdiff/gptdiff.py,sha256=k4-iqho7h6NV0hxfpiSVpT3wyG3liBr8Ut_5V5-hjyk,27595
|
3
|
+
gptdiff-0.1.9.dist-info/LICENSE.txt,sha256=zCJk7yUYpMjFvlipi1dKtaljF8WdZ2NASndBYYbU8BY,1228
|
4
|
+
gptdiff-0.1.9.dist-info/METADATA,sha256=jG17S0CxskLxN2HyTXKYOH1Az7i5iafyqe4PcbCj9Ok,7317
|
5
|
+
gptdiff-0.1.9.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
6
|
+
gptdiff-0.1.9.dist-info/entry_points.txt,sha256=0yvXYEVAZFI-p32kQ4-h3qKVWS0a86jsM9FAwF89t9w,49
|
7
|
+
gptdiff-0.1.9.dist-info/top_level.txt,sha256=XNkQkQGINaDndEwRxg8qToOrJ9coyfAb-EHrSUXzdCE,8
|
8
|
+
gptdiff-0.1.9.dist-info/RECORD,,
|
gptdiff-0.1.8.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
gptdiff/__init__.py,sha256=yGjgwv7tNvH1ZLPsQyoo1CxpTOl1iCAwwDBp-_17ksQ,89
|
2
|
-
gptdiff/gptdiff.py,sha256=kzLeNc5M3saCdqBOoE-OjkyHztGbQr39XPiVcFJ_pyY,25958
|
3
|
-
gptdiff-0.1.8.dist-info/LICENSE.txt,sha256=zCJk7yUYpMjFvlipi1dKtaljF8WdZ2NASndBYYbU8BY,1228
|
4
|
-
gptdiff-0.1.8.dist-info/METADATA,sha256=ErNMAtAqN7HDzarpVJi0IVA5i1pryUQwkjVjus9kjkM,7317
|
5
|
-
gptdiff-0.1.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
6
|
-
gptdiff-0.1.8.dist-info/entry_points.txt,sha256=0yvXYEVAZFI-p32kQ4-h3qKVWS0a86jsM9FAwF89t9w,49
|
7
|
-
gptdiff-0.1.8.dist-info/top_level.txt,sha256=XNkQkQGINaDndEwRxg8qToOrJ9coyfAb-EHrSUXzdCE,8
|
8
|
-
gptdiff-0.1.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|