opendraft 1.6.16 → 1.6.17
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 +31 -20
- package/bin/opendraft.js +272 -89
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenDraft
|
|
2
2
|
|
|
3
|
-
AI-powered research paper
|
|
3
|
+
AI-powered research paper generator with verified citations.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -8,10 +8,12 @@ AI-powered research paper draft generator.
|
|
|
8
8
|
npx opendraft
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
That's it! The CLI will
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
That's it! The CLI will guide you through setup.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- **Node.js 14+** (for npx)
|
|
16
|
+
- **Python 3.10+** (installed automatically on first run)
|
|
15
17
|
|
|
16
18
|
## Usage
|
|
17
19
|
|
|
@@ -20,37 +22,46 @@ That's it! The CLI will:
|
|
|
20
22
|
npx opendraft
|
|
21
23
|
|
|
22
24
|
# Quick generate
|
|
23
|
-
npx opendraft "
|
|
25
|
+
npx opendraft "Your Research Topic"
|
|
24
26
|
|
|
25
27
|
# With options
|
|
26
|
-
npx opendraft "
|
|
28
|
+
npx opendraft "AI in Healthcare" --level master --lang en
|
|
27
29
|
```
|
|
28
30
|
|
|
29
31
|
## Options
|
|
30
32
|
|
|
31
|
-
| Option |
|
|
32
|
-
|
|
33
|
-
| `--level
|
|
34
|
-
| `--style
|
|
35
|
-
| `--
|
|
33
|
+
| Option | Description |
|
|
34
|
+
|--------|-------------|
|
|
35
|
+
| `--level` | Academic level: `research_paper`, `bachelor`, `master`, `phd` |
|
|
36
|
+
| `--style` | Citation style: `apa`, `mla`, `chicago`, `ieee` |
|
|
37
|
+
| `--lang` | Language: `en`, `de`, `es`, `fr`, `it`, `pt`, `zh`, `ja`, `ko`, `ru` |
|
|
38
|
+
| `--author` | Your name (for cover page) |
|
|
39
|
+
| `--institution` | University/institution name |
|
|
36
40
|
|
|
37
|
-
##
|
|
41
|
+
## Troubleshooting
|
|
42
|
+
|
|
43
|
+
### Python Not Found
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
- Python 3.9+ (installed automatically if missing guidance provided)
|
|
45
|
+
If you see "Python not found", install Python 3.10+:
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
- **macOS**: `brew install python@3.11` or download from [python.org](https://python.org)
|
|
48
|
+
- **Windows**: Download from [python.org](https://python.org) (check "Add to PATH")
|
|
49
|
+
- **Linux**: `sudo apt install python3 python3-pip`
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
### Installation Failed
|
|
52
|
+
|
|
53
|
+
Try installing the Python package manually:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install opendraft
|
|
57
|
+
```
|
|
48
58
|
|
|
49
59
|
## Links
|
|
50
60
|
|
|
51
61
|
- Website: https://opendraft.xyz
|
|
52
62
|
- Documentation: https://opendraft.xyz/docs
|
|
53
63
|
- GitHub: https://github.com/federicodeponte/opendraft
|
|
64
|
+
- Issues: https://github.com/federicodeponte/opendraft/issues
|
|
54
65
|
|
|
55
66
|
## License
|
|
56
67
|
|
package/bin/opendraft.js
CHANGED
|
@@ -13,6 +13,7 @@ const { spawn, execSync } = require('child_process');
|
|
|
13
13
|
const os = require('os');
|
|
14
14
|
const path = require('path');
|
|
15
15
|
|
|
16
|
+
// ANSI colors for terminal output
|
|
16
17
|
const PURPLE = '\x1b[95m';
|
|
17
18
|
const GREEN = '\x1b[92m';
|
|
18
19
|
const YELLOW = '\x1b[93m';
|
|
@@ -26,6 +27,21 @@ function print(msg) {
|
|
|
26
27
|
console.log(` ${msg}`);
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
function printBox(lines, color = PURPLE) {
|
|
31
|
+
const maxLen = Math.max(...lines.map(l => l.replace(/\x1b\[[0-9;]*m/g, '').length));
|
|
32
|
+
const width = maxLen + 4;
|
|
33
|
+
|
|
34
|
+
console.log();
|
|
35
|
+
print(`${color}${'─'.repeat(width)}${RESET}`);
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
const cleanLen = line.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
38
|
+
const padding = ' '.repeat(maxLen - cleanLen);
|
|
39
|
+
print(`${color}│${RESET} ${line}${padding} ${color}│${RESET}`);
|
|
40
|
+
}
|
|
41
|
+
print(`${color}${'─'.repeat(width)}${RESET}`);
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
function printLogo() {
|
|
30
46
|
console.log(`
|
|
31
47
|
${PURPLE}${BOLD} ╔══════════════════════════════════════════════════════════╗
|
|
@@ -50,8 +66,7 @@ ${PURPLE}${BOLD} ╔═══════════════════
|
|
|
50
66
|
function checkPython() {
|
|
51
67
|
const home = os.homedir();
|
|
52
68
|
|
|
53
|
-
// Check Python commands - prefer stable versions (3.
|
|
54
|
-
// Order matters: check specific stable versions first before generic python3
|
|
69
|
+
// Check Python commands - prefer stable versions (3.10-3.13)
|
|
55
70
|
const pythonCommands = [
|
|
56
71
|
// Homebrew (stable versions first)
|
|
57
72
|
'/opt/homebrew/bin/python3.13',
|
|
@@ -75,7 +90,7 @@ function checkPython() {
|
|
|
75
90
|
// pyenv
|
|
76
91
|
`${home}/.pyenv/shims/python3`,
|
|
77
92
|
`${home}/.pyenv/shims/python`,
|
|
78
|
-
// Generic
|
|
93
|
+
// Generic
|
|
79
94
|
'python3.13',
|
|
80
95
|
'python3.12',
|
|
81
96
|
'python3.11',
|
|
@@ -93,7 +108,7 @@ function checkPython() {
|
|
|
93
108
|
if (match) {
|
|
94
109
|
const major = parseInt(match[1]);
|
|
95
110
|
const minor = parseInt(match[2]);
|
|
96
|
-
// Require Python 3.10-3.13
|
|
111
|
+
// Require Python 3.10-3.13
|
|
97
112
|
if (major === 3 && minor >= 10 && minor <= 13) {
|
|
98
113
|
return { cmd, version: `${major}.${minor}` };
|
|
99
114
|
}
|
|
@@ -107,22 +122,38 @@ function checkPython() {
|
|
|
107
122
|
|
|
108
123
|
function checkOpendraftInstalled(pythonCmd) {
|
|
109
124
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
125
|
+
// Check specifically for opendraft.cli module (not just opendraft)
|
|
126
|
+
execSync(`${pythonCmd} -c "from opendraft.cli import main"`, {
|
|
127
|
+
encoding: 'utf8',
|
|
128
|
+
stdio: 'pipe'
|
|
129
|
+
});
|
|
130
|
+
return { installed: true, error: null };
|
|
112
131
|
} catch (e) {
|
|
113
|
-
|
|
132
|
+
// Parse the error to give helpful feedback
|
|
133
|
+
const stderr = e.stderr || e.message || '';
|
|
134
|
+
|
|
135
|
+
if (stderr.includes('No module named')) {
|
|
136
|
+
return { installed: false, error: 'not_installed' };
|
|
137
|
+
} else if (stderr.includes('SyntaxError')) {
|
|
138
|
+
return { installed: false, error: 'syntax_error' };
|
|
139
|
+
} else if (stderr.includes('ImportError')) {
|
|
140
|
+
return { installed: false, error: 'import_error' };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { installed: false, error: 'unknown', details: stderr };
|
|
114
144
|
}
|
|
115
145
|
}
|
|
116
146
|
|
|
117
147
|
function installOpendraft(pythonCmd) {
|
|
118
|
-
print(`${CYAN}Installing OpenDraft...${RESET}`);
|
|
148
|
+
print(`${CYAN}Installing OpenDraft Python package...${RESET}`);
|
|
149
|
+
console.log();
|
|
119
150
|
|
|
120
151
|
// Try pipx first (cleanest for CLI tools)
|
|
121
152
|
try {
|
|
122
153
|
execSync('which pipx', { encoding: 'utf8', stdio: 'pipe' });
|
|
123
|
-
print(`${GRAY}Using pipx...${RESET}`);
|
|
154
|
+
print(`${GRAY}Using pipx (recommended)...${RESET}`);
|
|
124
155
|
execSync('pipx install opendraft', { encoding: 'utf8', stdio: 'inherit' });
|
|
125
|
-
return true;
|
|
156
|
+
return { success: true };
|
|
126
157
|
} catch (e) {
|
|
127
158
|
// pipx not available, try pip
|
|
128
159
|
}
|
|
@@ -133,7 +164,7 @@ function installOpendraft(pythonCmd) {
|
|
|
133
164
|
encoding: 'utf8',
|
|
134
165
|
stdio: 'inherit'
|
|
135
166
|
});
|
|
136
|
-
return true;
|
|
167
|
+
return { success: true };
|
|
137
168
|
} catch (e) {
|
|
138
169
|
// Try without --break-system-packages for older pip
|
|
139
170
|
}
|
|
@@ -144,31 +175,183 @@ function installOpendraft(pythonCmd) {
|
|
|
144
175
|
encoding: 'utf8',
|
|
145
176
|
stdio: 'inherit'
|
|
146
177
|
});
|
|
147
|
-
return true;
|
|
178
|
+
return { success: true };
|
|
148
179
|
} catch (e) {
|
|
149
|
-
return
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
error: e.stderr || e.message || 'Unknown installation error'
|
|
183
|
+
};
|
|
150
184
|
}
|
|
151
185
|
}
|
|
152
186
|
|
|
153
187
|
function runOpendraft(pythonCmd, args) {
|
|
154
|
-
//
|
|
155
|
-
// This ensures we use Python 3.10+ that was checked earlier
|
|
188
|
+
// Run via the verified Python to avoid version mismatches
|
|
156
189
|
const script = `
|
|
157
190
|
import sys
|
|
158
191
|
sys.argv = ['opendraft'] + ${JSON.stringify(args)}
|
|
159
192
|
from opendraft.cli import main
|
|
160
193
|
main()
|
|
161
194
|
`;
|
|
195
|
+
|
|
162
196
|
const proc = spawn(pythonCmd, ['-c', script], {
|
|
163
197
|
stdio: 'inherit',
|
|
164
198
|
env: process.env
|
|
165
199
|
});
|
|
166
200
|
|
|
201
|
+
proc.on('error', (err) => {
|
|
202
|
+
showFriendlyError('run_failed', {
|
|
203
|
+
pythonCmd,
|
|
204
|
+
error: err.message
|
|
205
|
+
});
|
|
206
|
+
process.exit(1);
|
|
207
|
+
});
|
|
208
|
+
|
|
167
209
|
proc.on('close', (code) => {
|
|
168
|
-
process.exit(code);
|
|
210
|
+
process.exit(code || 0);
|
|
169
211
|
});
|
|
170
212
|
}
|
|
171
213
|
|
|
214
|
+
function showFriendlyError(errorType, details = {}) {
|
|
215
|
+
console.log();
|
|
216
|
+
|
|
217
|
+
switch (errorType) {
|
|
218
|
+
case 'no_python':
|
|
219
|
+
printBox([
|
|
220
|
+
`${RED}${BOLD}Python Not Found${RESET}`,
|
|
221
|
+
``,
|
|
222
|
+
`OpenDraft needs Python 3.10 or higher to run.`,
|
|
223
|
+
``,
|
|
224
|
+
`${BOLD}To fix this:${RESET}`,
|
|
225
|
+
], RED);
|
|
226
|
+
|
|
227
|
+
const platform = os.platform();
|
|
228
|
+
if (platform === 'darwin') {
|
|
229
|
+
print(`${BOLD}Option 1: Download from python.org (easiest)${RESET}`);
|
|
230
|
+
print(` 1. Go to ${CYAN}https://python.org/downloads${RESET}`);
|
|
231
|
+
print(` 2. Click the yellow "Download Python" button`);
|
|
232
|
+
print(` 3. Run the installer`);
|
|
233
|
+
print(` 4. Try ${CYAN}npx opendraft${RESET} again`);
|
|
234
|
+
console.log();
|
|
235
|
+
print(`${BOLD}Option 2: Use Homebrew${RESET}`);
|
|
236
|
+
print(` ${CYAN}brew install python@3.11${RESET}`);
|
|
237
|
+
} else if (platform === 'win32') {
|
|
238
|
+
print(`${BOLD}Download Python:${RESET}`);
|
|
239
|
+
print(` 1. Go to ${CYAN}https://python.org/downloads${RESET}`);
|
|
240
|
+
print(` 2. Click "Download Python"`);
|
|
241
|
+
print(` 3. ${YELLOW}IMPORTANT: Check "Add Python to PATH"${RESET}`);
|
|
242
|
+
print(` 4. Run the installer`);
|
|
243
|
+
print(` 5. ${BOLD}Restart your terminal${RESET}`);
|
|
244
|
+
print(` 6. Try ${CYAN}npx opendraft${RESET} again`);
|
|
245
|
+
} else {
|
|
246
|
+
print(`${BOLD}Install Python:${RESET}`);
|
|
247
|
+
print(` ${CYAN}sudo apt install python3 python3-pip${RESET} (Ubuntu/Debian)`);
|
|
248
|
+
print(` ${CYAN}sudo dnf install python3 python3-pip${RESET} (Fedora)`);
|
|
249
|
+
print(` ${CYAN}sudo pacman -S python python-pip${RESET} (Arch)`);
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
case 'install_failed':
|
|
254
|
+
printBox([
|
|
255
|
+
`${RED}${BOLD}Installation Failed${RESET}`,
|
|
256
|
+
``,
|
|
257
|
+
`We couldn't install the OpenDraft Python package.`,
|
|
258
|
+
], RED);
|
|
259
|
+
|
|
260
|
+
print(`${BOLD}Try these fixes:${RESET}`);
|
|
261
|
+
console.log();
|
|
262
|
+
print(`${BOLD}1. Install manually with pip:${RESET}`);
|
|
263
|
+
print(` ${CYAN}pip install opendraft${RESET}`);
|
|
264
|
+
console.log();
|
|
265
|
+
print(`${BOLD}2. If that fails, try with sudo (Linux/Mac):${RESET}`);
|
|
266
|
+
print(` ${CYAN}sudo pip install opendraft${RESET}`);
|
|
267
|
+
console.log();
|
|
268
|
+
print(`${BOLD}3. Or use pipx (recommended for CLI tools):${RESET}`);
|
|
269
|
+
print(` ${CYAN}brew install pipx && pipx install opendraft${RESET}`);
|
|
270
|
+
console.log();
|
|
271
|
+
|
|
272
|
+
if (details.error) {
|
|
273
|
+
print(`${GRAY}Technical details: ${details.error.substring(0, 200)}${RESET}`);
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
|
|
277
|
+
case 'module_not_found':
|
|
278
|
+
printBox([
|
|
279
|
+
`${RED}${BOLD}OpenDraft Package Issue${RESET}`,
|
|
280
|
+
``,
|
|
281
|
+
`Python is installed, but the OpenDraft package`,
|
|
282
|
+
`is missing or incomplete.`,
|
|
283
|
+
], RED);
|
|
284
|
+
|
|
285
|
+
print(`${BOLD}To fix this, reinstall the package:${RESET}`);
|
|
286
|
+
console.log();
|
|
287
|
+
print(` ${CYAN}pip uninstall opendraft -y${RESET}`);
|
|
288
|
+
print(` ${CYAN}pip install opendraft${RESET}`);
|
|
289
|
+
console.log();
|
|
290
|
+
print(`Then try again: ${CYAN}npx opendraft${RESET}`);
|
|
291
|
+
console.log();
|
|
292
|
+
|
|
293
|
+
print(`${GRAY}If the problem persists, you may need to upgrade pip:${RESET}`);
|
|
294
|
+
print(` ${CYAN}pip install --upgrade pip${RESET}`);
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case 'import_error':
|
|
298
|
+
printBox([
|
|
299
|
+
`${RED}${BOLD}Missing Dependencies${RESET}`,
|
|
300
|
+
``,
|
|
301
|
+
`OpenDraft is installed but some required`,
|
|
302
|
+
`Python packages are missing.`,
|
|
303
|
+
], RED);
|
|
304
|
+
|
|
305
|
+
print(`${BOLD}To fix this:${RESET}`);
|
|
306
|
+
console.log();
|
|
307
|
+
print(` ${CYAN}pip install --upgrade opendraft${RESET}`);
|
|
308
|
+
console.log();
|
|
309
|
+
print(`This will install all required dependencies.`);
|
|
310
|
+
console.log();
|
|
311
|
+
print(`Then try again: ${CYAN}npx opendraft${RESET}`);
|
|
312
|
+
break;
|
|
313
|
+
|
|
314
|
+
case 'run_failed':
|
|
315
|
+
printBox([
|
|
316
|
+
`${RED}${BOLD}Failed to Start${RESET}`,
|
|
317
|
+
``,
|
|
318
|
+
`Something went wrong while starting OpenDraft.`,
|
|
319
|
+
], RED);
|
|
320
|
+
|
|
321
|
+
print(`${BOLD}Try these steps:${RESET}`);
|
|
322
|
+
console.log();
|
|
323
|
+
print(`1. Reinstall the package:`);
|
|
324
|
+
print(` ${CYAN}pip install --upgrade --force-reinstall opendraft${RESET}`);
|
|
325
|
+
console.log();
|
|
326
|
+
print(`2. If using a virtual environment, make sure it's activated`);
|
|
327
|
+
console.log();
|
|
328
|
+
print(`3. Check Python version (need 3.10+):`);
|
|
329
|
+
print(` ${CYAN}python3 --version${RESET}`);
|
|
330
|
+
console.log();
|
|
331
|
+
|
|
332
|
+
if (details.error) {
|
|
333
|
+
print(`${GRAY}Error: ${details.error}${RESET}`);
|
|
334
|
+
}
|
|
335
|
+
break;
|
|
336
|
+
|
|
337
|
+
default:
|
|
338
|
+
printBox([
|
|
339
|
+
`${RED}${BOLD}Something Went Wrong${RESET}`,
|
|
340
|
+
``,
|
|
341
|
+
`An unexpected error occurred.`,
|
|
342
|
+
], RED);
|
|
343
|
+
|
|
344
|
+
print(`${BOLD}Please try:${RESET}`);
|
|
345
|
+
print(` ${CYAN}pip install --upgrade opendraft${RESET}`);
|
|
346
|
+
print(` ${CYAN}npx opendraft${RESET}`);
|
|
347
|
+
console.log();
|
|
348
|
+
print(`${BOLD}Still having issues?${RESET}`);
|
|
349
|
+
print(` Report at: ${CYAN}https://github.com/federicodeponte/opendraft/issues${RESET}`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
console.log();
|
|
353
|
+
}
|
|
354
|
+
|
|
172
355
|
function hasHomebrew() {
|
|
173
356
|
try {
|
|
174
357
|
execSync('which brew', { encoding: 'utf8', stdio: 'pipe' });
|
|
@@ -193,78 +376,39 @@ function askQuestion(question) {
|
|
|
193
376
|
});
|
|
194
377
|
}
|
|
195
378
|
|
|
196
|
-
async function
|
|
197
|
-
print(`${CYAN}Installing Python 3.11 via Homebrew...${RESET}`);
|
|
198
|
-
print(`${GRAY}This may take a few minutes.${RESET}`);
|
|
199
|
-
console.log();
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
execSync('brew install python@3.11', { stdio: 'inherit' });
|
|
203
|
-
print(`${GREEN}✓${RESET} Python installed successfully!`);
|
|
204
|
-
return true;
|
|
205
|
-
} catch (e) {
|
|
206
|
-
print(`${RED}✗${RESET} Installation failed`);
|
|
207
|
-
return false;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async function showInstallInstructions() {
|
|
212
|
-
console.log();
|
|
213
|
-
print(`${YELLOW}Python 3.10+ is needed to run OpenDraft.${RESET}`);
|
|
214
|
-
console.log();
|
|
215
|
-
|
|
379
|
+
async function offerPythonInstall() {
|
|
216
380
|
const platform = os.platform();
|
|
217
381
|
|
|
218
382
|
if (platform === 'darwin' && hasHomebrew()) {
|
|
219
|
-
|
|
220
|
-
print(
|
|
383
|
+
console.log();
|
|
384
|
+
print(`${GREEN}Good news!${RESET} We can install Python automatically.`);
|
|
221
385
|
console.log();
|
|
222
386
|
|
|
223
|
-
const answer = await askQuestion(` Install Python now? (Y/n): `);
|
|
387
|
+
const answer = await askQuestion(` Install Python 3.11 now? (Y/n): `);
|
|
224
388
|
|
|
225
389
|
if (answer === '' || answer === 'y' || answer === 'yes') {
|
|
226
390
|
console.log();
|
|
227
|
-
|
|
228
|
-
|
|
391
|
+
print(`${CYAN}Installing Python 3.11 via Homebrew...${RESET}`);
|
|
392
|
+
print(`${GRAY}This may take a few minutes.${RESET}`);
|
|
393
|
+
console.log();
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
execSync('brew install python@3.11', { stdio: 'inherit' });
|
|
229
397
|
console.log();
|
|
230
|
-
print(`${GREEN}
|
|
231
|
-
print(` ${CYAN}npx opendraft${RESET}`);
|
|
398
|
+
print(`${GREEN}${BOLD}Success!${RESET} Python is now installed.`);
|
|
232
399
|
console.log();
|
|
233
|
-
|
|
400
|
+
print(`Run this command again: ${CYAN}npx opendraft${RESET}`);
|
|
401
|
+
console.log();
|
|
402
|
+
return true;
|
|
403
|
+
} catch (e) {
|
|
404
|
+
console.log();
|
|
405
|
+
print(`${RED}Installation failed.${RESET} Please install manually.`);
|
|
406
|
+
return false;
|
|
234
407
|
}
|
|
235
408
|
}
|
|
236
|
-
|
|
237
|
-
// User declined or install failed
|
|
238
|
-
console.log();
|
|
239
|
-
print(`To install manually:`);
|
|
240
|
-
print(` ${CYAN}brew install python@3.11${RESET}`);
|
|
241
|
-
|
|
242
|
-
} else if (platform === 'darwin') {
|
|
243
|
-
// macOS without Homebrew
|
|
244
|
-
print(`Download Python from:`);
|
|
245
|
-
console.log();
|
|
246
|
-
print(` ${CYAN}https://python.org/downloads${RESET}`);
|
|
247
|
-
console.log();
|
|
248
|
-
print(`${GRAY}(Click the big yellow "Download Python" button)${RESET}`);
|
|
249
|
-
|
|
250
|
-
} else if (platform === 'win32') {
|
|
251
|
-
print(`${BOLD}Download Python:${RESET}`);
|
|
252
|
-
console.log();
|
|
253
|
-
print(` ${CYAN}https://python.org/downloads${RESET}`);
|
|
254
|
-
console.log();
|
|
255
|
-
print(` ${YELLOW}Important:${RESET} Check "Add Python to PATH" during install!`);
|
|
256
|
-
|
|
257
|
-
} else {
|
|
258
|
-
// Linux
|
|
259
|
-
print(`${BOLD}Install with your package manager:${RESET}`);
|
|
260
|
-
console.log();
|
|
261
|
-
print(` ${CYAN}sudo apt install python3 python3-pip${RESET} (Ubuntu/Debian)`);
|
|
262
|
-
print(` ${CYAN}sudo dnf install python3 python3-pip${RESET} (Fedora)`);
|
|
263
409
|
}
|
|
264
410
|
|
|
265
|
-
|
|
266
|
-
print(`Then run: ${CYAN}npx opendraft${RESET}`);
|
|
267
|
-
console.log();
|
|
411
|
+
return false;
|
|
268
412
|
}
|
|
269
413
|
|
|
270
414
|
async function main() {
|
|
@@ -299,14 +443,14 @@ async function main() {
|
|
|
299
443
|
console.log();
|
|
300
444
|
print(`${BOLD}Examples:${RESET}`);
|
|
301
445
|
print(` ${CYAN}npx opendraft "AI in Healthcare" --level master${RESET}`);
|
|
302
|
-
print(` ${CYAN}npx opendraft "Climate Change" --lang de --author "Max
|
|
446
|
+
print(` ${CYAN}npx opendraft "Climate Change" --lang de --author "Max Muller"${RESET}`);
|
|
303
447
|
console.log();
|
|
304
448
|
print(`${GRAY}https://opendraft.xyz/docs${RESET}`);
|
|
305
449
|
console.log();
|
|
306
450
|
return;
|
|
307
451
|
}
|
|
308
452
|
|
|
309
|
-
// Show logo immediately
|
|
453
|
+
// Show logo immediately
|
|
310
454
|
printLogo();
|
|
311
455
|
print(`${GRAY}Checking environment...${RESET}`);
|
|
312
456
|
|
|
@@ -314,42 +458,81 @@ async function main() {
|
|
|
314
458
|
const python = checkPython();
|
|
315
459
|
|
|
316
460
|
if (!python) {
|
|
317
|
-
|
|
318
|
-
|
|
461
|
+
showFriendlyError('no_python');
|
|
462
|
+
|
|
463
|
+
// Offer to install automatically on macOS with Homebrew
|
|
464
|
+
const installed = await offerPythonInstall();
|
|
465
|
+
if (!installed) {
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Re-check Python after installation
|
|
470
|
+
const pythonAfter = checkPython();
|
|
471
|
+
if (!pythonAfter) {
|
|
472
|
+
print(`${RED}Python still not found.${RESET} Please restart your terminal and try again.`);
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
return;
|
|
319
476
|
}
|
|
320
477
|
|
|
321
478
|
print(`${GREEN}✓${RESET} Python ${python.version} found`);
|
|
322
479
|
|
|
323
480
|
// Handle --install
|
|
324
481
|
if (args.includes('--install')) {
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
482
|
+
const result = installOpendraft(python.cmd);
|
|
483
|
+
if (result.success) {
|
|
484
|
+
console.log();
|
|
485
|
+
print(`${GREEN}${BOLD}Success!${RESET} OpenDraft is ready.`);
|
|
328
486
|
console.log();
|
|
329
487
|
print(`Run: ${CYAN}npx opendraft${RESET}`);
|
|
488
|
+
console.log();
|
|
330
489
|
} else {
|
|
331
|
-
|
|
490
|
+
showFriendlyError('install_failed', { error: result.error });
|
|
332
491
|
process.exit(1);
|
|
333
492
|
}
|
|
334
|
-
console.log();
|
|
335
493
|
return;
|
|
336
494
|
}
|
|
337
495
|
|
|
338
496
|
// Check if opendraft is installed
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
497
|
+
const installCheck = checkOpendraftInstalled(python.cmd);
|
|
498
|
+
|
|
499
|
+
if (!installCheck.installed) {
|
|
500
|
+
if (installCheck.error === 'not_installed') {
|
|
501
|
+
print(`${YELLOW}First-time setup${RESET} - installing OpenDraft...`);
|
|
502
|
+
console.log();
|
|
503
|
+
|
|
504
|
+
const result = installOpendraft(python.cmd);
|
|
505
|
+
|
|
506
|
+
if (!result.success) {
|
|
507
|
+
showFriendlyError('install_failed', { error: result.error });
|
|
508
|
+
process.exit(1);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
print(`${GREEN}✓${RESET} OpenDraft installed`);
|
|
512
|
+
|
|
513
|
+
// Verify installation worked
|
|
514
|
+
const verifyCheck = checkOpendraftInstalled(python.cmd);
|
|
515
|
+
if (!verifyCheck.installed) {
|
|
516
|
+
showFriendlyError('module_not_found');
|
|
517
|
+
process.exit(1);
|
|
518
|
+
}
|
|
519
|
+
} else if (installCheck.error === 'import_error') {
|
|
520
|
+
showFriendlyError('import_error');
|
|
521
|
+
process.exit(1);
|
|
522
|
+
} else {
|
|
523
|
+
showFriendlyError('module_not_found');
|
|
343
524
|
process.exit(1);
|
|
344
525
|
}
|
|
345
|
-
print(`${GREEN}✓${RESET} OpenDraft installed`);
|
|
346
526
|
}
|
|
347
527
|
|
|
528
|
+
print(`${GREEN}✓${RESET} OpenDraft ready`);
|
|
529
|
+
console.log();
|
|
530
|
+
|
|
348
531
|
// Run opendraft
|
|
349
532
|
runOpendraft(python.cmd, args);
|
|
350
533
|
}
|
|
351
534
|
|
|
352
535
|
main().catch((err) => {
|
|
353
|
-
|
|
536
|
+
showFriendlyError('unknown', { error: err.message });
|
|
354
537
|
process.exit(1);
|
|
355
538
|
});
|
package/package.json
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opendraft",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "AI-powered research paper
|
|
3
|
+
"version": "1.6.17",
|
|
4
|
+
"description": "AI-powered research paper generator with verified citations",
|
|
5
5
|
"bin": {
|
|
6
|
-
"opendraft": "
|
|
7
|
-
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"test": "node bin/opendraft.js --version"
|
|
6
|
+
"opendraft": "bin/opendraft.js"
|
|
10
7
|
},
|
|
11
8
|
"keywords": [
|
|
12
9
|
"research",
|
|
13
10
|
"paper",
|
|
14
11
|
"thesis",
|
|
15
|
-
"academic",
|
|
16
12
|
"ai",
|
|
13
|
+
"academic",
|
|
17
14
|
"writing",
|
|
18
15
|
"citations",
|
|
19
16
|
"generator"
|
|
20
17
|
],
|
|
21
|
-
"author": "
|
|
18
|
+
"author": "Federico De Ponte",
|
|
22
19
|
"license": "MIT",
|
|
23
20
|
"repository": {
|
|
24
21
|
"type": "git",
|
|
25
|
-
"url": "https://github.com/federicodeponte/opendraft.git"
|
|
22
|
+
"url": "git+https://github.com/federicodeponte/opendraft.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/federicodeponte/opendraft/issues"
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://opendraft.xyz",
|
|
28
28
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
29
|
+
"node": ">=14.0.0"
|
|
30
30
|
}
|
|
31
31
|
}
|