mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
[eric] shrink prod payload another ~125MB: drop unused binary (-97MB), trim babel non-en locale data (-30MB), strip pip-only dist-info
noise (-2MB), move pytest to dev-requirements (-4MB)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "notionhq-notion-mcp-server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"@notionhq/notion-mcp-server": "^2.2.1"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "softeria-ms-365-mcp-server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"@softeria/ms-365-mcp-server": "^0.85.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Development-only dependencies. NOT installed by build-python-env.{sh,ps1},
|
||||
# so these never ship to production users (the embedded electron python-env
|
||||
# only installs requirements.txt).
|
||||
#
|
||||
# To install for local development:
|
||||
# pip install -r backend/requirements.txt -r backend/requirements-dev.txt
|
||||
#
|
||||
# CI test runs should also install both files.
|
||||
|
||||
pytest==8.3.4
|
||||
pytest-asyncio==0.25.2
|
||||
@@ -5,11 +5,12 @@ fastapi[standard]
|
||||
pydantic==2.10.5
|
||||
langchain-core==0.3.51
|
||||
langchain-openai==0.3.12
|
||||
pytest==8.3.4
|
||||
pytest-asyncio==0.25.2
|
||||
typeguard==4.4.2
|
||||
python-dotenv==1.1.1
|
||||
Pillow
|
||||
posthog
|
||||
httpx>=0.27.0
|
||||
trafilatura
|
||||
trafilatura
|
||||
# Test deps (pytest, pytest-asyncio) live in requirements-dev.txt — they
|
||||
# never ship to production users and shaved ~3 MB / ~200 files off the
|
||||
# Mac DMG when removed from the prod env.
|
||||
@@ -60,10 +60,18 @@ if ($Sign) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Step 0: Bundled uv/uvx (Windows zip) ---
|
||||
# --- Step 0: Bundled uvx for Windows ---
|
||||
# We deliberately ship ONLY uvx.exe (~700KB), NOT uv.exe (~30MB). Tools
|
||||
# only ever invoke uvx; bare uv is a build-time installer/manager. Saves
|
||||
# ~30MB from the Windows installer. See scripts/build-app.sh for context.
|
||||
$UvBinDir = Join-Path $ProjectRoot 'backend\uv-bin'
|
||||
# Defensively drop a stale uv.exe from prior builds.
|
||||
if (Test-Path (Join-Path $UvBinDir 'uv.exe')) {
|
||||
Write-Host "[0] Removing legacy uv.exe (we now ship uvx only)..."
|
||||
Remove-Item -Force (Join-Path $UvBinDir 'uv.exe')
|
||||
}
|
||||
if (-not (Test-Path (Join-Path $UvBinDir 'uvx.exe'))) {
|
||||
Write-Host "[0] Downloading uv/uvx for Windows..."
|
||||
Write-Host "[0] Downloading uvx for Windows..."
|
||||
New-Item -ItemType Directory -Force -Path $UvBinDir | Out-Null
|
||||
$UvUrl = 'https://github.com/astral-sh/uv/releases/latest/download/uv-x86_64-pc-windows-msvc.zip'
|
||||
$TmpZip = Join-Path $env:TEMP "uv-win-$([guid]::NewGuid()).zip"
|
||||
@@ -71,15 +79,15 @@ if (-not (Test-Path (Join-Path $UvBinDir 'uvx.exe'))) {
|
||||
try {
|
||||
Invoke-WebRequest -Uri $UvUrl -OutFile $TmpZip -UseBasicParsing
|
||||
Expand-Archive -Path $TmpZip -DestinationPath $TmpExtract -Force
|
||||
Get-ChildItem -Path $TmpExtract -Recurse -Filter 'uv.exe' | Select-Object -First 1 | ForEach-Object { Copy-Item $_.FullName (Join-Path $UvBinDir 'uv.exe') -Force }
|
||||
# Only copy uvx.exe — skip uv.exe entirely.
|
||||
Get-ChildItem -Path $TmpExtract -Recurse -Filter 'uvx.exe' | Select-Object -First 1 | ForEach-Object { Copy-Item $_.FullName (Join-Path $UvBinDir 'uvx.exe') -Force }
|
||||
Write-Host "uv/uvx downloaded and bundled."
|
||||
Write-Host "uvx.exe downloaded and bundled."
|
||||
} finally {
|
||||
Remove-Item -Force $TmpZip -ErrorAction SilentlyContinue
|
||||
Remove-Item -Recurse -Force $TmpExtract -ErrorAction SilentlyContinue
|
||||
}
|
||||
} else {
|
||||
Write-Host "[0] uv/uvx binaries already present."
|
||||
Write-Host "[0] uvx.exe already present."
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
|
||||
+17
-7
@@ -68,22 +68,32 @@ if $SIGN_MODE; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 0: Ensure bundled uv/uvx binaries exist
|
||||
# Step 0: Ensure bundled uvx binary exists.
|
||||
# We deliberately ship ONLY uvx (~681KB universal), NOT uv (~97MB universal).
|
||||
# tools_lib.py probes for both, but the only tool config that uses either is
|
||||
# Google Workspace (cmd: "uvx"). Bare `uv` (the package installer/manager) is
|
||||
# never invoked at runtime by any shipped tool — it's a build-time tool.
|
||||
# Saves 97MB from the Mac DMG. If a future MCP needs `uv`, this is a one-line
|
||||
# add-back here.
|
||||
UV_BIN_DIR="$PROJECT_ROOT/backend/uv-bin"
|
||||
# Defensively drop a stale `uv` from prior builds so it doesn't ride along.
|
||||
if [[ -f "$UV_BIN_DIR/uv" ]]; then
|
||||
echo "[0] Removing legacy uv binary (we now ship uvx only)..."
|
||||
rm -f "$UV_BIN_DIR/uv"
|
||||
fi
|
||||
if [[ ! -f "$UV_BIN_DIR/uvx" ]]; then
|
||||
echo "[0] Downloading uv/uvx binaries..."
|
||||
echo "[0] Downloading uvx binary..."
|
||||
mkdir -p "$UV_BIN_DIR"
|
||||
TMPDIR_UV=$(mktemp -d)
|
||||
# Download both architectures and create universal binaries
|
||||
curl -sL "https://github.com/astral-sh/uv/releases/latest/download/uv-aarch64-apple-darwin.tar.gz" | tar xz -C "$TMPDIR_UV"
|
||||
curl -sL "https://github.com/astral-sh/uv/releases/latest/download/uv-x86_64-apple-darwin.tar.gz" | tar xz -C "$TMPDIR_UV"
|
||||
lipo -create "$TMPDIR_UV/uv-aarch64-apple-darwin/uv" "$TMPDIR_UV/uv-x86_64-apple-darwin/uv" -output "$UV_BIN_DIR/uv"
|
||||
# Only lipo uvx — skip uv entirely.
|
||||
lipo -create "$TMPDIR_UV/uv-aarch64-apple-darwin/uvx" "$TMPDIR_UV/uv-x86_64-apple-darwin/uvx" -output "$UV_BIN_DIR/uvx"
|
||||
chmod +x "$UV_BIN_DIR/uv" "$UV_BIN_DIR/uvx"
|
||||
chmod +x "$UV_BIN_DIR/uvx"
|
||||
rm -rf "$TMPDIR_UV"
|
||||
echo "uv/uvx downloaded and bundled."
|
||||
echo "uvx downloaded and bundled."
|
||||
else
|
||||
echo "[0] uv/uvx binaries already present."
|
||||
echo "[0] uvx binary already present."
|
||||
fi
|
||||
echo ""
|
||||
|
||||
|
||||
@@ -92,9 +92,7 @@ Get-ChildItem -Path $PythonEnvDir -Recurse -Force -Filter '*.pyc' `
|
||||
| Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# Strip parts of the Python distribution we provably don't use at runtime.
|
||||
# Each removal here has been individually verified — conservative on purpose.
|
||||
# NOT removing pip/, babel/locale-data/, pygments lexers, or PIL — each had
|
||||
# at least one weak import-evidence trail.
|
||||
# Each removal here has been individually verified.
|
||||
Write-Host "Stripping unused Python distribution files..."
|
||||
$ToStrip = @(
|
||||
(Join-Path $PythonEnvDir 'include'), # C headers — never used at runtime
|
||||
@@ -108,6 +106,40 @@ foreach ($p in $ToStrip) {
|
||||
if (Test-Path $p) { Remove-Item -Recurse -Force $p -ErrorAction SilentlyContinue }
|
||||
}
|
||||
|
||||
# ----- Babel locale-data trim (~30 MB / ~900 files) -----
|
||||
# Babel ships 1,084 CLDR locale .dat files. Trafilatura's transitive dep
|
||||
# courlan/filters.py:184 calls Locale.parse(seg) on URL path segments —
|
||||
# UnknownLocaleError IS caught at line 188 (graceful degradation: that URL
|
||||
# just doesn't get language-filtered). Keeping the 20 most common base
|
||||
# languages preserves filtering for the URLs we'll actually see.
|
||||
$Sp = Join-Path $PythonEnvDir 'lib\python3.13\site-packages'
|
||||
$LocaleDir = Join-Path $Sp 'babel\locale-data'
|
||||
if (Test-Path $LocaleDir) {
|
||||
Write-Host "Trimming babel/locale-data..."
|
||||
$KeepLangs = @('ar','de','es','fr','it','ja','ko','nl','pl','pt','ru','sv','tr','zh','hi','th','vi','id','da','no','fi','cs','el','he','uk')
|
||||
Get-ChildItem -Path $LocaleDir -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
$name = $_.Name
|
||||
$keep = $false
|
||||
if ($name -eq 'root.dat' -or $name -eq 'LICENSE.unicode') { $keep = $true }
|
||||
elseif ($name -match '^en($|_)') { $keep = $true }
|
||||
else {
|
||||
foreach ($l in $KeepLangs) {
|
||||
if ($name -eq "$l.dat") { $keep = $true; break }
|
||||
}
|
||||
}
|
||||
if (-not $keep) { Remove-Item -Force $_.FullName -ErrorAction SilentlyContinue }
|
||||
}
|
||||
}
|
||||
|
||||
# ----- dist-info noise trim (~2 MB / ~280 files) -----
|
||||
# pip-only metadata. METADATA is kept (some packages call importlib.metadata).
|
||||
Write-Host "Trimming pip dist-info noise..."
|
||||
foreach ($pattern in @('RECORD','INSTALLER','WHEEL','top_level.txt','entry_points.txt')) {
|
||||
Get-ChildItem -Path $Sp -Recurse -Filter $pattern -File -ErrorAction SilentlyContinue `
|
||||
| Where-Object { $_.FullName -match '\.dist-info[\\/]' } `
|
||||
| Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Pre-compile bytecode so cold backend startup skips parse+compile on
|
||||
# every imported .py. Worth ~5-10s on Windows under Defender (parsing
|
||||
# Python source is parser-bound; loading .pyc is just bytes). We cap
|
||||
|
||||
@@ -117,13 +117,7 @@ find "$PYTHON_ENV_DIR" -type d -name "tests" -exec rm -rf {} + 2>/dev/null || tr
|
||||
find "$PYTHON_ENV_DIR" -type d -name "test" -exec rm -rf {} + 2>/dev/null || true
|
||||
|
||||
# Strip parts of the Python distribution we provably don't use at runtime.
|
||||
# Each removal here has been individually verified — see the audit notes in
|
||||
# the project plan. Doing this BEFORE compileall would also work, but doing
|
||||
# it after means the dirs are already definitely-not-imported (compileall
|
||||
# would have surfaced any backend code that touches them).
|
||||
#
|
||||
# Conservative on purpose. NOT removing pip/, babel/locale-data/, pygments
|
||||
# lexers, or PIL — each had at least one weak import-evidence trail.
|
||||
# Each removal here has been individually verified.
|
||||
echo "Stripping unused Python distribution files..."
|
||||
# C headers — only needed when building C extensions, never at runtime.
|
||||
rm -rf "$PYTHON_ENV_DIR/include"
|
||||
@@ -137,6 +131,48 @@ rm -rf "$PYTHON_ENV_DIR/lib/python3.13/turtledemo"
|
||||
# Man pages / desktop-integration files — embedded Python doesn't read these.
|
||||
rm -rf "$PYTHON_ENV_DIR/share"
|
||||
|
||||
# ----- Babel locale-data trim (~30 MB / ~900 files) -----
|
||||
# Babel ships 1,084 CLDR locale .dat files (~30 MB). Our backend doesn't use
|
||||
# babel directly, but trafilatura's transitive dep `courlan/filters.py:184`
|
||||
# calls `Locale.parse(seg)` on URL path segments — if a stripped locale's
|
||||
# .dat is missing courlan raises `UnknownLocaleError`, which IS caught at
|
||||
# line 188 (graceful degradation: that URL just doesn't get language-
|
||||
# filtered). Even so, keeping the most-common 20 base languages preserves
|
||||
# language detection for the URLs we'll actually see in practice.
|
||||
SP="$PYTHON_ENV_DIR/lib/python3.13/site-packages"
|
||||
if [[ -d "$SP/babel/locale-data" ]]; then
|
||||
echo "Trimming babel/locale-data..."
|
||||
LOCALE_DIR="$SP/babel/locale-data"
|
||||
# Keep:
|
||||
# - root.dat — fallback for unknown locales
|
||||
# - LICENSE.unicode — required by Unicode/CLDR license
|
||||
# - en*.dat — every English variant (130 files; small)
|
||||
# - <lang>.dat for the 20 most common base languages we'd plausibly see
|
||||
# in URL path segments. Country-suffix variants (fr_CA.dat, de_AT.dat
|
||||
# etc.) get dropped — courlan only uses .language so the base is enough.
|
||||
KEEP_LANGS="ar de es fr it ja ko nl pl pt ru sv tr zh hi th vi id da no fi cs el he uk"
|
||||
# Build a regex of "files to KEEP" so find can delete the rest.
|
||||
KEEP_RE='^(root\.dat|LICENSE\.unicode|en($|_).*\.dat'
|
||||
for L in $KEEP_LANGS; do KEEP_RE="$KEEP_RE|${L}\.dat"; done
|
||||
KEEP_RE="$KEEP_RE)$"
|
||||
# Find every file in locale-data that DOESN'T match KEEP_RE and delete it.
|
||||
find "$LOCALE_DIR" -maxdepth 1 -type f \
|
||||
| awk -v re="$KEEP_RE" 'BEGIN { FS="/" } { if ($NF !~ re) print }' \
|
||||
| xargs -r -n 50 rm -f
|
||||
fi
|
||||
|
||||
# ----- dist-info noise trim (~2 MB / ~280 files) -----
|
||||
# pip metadata that's only consulted by pip itself (which we don't run at
|
||||
# runtime). RECORD/INSTALLER/WHEEL/entry_points.txt/top_level.txt have zero
|
||||
# runtime readers in our shipped deps. METADATA we KEEP — some packages and
|
||||
# transitive deps occasionally call importlib.metadata.metadata("pkg").
|
||||
echo "Trimming pip dist-info noise..."
|
||||
find "$SP" -path '*.dist-info/RECORD' -delete 2>/dev/null
|
||||
find "$SP" -path '*.dist-info/INSTALLER' -delete 2>/dev/null
|
||||
find "$SP" -path '*.dist-info/WHEEL' -delete 2>/dev/null
|
||||
find "$SP" -path '*.dist-info/top_level.txt' -delete 2>/dev/null
|
||||
find "$SP" -path '*.dist-info/entry_points.txt' -delete 2>/dev/null
|
||||
|
||||
# Pre-compile bytecode so cold backend startup skips the parse+compile
|
||||
# step on every imported .py. Worth ~5-10s on Windows under Defender
|
||||
# (parsing Python source is parser-bound; loading .pyc is just bytes).
|
||||
|
||||
Reference in New Issue
Block a user