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 +21 -0
- apipatch-0.3.0/PKG-INFO +197 -0
- apipatch-0.3.0/README.md +164 -0
- apipatch-0.3.0/apipatch/__init__.py +22 -0
- apipatch-0.3.0/apipatch/auto_detector.py +223 -0
- apipatch-0.3.0/apipatch/cli.py +101 -0
- apipatch-0.3.0/apipatch/engine.py +260 -0
- apipatch-0.3.0/apipatch/proactive_hunter.py +133 -0
- apipatch-0.3.0/apipatch/providers/__init__.py +17 -0
- apipatch-0.3.0/apipatch/providers/anthropic_provider.py +39 -0
- apipatch-0.3.0/apipatch/providers/base.py +124 -0
- apipatch-0.3.0/apipatch/providers/factory.py +47 -0
- apipatch-0.3.0/apipatch/providers/gemini_provider.py +63 -0
- apipatch-0.3.0/apipatch/providers/openai_provider.py +50 -0
- apipatch-0.3.0/apipatch/validator.py +116 -0
- apipatch-0.3.0/apipatch.egg-info/PKG-INFO +197 -0
- apipatch-0.3.0/apipatch.egg-info/SOURCES.txt +25 -0
- apipatch-0.3.0/apipatch.egg-info/dependency_links.txt +1 -0
- apipatch-0.3.0/apipatch.egg-info/entry_points.txt +2 -0
- apipatch-0.3.0/apipatch.egg-info/requires.txt +8 -0
- apipatch-0.3.0/apipatch.egg-info/top_level.txt +1 -0
- apipatch-0.3.0/pyproject.toml +53 -0
- apipatch-0.3.0/setup.cfg +4 -0
- apipatch-0.3.0/tests/test_cli.py +82 -0
- apipatch-0.3.0/tests/test_detector.py +133 -0
- apipatch-0.3.0/tests/test_engine.py +108 -0
- apipatch-0.3.0/tests/test_validator.py +69 -0
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.
|
apipatch-0.3.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
[](https://www.python.org/downloads/)
|
|
39
|
+
[](https://github.com/MoradMoqbel/apipatch)
|
|
40
|
+
[](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).
|
apipatch-0.3.0/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# β‘ ApiPatch
|
|
2
|
+
> **Autonomous AI Agent for API Breaking Changes & Self-Maintaining Codebases**
|
|
3
|
+
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](https://github.com/MoradMoqbel/apipatch)
|
|
7
|
+
[](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
|
+
}
|