open-webui/scripts/prepare-pyodide.js
2025-03-17 08:32:59 +01:00

311 lines
4.9 KiB
JavaScript

const packages = [
'affine',
'altair',
'annotated-types',
'apsw',
'argon2-cffi',
'argon2-cffi-bindings',
'arro3-compute',
'arro3-core',
'arro3-io',
'asciitree',
'astropy',
'astropy_iers_data',
'asttokens',
'async-timeout',
'atomicwrites',
'attrs',
'autograd',
'awkward-cpp',
'b2d',
'bcrypt',
'beautifulsoup4',
'biopython',
'bitarray',
'bitstring',
'bleach',
'bokeh',
'boost-histogram',
'brotli',
'cachetools',
'Cartopy',
'casadi',
'cbor-diag',
'cffi',
'cffi_example',
'cftime',
'charset-normalizer',
'clarabel',
'click',
'cligj',
'clingo',
'cloudpickle',
'cmyt',
'colorspacious',
'contourpy',
'coolprop',
'coverage',
'cramjam',
'crc32c',
'cryptography',
'css-inline',
'cssselect',
'cvxpy-base',
'cycler',
'cysignals',
'cytoolz',
'decorator',
'demes',
'deprecation',
'distlib',
'docutils',
'duckdb',
'ewah_bool_utils',
'exceptiongroup',
'executing',
'fastparquet',
'fiona',
'fonttools',
'freesasa',
'frozenlist',
'fsspec',
'future',
'galpy',
'gmpy2',
'gsw',
'h5py',
'html5lib',
'igraph',
'imageio',
'iminuit',
'iniconfig',
'ipython',
'jedi',
'Jinja2',
'joblib',
'jsonschema',
'jsonschema_specifications',
'kiwisolver',
'lakers-python',
'lazy-object-proxy',
'lazy_loader',
'libcst',
'logbook',
'lxml',
'MarkupSafe',
'matplotlib',
'matplotlib-inline',
'matplotlib-pyodide',
'memory-allocator',
'mmh3',
'mne',
'more-itertools',
'mpmath',
'msgpack',
'msgspec',
'msprime',
'multidict',
'munch',
'mypy',
'narwhals',
'netcdf4',
'networkx',
'newick',
'nh3',
'nlopt',
'nltk',
'numcodecs',
'numpy',
'opencv-python',
'optlang',
'orjson',
'packaging',
'pandas',
'parso',
'patsy',
'peewee',
'pi-heif',
'Pillow',
'pillow-heif',
'pkgconfig',
'pluggy',
'polars',
'pplpy',
'primecountpy',
'prompt_toolkit',
'protobuf',
'pure-eval',
'py',
'pyclipper',
'pycparser',
'pycryptodome',
'pydantic',
'pydantic_core',
'pyerfa',
'pygame-ce',
'Pygments',
'pyheif',
'pyiceberg',
'pyinstrument',
'pynacl',
'pyodide-unix-timezones',
'pyparsing',
'pyproj',
'pyrsistent',
'pysam',
'pyshp',
'pytest',
'pytest-asyncio',
'pytest-benchmark',
'python-dateutil',
'python-flint',
'python-magic',
'python-sat',
'python-solvespace',
'pytz',
'pywavelets',
'pyxel',
'pyxirr',
'pyyaml',
'qrcode',
'rasterio',
'rateslib',
'rebound',
'reboundx',
'referencing',
'regex',
'retrying',
'rich',
'river',
'rpds-py',
'ruamel.yaml',
'rust-abi-test',
'rust-panic-test',
'scipy',
'screed',
'setuptools',
'shapely',
'simplejson',
'sisl',
'six',
'smart-open',
'sortedcontainers',
'soupsieve',
'sourmash',
'soxr',
'sparseqr',
'sqlalchemy',
'stack-data',
'statsmodels',
'strictyaml',
'svgwrite',
'swiglpk',
'sympy',
'tblib',
'termcolor',
'texttable',
'threadpoolctl',
'tiktoken',
'tomli',
'tomli-w',
'toolz',
'tqdm',
'traitlets',
'traits',
'tree-sitter',
'tree-sitter-go',
'tree-sitter-java',
'tree-sitter-python',
'tskit',
'typing-extensions',
'tzdata',
'uncertainties',
'unyt',
'vega-datasets',
'wcwidth',
'webencodings',
'wordcloud',
'wrapt',
'xarray',
'xlrd',
'xxhash',
'xyzservices',
'yt',
'zarr',
'zengl',
'zfpy',
'zstandard'
];
import { loadPyodide } from 'pyodide';
import { writeFile, readFile, copyFile, readdir, rmdir } from 'fs/promises';
async function downloadPackages() {
console.log('Setting up pyodide + micropip');
let pyodide;
try {
pyodide = await loadPyodide({
packageCacheDir: 'static/pyodide'
});
} catch (err) {
console.error('Failed to load Pyodide:', err);
return;
}
const packageJson = JSON.parse(await readFile('package.json'));
const pyodideVersion = packageJson.dependencies.pyodide.replace('^', '');
try {
const pyodidePackageJson = JSON.parse(await readFile('static/pyodide/package.json'));
const pyodidePackageVersion = pyodidePackageJson.version.replace('^', '');
if (pyodideVersion !== pyodidePackageVersion) {
console.log('Pyodide version mismatch, removing static/pyodide directory');
await rmdir('static/pyodide', { recursive: true });
}
} catch (e) {
console.log('Pyodide package not found, proceeding with download.');
}
try {
console.log('Loading micropip package');
await pyodide.loadPackage('micropip');
const micropip = pyodide.pyimport('micropip');
console.log('Downloading Pyodide packages:', packages);
try {
for (const pkg of packages) {
console.log(`Installing package: ${pkg}`);
await micropip.install(pkg);
}
} catch (err) {
console.error('Package installation failed:', err);
return;
}
console.log('Pyodide packages downloaded, freezing into lock file');
try {
const lockFile = await micropip.freeze();
await writeFile('static/pyodide/pyodide-lock.json', lockFile);
} catch (err) {
console.error('Failed to write lock file:', err);
}
} catch (err) {
console.error('Failed to load or install micropip:', err);
}
}
async function copyPyodide() {
console.log('Copying Pyodide files into static directory');
// Copy all files from node_modules/pyodide to static/pyodide
for await (const entry of await readdir('node_modules/pyodide')) {
await copyFile(`node_modules/pyodide/${entry}`, `static/pyodide/${entry}`);
}
}
await downloadPackages();
await copyPyodide();