opendraft 1.6.17 → 1.6.19

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.
Files changed (2) hide show
  1. package/bin/opendraft.js +164 -5
  2. package/package.json +1 -1
package/bin/opendraft.js CHANGED
@@ -101,6 +101,8 @@ function checkPython() {
101
101
  '/usr/bin/python3',
102
102
  ];
103
103
 
104
+ let oldestFound = null; // Track if we find an old Python version
105
+
104
106
  for (const cmd of pythonCommands) {
105
107
  try {
106
108
  const version = execSync(`${cmd} --version 2>&1`, { encoding: 'utf8' }).trim();
@@ -110,13 +112,25 @@ function checkPython() {
110
112
  const minor = parseInt(match[2]);
111
113
  // Require Python 3.10-3.13
112
114
  if (major === 3 && minor >= 10 && minor <= 13) {
113
- return { cmd, version: `${major}.${minor}` };
115
+ return { cmd, version: `${major}.${minor}`, status: 'ok' };
116
+ }
117
+ // Track old Python versions (3.7, 3.8, 3.9)
118
+ if (major === 3 && minor >= 7 && minor < 10) {
119
+ if (!oldestFound || minor > oldestFound.minor) {
120
+ oldestFound = { cmd, major, minor, version: `${major}.${minor}` };
121
+ }
114
122
  }
115
123
  }
116
124
  } catch (e) {
117
125
  // Command not found, try next
118
126
  }
119
127
  }
128
+
129
+ // Return info about old Python if found
130
+ if (oldestFound) {
131
+ return { cmd: oldestFound.cmd, version: oldestFound.version, status: 'too_old' };
132
+ }
133
+
120
134
  return null;
121
135
  }
122
136
 
@@ -177,6 +191,25 @@ function installOpendraft(pythonCmd) {
177
191
  });
178
192
  return { success: true };
179
193
  } catch (e) {
194
+ const errorMsg = (e.stderr || e.message || '').toLowerCase();
195
+
196
+ // Detect specific error types for better messages
197
+ if (errorMsg.includes('permission denied') || errorMsg.includes('errno 13') || errorMsg.includes('access denied')) {
198
+ return { success: false, error: 'permission_denied' };
199
+ }
200
+ if (errorMsg.includes('network') || errorMsg.includes('connection') || errorMsg.includes('timeout') ||
201
+ errorMsg.includes('could not find') || errorMsg.includes('no matching distribution') ||
202
+ errorMsg.includes('retrying') || errorMsg.includes('ssl')) {
203
+ return { success: false, error: 'network_error' };
204
+ }
205
+ if (errorMsg.includes('no space') || errorMsg.includes('disk full') || errorMsg.includes('errno 28')) {
206
+ return { success: false, error: 'disk_full' };
207
+ }
208
+ if (errorMsg.includes('no module named pip') || errorMsg.includes('pip not found') ||
209
+ errorMsg.includes('no such file') && errorMsg.includes('pip')) {
210
+ return { success: false, error: 'no_pip' };
211
+ }
212
+
180
213
  return {
181
214
  success: false,
182
215
  error: e.stderr || e.message || 'Unknown installation error'
@@ -250,6 +283,38 @@ function showFriendlyError(errorType, details = {}) {
250
283
  }
251
284
  break;
252
285
 
286
+ case 'python_too_old':
287
+ printBox([
288
+ `${RED}${BOLD}Python Version Too Old${RESET}`,
289
+ ``,
290
+ `You have Python ${details.version}, but OpenDraft needs 3.10+`,
291
+ ], RED);
292
+
293
+ const platOld = os.platform();
294
+ print(`${BOLD}You need to install a newer Python version:${RESET}`);
295
+ console.log();
296
+
297
+ if (platOld === 'darwin') {
298
+ print(`${BOLD}Option 1: Homebrew (recommended)${RESET}`);
299
+ print(` ${CYAN}brew install python@3.11${RESET}`);
300
+ console.log();
301
+ print(`${BOLD}Option 2: Download from python.org${RESET}`);
302
+ print(` ${CYAN}https://python.org/downloads${RESET}`);
303
+ } else if (platOld === 'win32') {
304
+ print(`1. Go to ${CYAN}https://python.org/downloads${RESET}`);
305
+ print(`2. Download Python 3.11 or newer`);
306
+ print(`3. ${YELLOW}Check "Add Python to PATH"${RESET} during install`);
307
+ print(`4. ${BOLD}Restart your terminal${RESET}`);
308
+ } else {
309
+ print(`${CYAN}sudo apt install python3.11${RESET} (Ubuntu/Debian)`);
310
+ print(`${CYAN}sudo dnf install python3.11${RESET} (Fedora)`);
311
+ }
312
+ console.log();
313
+ print(`Then try again: ${CYAN}npx opendraft${RESET}`);
314
+ console.log();
315
+ print(`${GRAY}Your current Python ${details.version} will not be affected.${RESET}`)
316
+ break;
317
+
253
318
  case 'install_failed':
254
319
  printBox([
255
320
  `${RED}${BOLD}Installation Failed${RESET}`,
@@ -269,11 +334,93 @@ function showFriendlyError(errorType, details = {}) {
269
334
  print(` ${CYAN}brew install pipx && pipx install opendraft${RESET}`);
270
335
  console.log();
271
336
 
272
- if (details.error) {
337
+ if (details.error && typeof details.error === 'string' && !['permission_denied', 'network_error', 'disk_full'].includes(details.error)) {
273
338
  print(`${GRAY}Technical details: ${details.error.substring(0, 200)}${RESET}`);
274
339
  }
275
340
  break;
276
341
 
342
+ case 'permission_denied':
343
+ printBox([
344
+ `${RED}${BOLD}Permission Denied${RESET}`,
345
+ ``,
346
+ `Can't install packages - you don't have permission.`,
347
+ ], RED);
348
+
349
+ print(`${BOLD}Try one of these:${RESET}`);
350
+ console.log();
351
+ print(`${BOLD}Option 1: Install for your user only (recommended)${RESET}`);
352
+ print(` ${CYAN}pip install --user opendraft${RESET}`);
353
+ console.log();
354
+ print(`${BOLD}Option 2: Use sudo (if Option 1 doesn't work)${RESET}`);
355
+ print(` ${CYAN}sudo pip install opendraft${RESET}`);
356
+ console.log();
357
+ print(`${BOLD}Option 3: Use pipx (cleanest)${RESET}`);
358
+ print(` ${CYAN}pipx install opendraft${RESET}`);
359
+ break;
360
+
361
+ case 'network_error':
362
+ printBox([
363
+ `${RED}${BOLD}Network Error${RESET}`,
364
+ ``,
365
+ `Can't download the package. Check your internet.`,
366
+ ], RED);
367
+
368
+ print(`${BOLD}Things to try:${RESET}`);
369
+ console.log();
370
+ print(`1. Check your internet connection`);
371
+ print(`2. If on VPN, try disconnecting temporarily`);
372
+ print(`3. If on corporate network, you may need proxy settings`);
373
+ console.log();
374
+ print(`${BOLD}Then try again:${RESET}`);
375
+ print(` ${CYAN}npx opendraft${RESET}`);
376
+ console.log();
377
+ print(`${GRAY}Still not working? Try downloading manually:${RESET}`);
378
+ print(` ${CYAN}pip install opendraft --timeout 120${RESET}`);
379
+ break;
380
+
381
+ case 'disk_full':
382
+ printBox([
383
+ `${RED}${BOLD}Disk Full${RESET}`,
384
+ ``,
385
+ `Not enough disk space to install the package.`,
386
+ ], RED);
387
+
388
+ print(`${BOLD}Free up some space:${RESET}`);
389
+ console.log();
390
+ print(`1. Empty your Trash/Recycle Bin`);
391
+ print(`2. Delete old downloads or unused apps`);
392
+ print(`3. Clear pip cache: ${CYAN}pip cache purge${RESET}`);
393
+ console.log();
394
+ print(`Then try again: ${CYAN}npx opendraft${RESET}`);
395
+ break;
396
+
397
+ case 'no_pip':
398
+ printBox([
399
+ `${RED}${BOLD}pip Not Found${RESET}`,
400
+ ``,
401
+ `Python is installed but pip (package manager) is missing.`,
402
+ ], RED);
403
+
404
+ const platPip = os.platform();
405
+ print(`${BOLD}Install pip:${RESET}`);
406
+ console.log();
407
+
408
+ if (platPip === 'darwin') {
409
+ print(`${CYAN}python3 -m ensurepip --upgrade${RESET}`);
410
+ console.log();
411
+ print(`Or reinstall Python from ${CYAN}https://python.org${RESET}`);
412
+ } else if (platPip === 'win32') {
413
+ print(`${CYAN}python -m ensurepip --upgrade${RESET}`);
414
+ console.log();
415
+ print(`Or reinstall Python and check "pip" during install`);
416
+ } else {
417
+ print(`${CYAN}sudo apt install python3-pip${RESET} (Ubuntu/Debian)`);
418
+ print(`${CYAN}sudo dnf install python3-pip${RESET} (Fedora)`);
419
+ }
420
+ console.log();
421
+ print(`Then try again: ${CYAN}npx opendraft${RESET}`);
422
+ break;
423
+
277
424
  case 'module_not_found':
278
425
  printBox([
279
426
  `${RED}${BOLD}OpenDraft Package Issue${RESET}`,
@@ -468,13 +615,19 @@ async function main() {
468
615
 
469
616
  // Re-check Python after installation
470
617
  const pythonAfter = checkPython();
471
- if (!pythonAfter) {
618
+ if (!pythonAfter || pythonAfter.status === 'too_old') {
472
619
  print(`${RED}Python still not found.${RESET} Please restart your terminal and try again.`);
473
620
  process.exit(1);
474
621
  }
475
622
  return;
476
623
  }
477
624
 
625
+ // Check if Python version is too old
626
+ if (python.status === 'too_old') {
627
+ showFriendlyError('python_too_old', { version: python.version });
628
+ process.exit(1);
629
+ }
630
+
478
631
  print(`${GREEN}✓${RESET} Python ${python.version} found`);
479
632
 
480
633
  // Handle --install
@@ -487,7 +640,10 @@ async function main() {
487
640
  print(`Run: ${CYAN}npx opendraft${RESET}`);
488
641
  console.log();
489
642
  } else {
490
- showFriendlyError('install_failed', { error: result.error });
643
+ // Show specific error message based on error type
644
+ const errorType = ['permission_denied', 'network_error', 'disk_full', 'no_pip'].includes(result.error)
645
+ ? result.error : 'install_failed';
646
+ showFriendlyError(errorType, { error: result.error });
491
647
  process.exit(1);
492
648
  }
493
649
  return;
@@ -504,7 +660,10 @@ async function main() {
504
660
  const result = installOpendraft(python.cmd);
505
661
 
506
662
  if (!result.success) {
507
- showFriendlyError('install_failed', { error: result.error });
663
+ // Show specific error message based on error type
664
+ const errorType = ['permission_denied', 'network_error', 'disk_full', 'no_pip'].includes(result.error)
665
+ ? result.error : 'install_failed';
666
+ showFriendlyError(errorType, { error: result.error });
508
667
  process.exit(1);
509
668
  }
510
669
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opendraft",
3
- "version": "1.6.17",
3
+ "version": "1.6.19",
4
4
  "description": "AI-powered research paper generator with verified citations",
5
5
  "bin": {
6
6
  "opendraft": "bin/opendraft.js"