gptdiff 0.1.21__py3-none-any.whl → 0.1.22__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 +58 -16
- {gptdiff-0.1.21.dist-info → gptdiff-0.1.22.dist-info}/METADATA +1 -1
- gptdiff-0.1.22.dist-info/RECORD +9 -0
- gptdiff-0.1.21.dist-info/RECORD +0 -9
- {gptdiff-0.1.21.dist-info → gptdiff-0.1.22.dist-info}/LICENSE.txt +0 -0
- {gptdiff-0.1.21.dist-info → gptdiff-0.1.22.dist-info}/WHEEL +0 -0
- {gptdiff-0.1.21.dist-info → gptdiff-0.1.22.dist-info}/entry_points.txt +0 -0
- {gptdiff-0.1.21.dist-info → gptdiff-0.1.22.dist-info}/top_level.txt +0 -0
    
        gptdiff/gptdiff.py
    CHANGED
    
    | @@ -345,7 +345,8 @@ def smartapply(diff_text, files, model=None, api_key=None, base_url=None): | |
| 345 345 | 
             
                            del files[path]
         | 
| 346 346 | 
             
                    else:
         | 
| 347 347 | 
             
                        updated = call_llm_for_apply_with_think_tool_available(path, original, patch, model, api_key=api_key, base_url=base_url)
         | 
| 348 | 
            -
                         | 
| 348 | 
            +
                        cleaned = strip_bad_output(updated, original)
         | 
| 349 | 
            +
                        files[path] = cleaned
         | 
| 349 350 |  | 
| 350 351 | 
             
                threads = []
         | 
| 351 352 |  | 
| @@ -585,7 +586,7 @@ def parse_diff_per_file(diff_text): | |
| 585 586 | 
             
                    for line in lines:
         | 
| 586 587 | 
             
                        if header_line_re.match(line):
         | 
| 587 588 | 
             
                            if current_file is not None and current_lines:
         | 
| 588 | 
            -
                                if deletion_mode and not any(l.startswith("+++ ") for l in current_lines):
         | 
| 589 | 
            +
                                if deletion_mode and not any(l.startswith("+++ /dev/null") for l in current_lines):
         | 
| 589 590 | 
             
                                    current_lines.append("+++ /dev/null")
         | 
| 590 591 | 
             
                                diffs.append((current_file, "\n".join(current_lines)))
         | 
| 591 592 | 
             
                            current_lines = [line]
         | 
| @@ -778,24 +779,41 @@ def smart_apply_patch(project_dir, diff_text, user_prompt, args): | |
| 778 779 | 
             
                        else:
         | 
| 779 780 | 
             
                            print(f"\033[1;33mFile {file_path} not found - skipping deletion\033[0m")
         | 
| 780 781 | 
             
                        return
         | 
| 781 | 
            -
             | 
| 782 | 
            -
                     | 
| 783 | 
            -
                         | 
| 784 | 
            -
             | 
| 785 | 
            -
                         | 
| 786 | 
            -
             | 
| 787 | 
            -
             | 
| 788 | 
            -
                     | 
| 789 | 
            -
             | 
| 790 | 
            -
                    if  | 
| 791 | 
            -
                         | 
| 782 | 
            +
             | 
| 783 | 
            +
                    try:
         | 
| 784 | 
            +
                        original_content = full_path.read_text()
         | 
| 785 | 
            +
                    except (UnicodeDecodeError, IOError):
         | 
| 786 | 
            +
                        print(f"Skipping file {file_path} due to read error")
         | 
| 787 | 
            +
                        return
         | 
| 788 | 
            +
             | 
| 789 | 
            +
                    # Use SMARTAPPLY-specific environment variables if set, otherwise fallback.
         | 
| 790 | 
            +
                    smart_apply_model = os.getenv("GPTDIFF_SMARTAPPLY_MODEL")
         | 
| 791 | 
            +
                    if smart_apply_model and smart_apply_model.strip():
         | 
| 792 | 
            +
                        model = smart_apply_model
         | 
| 793 | 
            +
                    elif hasattr(args, "applymodel") and args.applymodel:
         | 
| 794 | 
            +
                        model = args.applymodel
         | 
| 795 | 
            +
                    else:
         | 
| 796 | 
            +
                        model = os.getenv("GPTDIFF_MODEL", "deepseek-reasoner")
         | 
| 797 | 
            +
             | 
| 798 | 
            +
                    smart_api_key = os.getenv("GPTDIFF_SMARTAPPLY_API_KEY")
         | 
| 799 | 
            +
                    if smart_api_key and smart_api_key.strip():
         | 
| 800 | 
            +
                        api_key = smart_api_key
         | 
| 801 | 
            +
                    else:
         | 
| 802 | 
            +
                        api_key = os.getenv("GPTDIFF_LLM_API_KEY")
         | 
| 803 | 
            +
             | 
| 804 | 
            +
                    smart_base_url = os.getenv("GPTDIFF_SMARTAPPLY_BASE_URL")
         | 
| 805 | 
            +
                    if smart_base_url and smart_base_url.strip():
         | 
| 806 | 
            +
                        base_url = smart_base_url
         | 
| 807 | 
            +
                    else:
         | 
| 808 | 
            +
                        base_url = os.getenv("GPTDIFF_LLM_BASE_URL", "https://nano-gpt.com/api/v1/")
         | 
| 792 809 |  | 
| 793 810 | 
             
                    print("-" * 40)
         | 
| 794 | 
            -
                    print("Running smartapply with",  | 
| 811 | 
            +
                    print("Running smartapply with", model, "on", file_path)
         | 
| 795 812 | 
             
                    print("-" * 40)
         | 
| 796 813 | 
             
                    try:
         | 
| 797 814 | 
             
                        updated_content = call_llm_for_apply_with_think_tool_available(
         | 
| 798 | 
            -
                            file_path, original_content, file_diff,  | 
| 815 | 
            +
                            file_path, original_content, file_diff, model,
         | 
| 816 | 
            +
                            api_key=api_key, base_url=base_url,
         | 
| 799 817 | 
             
                            extra_prompt=f"This changeset is from the following instructions:\n{user_prompt}",
         | 
| 800 818 | 
             
                            max_tokens=args.max_tokens)
         | 
| 801 819 | 
             
                        if updated_content.strip() == "":
         | 
| @@ -1003,5 +1021,29 @@ def swallow_reasoning(full_response: str) -> (str, str): | |
| 1003 1021 | 
             
                    final_content = full_response.strip()
         | 
| 1004 1022 | 
             
                return final_content, reasoning
         | 
| 1005 1023 |  | 
| 1024 | 
            +
            def strip_bad_output(updated: str, original: str) -> str:
         | 
| 1025 | 
            +
                """
         | 
| 1026 | 
            +
                If the original file content does not start with a code fence but the LLM’s updated output
         | 
| 1027 | 
            +
                starts with triple backticks (possibly with an introductory message), extract and return only
         | 
| 1028 | 
            +
                the content within the first code block.
         | 
| 1029 | 
            +
                """
         | 
| 1030 | 
            +
                updated_stripped = updated.strip()
         | 
| 1031 | 
            +
                # If the original file does not start with a code fence, but the updated output contains a code block,
         | 
| 1032 | 
            +
                # extract and return only the content inside the first code block.
         | 
| 1033 | 
            +
                if not original.lstrip().startswith("```"):
         | 
| 1034 | 
            +
                    # Search for the first code block in the updated output.
         | 
| 1035 | 
            +
                    m = re.search(r"```(.*?)```", updated_stripped, re.DOTALL)
         | 
| 1036 | 
            +
                    if m:
         | 
| 1037 | 
            +
                        content = m.group(1).strip()
         | 
| 1038 | 
            +
                        lines = content.splitlines()
         | 
| 1039 | 
            +
                        if len(lines) > 1:
         | 
| 1040 | 
            +
                            first_line = lines[0].strip()
         | 
| 1041 | 
            +
                            # If the first line appears to be a language specifier (i.e., a single word)
         | 
| 1042 | 
            +
                            # and is not "diff", then drop it.
         | 
| 1043 | 
            +
                            if " " not in first_line and first_line.lower() != "diff":
         | 
| 1044 | 
            +
                                content = "\n".join(lines[1:]).strip()
         | 
| 1045 | 
            +
                        return content
         | 
| 1046 | 
            +
                return updated_stripped
         | 
| 1047 | 
            +
             | 
| 1006 1048 | 
             
            if __name__ == "__main__":
         | 
| 1007 | 
            -
                main()
         | 
| 1049 | 
            +
                main()
         | 
| @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            gptdiff/__init__.py,sha256=o1hrK4GFvbfKcHPlLVArz4OunE3euIicEBYaLrdDo0k,198
         | 
| 2 | 
            +
            gptdiff/gptdiff.py,sha256=AuZwZ1pg52RPheAzdhtZXSTjBGH4t4KRm7r9ziGHJVQ,41388
         | 
| 3 | 
            +
            gptdiff/gptpatch.py,sha256=Z8CWWIfIL2o7xPLVdhzN5GSyJq0vsK4XQRzu4hMWNQk,2194
         | 
| 4 | 
            +
            gptdiff-0.1.22.dist-info/LICENSE.txt,sha256=zCJk7yUYpMjFvlipi1dKtaljF8WdZ2NASndBYYbU8BY,1228
         | 
| 5 | 
            +
            gptdiff-0.1.22.dist-info/METADATA,sha256=_RspqYV4VPaRrpYTQXNVecFirrxzZq7MelPpZLV3O9Q,8785
         | 
| 6 | 
            +
            gptdiff-0.1.22.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         | 
| 7 | 
            +
            gptdiff-0.1.22.dist-info/entry_points.txt,sha256=0VlVNr-gc04a3SZD5_qKIBbtg_L5P2x3xlKE5ftcdkc,82
         | 
| 8 | 
            +
            gptdiff-0.1.22.dist-info/top_level.txt,sha256=XNkQkQGINaDndEwRxg8qToOrJ9coyfAb-EHrSUXzdCE,8
         | 
| 9 | 
            +
            gptdiff-0.1.22.dist-info/RECORD,,
         | 
    
        gptdiff-0.1.21.dist-info/RECORD
    DELETED
    
    | @@ -1,9 +0,0 @@ | |
| 1 | 
            -
            gptdiff/__init__.py,sha256=o1hrK4GFvbfKcHPlLVArz4OunE3euIicEBYaLrdDo0k,198
         | 
| 2 | 
            -
            gptdiff/gptdiff.py,sha256=kDp7gDgBydfKxNm73QIT54AKnv117cZdXhRYQnfJm6A,39426
         | 
| 3 | 
            -
            gptdiff/gptpatch.py,sha256=Z8CWWIfIL2o7xPLVdhzN5GSyJq0vsK4XQRzu4hMWNQk,2194
         | 
| 4 | 
            -
            gptdiff-0.1.21.dist-info/LICENSE.txt,sha256=zCJk7yUYpMjFvlipi1dKtaljF8WdZ2NASndBYYbU8BY,1228
         | 
| 5 | 
            -
            gptdiff-0.1.21.dist-info/METADATA,sha256=Y5O4deytuqvxRV4WaK2vAw9jFuz0OdR3Rxm3lIBNxHk,8785
         | 
| 6 | 
            -
            gptdiff-0.1.21.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         | 
| 7 | 
            -
            gptdiff-0.1.21.dist-info/entry_points.txt,sha256=0VlVNr-gc04a3SZD5_qKIBbtg_L5P2x3xlKE5ftcdkc,82
         | 
| 8 | 
            -
            gptdiff-0.1.21.dist-info/top_level.txt,sha256=XNkQkQGINaDndEwRxg8qToOrJ9coyfAb-EHrSUXzdCE,8
         | 
| 9 | 
            -
            gptdiff-0.1.21.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |