postinstall.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #!/usr/bin/env node
  2. /**
  3. * Postinstall script - downloads the embedding model to ~/.codegraph/models
  4. * This runs after `npm install` or `npx @colbymchenry/codegraph`
  5. */
  6. const { existsSync, mkdirSync } = require('fs');
  7. const { join } = require('path');
  8. const { homedir } = require('os');
  9. const CODEGRAPH_DIR = join(homedir(), '.codegraph');
  10. const MODELS_DIR = join(CODEGRAPH_DIR, 'models');
  11. const MODEL_ID = 'nomic-ai/nomic-embed-text-v1.5';
  12. async function downloadModel() {
  13. // Ensure directories exist
  14. if (!existsSync(CODEGRAPH_DIR)) {
  15. mkdirSync(CODEGRAPH_DIR, { recursive: true });
  16. }
  17. if (!existsSync(MODELS_DIR)) {
  18. mkdirSync(MODELS_DIR, { recursive: true });
  19. }
  20. // Check if model is already cached
  21. const modelCachePath = join(MODELS_DIR, MODEL_ID.replace('/', '/'));
  22. if (existsSync(modelCachePath)) {
  23. console.log('Embedding model already downloaded.');
  24. return;
  25. }
  26. console.log('Downloading embedding model (~130MB)...');
  27. console.log('This is a one-time download for semantic code search.\n');
  28. try {
  29. // Dynamic import for @xenova/transformers (ESM-only package)
  30. const { pipeline, env } = await import('@xenova/transformers');
  31. // Configure cache directory
  32. env.cacheDir = MODELS_DIR;
  33. // Download with progress
  34. await pipeline('feature-extraction', MODEL_ID, {
  35. progress_callback: (progress) => {
  36. if (progress.status === 'progress' && progress.file && progress.progress !== undefined) {
  37. const fileName = progress.file.split('/').pop();
  38. const percent = Math.round(progress.progress);
  39. process.stdout.write(`\rDownloading ${fileName}... ${percent}% `);
  40. } else if (progress.status === 'done') {
  41. process.stdout.write('\n');
  42. }
  43. },
  44. });
  45. console.log('\nEmbedding model ready!');
  46. } catch (error) {
  47. // Don't fail the install if model download fails
  48. // User can still use codegraph without semantic search
  49. console.log('\nNote: Could not download embedding model.');
  50. console.log('Semantic search will download it on first use.');
  51. if (process.env.DEBUG) {
  52. console.error(error);
  53. }
  54. }
  55. }
  56. // @sengac/tree-sitter-dart ships with NAPI prebuilds for all platforms
  57. // No patching needed (replaced old tree-sitter-dart v1.0.0 which used NAN bindings)
  58. downloadModel().catch(() => {
  59. // Silent exit - don't break npm install
  60. process.exit(0);
  61. });