apipatch 0.3.0__tar.gz

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.

Potentially problematic release.


This version of apipatch might be problematic. Click here for more details.

apipatch-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Morad Moqbel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: apipatch
3
+ Version: 0.3.0
4
+ Summary: Autonomous AI Agent that detects and fixes deprecated API calls in Python, JS, TS via LLM-powered Pull Requests
5
+ Author-email: Morad Moqbel <moradmoqbel@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/MoradMoqbel/apipatch
8
+ Project-URL: Repository, https://github.com/MoradMoqbel/apipatch
9
+ Project-URL: Bug-Tracker, https://github.com/MoradMoqbel/apipatch/issues
10
+ Keywords: api,deprecation,breaking-changes,refactoring,ai-agent,codemod,github,autonomous,llm,openai,pydantic,migration,typescript,javascript,dependabot
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Development Status :: 4 - Beta
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Classifier: Topic :: Software Development :: Code Generators
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: ai
27
+ Requires-Dist: openai>=1.0.0; extra == "ai"
28
+ Requires-Dist: anthropic>=0.18.0; extra == "ai"
29
+ Requires-Dist: google-genai>=0.1.0; extra == "ai"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # ⚑ ApiPatch
35
+ > **Autonomous AI Agent for API Breaking Changes & Self-Maintaining Codebases**
36
+
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
38
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
39
+ [![Open Source](https://img.shields.io/badge/Open%20Source-Yes-brightgreen.svg)](https://github.com/MoradMoqbel/apipatch)
40
+ [![Tests: Passing](https://img.shields.io/badge/Tests-23%2F23%20Passing-brightgreen.svg)](https://github.com/MoradMoqbel/apipatch)
41
+
42
+ ---
43
+
44
+ ## πŸ›‘ The Problem
45
+
46
+ Over **30% of cloud outages and broken builds** are caused by silent, third-party API breaking changes. When vendors release major SDK updates (OpenAI v1.0+, Pydantic v2, Stripe SCA/PaymentIntents, LangChain LCEL, React hooks, Next.js App Router…), engineering teams spend days hunting broken calls and rewriting legacy code.
47
+
48
+ Tools like **Dependabot** and **Renovate** only bump version numbers in `requirements.txt` or `package.json`β€”they **do not fix actual code logic**.
49
+
50
+ ```
51
+ [ Traditional Dependency Bumper ]
52
+ requirements.txt: openai==0.28.0 ──► openai==1.50.0 β”€β”€βŒ (Code breaks at runtime!)
53
+
54
+ [ ApiPatch Autonomous Agent ]
55
+ 1. Detects breaking API calls across ANY library β€” Python, JS, TS, JSX, TSX…
56
+ 2. Refactors code via LLM reasoning (Gemini, Claude, GPT-4o)
57
+ 3. Validates safety before accepting any change
58
+ 4. Generates ready-to-merge Pull Requests β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€βœ… (Build passes!)
59
+ ```
60
+
61
+ ---
62
+
63
+ ## πŸš€ Key Features
64
+
65
+ * 🧠 **Universal LLM Engine:** Audits **ANY** third-party library in **any language** dynamically β€” no hardcoded rules required. If a library has a breaking change, ApiPatch finds and fixes it.
66
+ * 🌐 **Multi-Language Support:** Full support for `.py`, `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs` files in a single scan.
67
+ * πŸ›‘οΈ **AST & Safety Guard:** Validates every refactored Python file through AST syntax parsing before accepting it. JS/TS files are checked for truncation and structural integrity.
68
+ * πŸ“¦ **Flexible CLI:** Rich terminal interface supporting `apipatch scan`, `apipatch fix --write`, `apipatch detect`, and `apipatch hunt`.
69
+ * πŸ”„ **Safe In-Place Refactoring:** Automatically generates `.bak` backups before modifying any files.
70
+ * πŸ€– **Proactive GitHub Hunter:** Searches public GitHub repositories for deprecated code patterns and drafts complete, structured Pull Requests.
71
+ * πŸ”Œ **Multi-Provider:** Works with **Google Gemini** (free tier), **OpenAI GPT-4o**, and **Anthropic Claude** β€” auto-detected from environment variables.
72
+
73
+ ---
74
+
75
+ ## 🌍 Universal Coverage β€” Any Library, Any Language
76
+
77
+ ApiPatch is not limited to a fixed list of rules. The LLM engine can detect and fix breaking changes in **any** third-party library it has been trained on, including (but not limited to):
78
+
79
+ | Language | Libraries / Frameworks |
80
+ | :--- | :--- |
81
+ | **Python** | OpenAI, Pydantic, Stripe, LangChain, Supabase, SQLAlchemy, FastAPI, Boto3/AWS, Celery, HuggingFace, Twilio, and more |
82
+ | **JavaScript / TypeScript** | React (class β†’ hooks), Next.js (Pages β†’ App Router), Axios, Stripe.js, Supabase JS, OpenAI Node SDK, Express, and more |
83
+ | **Any Language** | If the LLM knows about a library's breaking change, ApiPatch can fix it |
84
+
85
+ ---
86
+
87
+ ## ⚑ Quickstart
88
+
89
+ ### 1. Installation
90
+
91
+ #### Direct install via Git:
92
+ ```bash
93
+ pip install git+https://github.com/MoradMoqbel/apipatch.git
94
+ ```
95
+
96
+ #### Or clone and install in editable mode:
97
+ ```bash
98
+ git clone https://github.com/MoradMoqbel/apipatch.git
99
+ cd apipatch
100
+ pip install -e .
101
+ ```
102
+
103
+ ---
104
+
105
+ ## πŸ”‘ Setting Up AI Provider Keys
106
+
107
+ ApiPatch requires an LLM provider key for full analysis.
108
+
109
+ ### Option A: Environment Variables (Recommended)
110
+
111
+ ```bash
112
+ # Google Gemini (Fast & Free Tier Available)
113
+ export GEMINI_API_KEY="your-gemini-api-key-here"
114
+
115
+ # OpenAI
116
+ export OPENAI_API_KEY="sk-..."
117
+
118
+ # Anthropic Claude
119
+ export ANTHROPIC_API_KEY="sk-ant-..."
120
+ ```
121
+
122
+ **Windows (PowerShell):**
123
+ ```powershell
124
+ $env:GEMINI_API_KEY = "your-gemini-api-key-here"
125
+ ```
126
+
127
+ ### Option B: CLI Flags
128
+
129
+ ```bash
130
+ apipatch scan ./project --provider gemini --api-key "your-key"
131
+ apipatch scan ./project --provider openai --api-key "sk-..."
132
+ apipatch scan ./project --provider anthropic --api-key "sk-ant-..."
133
+ ```
134
+
135
+ ---
136
+
137
+ ## πŸ’» CLI Commands & Usage
138
+
139
+ ### 1. πŸ” Scan a Codebase (Dry Run)
140
+ Audits files recursively (`.py`, `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs`),
141
+ detects deprecated calls, and outputs colorized diff previews without modifying files:
142
+ ```bash
143
+ apipatch scan /path/to/project
144
+ apipatch scan /path/to/project --provider gemini
145
+ ```
146
+
147
+ ### 2. ⚑ Refactor and Apply Fixes In-Place
148
+ Automatically updates the code and generates `.bak` safety backups:
149
+ ```bash
150
+ apipatch fix /path/to/project --write
151
+ apipatch fix /path/to/single/file.py --write --provider openai
152
+ ```
153
+ *(Add `--no-backup` to skip automatic `.bak` backup creation.)*
154
+
155
+ ### 3. πŸ“¦ Discover All Project Dependencies
156
+ Inspects `requirements.txt`, `package.json`, `pyproject.toml`, and all source file
157
+ imports (Python AST + JS/TS regex) to list every third-party library in use:
158
+ ```bash
159
+ apipatch detect /path/to/project
160
+ ```
161
+
162
+ ### 4. 🎯 Hunt for Deprecated Code on GitHub & Prepare PRs
163
+ Searches GitHub for legacy patterns and prepares ready-to-merge Pull Requests:
164
+ ```bash
165
+ apipatch hunt "openai.ChatCompletion.create language:python"
166
+ apipatch hunt "stripe.Charge.create language:javascript"
167
+ ```
168
+
169
+ ---
170
+
171
+ ## πŸ§ͺ Testing
172
+
173
+ ```bash
174
+ python -m pytest tests/ -v
175
+ ```
176
+
177
+ All 23 tests are offline-safe (no API key required for the test suite).
178
+
179
+ ---
180
+
181
+ ## πŸ—ΊοΈ Roadmap
182
+
183
+ - [x] Universal LLM engine β€” no hardcoded rules, ANY library supported
184
+ - [x] Multi-language support: Python, JavaScript, TypeScript, JSX, TSX
185
+ - [x] AST Syntax & Safety Validator
186
+ - [x] Multi-LLM Provider (Gemini, OpenAI, Claude) with auto-discovery
187
+ - [x] In-place refactoring with automatic backup (`--write`)
188
+ - [x] Autonomous dependency discovery (requirements.txt / package.json / AST scan)
189
+ - [x] Automated test suite (23/23 tests passing)
190
+ - [ ] 1-Click Autonomous GitHub App Webhook Integration
191
+ - [ ] PyPI Global Package Release (`pip install apipatch`)
192
+
193
+ ---
194
+
195
+ ## πŸ“„ License
196
+
197
+ MIT License. Built by [Morad Moqbel](https://github.com/MoradMoqbel).
@@ -0,0 +1,164 @@
1
+ # ⚑ ApiPatch
2
+ > **Autonomous AI Agent for API Breaking Changes & Self-Maintaining Codebases**
3
+
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
6
+ [![Open Source](https://img.shields.io/badge/Open%20Source-Yes-brightgreen.svg)](https://github.com/MoradMoqbel/apipatch)
7
+ [![Tests: Passing](https://img.shields.io/badge/Tests-23%2F23%20Passing-brightgreen.svg)](https://github.com/MoradMoqbel/apipatch)
8
+
9
+ ---
10
+
11
+ ## πŸ›‘ The Problem
12
+
13
+ Over **30% of cloud outages and broken builds** are caused by silent, third-party API breaking changes. When vendors release major SDK updates (OpenAI v1.0+, Pydantic v2, Stripe SCA/PaymentIntents, LangChain LCEL, React hooks, Next.js App Router…), engineering teams spend days hunting broken calls and rewriting legacy code.
14
+
15
+ Tools like **Dependabot** and **Renovate** only bump version numbers in `requirements.txt` or `package.json`β€”they **do not fix actual code logic**.
16
+
17
+ ```
18
+ [ Traditional Dependency Bumper ]
19
+ requirements.txt: openai==0.28.0 ──► openai==1.50.0 β”€β”€βŒ (Code breaks at runtime!)
20
+
21
+ [ ApiPatch Autonomous Agent ]
22
+ 1. Detects breaking API calls across ANY library β€” Python, JS, TS, JSX, TSX…
23
+ 2. Refactors code via LLM reasoning (Gemini, Claude, GPT-4o)
24
+ 3. Validates safety before accepting any change
25
+ 4. Generates ready-to-merge Pull Requests β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€βœ… (Build passes!)
26
+ ```
27
+
28
+ ---
29
+
30
+ ## πŸš€ Key Features
31
+
32
+ * 🧠 **Universal LLM Engine:** Audits **ANY** third-party library in **any language** dynamically β€” no hardcoded rules required. If a library has a breaking change, ApiPatch finds and fixes it.
33
+ * 🌐 **Multi-Language Support:** Full support for `.py`, `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs` files in a single scan.
34
+ * πŸ›‘οΈ **AST & Safety Guard:** Validates every refactored Python file through AST syntax parsing before accepting it. JS/TS files are checked for truncation and structural integrity.
35
+ * πŸ“¦ **Flexible CLI:** Rich terminal interface supporting `apipatch scan`, `apipatch fix --write`, `apipatch detect`, and `apipatch hunt`.
36
+ * πŸ”„ **Safe In-Place Refactoring:** Automatically generates `.bak` backups before modifying any files.
37
+ * πŸ€– **Proactive GitHub Hunter:** Searches public GitHub repositories for deprecated code patterns and drafts complete, structured Pull Requests.
38
+ * πŸ”Œ **Multi-Provider:** Works with **Google Gemini** (free tier), **OpenAI GPT-4o**, and **Anthropic Claude** β€” auto-detected from environment variables.
39
+
40
+ ---
41
+
42
+ ## 🌍 Universal Coverage β€” Any Library, Any Language
43
+
44
+ ApiPatch is not limited to a fixed list of rules. The LLM engine can detect and fix breaking changes in **any** third-party library it has been trained on, including (but not limited to):
45
+
46
+ | Language | Libraries / Frameworks |
47
+ | :--- | :--- |
48
+ | **Python** | OpenAI, Pydantic, Stripe, LangChain, Supabase, SQLAlchemy, FastAPI, Boto3/AWS, Celery, HuggingFace, Twilio, and more |
49
+ | **JavaScript / TypeScript** | React (class β†’ hooks), Next.js (Pages β†’ App Router), Axios, Stripe.js, Supabase JS, OpenAI Node SDK, Express, and more |
50
+ | **Any Language** | If the LLM knows about a library's breaking change, ApiPatch can fix it |
51
+
52
+ ---
53
+
54
+ ## ⚑ Quickstart
55
+
56
+ ### 1. Installation
57
+
58
+ #### Direct install via Git:
59
+ ```bash
60
+ pip install git+https://github.com/MoradMoqbel/apipatch.git
61
+ ```
62
+
63
+ #### Or clone and install in editable mode:
64
+ ```bash
65
+ git clone https://github.com/MoradMoqbel/apipatch.git
66
+ cd apipatch
67
+ pip install -e .
68
+ ```
69
+
70
+ ---
71
+
72
+ ## πŸ”‘ Setting Up AI Provider Keys
73
+
74
+ ApiPatch requires an LLM provider key for full analysis.
75
+
76
+ ### Option A: Environment Variables (Recommended)
77
+
78
+ ```bash
79
+ # Google Gemini (Fast & Free Tier Available)
80
+ export GEMINI_API_KEY="your-gemini-api-key-here"
81
+
82
+ # OpenAI
83
+ export OPENAI_API_KEY="sk-..."
84
+
85
+ # Anthropic Claude
86
+ export ANTHROPIC_API_KEY="sk-ant-..."
87
+ ```
88
+
89
+ **Windows (PowerShell):**
90
+ ```powershell
91
+ $env:GEMINI_API_KEY = "your-gemini-api-key-here"
92
+ ```
93
+
94
+ ### Option B: CLI Flags
95
+
96
+ ```bash
97
+ apipatch scan ./project --provider gemini --api-key "your-key"
98
+ apipatch scan ./project --provider openai --api-key "sk-..."
99
+ apipatch scan ./project --provider anthropic --api-key "sk-ant-..."
100
+ ```
101
+
102
+ ---
103
+
104
+ ## πŸ’» CLI Commands & Usage
105
+
106
+ ### 1. πŸ” Scan a Codebase (Dry Run)
107
+ Audits files recursively (`.py`, `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs`),
108
+ detects deprecated calls, and outputs colorized diff previews without modifying files:
109
+ ```bash
110
+ apipatch scan /path/to/project
111
+ apipatch scan /path/to/project --provider gemini
112
+ ```
113
+
114
+ ### 2. ⚑ Refactor and Apply Fixes In-Place
115
+ Automatically updates the code and generates `.bak` safety backups:
116
+ ```bash
117
+ apipatch fix /path/to/project --write
118
+ apipatch fix /path/to/single/file.py --write --provider openai
119
+ ```
120
+ *(Add `--no-backup` to skip automatic `.bak` backup creation.)*
121
+
122
+ ### 3. πŸ“¦ Discover All Project Dependencies
123
+ Inspects `requirements.txt`, `package.json`, `pyproject.toml`, and all source file
124
+ imports (Python AST + JS/TS regex) to list every third-party library in use:
125
+ ```bash
126
+ apipatch detect /path/to/project
127
+ ```
128
+
129
+ ### 4. 🎯 Hunt for Deprecated Code on GitHub & Prepare PRs
130
+ Searches GitHub for legacy patterns and prepares ready-to-merge Pull Requests:
131
+ ```bash
132
+ apipatch hunt "openai.ChatCompletion.create language:python"
133
+ apipatch hunt "stripe.Charge.create language:javascript"
134
+ ```
135
+
136
+ ---
137
+
138
+ ## πŸ§ͺ Testing
139
+
140
+ ```bash
141
+ python -m pytest tests/ -v
142
+ ```
143
+
144
+ All 23 tests are offline-safe (no API key required for the test suite).
145
+
146
+ ---
147
+
148
+ ## πŸ—ΊοΈ Roadmap
149
+
150
+ - [x] Universal LLM engine β€” no hardcoded rules, ANY library supported
151
+ - [x] Multi-language support: Python, JavaScript, TypeScript, JSX, TSX
152
+ - [x] AST Syntax & Safety Validator
153
+ - [x] Multi-LLM Provider (Gemini, OpenAI, Claude) with auto-discovery
154
+ - [x] In-place refactoring with automatic backup (`--write`)
155
+ - [x] Autonomous dependency discovery (requirements.txt / package.json / AST scan)
156
+ - [x] Automated test suite (23/23 tests passing)
157
+ - [ ] 1-Click Autonomous GitHub App Webhook Integration
158
+ - [ ] PyPI Global Package Release (`pip install apipatch`)
159
+
160
+ ---
161
+
162
+ ## πŸ“„ License
163
+
164
+ MIT License. Built by [Morad Moqbel](https://github.com/MoradMoqbel).
@@ -0,0 +1,22 @@
1
+ """
2
+ ApiPatch - Autonomous AI Agent for API Breaking Changes & Self-Maintaining Codebases
3
+ Detects and fixes deprecated third-party API calls in Python, JavaScript, TypeScript,
4
+ JSX, TSX, and any other language β€” powered by LLM reasoning.
5
+ """
6
+
7
+ __version__ = "0.3.0"
8
+ __author__ = "Morad Moqbel"
9
+ __license__ = "MIT"
10
+
11
+ from apipatch.engine import ApiPatchEngine
12
+ from apipatch.validator import CodeValidator
13
+ from apipatch.auto_detector import AutoDeprecationDetector
14
+ from apipatch.proactive_hunter import GitHubPRHunter
15
+
16
+ __all__ = [
17
+ "ApiPatchEngine",
18
+ "CodeValidator",
19
+ "AutoDeprecationDetector",
20
+ "GitHubPRHunter",
21
+ "__version__",
22
+ ]
@@ -0,0 +1,223 @@
1
+ """
2
+ ApiPatch Autonomous Dependency & Import Detector
3
+ Discovers all third-party libraries used in a project (Python, JavaScript, TypeScript)
4
+ without any hardcoded rules β€” enabling the LLM engine to reason about ANY library.
5
+ """
6
+
7
+ import os
8
+ import ast
9
+ import json
10
+ import re
11
+ from typing import List, Set, Dict, Any, Optional
12
+ from apipatch.providers.factory import ProviderFactory
13
+
14
+ # Python standard library module names (excluded from "third-party" list)
15
+ STANDARD_LIB_MODULES = {
16
+ "abc", "argparse", "array", "ast", "asyncio", "base64", "binascii", "bisect",
17
+ "builtins", "calendar", "cmath", "collections", "concurrent", "contextlib",
18
+ "copy", "csv", "ctypes", "dataclasses", "datetime", "decimal", "difflib",
19
+ "dis", "doctest", "email", "enum", "errno", "faulthandler", "fcntl", "filecmp",
20
+ "fileinput", "fnmatch", "fractions", "functools", "gc", "getopt", "getpass",
21
+ "gettext", "glob", "graphlib", "gzip", "hashlib", "heapq", "hmac", "html",
22
+ "http", "idlelib", "imaplib", "imghdr", "importlib", "inspect", "io",
23
+ "ipaddress", "itertools", "json", "keyword", "linecache", "locale", "logging",
24
+ "lzma", "mailbox", "mailcap", "marshal", "math", "mimetypes", "mmap",
25
+ "modulefinder", "multiprocessing", "netrc", "nntplib", "numbers", "operator",
26
+ "os", "pathlib", "pdb", "pickle", "pipes", "pkgutil", "platform", "plistlib",
27
+ "poplib", "posix", "pprint", "profile", "pstats", "pty", "pwd", "py_compile",
28
+ "pyclbr", "pydoc", "queue", "quopri", "random", "re", "readline", "reprlib",
29
+ "resource", "rlcompleter", "runpy", "sched", "secrets", "select", "selectors",
30
+ "shelve", "shlex", "shutil", "signal", "site", "smtpd", "smtplib", "sndhdr",
31
+ "socket", "socketserver", "spwd", "sqlite3", "ssl", "stat", "statistics",
32
+ "string", "stringprep", "struct", "subprocess", "sunau", "symtable", "sys",
33
+ "sysconfig", "syslog", "tabnanny", "tarfile", "telnetlib", "tempfile", "termios",
34
+ "test", "textwrap", "threading", "time", "timeit", "tkinter", "token",
35
+ "tokenize", "tomllib", "trace", "traceback", "tracemalloc", "tty", "turtle",
36
+ "turtledemo", "types", "typing", "unicodedata", "unittest", "urllib", "uu",
37
+ "uuid", "venv", "warnings", "wave", "weakref", "webbrowser", "winreg", "winsound",
38
+ "wsgiref", "xdrlib", "xml", "xmlrpc", "zipapp", "zipfile", "zipimport", "zlib",
39
+ "zoneinfo"
40
+ }
41
+
42
+ # Node.js built-in modules (excluded from third-party list for JS/TS projects)
43
+ NODE_BUILTIN_MODULES = {
44
+ "fs", "path", "http", "https", "os", "crypto", "stream", "util", "events",
45
+ "child_process", "cluster", "dgram", "dns", "domain", "net", "querystring",
46
+ "readline", "repl", "string_decoder", "timers", "tls", "tty", "url",
47
+ "v8", "vm", "worker_threads", "zlib", "buffer", "assert", "console",
48
+ "module", "process", "inspector", "perf_hooks", "async_hooks"
49
+ }
50
+
51
+
52
+ class AutoDeprecationDetector:
53
+ def __init__(
54
+ self,
55
+ target_dir: str = ".",
56
+ provider_name: Optional[str] = None,
57
+ api_key: Optional[str] = None
58
+ ):
59
+ self.target_dir = os.path.abspath(target_dir)
60
+ self.provider = ProviderFactory.get_provider(
61
+ provider_name=provider_name, api_key=api_key
62
+ )
63
+
64
+ # ─── Python Import Extraction ─────────────────────────────────────────────
65
+
66
+ def extract_imports_from_file(self, file_path: str) -> Set[str]:
67
+ """
68
+ Uses Python AST to extract all third-party imported module names
69
+ from a .py or .pyw source file.
70
+ """
71
+ imports: Set[str] = set()
72
+ if not file_path.endswith((".py", ".pyw")):
73
+ return imports
74
+ try:
75
+ with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
76
+ content = f.read()
77
+ tree = ast.parse(content)
78
+ for node in ast.walk(tree):
79
+ if isinstance(node, ast.Import):
80
+ for alias in node.names:
81
+ top_pkg = alias.name.split('.')[0]
82
+ if top_pkg not in STANDARD_LIB_MODULES:
83
+ imports.add(top_pkg)
84
+ elif isinstance(node, ast.ImportFrom):
85
+ if node.module:
86
+ top_pkg = node.module.split('.')[0]
87
+ if top_pkg not in STANDARD_LIB_MODULES:
88
+ imports.add(top_pkg)
89
+ except Exception:
90
+ pass
91
+ return imports
92
+
93
+ # ─── JS/TS Import Extraction ──────────────────────────────────────────────
94
+
95
+ def extract_imports_from_js_file(self, file_path: str) -> Set[str]:
96
+ """
97
+ Uses regex to extract third-party package names from
98
+ JS / TS / JSX / TSX / MJS / CJS source files.
99
+ """
100
+ imports: Set[str] = set()
101
+ ext = os.path.splitext(file_path)[1].lower()
102
+ if ext not in {".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"}:
103
+ return imports
104
+ try:
105
+ with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
106
+ content = f.read()
107
+
108
+ # ESM: import ... from 'pkg' / import 'pkg'
109
+ esm_patterns = re.findall(
110
+ r"""(?:^|\n)\s*import\s+(?:[^'"]*?from\s+)?['"]([@\w][\w/.-]*)['"]""",
111
+ content
112
+ )
113
+ # CJS: require('pkg')
114
+ cjs_patterns = re.findall(r"""require\s*\(\s*['"]([@\w][\w/.-]*)['"]\s*\)""", content)
115
+
116
+ for raw in esm_patterns + cjs_patterns:
117
+ # Normalise scoped packages: @org/pkg -> @org/pkg
118
+ # Strip sub-paths: lodash/merge -> lodash
119
+ if raw.startswith('@'):
120
+ parts = raw.split('/')
121
+ pkg = '/'.join(parts[:2]) if len(parts) >= 2 else raw
122
+ else:
123
+ pkg = raw.split('/')[0]
124
+
125
+ if pkg and pkg not in NODE_BUILTIN_MODULES and not pkg.startswith('.'):
126
+ imports.add(pkg)
127
+ except Exception:
128
+ pass
129
+ return imports
130
+
131
+ # ─── Manifest-based Dependency Discovery ─────────────────────────────────
132
+
133
+ def _parse_requirements_txt(self) -> Set[str]:
134
+ deps: Set[str] = set()
135
+ req_path = os.path.join(self.target_dir, "requirements.txt")
136
+ if os.path.exists(req_path):
137
+ with open(req_path, "r", encoding="utf-8", errors="ignore") as f:
138
+ for line in f:
139
+ line = line.strip()
140
+ if line and not line.startswith("#") and not line.startswith("-"):
141
+ pkg = re.split(r"[><=~;!@\[]", line)[0].strip().lower()
142
+ if pkg:
143
+ deps.add(pkg)
144
+ return deps
145
+
146
+ def _parse_package_json(self) -> Set[str]:
147
+ deps: Set[str] = set()
148
+ pkg_json = os.path.join(self.target_dir, "package.json")
149
+ if os.path.exists(pkg_json):
150
+ try:
151
+ with open(pkg_json, "r", encoding="utf-8", errors="ignore") as f:
152
+ data = json.load(f)
153
+ for key in ("dependencies", "devDependencies", "peerDependencies"):
154
+ if key in data and isinstance(data[key], dict):
155
+ deps.update(p.lower() for p in data[key].keys())
156
+ except Exception:
157
+ pass
158
+ return deps
159
+
160
+ def _parse_pyproject_toml(self) -> Set[str]:
161
+ deps: Set[str] = set()
162
+ pyproject = os.path.join(self.target_dir, "pyproject.toml")
163
+ if os.path.exists(pyproject):
164
+ try:
165
+ with open(pyproject, "r", encoding="utf-8", errors="ignore") as f:
166
+ content = f.read()
167
+ # Extract quoted package names from dependency lists
168
+ for match in re.findall(r'"([a-zA-Z0-9_\-]+)(?:[><=~;].*)?[">\s]', content):
169
+ m = match.strip().lower()
170
+ if m and m not in {"apipatch", "setuptools", "wheel", "pytest", "python"}:
171
+ deps.add(m)
172
+ except Exception:
173
+ pass
174
+ return deps
175
+
176
+ # ─── Main Detection API ───────────────────────────────────────────────────
177
+
178
+ def detect_dependencies(self) -> List[str]:
179
+ """
180
+ Discovers all third-party packages from:
181
+ 1. requirements.txt
182
+ 2. package.json
183
+ 3. pyproject.toml
184
+ 4. Recursive AST inspection of Python source files
185
+ 5. Regex inspection of JS/TS source files
186
+ """
187
+ dependencies: Set[str] = set()
188
+
189
+ dependencies.update(self._parse_requirements_txt())
190
+ dependencies.update(self._parse_package_json())
191
+ dependencies.update(self._parse_pyproject_toml())
192
+
193
+ ignore_dirs = {
194
+ ".git", "node_modules", "venv", ".venv", "__pycache__",
195
+ ".gemini", "dist", "build", ".next", ".nuxt", "out", "coverage"
196
+ }
197
+
198
+ for root, dirs, files in os.walk(self.target_dir):
199
+ dirs[:] = [d for d in dirs if d not in ignore_dirs]
200
+ for file in files:
201
+ full_path = os.path.join(root, file)
202
+ ext = os.path.splitext(file)[1].lower()
203
+ if ext in {".py", ".pyw"}:
204
+ dependencies.update(self.extract_imports_from_file(full_path))
205
+ elif ext in {".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"}:
206
+ dependencies.update(self.extract_imports_from_js_file(full_path))
207
+
208
+ return sorted(dependencies)
209
+
210
+ def run_autonomous_discovery(self) -> Dict[str, Any]:
211
+ """Runs end-to-end autonomous dependency discovery and prints a summary."""
212
+ deps = self.detect_dependencies()
213
+ print(f"\n[ApiPatch] Detected {len(deps)} third-party package(s) in '{self.target_dir}':")
214
+ for dep in deps:
215
+ print(f" - {dep}")
216
+ print(
217
+ "\nAll detected packages will be passed to the AI engine "
218
+ "for dynamic deprecation analysis when you run `apipatch scan` or `apipatch fix`.\n"
219
+ )
220
+ return {
221
+ "target_directory": self.target_dir,
222
+ "detected_packages": deps,
223
+ }