selenium-selector-autocorrect 0.1.1__tar.gz → 0.1.2__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.
- {selenium_selector_autocorrect-0.1.1/src/selenium_selector_autocorrect.egg-info → selenium_selector_autocorrect-0.1.2}/PKG-INFO +48 -104
- selenium_selector_autocorrect-0.1.2/README.md +181 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/pyproject.toml +1 -1
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect/__init__.py +1 -1
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect/ai_providers.py +43 -18
- selenium_selector_autocorrect-0.1.2/src/selenium_selector_autocorrect/correction_tracker.py +686 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2/src/selenium_selector_autocorrect.egg-info}/PKG-INFO +48 -104
- selenium_selector_autocorrect-0.1.1/README.md +0 -237
- selenium_selector_autocorrect-0.1.1/src/selenium_selector_autocorrect/correction_tracker.py +0 -251
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/LICENSE +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/setup.cfg +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect/auto_correct.py +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect/wait_hook.py +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect.egg-info/SOURCES.txt +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect.egg-info/dependency_links.txt +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect.egg-info/requires.txt +0 -0
- {selenium_selector_autocorrect-0.1.1 → selenium_selector_autocorrect-0.1.2}/src/selenium_selector_autocorrect.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: selenium-selector-autocorrect
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Automatic Selenium selector correction using AI when elements fail to be found
|
|
5
5
|
Author-email: Marty Zhou <marty.zhou@example.com>
|
|
6
6
|
Maintainer-email: Marty Zhou <marty.zhou@example.com>
|
|
@@ -75,22 +75,6 @@ element = WebDriverWait(driver, 10).until(
|
|
|
75
75
|
)
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
## AI Service Setup
|
|
79
|
-
|
|
80
|
-
This package requires a local AI service with an OpenAI-compatible API. We recommend using **[VS Code Copilot as Service](https://marketplace.visualstudio.com/items?itemName=MartyZhou.vscode-copilot-as-service)**, which exposes GitHub Copilot through a local HTTP server.
|
|
81
|
-
|
|
82
|
-
### Installing VS Code Copilot as Service
|
|
83
|
-
|
|
84
|
-
1. Install from VS Code Marketplace or run:
|
|
85
|
-
```bash
|
|
86
|
-
code --install-extension MartyZhou.vscode-copilot-as-service
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
2. The extension automatically starts a server on `http://localhost:8765`
|
|
90
|
-
|
|
91
|
-
3. Requires an active GitHub Copilot subscription
|
|
92
|
-
|
|
93
|
-
|
|
94
78
|
## Configuration
|
|
95
79
|
|
|
96
80
|
Configure via environment variables:
|
|
@@ -124,67 +108,28 @@ install_auto_correct_hook()
|
|
|
124
108
|
|
|
125
109
|
```python
|
|
126
110
|
from selenium_selector_autocorrect import (
|
|
127
|
-
install_auto_correct_hook,
|
|
128
111
|
get_auto_correct,
|
|
129
112
|
get_correction_tracker,
|
|
130
|
-
export_corrections_report
|
|
113
|
+
export_corrections_report,
|
|
131
114
|
)
|
|
132
115
|
|
|
133
|
-
install_auto_correct_hook()
|
|
134
|
-
|
|
135
116
|
auto_correct = get_auto_correct()
|
|
136
117
|
auto_correct.enabled = True
|
|
137
|
-
auto_correct.suggest_better_selectors = False
|
|
138
118
|
|
|
139
|
-
# Export corrections report at end of test run
|
|
140
119
|
tracker = get_correction_tracker()
|
|
141
120
|
export_corrections_report("corrections_report.json")
|
|
142
|
-
tracker = get_correction_tracker()
|
|
143
|
-
export_corrections_report("corrections_report.json")
|
|
144
|
-
|
|
145
|
-
print(f"Total corrections: {len(tracker.get_corrections())}")
|
|
146
|
-
print(f"Successful corrections: {len(tracker.get_successful_corrections())}")
|
|
147
121
|
```
|
|
148
122
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
```python
|
|
152
|
-
from selenium_selector_autocorrect import AIProvider, configure_provider
|
|
153
|
-
|
|
154
|
-
class CustomAIProvider(AIProvider):
|
|
155
|
-
def is_available(self) -> bool:
|
|
156
|
-
return True
|
|
157
|
-
|
|
158
|
-
def suggest_selector(self, system_prompt: str, user_prompt: str):))
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## How It Works
|
|
162
|
-
|
|
163
|
-
1. **Hook Installation**: Patches `WebDriverWait.until()` to add auto-correction
|
|
164
|
-
2. **Timeout Detection**: When a selector times out, the original exception is caught
|
|
165
|
-
3. **Page Analysis**: JavaScript extracts visible elements and their attributes
|
|
166
|
-
4. **AI Suggestion**: Sends page context to AI provider for selector suggestion
|
|
167
|
-
5. **Verification**: Tests the suggested selector
|
|
168
|
-
6. **Success Handling**: If successful, records the correction and optionally updates the test file
|
|
169
|
-
7. **Fallback**: If correction fails, raises the original TimeoutException
|
|
170
|
-
|
|
171
|
-
## AI Provider Setup
|
|
172
|
-
|
|
173
|
-
### Local AI Service
|
|
174
|
-
|
|
175
|
-
The package requires a local AI service with OpenAI-compatible API:
|
|
123
|
+
## AI Service Setup
|
|
176
124
|
|
|
177
|
-
|
|
178
|
-
POST http://localhost:8765/v1/chat/completions
|
|
179
|
-
```
|
|
125
|
+
This package requires a local AI service with an OpenAI-compatible API. The following endpoints are used:
|
|
180
126
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
POST
|
|
184
|
-
POST
|
|
185
|
-
## Correction Reports
|
|
127
|
+
- `POST {LOCAL_AI_API_URL}/v1/chat/completions` — chat completions for suggestions
|
|
128
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/read` — read file content
|
|
129
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/edit` — apply edits to files
|
|
130
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/search` — search workspace
|
|
186
131
|
|
|
187
|
-
|
|
132
|
+
## Exporting Reports
|
|
188
133
|
|
|
189
134
|
```python
|
|
190
135
|
from selenium_selector_autocorrect import export_corrections_report
|
|
@@ -193,6 +138,7 @@ export_corrections_report("corrections_report.json")
|
|
|
193
138
|
```
|
|
194
139
|
|
|
195
140
|
Report format:
|
|
141
|
+
|
|
196
142
|
```json
|
|
197
143
|
{
|
|
198
144
|
"corrections": [
|
|
@@ -215,13 +161,13 @@ Report format:
|
|
|
215
161
|
}
|
|
216
162
|
```
|
|
217
163
|
|
|
218
|
-
##
|
|
164
|
+
## Troubleshooting
|
|
165
|
+
|
|
166
|
+
**AI service not available**: Ensure the local AI service is running and reachable via `LOCAL_AI_API_URL`.
|
|
219
167
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
4. **Monitor AI Service**: Ensure your AI service is running and responsive
|
|
224
|
-
5. **Use Strong Selectors**: The tool helps with failures but writing robust selectors is still preferred
|
|
168
|
+
**Auto-update not running**: Verify `SELENIUM_AUTO_UPDATE_TESTS` is set to `"1"`.
|
|
169
|
+
|
|
170
|
+
**Selector strings not found when updating**: Check quote styles in your source files match those used in the correction.
|
|
225
171
|
|
|
226
172
|
## Requirements
|
|
227
173
|
|
|
@@ -231,47 +177,45 @@ Report format:
|
|
|
231
177
|
|
|
232
178
|
## License
|
|
233
179
|
|
|
234
|
-
|
|
235
|
-
2. Review correction reports regularly to identify brittle selectors
|
|
236
|
-
3. Use auto-update sparingly and review changes before committing
|
|
237
|
-
4. Ensure your AI service is running and responsive
|
|
238
|
-
5. Write robust selectors - the tool helps with failures but prevention is better
|
|
180
|
+
MIT
|
|
239
181
|
|
|
240
|
-
|
|
241
|
-
1. Follow PEP 8 style guidelines
|
|
242
|
-
2. Add tests for new features
|
|
243
|
-
3. Update documentation
|
|
244
|
-
4. No emojis in code or documentation
|
|
182
|
+
## Contributing
|
|
245
183
|
|
|
246
|
-
|
|
184
|
+
Please follow PEP 8, add tests for new features, and update documentation when changing behavior.
|
|
247
185
|
|
|
248
|
-
|
|
186
|
+
See [CHANGELOG.md](CHANGELOG.md) for release notes and version history.
|
|
249
187
|
|
|
250
|
-
|
|
251
|
-
1. Follow PEP 8 style guidelines
|
|
252
|
-
2. Add tests for new features
|
|
253
|
-
3. Update documentation
|
|
254
|
-
4. Maintain consistency with existing code
|
|
188
|
+
## Publishing to PyPI
|
|
255
189
|
|
|
256
|
-
|
|
257
|
-
- `SELENIUM_AUTO_UPDATE_TESTS` not set to `"1"`
|
|
258
|
-
- Test file path not detected correctly
|
|
259
|
-
- Selector string not found in source file (check quotes)
|
|
190
|
+
Create a PyPI API token at https://pypi.org/manage/account/#api-tokens (recommended scope: project or account) and keep the token secret. PyPI no longer accepts username/password uploads — use the token as the password and `__token__` as the username.
|
|
260
191
|
|
|
261
|
-
|
|
262
|
-
Solution: Ensure your local AI service is running on the configured port.
|
|
192
|
+
PowerShell (Windows) example:
|
|
263
193
|
|
|
264
|
-
|
|
194
|
+
```powershell
|
|
195
|
+
$env:TWINE_USERNAME='__token__'
|
|
196
|
+
$env:TWINE_PASSWORD='pypi-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
|
197
|
+
.\venv\Scripts\python.exe -m pip install --upgrade build twine
|
|
198
|
+
.\venv\Scripts\python.exe -m build
|
|
199
|
+
.\venv\Scripts\python.exe -m twine upload dist/*
|
|
200
|
+
```
|
|
265
201
|
|
|
266
|
-
|
|
267
|
-
- `SELENIUM_AUTO_UPDATE_TESTS` not set to "1"
|
|
268
|
-
- Test file path not detected correctly
|
|
269
|
-
- Selector string not found in source file
|
|
202
|
+
Unix / macOS example:
|
|
270
203
|
|
|
271
|
-
|
|
204
|
+
```bash
|
|
205
|
+
export TWINE_USERNAME='__token__'
|
|
206
|
+
export TWINE_PASSWORD='pypi-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
|
207
|
+
python3 -m pip install --upgrade build twine
|
|
208
|
+
python3 -m build
|
|
209
|
+
python3 -m twine upload dist/*
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
To publish to TestPyPI (verify release first):
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
|
|
216
|
+
```
|
|
272
217
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
See CHANGELOG.md for version history and changes.
|
|
218
|
+
Notes:
|
|
219
|
+
- Use an API token (not account password). If using a CI system, store the token in secure secrets.
|
|
220
|
+
- You can add a persistent `~/.pypirc` for repeated uploads; see PyPI documentation for details.
|
|
221
|
+
- If upload fails with a 403, verify the token is correct and has the required scope.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Selenium Selector AutoCorrect
|
|
2
|
+
|
|
3
|
+
A Python package that automatically corrects Selenium element selectors using AI when they fail, reducing test maintenance and improving test reliability.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Automatic Selector Correction**: When a WebDriverWait times out, the package uses AI to analyze the page and suggest working alternatives
|
|
8
|
+
- **Local AI Integration**: Uses a local AI service with OpenAI-compatible API
|
|
9
|
+
- **Correction Tracking**: Records all corrections with source file and line information
|
|
10
|
+
- **Optional Auto-Update**: Can automatically update test files with corrected selectors
|
|
11
|
+
- **Zero Code Changes**: Works by hooking into Selenium's WebDriverWait
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install selenium-selector-autocorrect
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from selenium import webdriver
|
|
23
|
+
from selenium.webdriver.common.by import By
|
|
24
|
+
from selenium.webdriver.support.wait import WebDriverWait
|
|
25
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
26
|
+
from selenium_selector_autocorrect import install_auto_correct_hook
|
|
27
|
+
|
|
28
|
+
install_auto_correct_hook()
|
|
29
|
+
|
|
30
|
+
driver = webdriver.Chrome()
|
|
31
|
+
driver.get("https://example.com")
|
|
32
|
+
|
|
33
|
+
element = WebDriverWait(driver, 10).until(
|
|
34
|
+
EC.presence_of_element_located((By.ID, "some-element"))
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Configuration
|
|
39
|
+
|
|
40
|
+
Configure via environment variables:
|
|
41
|
+
|
|
42
|
+
- `LOCAL_AI_API_URL`: URL of local AI service (default: `http://localhost:8765`)
|
|
43
|
+
- `SELENIUM_AUTO_CORRECT`: Enable/disable auto-correction (default: `"1"`)
|
|
44
|
+
- `SELENIUM_SUGGEST_BETTER`: Suggest better selectors for found elements (default: `"0"`)
|
|
45
|
+
- `SELENIUM_AUTO_UPDATE_TESTS`: Auto-update test files with corrections (default: `"0"`)
|
|
46
|
+
|
|
47
|
+
### Example
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import os
|
|
51
|
+
|
|
52
|
+
os.environ['LOCAL_AI_API_URL'] = 'http://localhost:8765'
|
|
53
|
+
os.environ['SELENIUM_AUTO_CORRECT'] = '1'
|
|
54
|
+
os.environ['SELENIUM_AUTO_UPDATE_TESTS'] = '1' # Enable auto-update
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### Basic Usage
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from selenium_selector_autocorrect import install_auto_correct_hook
|
|
63
|
+
|
|
64
|
+
install_auto_correct_hook()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Advanced Usage
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from selenium_selector_autocorrect import (
|
|
71
|
+
get_auto_correct,
|
|
72
|
+
get_correction_tracker,
|
|
73
|
+
export_corrections_report,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
auto_correct = get_auto_correct()
|
|
77
|
+
auto_correct.enabled = True
|
|
78
|
+
|
|
79
|
+
tracker = get_correction_tracker()
|
|
80
|
+
export_corrections_report("corrections_report.json")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## AI Service Setup
|
|
84
|
+
|
|
85
|
+
This package requires a local AI service with an OpenAI-compatible API. The following endpoints are used:
|
|
86
|
+
|
|
87
|
+
- `POST {LOCAL_AI_API_URL}/v1/chat/completions` — chat completions for suggestions
|
|
88
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/read` — read file content
|
|
89
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/edit` — apply edits to files
|
|
90
|
+
- `POST {LOCAL_AI_API_URL}/v1/workspace/files/search` — search workspace
|
|
91
|
+
|
|
92
|
+
## Exporting Reports
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from selenium_selector_autocorrect import export_corrections_report
|
|
96
|
+
|
|
97
|
+
export_corrections_report("corrections_report.json")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Report format:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"corrections": [
|
|
105
|
+
{
|
|
106
|
+
"original_by": "id",
|
|
107
|
+
"original_value": "old-selector",
|
|
108
|
+
"corrected_by": "css selector",
|
|
109
|
+
"corrected_value": ".new-selector",
|
|
110
|
+
"success": true,
|
|
111
|
+
"test_file": "/path/to/test.py",
|
|
112
|
+
"test_line": 42,
|
|
113
|
+
"timestamp": "2024-01-31T10:30:00"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"summary": {
|
|
117
|
+
"total": 10,
|
|
118
|
+
"successful": 8,
|
|
119
|
+
"generated_at": "2024-01-31T10:35:00"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Troubleshooting
|
|
125
|
+
|
|
126
|
+
**AI service not available**: Ensure the local AI service is running and reachable via `LOCAL_AI_API_URL`.
|
|
127
|
+
|
|
128
|
+
**Auto-update not running**: Verify `SELENIUM_AUTO_UPDATE_TESTS` is set to `"1"`.
|
|
129
|
+
|
|
130
|
+
**Selector strings not found when updating**: Check quote styles in your source files match those used in the correction.
|
|
131
|
+
|
|
132
|
+
## Requirements
|
|
133
|
+
|
|
134
|
+
- Python >= 3.8
|
|
135
|
+
- selenium >= 4.0.0
|
|
136
|
+
- requests >= 2.25.0
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
|
141
|
+
|
|
142
|
+
## Contributing
|
|
143
|
+
|
|
144
|
+
Please follow PEP 8, add tests for new features, and update documentation when changing behavior.
|
|
145
|
+
|
|
146
|
+
See [CHANGELOG.md](CHANGELOG.md) for release notes and version history.
|
|
147
|
+
|
|
148
|
+
## Publishing to PyPI
|
|
149
|
+
|
|
150
|
+
Create a PyPI API token at https://pypi.org/manage/account/#api-tokens (recommended scope: project or account) and keep the token secret. PyPI no longer accepts username/password uploads — use the token as the password and `__token__` as the username.
|
|
151
|
+
|
|
152
|
+
PowerShell (Windows) example:
|
|
153
|
+
|
|
154
|
+
```powershell
|
|
155
|
+
$env:TWINE_USERNAME='__token__'
|
|
156
|
+
$env:TWINE_PASSWORD='pypi-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
|
157
|
+
.\venv\Scripts\python.exe -m pip install --upgrade build twine
|
|
158
|
+
.\venv\Scripts\python.exe -m build
|
|
159
|
+
.\venv\Scripts\python.exe -m twine upload dist/*
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Unix / macOS example:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
export TWINE_USERNAME='__token__'
|
|
166
|
+
export TWINE_PASSWORD='pypi-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
|
167
|
+
python3 -m pip install --upgrade build twine
|
|
168
|
+
python3 -m build
|
|
169
|
+
python3 -m twine upload dist/*
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
To publish to TestPyPI (verify release first):
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Notes:
|
|
179
|
+
- Use an API token (not account password). If using a CI system, store the token in secure secrets.
|
|
180
|
+
- You can add a persistent `~/.pypirc` for repeated uploads; see PyPI documentation for details.
|
|
181
|
+
- If upload fails with a 403, verify the token is correct and has the required scope.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "selenium-selector-autocorrect"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "Automatic Selenium selector correction using AI when elements fail to be found"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -15,7 +15,7 @@ Environment Variables:
|
|
|
15
15
|
SELENIUM_AUTO_UPDATE_TESTS: Auto-update test files with corrections (default: "0")
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
__version__ = "0.1.
|
|
18
|
+
__version__ = "0.1.2"
|
|
19
19
|
|
|
20
20
|
from .ai_providers import AIProvider, LocalAIProvider, configure_provider, get_provider
|
|
21
21
|
from .auto_correct import (
|
|
@@ -48,14 +48,24 @@ class LocalAIProvider(AIProvider):
|
|
|
48
48
|
if self._available is not None:
|
|
49
49
|
return self._available
|
|
50
50
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
51
|
+
url = f"{self.base_url}/v1/chat/completions"
|
|
52
|
+
payload = {"messages": [{"role": "user", "content": "test"}], "max_tokens": 1}
|
|
53
|
+
|
|
54
|
+
logger.debug(f"[AI-REQUEST] POST {url}")
|
|
55
|
+
logger.debug(f"[AI-REQUEST] Payload: {payload}")
|
|
56
|
+
|
|
57
|
+
response = requests.post(url, json=payload, timeout=30)
|
|
58
|
+
|
|
59
|
+
logger.debug(f"[AI-RESPONSE] Status: {response.status_code}")
|
|
60
|
+
logger.debug(f"[AI-RESPONSE] Headers: {dict(response.headers)}")
|
|
61
|
+
logger.debug(f"[AI-RESPONSE] Body length: {len(response.text)} chars")
|
|
62
|
+
if response.text:
|
|
63
|
+
logger.debug(f"[AI-RESPONSE] Body preview: {response.text[:500]}")
|
|
64
|
+
|
|
56
65
|
self._available = response.status_code in (200, 400)
|
|
57
66
|
except Exception as e:
|
|
58
67
|
logger.info(f"Local AI service not available at {self.base_url}: {e}")
|
|
68
|
+
logger.debug(f"[AI-ERROR] Exception details: {type(e).__name__}: {str(e)}")
|
|
59
69
|
self._available = False
|
|
60
70
|
return self._available
|
|
61
71
|
|
|
@@ -70,23 +80,37 @@ class LocalAIProvider(AIProvider):
|
|
|
70
80
|
AI response text or None if request fails
|
|
71
81
|
"""
|
|
72
82
|
try:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
83
|
+
url = f"{self.base_url}/v1/chat/completions"
|
|
84
|
+
payload = {
|
|
85
|
+
"messages": [
|
|
86
|
+
{"role": "system", "content": system_prompt},
|
|
87
|
+
{"role": "user", "content": user_prompt}
|
|
88
|
+
],
|
|
89
|
+
"temperature": 0.3,
|
|
90
|
+
"max_tokens": 500
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
logger.debug(f"[AI-REQUEST] POST {url}")
|
|
94
|
+
logger.debug(f"[AI-REQUEST] System prompt ({len(system_prompt)} chars): {system_prompt[:200]}...")
|
|
95
|
+
logger.debug(f"[AI-REQUEST] User prompt ({len(user_prompt)} chars): {user_prompt[:200]}...")
|
|
96
|
+
logger.debug(f"[AI-REQUEST] Full payload: {payload}")
|
|
97
|
+
|
|
98
|
+
response = requests.post(url, json=payload, timeout=30)
|
|
99
|
+
|
|
100
|
+
logger.debug(f"[AI-RESPONSE] Status: {response.status_code}")
|
|
101
|
+
logger.debug(f"[AI-RESPONSE] Headers: {dict(response.headers)}")
|
|
102
|
+
logger.debug(f"[AI-RESPONSE] Body length: {len(response.text)} chars")
|
|
103
|
+
logger.debug(f"[AI-RESPONSE] Full body: {response.text[:2000]}")
|
|
104
|
+
|
|
85
105
|
response.raise_for_status()
|
|
86
106
|
data: Dict[str, Any] = response.json()
|
|
87
107
|
content: Optional[str] = data.get("choices", [{}])[0].get("message", {}).get("content", "")
|
|
108
|
+
logger.debug(f"[AI-PARSED] Content length: {len(content) if content else 0} chars")
|
|
109
|
+
logger.debug(f"[AI-PARSED] Content preview: {content[:500] if content else 'None'}")
|
|
88
110
|
return content
|
|
89
111
|
except requests.exceptions.HTTPError as e:
|
|
112
|
+
logger.error(f"[AI-ERROR] HTTP Error {e.response.status_code}")
|
|
113
|
+
logger.error(f"[AI-ERROR] Response body: {e.response.text[:1000]}")
|
|
90
114
|
if e.response.status_code == 503:
|
|
91
115
|
logger.info(f"Local AI service unavailable (503). Disabling auto-correction.")
|
|
92
116
|
self._available = False
|
|
@@ -94,7 +118,8 @@ class LocalAIProvider(AIProvider):
|
|
|
94
118
|
logger.warning(f"Local AI HTTP error: {e}")
|
|
95
119
|
return None
|
|
96
120
|
except Exception as e:
|
|
97
|
-
logger.
|
|
121
|
+
logger.error(f"[AI-ERROR] Request failed: {type(e).__name__}: {str(e)}")
|
|
122
|
+
logger.debug(f"[AI-ERROR] Exception details: {e}", exc_info=True)
|
|
98
123
|
self._available = False
|
|
99
124
|
return None
|
|
100
125
|
|