eggpool 0.2.0__tar.gz → 0.2.1__tar.gz
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.
- {eggpool-0.2.0 → eggpool-0.2.1}/CHANGELOG.md +12 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/PKG-INFO +1 -1
- {eggpool-0.2.0 → eggpool-0.2.1}/pyproject.toml +1 -1
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/cli.py +12 -17
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/lifecycle/uninstall.py +67 -3
- {eggpool-0.2.0 → eggpool-0.2.1}/uv.lock +1 -1
- {eggpool-0.2.0 → eggpool-0.2.1}/.env.example +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/.github/workflows/ci.yml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/.github/workflows/release.yml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/.gitignore +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/AGENTS.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/LICENSE +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/README.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/architecture/README.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/config-examples/claude-code.env +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/config-examples/opencode.jsonc +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/config.example.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/deploy/eggpool-logrotate.conf +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/deploy/eggpool.service +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/deploy/env.example +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/backup-restore.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/deployment.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/filesystem-layout.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/firewall.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/model-limits.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/providers.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/proxy.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/docs/raspberry-pi.md +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/check_database.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/install.sh +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/install_prompt.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/smoke_test.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/scripts/verify_upstream_auth.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/__main__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/_share/.env.example +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/_share/config.example.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/accounts/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/accounts/registry.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/accounts/state.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/chat_completions.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/errors.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/messages.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/models.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/proxy_request.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/api/stats.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/app.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/auth.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/background/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/background/cleanup.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/cache.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/fetcher.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/limits.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/normalizer.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/pricing.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/protocols.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/catalog/service.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/config.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/constants.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/_resources.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/escape.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/render.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/routes.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/static/chart.umd.min.js +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/static/dashboard.css +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/static/favicon.svg +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/theme.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Booberry.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Catppuccin Latte.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Catppuccin Macchiato.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Catppuccin Mocha.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Cyber Red.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Cyberpunk.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Dark Green.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Discord (80_ Saturation).toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Discord.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Dracula.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Ferra Light.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Flexor Dark.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Gruvbox.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Halcyon Dark.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/IntelliJ Light.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Kanagawa.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Macaw Dark.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Macaw Light.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Matrix.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Noctis Lilac.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Nord.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Nostromo Terminal.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/One Dark.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Oxocarbon.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Rose Pine Dawn.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Rose Pine Moon.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Rose Pine.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Solarized Dark.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Sonokai.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Tokyo Night Storm.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/VESPER.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/Zenburn.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/acton.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/bam.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/base16-atelier-forest-light.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/berlin.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/black but with important highlights.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/broc.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/cork.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/ferra.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/forest.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/lisbon.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/midnight.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/oslo.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/plum.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/portland.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/sunset.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/tofino.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/vanimo.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/vik.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/connection.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/migrations.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/repositories.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0001_initial.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0002_indexes.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0003_request_attempts.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0004_integration_hardening.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0005_price_microdollars.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0006_correct_price_microdollars.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0007_price_cache_rates.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0008_proxy_request_identity.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0009_model_protocol_source.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0010_health_probe.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0011_model_resolution_status.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0012_drop_reservations_estimated_microdollars.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0013_request_attempts_account_id_index.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0014_bandwidth_tracking.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0015_multi_provider.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0016_requests_provider_id.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0017_price_snapshots_provider_id.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0018_provider_pings.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0019_client_ip.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0020_performance_indexes.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0021_provider_model_metadata.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0022_dashboard_indexes.sql +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/checksums.json +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/deploy/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/errors.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/health/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/health/circuit_breaker.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/health/health_manager.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/integrations/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/integrations/opencode.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/lifecycle/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/lifecycle/backup.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/logging.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/models/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/models/api.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/models/config.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/models/database.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/models/domain.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/onboard.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/_templates.toml +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/auth.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/client_pool.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/connect.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/contract.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/providers/pproxy_transport.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/proxy/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/proxy/client.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/proxy/sse_observer.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/proxy/usage.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/py.typed +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/quota/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/quota/estimation.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/quota/reservation.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/quota/scorer.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/attempt_finalizer.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/body.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/coordinator.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/finalizer.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/request/limits.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/retry/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/retry/classification.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/routing/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/routing/eligibility.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/routing/provider.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/routing/router.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/security/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/security/redaction.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/stats/__init__.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/stats/queries.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/stats/service.py +0 -0
- {eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/toml_edit.py +0 -0
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1] - 2026-06-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `eggpool serve` returning 500 with `TypeError: 'NoneType' object is not
|
|
15
|
+
callable` on Python 3.14 / spawn-based multiprocessing start methods.
|
|
16
|
+
Granian workers re-import `eggpool.cli` in a fresh interpreter, so the
|
|
17
|
+
module-level `_app` set by the parent process was `None` in the worker
|
|
18
|
+
and the `target_loader` returned `None` as the ASGI callback. `_app_loader`
|
|
19
|
+
now rebuilds the `FastAPI` app from the config path inside each worker.
|
|
20
|
+
Follow-up to the [0.1.4] module-level loader fix.
|
|
21
|
+
|
|
10
22
|
## [0.2.0] - 2026-06-24
|
|
11
23
|
|
|
12
24
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eggpool
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A lightweight proxy that aggregates multiple LLM provider accounts behind one OpenAI-compatible endpoint
|
|
5
5
|
Project-URL: Homepage, https://github.com/eggstack/eggpool
|
|
6
6
|
Project-URL: Repository, https://github.com/eggstack/eggpool
|
|
@@ -91,16 +91,18 @@ class _ConfigPathGroup(click.Group):
|
|
|
91
91
|
# Re-apply the group class after the decorator
|
|
92
92
|
cli.__class__ = _ConfigPathGroup
|
|
93
93
|
|
|
94
|
-
# Module-level app reference for Granian's multiprocessing pickling.
|
|
95
|
-
# Granian spawns worker processes via multiprocessing which requires
|
|
96
|
-
# serializable target_loader callables. Local functions (closures) cannot
|
|
97
|
-
# be pickled, so _app_loader must live at module level.
|
|
98
|
-
_app: Any = None
|
|
99
94
|
|
|
95
|
+
def _app_loader(target: str) -> Any:
|
|
96
|
+
"""Build the ASGI app for a Granian worker from the config-path target.
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
Granian spawns worker subprocesses via multiprocessing, which produces
|
|
99
|
+
a fresh Python interpreter that re-imports ``eggpool.cli``. Module-level
|
|
100
|
+
mutable state set in the parent process is not inherited by the worker,
|
|
101
|
+
so the app must be reconstructed from the config path inside the worker.
|
|
102
|
+
"""
|
|
103
|
+
from eggpool.app import create_app
|
|
104
|
+
|
|
105
|
+
return create_app(config_path=target)
|
|
104
106
|
|
|
105
107
|
|
|
106
108
|
@cli.command()
|
|
@@ -132,23 +134,16 @@ def serve(ctx: click.Context) -> None:
|
|
|
132
134
|
|
|
133
135
|
configure_logging(level=config.server.log_level)
|
|
134
136
|
|
|
135
|
-
from functools import partial
|
|
136
|
-
|
|
137
|
-
from eggpool.app import create_app
|
|
138
|
-
|
|
139
|
-
global _app # noqa: PLW0603
|
|
140
|
-
_app = create_app(config, config_path=config_path)
|
|
141
|
-
|
|
142
137
|
log_level = config.server.log_level.lower()
|
|
143
138
|
Granian(
|
|
144
|
-
|
|
139
|
+
config_path,
|
|
145
140
|
address=config.server.host,
|
|
146
141
|
port=config.server.port,
|
|
147
142
|
interface="asgi", # type: ignore[reportArgumentType]
|
|
148
143
|
workers=1,
|
|
149
144
|
log_level=log_level, # type: ignore[reportArgumentType]
|
|
150
145
|
log_access=config.server.access_log,
|
|
151
|
-
).serve(target_loader=
|
|
146
|
+
).serve(target_loader=_app_loader) # type: ignore[reportArgumentType]
|
|
152
147
|
|
|
153
148
|
|
|
154
149
|
@cli.group(invoke_without_command=True)
|
|
@@ -176,9 +176,13 @@ def tomllib_load(blob: bytes) -> dict[str, object]:
|
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
def _pipx_uninstall(env: dict[str, str]) -> subprocess.CompletedProcess[str]:
|
|
179
|
-
"""Run ``pipx uninstall eggpool``
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
"""Run ``pipx uninstall eggpool`` using the correct interpreter.
|
|
180
|
+
|
|
181
|
+
pipx is not installed inside the eggpool venv that pipx itself
|
|
182
|
+
manages, so we cannot use ``sys.executable`` directly. See
|
|
183
|
+
:func:`_find_pipx_invocation` for resolution details.
|
|
184
|
+
"""
|
|
185
|
+
cmd = _find_pipx_invocation(env)
|
|
182
186
|
return subprocess.run( # noqa: S603
|
|
183
187
|
cmd,
|
|
184
188
|
capture_output=True,
|
|
@@ -188,6 +192,66 @@ def _pipx_uninstall(env: dict[str, str]) -> subprocess.CompletedProcess[str]:
|
|
|
188
192
|
)
|
|
189
193
|
|
|
190
194
|
|
|
195
|
+
def _find_pipx_invocation(env: dict[str, str]) -> list[str]:
|
|
196
|
+
"""Resolve the command argv that runs ``pipx`` on this machine.
|
|
197
|
+
|
|
198
|
+
Resolution order:
|
|
199
|
+
|
|
200
|
+
1. The ``pipx`` binary on ``PATH`` (preferred — it has its own
|
|
201
|
+
shebang pointing at the Python pipx was installed under).
|
|
202
|
+
2. ``EGGPOOL_PYTHON`` env override (escape hatch for unusual setups).
|
|
203
|
+
3. A Python interpreter that has ``pipx`` importable, scanned from
|
|
204
|
+
common locations (``/usr/bin/python3``, ``/usr/local/bin/python3``,
|
|
205
|
+
then ``shutil.which`` fallbacks).
|
|
206
|
+
4. ``sys.executable`` as a last-resort fallback so we surface pipx's
|
|
207
|
+
own error instead of silently no-oping.
|
|
208
|
+
"""
|
|
209
|
+
pipx_path = shutil.which("pipx")
|
|
210
|
+
if pipx_path:
|
|
211
|
+
return [pipx_path, "uninstall", "eggpool"]
|
|
212
|
+
|
|
213
|
+
override = env.get("EGGPOOL_PYTHON")
|
|
214
|
+
if override and Path(override).is_file():
|
|
215
|
+
return [override, "-m", "pipx", "uninstall", "eggpool"]
|
|
216
|
+
|
|
217
|
+
for candidate in _candidate_pythons():
|
|
218
|
+
if _python_has_pipx(candidate):
|
|
219
|
+
return [candidate, "-m", "pipx", "uninstall", "eggpool"]
|
|
220
|
+
|
|
221
|
+
return [sys.executable, "-m", "pipx", "uninstall", "eggpool"]
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _candidate_pythons() -> list[str]:
|
|
225
|
+
"""Return Python interpreters worth probing for a ``pipx`` install."""
|
|
226
|
+
found: list[str] = []
|
|
227
|
+
seen: set[str] = set()
|
|
228
|
+
for raw in ("/usr/bin/python3", "/usr/local/bin/python3"):
|
|
229
|
+
if Path(raw).is_file() and raw not in seen:
|
|
230
|
+
found.append(raw)
|
|
231
|
+
seen.add(raw)
|
|
232
|
+
for name in ("python3", "python"):
|
|
233
|
+
resolved = shutil.which(name)
|
|
234
|
+
if resolved and resolved not in seen:
|
|
235
|
+
found.append(resolved)
|
|
236
|
+
seen.add(resolved)
|
|
237
|
+
return found
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _python_has_pipx(python: str) -> bool:
|
|
241
|
+
"""Return True if ``python -m pipx --version`` exits 0."""
|
|
242
|
+
try:
|
|
243
|
+
proc = subprocess.run( # noqa: S603
|
|
244
|
+
[python, "-m", "pipx", "--version"],
|
|
245
|
+
capture_output=True,
|
|
246
|
+
text=True,
|
|
247
|
+
check=False,
|
|
248
|
+
timeout=5,
|
|
249
|
+
)
|
|
250
|
+
except (OSError, subprocess.SubprocessError):
|
|
251
|
+
return False
|
|
252
|
+
return proc.returncode == 0
|
|
253
|
+
|
|
254
|
+
|
|
191
255
|
def _uv_tool_uninstall(env: dict[str, str]) -> subprocess.CompletedProcess[str]:
|
|
192
256
|
"""Run ``uv tool uninstall eggpool``."""
|
|
193
257
|
cmd = ["uv", "tool", "uninstall", "eggpool"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/dashboard/themes/base16-atelier-forest-light.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eggpool-0.2.0 → eggpool-0.2.1}/src/eggpool/db/schema/0013_request_attempts_account_id_index.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|