gptdiff 0.1.8__py3-none-any.whl → 0.1.9__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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
|