paddleocr-skills 1.0.0
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.
- package/README.md +220 -0
- package/bin/paddleocr-skills.js +20 -0
- package/lib/copy.js +39 -0
- package/lib/installer.js +70 -0
- package/lib/prompts.js +67 -0
- package/lib/python.js +75 -0
- package/lib/verify.js +121 -0
- package/package.json +42 -0
- package/templates/.env.example +12 -0
- package/templates/paddleocr-vl/references/paddleocr-vl/layout_schema.md +64 -0
- package/templates/paddleocr-vl/references/paddleocr-vl/output_format.md +154 -0
- package/templates/paddleocr-vl/references/paddleocr-vl/vl_model_spec.md +157 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/_lib.py +780 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/configure.py +270 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/optimize_file.py +226 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/requirements-optimize.txt +8 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/requirements.txt +7 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/smoke_test.py +199 -0
- package/templates/paddleocr-vl/scripts/paddleocr-vl/vl_caller.py +232 -0
- package/templates/paddleocr-vl/skills/paddleocr-vl/SKILL.md +481 -0
- package/templates/ppocrv5/references/ppocrv5/agent_policy.md +258 -0
- package/templates/ppocrv5/references/ppocrv5/normalized_schema.md +257 -0
- package/templates/ppocrv5/references/ppocrv5/provider_api.md +140 -0
- package/templates/ppocrv5/scripts/ppocrv5/_lib.py +635 -0
- package/templates/ppocrv5/scripts/ppocrv5/configure.py +346 -0
- package/templates/ppocrv5/scripts/ppocrv5/ocr_caller.py +684 -0
- package/templates/ppocrv5/scripts/ppocrv5/requirements.txt +4 -0
- package/templates/ppocrv5/scripts/ppocrv5/smoke_test.py +139 -0
- package/templates/ppocrv5/skills/ppocrv5/SKILL.md +272 -0
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# PaddleOCR Skills
|
|
2
|
+
|
|
3
|
+
One-command installer to add PaddleOCR Skills to your Claude Code project.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
Install PaddleOCR Skills in your Claude Code project with a single command:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx paddleocr-skills
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The installer will:
|
|
14
|
+
1. Prompt you to select skills (PP-OCRv5 and/or PaddleOCR-VL)
|
|
15
|
+
2. Copy skill files to your project
|
|
16
|
+
3. Install Python dependencies
|
|
17
|
+
4. Guide you through API configuration
|
|
18
|
+
5. Verify the installation
|
|
19
|
+
|
|
20
|
+
## What's Included
|
|
21
|
+
|
|
22
|
+
### PP-OCRv5 (Text OCR)
|
|
23
|
+
- Fast text recognition for images and documents
|
|
24
|
+
- Adaptive quality modes (auto/fast/quality)
|
|
25
|
+
- Supports URLs and local files
|
|
26
|
+
- Confidence scoring and quality metrics
|
|
27
|
+
|
|
28
|
+
### PaddleOCR-VL (Document Parsing)
|
|
29
|
+
- Advanced document structure analysis
|
|
30
|
+
- Table, formula, and chart recognition
|
|
31
|
+
- Layout detection (headers, footers, page numbers)
|
|
32
|
+
- Complete document parsing with reading order
|
|
33
|
+
|
|
34
|
+
## Prerequisites
|
|
35
|
+
|
|
36
|
+
- **Node.js**: 14.0.0 or higher
|
|
37
|
+
- **Python**: 3.7 or higher
|
|
38
|
+
- **Claude Code**: Installed and configured
|
|
39
|
+
- **API Access**: Get your API credentials at [Baidu AI Studio](https://aistudio.baidu.com/paddleocr/task)
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
### Interactive Mode (Recommended)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx paddleocr-skills
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The installer will guide you through:
|
|
50
|
+
- Skill selection
|
|
51
|
+
- Python dependency installation
|
|
52
|
+
- API configuration
|
|
53
|
+
|
|
54
|
+
### Skip Configuration
|
|
55
|
+
|
|
56
|
+
If you want to configure later:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx paddleocr-skills
|
|
60
|
+
# Choose "No" when asked about configuration
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then configure manually:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# For PP-OCRv5
|
|
67
|
+
python scripts/ppocrv5/configure.py
|
|
68
|
+
|
|
69
|
+
# For PaddleOCR-VL
|
|
70
|
+
python scripts/paddleocr-vl/configure.py
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
After installation, use the skills in your Claude Code session:
|
|
76
|
+
|
|
77
|
+
### PP-OCRv5 Example
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Extract text from an image
|
|
81
|
+
python scripts/ppocrv5/ocr_caller.py --file-url "https://example.com/image.jpg" --pretty
|
|
82
|
+
|
|
83
|
+
# Save result to file
|
|
84
|
+
python scripts/ppocrv5/ocr_caller.py --file-path "document.pdf" --output result.json --pretty
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### PaddleOCR-VL Example
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Parse a complex document
|
|
91
|
+
python scripts/paddleocr-vl/vl_caller.py --file-url "https://example.com/paper.pdf" --pretty
|
|
92
|
+
|
|
93
|
+
# Save result to file
|
|
94
|
+
python scripts/paddleocr-vl/vl_caller.py --file-path "invoice.pdf" --output result.json --pretty
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Project Structure
|
|
98
|
+
|
|
99
|
+
After installation, your project will have:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
your-project/
|
|
103
|
+
├── skills/
|
|
104
|
+
│ ├── ppocrv5/
|
|
105
|
+
│ │ └── SKILL.md
|
|
106
|
+
│ └── paddleocr-vl/
|
|
107
|
+
│ └── SKILL.md
|
|
108
|
+
├── scripts/
|
|
109
|
+
│ ├── ppocrv5/
|
|
110
|
+
│ │ ├── ocr_caller.py
|
|
111
|
+
│ │ ├── configure.py
|
|
112
|
+
│ │ ├── smoke_test.py
|
|
113
|
+
│ │ └── requirements.txt
|
|
114
|
+
│ └── paddleocr-vl/
|
|
115
|
+
│ ├── vl_caller.py
|
|
116
|
+
│ ├── configure.py
|
|
117
|
+
│ ├── smoke_test.py
|
|
118
|
+
│ └── requirements.txt
|
|
119
|
+
├── references/
|
|
120
|
+
│ ├── ppocrv5/
|
|
121
|
+
│ └── paddleocr-vl/
|
|
122
|
+
└── .env.example
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Configuration
|
|
126
|
+
|
|
127
|
+
### Manual Configuration
|
|
128
|
+
|
|
129
|
+
If you skipped auto-configuration, create a `.env` file:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Copy the example file
|
|
133
|
+
cp .env.example .env
|
|
134
|
+
|
|
135
|
+
# Edit with your credentials
|
|
136
|
+
nano .env
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Add your API credentials:
|
|
140
|
+
|
|
141
|
+
```env
|
|
142
|
+
# PP-OCRv5
|
|
143
|
+
API_URL=https://your-api-url.aistudio-app.com/ocr
|
|
144
|
+
TOKEN=your-token-here
|
|
145
|
+
|
|
146
|
+
# PaddleOCR-VL
|
|
147
|
+
VL_API_URL=https://your-vl-api-url.com/v1
|
|
148
|
+
VL_TOKEN=your-vl-token-here
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Using Configuration Scripts
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Configure PP-OCRv5
|
|
155
|
+
python scripts/ppocrv5/configure.py --api-url "YOUR_URL" --token "YOUR_TOKEN"
|
|
156
|
+
|
|
157
|
+
# Configure PaddleOCR-VL
|
|
158
|
+
python scripts/paddleocr-vl/configure.py --api-url "YOUR_URL" --token "YOUR_TOKEN"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Verification
|
|
162
|
+
|
|
163
|
+
Test your installation:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Test PP-OCRv5
|
|
167
|
+
python scripts/ppocrv5/smoke_test.py
|
|
168
|
+
|
|
169
|
+
# Test PaddleOCR-VL
|
|
170
|
+
python scripts/paddleocr-vl/smoke_test.py
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Troubleshooting
|
|
174
|
+
|
|
175
|
+
### Python Not Found
|
|
176
|
+
|
|
177
|
+
Ensure Python is in your PATH:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
python --version
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
If not found, install Python 3.7+ from [python.org](https://www.python.org/).
|
|
184
|
+
|
|
185
|
+
### API Configuration Error
|
|
186
|
+
|
|
187
|
+
Get your API credentials:
|
|
188
|
+
|
|
189
|
+
1. Visit [Baidu AI Studio](https://aistudio.baidu.com/paddleocr/task)
|
|
190
|
+
2. Create a new task or use an existing one
|
|
191
|
+
3. Copy the API URL and TOKEN
|
|
192
|
+
4. Run the configuration script
|
|
193
|
+
|
|
194
|
+
### Permission Denied
|
|
195
|
+
|
|
196
|
+
On Windows, run your terminal as Administrator if you encounter permission errors.
|
|
197
|
+
|
|
198
|
+
## Documentation
|
|
199
|
+
|
|
200
|
+
Each skill includes comprehensive documentation:
|
|
201
|
+
|
|
202
|
+
- **skills/ppocrv5/SKILL.md**: PP-OCRv5 usage guide
|
|
203
|
+
- **skills/paddleocr-vl/SKILL.md**: PaddleOCR-VL usage guide
|
|
204
|
+
- **references/**: Technical reference documentation
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
209
|
+
|
|
210
|
+
## Support
|
|
211
|
+
|
|
212
|
+
For issues and questions:
|
|
213
|
+
- GitHub Issues: [Report a bug](https://github.com/yourusername/PP-OCRv5-claude-code-Skill/issues)
|
|
214
|
+
- Documentation: See `skills/*/SKILL.md` files
|
|
215
|
+
|
|
216
|
+
## Credits
|
|
217
|
+
|
|
218
|
+
Built with:
|
|
219
|
+
- [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) by PaddlePaddle
|
|
220
|
+
- [Claude Code](https://claude.ai/claude-code) by Anthropic
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PaddleOCR Skills Installer for Claude Code
|
|
5
|
+
*
|
|
6
|
+
* Entry point for npx paddleocr-skills
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { runInstaller } = require('../lib/installer');
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
try {
|
|
13
|
+
await runInstaller();
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error('\n❌ Installation failed:', error.message);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
main();
|
package/lib/copy.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copy skill files from template to target directory
|
|
6
|
+
*/
|
|
7
|
+
async function copySkillFiles(skills, targetDir) {
|
|
8
|
+
const templateDir = path.join(__dirname, '../templates');
|
|
9
|
+
|
|
10
|
+
for (const skill of skills) {
|
|
11
|
+
const skillTemplateDir = path.join(templateDir, skill);
|
|
12
|
+
|
|
13
|
+
// Copy scripts directory
|
|
14
|
+
const scriptsSource = path.join(skillTemplateDir, 'scripts', skill);
|
|
15
|
+
const scriptsTarget = path.join(targetDir, 'scripts', skill);
|
|
16
|
+
await fs.copy(scriptsSource, scriptsTarget, { overwrite: false });
|
|
17
|
+
|
|
18
|
+
// Copy skills directory
|
|
19
|
+
const skillsSource = path.join(skillTemplateDir, 'skills', skill);
|
|
20
|
+
const skillsTarget = path.join(targetDir, 'skills', skill);
|
|
21
|
+
await fs.copy(skillsSource, skillsTarget, { overwrite: false });
|
|
22
|
+
|
|
23
|
+
// Copy references directory if exists
|
|
24
|
+
const referencesSource = path.join(skillTemplateDir, 'references', skill);
|
|
25
|
+
if (await fs.pathExists(referencesSource)) {
|
|
26
|
+
const referencesTarget = path.join(targetDir, 'references', skill);
|
|
27
|
+
await fs.copy(referencesSource, referencesTarget, { overwrite: false });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Copy .env.example if it doesn't exist
|
|
32
|
+
const envExampleSource = path.join(templateDir, '.env.example');
|
|
33
|
+
const envExampleTarget = path.join(targetDir, '.env.example');
|
|
34
|
+
if (await fs.pathExists(envExampleSource)) {
|
|
35
|
+
await fs.copy(envExampleSource, envExampleTarget, { overwrite: false });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = { copySkillFiles };
|
package/lib/installer.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const { promptForSkills, promptForConfiguration } = require('./prompts');
|
|
4
|
+
const { copySkillFiles } = require('./copy');
|
|
5
|
+
const { installPythonDeps } = require('./python');
|
|
6
|
+
const { runConfigurationWizard, runVerification } = require('./verify');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Main installer workflow
|
|
10
|
+
*/
|
|
11
|
+
async function runInstaller() {
|
|
12
|
+
console.log(chalk.bold.cyan('\n🎨 PaddleOCR Skills for Claude Code\n'));
|
|
13
|
+
|
|
14
|
+
// Get current working directory (where user ran the command)
|
|
15
|
+
const targetDir = process.cwd();
|
|
16
|
+
console.log(chalk.gray(`Installing to: ${targetDir}\n`));
|
|
17
|
+
|
|
18
|
+
// Step 1: Prompt user for which skills to install
|
|
19
|
+
const { skills } = await promptForSkills();
|
|
20
|
+
|
|
21
|
+
if (skills.length === 0) {
|
|
22
|
+
console.log(chalk.yellow('\n⚠️ No skills selected. Exiting.'));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(chalk.green(`\n✓ Selected skills: ${skills.join(', ')}\n`));
|
|
27
|
+
|
|
28
|
+
// Step 2: Copy skill files to target directory
|
|
29
|
+
console.log(chalk.cyan('📁 Copying skill files...'));
|
|
30
|
+
await copySkillFiles(skills, targetDir);
|
|
31
|
+
console.log(chalk.green('✓ Files copied successfully\n'));
|
|
32
|
+
|
|
33
|
+
// Step 3: Install Python dependencies
|
|
34
|
+
console.log(chalk.cyan('🐍 Installing Python dependencies...'));
|
|
35
|
+
await installPythonDeps(skills, targetDir);
|
|
36
|
+
console.log(chalk.green('✓ Python dependencies installed\n'));
|
|
37
|
+
|
|
38
|
+
// Step 4: Ask if user wants to configure now
|
|
39
|
+
const { configureNow } = await promptForConfiguration();
|
|
40
|
+
|
|
41
|
+
if (configureNow) {
|
|
42
|
+
console.log(chalk.cyan('⚙️ Running configuration wizard...\n'));
|
|
43
|
+
await runConfigurationWizard(skills, targetDir);
|
|
44
|
+
console.log(chalk.green('✓ Configuration complete\n'));
|
|
45
|
+
|
|
46
|
+
// Step 5: Run verification
|
|
47
|
+
console.log(chalk.cyan('🔍 Verifying installation...\n'));
|
|
48
|
+
await runVerification(skills, targetDir);
|
|
49
|
+
} else {
|
|
50
|
+
console.log(chalk.yellow('\n⚠️ Skipped configuration. You can configure later by running:'));
|
|
51
|
+
if (skills.includes('ppocrv5')) {
|
|
52
|
+
console.log(chalk.gray(` python scripts/ppocrv5/configure.py`));
|
|
53
|
+
}
|
|
54
|
+
if (skills.includes('paddleocr-vl')) {
|
|
55
|
+
console.log(chalk.gray(` python scripts/paddleocr-vl/configure.py`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Success message
|
|
60
|
+
console.log(chalk.bold.green('\n✅ Installation complete!\n'));
|
|
61
|
+
console.log(chalk.cyan('Next steps:'));
|
|
62
|
+
console.log(chalk.gray(' 1. Get your API credentials at: https://aistudio.baidu.com/paddleocr/task'));
|
|
63
|
+
if (!configureNow) {
|
|
64
|
+
console.log(chalk.gray(' 2. Run the configuration scripts shown above'));
|
|
65
|
+
}
|
|
66
|
+
console.log(chalk.gray(` ${configureNow ? '2' : '3'}. Use the skills in your Claude Code session`));
|
|
67
|
+
console.log(chalk.gray('\nFor more information, see the skill documentation in the skills/ directory.\n'));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { runInstaller };
|
package/lib/prompts.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const prompts = require('prompts');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Prompt user to select which skills to install
|
|
5
|
+
*/
|
|
6
|
+
async function promptForSkills() {
|
|
7
|
+
return await prompts({
|
|
8
|
+
type: 'multiselect',
|
|
9
|
+
name: 'skills',
|
|
10
|
+
message: 'Which PaddleOCR skills do you want to install?',
|
|
11
|
+
choices: [
|
|
12
|
+
{
|
|
13
|
+
title: 'PP-OCRv5 (Text OCR)',
|
|
14
|
+
value: 'ppocrv5',
|
|
15
|
+
description: 'Fast text recognition for images and documents',
|
|
16
|
+
selected: true
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
title: 'PaddleOCR-VL (Document Parsing)',
|
|
20
|
+
value: 'paddleocr-vl',
|
|
21
|
+
description: 'Advanced parsing with tables, formulas, charts, and layout',
|
|
22
|
+
selected: true
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
hint: '- Space to select. Return to submit'
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Prompt user for configuration preferences
|
|
31
|
+
*/
|
|
32
|
+
async function promptForConfiguration() {
|
|
33
|
+
return await prompts({
|
|
34
|
+
type: 'confirm',
|
|
35
|
+
name: 'configureNow',
|
|
36
|
+
message: 'Do you want to configure API credentials now?',
|
|
37
|
+
initial: true
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Prompt user for API credentials
|
|
43
|
+
*/
|
|
44
|
+
async function promptForCredentials(skillName) {
|
|
45
|
+
const displayName = skillName === 'ppocrv5' ? 'PP-OCRv5' : 'PaddleOCR-VL';
|
|
46
|
+
|
|
47
|
+
return await prompts([
|
|
48
|
+
{
|
|
49
|
+
type: 'text',
|
|
50
|
+
name: 'apiUrl',
|
|
51
|
+
message: `Enter ${displayName} API URL:`,
|
|
52
|
+
validate: value => value.length > 0 ? true : 'API URL is required'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'text',
|
|
56
|
+
name: 'token',
|
|
57
|
+
message: `Enter ${displayName} TOKEN:`,
|
|
58
|
+
validate: value => value.length > 0 ? true : 'TOKEN is required'
|
|
59
|
+
}
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
promptForSkills,
|
|
65
|
+
promptForConfiguration,
|
|
66
|
+
promptForCredentials
|
|
67
|
+
};
|
package/lib/python.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const { spawn } = require('child_process');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const ora = require('ora');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if Python is available
|
|
8
|
+
*/
|
|
9
|
+
async function checkPython() {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const python = spawn('python', ['--version']);
|
|
12
|
+
python.on('close', (code) => {
|
|
13
|
+
resolve(code === 0);
|
|
14
|
+
});
|
|
15
|
+
python.on('error', () => {
|
|
16
|
+
resolve(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Install Python dependencies for selected skills
|
|
23
|
+
*/
|
|
24
|
+
async function installPythonDeps(skills, targetDir) {
|
|
25
|
+
// Check if Python is available
|
|
26
|
+
const hasPython = await checkPython();
|
|
27
|
+
|
|
28
|
+
if (!hasPython) {
|
|
29
|
+
console.log(chalk.yellow('⚠️ Python not found. Skipping dependency installation.'));
|
|
30
|
+
console.log(chalk.gray(' Please install Python dependencies manually:'));
|
|
31
|
+
for (const skill of skills) {
|
|
32
|
+
console.log(chalk.gray(` pip install -r scripts/${skill}/requirements.txt`));
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Install dependencies for each skill
|
|
38
|
+
for (const skill of skills) {
|
|
39
|
+
const requirementsPath = path.join(targetDir, 'scripts', skill, 'requirements.txt');
|
|
40
|
+
const spinner = ora(`Installing ${skill} dependencies...`).start();
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await runPipInstall(requirementsPath);
|
|
44
|
+
spinner.succeed(`${skill} dependencies installed`);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
spinner.fail(`Failed to install ${skill} dependencies`);
|
|
47
|
+
console.log(chalk.yellow(` You can install manually: pip install -r ${requirementsPath}`));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Run pip install for a requirements file
|
|
54
|
+
*/
|
|
55
|
+
function runPipInstall(requirementsPath) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const pip = spawn('pip', ['install', '-r', requirementsPath], {
|
|
58
|
+
stdio: 'inherit'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
pip.on('close', (code) => {
|
|
62
|
+
if (code === 0) {
|
|
63
|
+
resolve();
|
|
64
|
+
} else {
|
|
65
|
+
reject(new Error(`pip install exited with code ${code}`));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
pip.on('error', (error) => {
|
|
70
|
+
reject(error);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { installPythonDeps };
|
package/lib/verify.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const { spawn } = require('child_process');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const ora = require('ora');
|
|
5
|
+
const { promptForCredentials } = require('./prompts');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Run configuration wizard for selected skills
|
|
9
|
+
*/
|
|
10
|
+
async function runConfigurationWizard(skills, targetDir) {
|
|
11
|
+
for (const skill of skills) {
|
|
12
|
+
console.log(chalk.bold(`\nConfiguring ${skill}...`));
|
|
13
|
+
|
|
14
|
+
// Prompt for credentials
|
|
15
|
+
const { apiUrl, token } = await promptForCredentials(skill);
|
|
16
|
+
|
|
17
|
+
// Run configure.py script
|
|
18
|
+
const configScript = path.join(targetDir, 'scripts', skill, 'configure.py');
|
|
19
|
+
const spinner = ora('Saving configuration...').start();
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await runConfigureScript(configScript, apiUrl, token);
|
|
23
|
+
spinner.succeed(`${skill} configured successfully`);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
spinner.fail(`Failed to configure ${skill}`);
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Run configure.py script with credentials
|
|
33
|
+
*/
|
|
34
|
+
function runConfigureScript(scriptPath, apiUrl, token) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const python = spawn('python', [
|
|
37
|
+
scriptPath,
|
|
38
|
+
'--api-url', apiUrl,
|
|
39
|
+
'--token', token,
|
|
40
|
+
'--quiet'
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
let stdout = '';
|
|
44
|
+
let stderr = '';
|
|
45
|
+
|
|
46
|
+
python.stdout.on('data', (data) => {
|
|
47
|
+
stdout += data.toString();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
python.stderr.on('data', (data) => {
|
|
51
|
+
stderr += data.toString();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
python.on('close', (code) => {
|
|
55
|
+
if (code === 0) {
|
|
56
|
+
resolve();
|
|
57
|
+
} else {
|
|
58
|
+
reject(new Error(stderr || stdout || `Configuration failed with exit code ${code}`));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
python.on('error', (error) => {
|
|
63
|
+
reject(error);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Run verification tests for selected skills
|
|
70
|
+
*/
|
|
71
|
+
async function runVerification(skills, targetDir) {
|
|
72
|
+
for (const skill of skills) {
|
|
73
|
+
const smokeTestScript = path.join(targetDir, 'scripts', skill, 'smoke_test.py');
|
|
74
|
+
const spinner = ora(`Testing ${skill}...`).start();
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await runSmokeTest(smokeTestScript);
|
|
78
|
+
spinner.succeed(`${skill} verification passed`);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
spinner.warn(`${skill} verification skipped (API test requires credentials)`);
|
|
81
|
+
console.log(chalk.gray(` You can test manually: python ${smokeTestScript}`));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Run smoke_test.py script
|
|
88
|
+
*/
|
|
89
|
+
function runSmokeTest(scriptPath) {
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
const python = spawn('python', [scriptPath]);
|
|
92
|
+
|
|
93
|
+
let stdout = '';
|
|
94
|
+
let stderr = '';
|
|
95
|
+
|
|
96
|
+
python.stdout.on('data', (data) => {
|
|
97
|
+
stdout += data.toString();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
python.stderr.on('data', (data) => {
|
|
101
|
+
stderr += data.toString();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
python.on('close', (code) => {
|
|
105
|
+
if (code === 0) {
|
|
106
|
+
resolve();
|
|
107
|
+
} else {
|
|
108
|
+
reject(new Error(stderr || stdout || `Smoke test failed with exit code ${code}`));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
python.on('error', (error) => {
|
|
113
|
+
reject(error);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
runConfigurationWizard,
|
|
120
|
+
runVerification
|
|
121
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "paddleocr-skills",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "PaddleOCR Skills - Install PP-OCRv5 and PaddleOCR-VL for Claude Code",
|
|
5
|
+
"main": "lib/installer.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"paddleocr-skills": "bin/paddleocr-skills.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"paddle-ocr",
|
|
11
|
+
"ocr",
|
|
12
|
+
"claude-code",
|
|
13
|
+
"skill",
|
|
14
|
+
"ai-studio",
|
|
15
|
+
"ppocrv5",
|
|
16
|
+
"paddleocr-vl"
|
|
17
|
+
],
|
|
18
|
+
"author": "Aidenwu0209 <wujinhe0209@aliyun.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=14.0.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"prompts": "^2.4.2",
|
|
25
|
+
"chalk": "^4.1.2",
|
|
26
|
+
"fs-extra": "^11.2.0",
|
|
27
|
+
"ora": "^5.4.1"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/Aidenwu0209/PaddleORC-Skills.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/Aidenwu0209/PaddleORC-Skills#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/Aidenwu0209/PaddleORC-Skills/issues"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"bin",
|
|
39
|
+
"lib",
|
|
40
|
+
"templates"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# PP-OCRv5 Configuration
|
|
2
|
+
# Get your API credentials at: https://aistudio.baidu.com/paddleocr/task
|
|
3
|
+
API_URL=
|
|
4
|
+
TOKEN=
|
|
5
|
+
|
|
6
|
+
# PaddleOCR-VL Configuration
|
|
7
|
+
VL_API_URL=
|
|
8
|
+
VL_TOKEN=
|
|
9
|
+
|
|
10
|
+
# Optional: Maximum file size for local files (in MB)
|
|
11
|
+
# Set to 0 for unlimited size
|
|
12
|
+
# VL_MAX_FILE_SIZE_MB=20
|