eggpool 0.3.7__tar.gz → 0.3.9__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.3.7 → eggpool-0.3.9}/PKG-INFO +1 -1
- {eggpool-0.3.7 → eggpool-0.3.9}/pyproject.toml +1 -1
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/catalog_resolvers.py +119 -24
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/cli_full.py +17 -5
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/connect.py +27 -1
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/openai_to_anthropic.py +3 -1
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/streaming.py +19 -4
- {eggpool-0.3.7 → eggpool-0.3.9}/uv.lock +1 -1
- {eggpool-0.3.7 → eggpool-0.3.9}/.env.example +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/.github/workflows/ci.yml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/.github/workflows/release.yml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/.gitignore +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/AGENTS.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/CHANGELOG.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/LICENSE +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/README.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/architecture/README.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/config-examples/claude-code.env +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/config-examples/opencode.jsonc +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/config.example.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/deploy/eggpool-logrotate.conf +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/deploy/eggpool.service +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/deploy/env.example +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/backup-restore.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/deployment.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/filesystem-layout.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/firewall.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/model-limits.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/network-diagnostics.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/providers.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/proxy.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/raspberry-pi.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/docs/transcoding.md +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/check_database.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/install.sh +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/install_prompt.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/smoke_test.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/validate_routing.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/scripts/verify_upstream_auth.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/__main__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/_share/.env.example +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/_share/config.example.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/accounts/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/accounts/registry.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/accounts/state.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/backoff.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/chat_completions.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/errors.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/messages.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/models.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/network.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/proxy_request.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/runtime.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/stats.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/api/update.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/app.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/auth.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/background/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/background/backup.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/background/cleanup.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/cache.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/fetcher.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/limits.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/normalizer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/pricing.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/pricing_aliases.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/pricing_resolver.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/protocols.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/catalog/service.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/cli.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/config.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/constants.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/cost_recompute.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/_resources.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/escape.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/render.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/routes.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/static/chart.umd.min.js +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/static/dashboard.css +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/static/dashboard.js +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/static/favicon.svg +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/theme.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Booberry.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Catppuccin Latte.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Catppuccin Macchiato.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Catppuccin Mocha.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Cyber Red.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Cyberpunk.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Dark Green.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Discord (80_ Saturation).toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Discord.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Dracula.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Ferra Light.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Flexor Dark.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Gruvbox.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Halcyon Dark.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/IntelliJ Light.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Kanagawa.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Macaw Dark.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Macaw Light.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Matrix.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Noctis Lilac.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Nord.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Nostromo Terminal.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/One Dark.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Oxocarbon.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Rose Pine Dawn.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Rose Pine Moon.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Rose Pine.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Solarized Dark.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Sonokai.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Tokyo Night Storm.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/VESPER.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/Zenburn.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/acton.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/bam.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/base16-atelier-forest-light.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/berlin.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/black but with important highlights.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/broc.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/cork.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/ferra.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/forest.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/lisbon.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/midnight.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/oslo.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/plum.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/portland.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/sunset.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/tofino.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/vanimo.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/dashboard/themes/vik.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/connection.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/migrations.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/repositories.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/rollup_repository.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0001_initial.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0002_indexes.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0003_request_attempts.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0004_integration_hardening.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0005_price_microdollars.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0006_correct_price_microdollars.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0007_price_cache_rates.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0008_proxy_request_identity.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0009_model_protocol_source.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0010_health_probe.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0011_model_resolution_status.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0012_drop_reservations_estimated_microdollars.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0013_request_attempts_account_id_index.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0014_bandwidth_tracking.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0015_multi_provider.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0016_requests_provider_id.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0017_price_snapshots_provider_id.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0018_provider_pings.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0019_client_ip.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0020_performance_indexes.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0021_provider_model_metadata.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0022_dashboard_indexes.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0023_deprecated_model_placeholder.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0024_account_backoffs.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0025_stale_request_index.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0026_attempt_observability.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0027_routing_decisions.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0028_operational_events.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0029_latency_phases.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0030_model_pricing_aliases.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0031_price_snapshot_provenance.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0032_usage_rollups.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0033_request_provider_local_cost.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0034_transcoding_daily.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/0035_routing_decision_score_components.sql +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/db/schema/checksums.json +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/deploy/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/deploy_user.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/errors.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/fastcli.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/health/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/health/backoff.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/health/circuit_breaker.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/health/health_manager.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/integrations/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/integrations/opencode.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/lifecycle/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/lifecycle/backup.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/lifecycle/uninstall.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/logging.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/metrics/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/metrics/buffer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/models/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/models/api.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/models/config.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/models/database.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/models/domain.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/onboard.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/_templates.toml +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/auth.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/client_pool.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/contract.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/dns_cache.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/outbound.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/providers/pproxy_transport.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/proxy/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/proxy/client.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/proxy/cost_reporting.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/proxy/sse_observer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/proxy/usage.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/py.typed +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/quota/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/quota/audit.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/quota/estimation.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/quota/reservation.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/quota/scorer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/attempt_finalizer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/body.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/coordinator.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/finalizer.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/request/limits.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/retry/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/retry/classification.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/routing/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/routing/eligibility.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/routing/provider.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/routing/router.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/runtime.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/runtime_dispatch.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/runtime_metrics.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/runtime_paths.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/security/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/security/redaction.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/stats/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/stats/grouped_timeseries.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/stats/queries.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/stats/service.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/toml_edit.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/__init__.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/anthropic_to_openai.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/context.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/errors.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/ids.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/policy.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/protocol.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/static_headers.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/transcoder/usage.py +0 -0
- {eggpool-0.3.7 → eggpool-0.3.9}/src/eggpool/update_checker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eggpool
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
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
|
|
@@ -106,6 +106,59 @@ class CatalogFetchError(RuntimeError):
|
|
|
106
106
|
"""Raised when a catalog fetch fails (network, parse, auth)."""
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def _safe_parse_catalog_price_per_1k(
|
|
110
|
+
*,
|
|
111
|
+
catalog_name: str,
|
|
112
|
+
model_id: str,
|
|
113
|
+
category: str,
|
|
114
|
+
value: object,
|
|
115
|
+
default_unit: str = "1k",
|
|
116
|
+
) -> float | None:
|
|
117
|
+
"""Parse an untrusted external catalog price field.
|
|
118
|
+
|
|
119
|
+
External catalogs are advisory. A malformed or negative field should
|
|
120
|
+
remove that category from the resolved pricing, not fail the whole
|
|
121
|
+
refresh cycle or discard other valid rates from the same model row.
|
|
122
|
+
"""
|
|
123
|
+
from eggpool.catalog.pricing import parse_price_per_1k
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
return parse_price_per_1k(value, default_unit=default_unit)
|
|
127
|
+
except Exception as exc:
|
|
128
|
+
logger.warning(
|
|
129
|
+
"Ignoring invalid %s %s price for %s: %s",
|
|
130
|
+
catalog_name,
|
|
131
|
+
category,
|
|
132
|
+
model_id,
|
|
133
|
+
exc,
|
|
134
|
+
)
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _safe_parse_catalog_microdollars(
|
|
139
|
+
*,
|
|
140
|
+
catalog_name: str,
|
|
141
|
+
model_id: str,
|
|
142
|
+
category: str,
|
|
143
|
+
value: object,
|
|
144
|
+
default_unit: str | None = None,
|
|
145
|
+
) -> int | None:
|
|
146
|
+
"""Parse an untrusted external catalog cache-rate field."""
|
|
147
|
+
from eggpool.catalog.pricing import parse_microdollars_per_million
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
return parse_microdollars_per_million(value, default_unit=default_unit)
|
|
151
|
+
except Exception as exc:
|
|
152
|
+
logger.warning(
|
|
153
|
+
"Ignoring invalid %s %s price for %s: %s",
|
|
154
|
+
catalog_name,
|
|
155
|
+
category,
|
|
156
|
+
model_id,
|
|
157
|
+
exc,
|
|
158
|
+
)
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
|
|
109
162
|
class CatalogHttpClient(Protocol):
|
|
110
163
|
"""Minimal async HTTP client interface used by catalog resolvers."""
|
|
111
164
|
|
|
@@ -224,8 +277,13 @@ class OpenRouterCatalogResolver:
|
|
|
224
277
|
payload_obj: object = response.json()
|
|
225
278
|
except (httpx.HTTPError, ValueError) as exc:
|
|
226
279
|
raise CatalogFetchError(f"OpenRouter fetch failed: {exc}") from exc
|
|
227
|
-
|
|
228
|
-
|
|
280
|
+
try:
|
|
281
|
+
entries = self._parse_catalog(payload_obj)
|
|
282
|
+
self._cache.store(entries)
|
|
283
|
+
except Exception as exc:
|
|
284
|
+
raise CatalogFetchError(
|
|
285
|
+
f"OpenRouter catalog parse failed: {exc}"
|
|
286
|
+
) from exc
|
|
229
287
|
return entries
|
|
230
288
|
|
|
231
289
|
@staticmethod
|
|
@@ -249,8 +307,13 @@ class OpenRouterCatalogResolver:
|
|
|
249
307
|
entry = OpenRouterCatalogResolver._parse_entry(
|
|
250
308
|
model_id_obj, pricing_obj, raw_dict
|
|
251
309
|
)
|
|
252
|
-
except
|
|
253
|
-
logger.warning(
|
|
310
|
+
except Exception as exc:
|
|
311
|
+
logger.warning(
|
|
312
|
+
"Skipping catalog entry %r after unexpected parse failure: %s",
|
|
313
|
+
model_id_obj,
|
|
314
|
+
exc,
|
|
315
|
+
exc_info=True,
|
|
316
|
+
)
|
|
254
317
|
continue
|
|
255
318
|
entries[model_id_obj] = entry
|
|
256
319
|
# Strip raw upstream JSON to bound the cache footprint;
|
|
@@ -264,27 +327,40 @@ class OpenRouterCatalogResolver:
|
|
|
264
327
|
model_id: str, pricing: object, raw: dict[str, Any]
|
|
265
328
|
) -> CatalogEntry:
|
|
266
329
|
"""Translate an OpenRouter pricing block into a CatalogEntry."""
|
|
267
|
-
from eggpool.catalog.pricing import (
|
|
268
|
-
parse_microdollars_per_million,
|
|
269
|
-
parse_price_per_1k,
|
|
270
|
-
)
|
|
271
330
|
|
|
272
331
|
def _opt(key: str) -> object | None:
|
|
273
332
|
if not isinstance(pricing, dict):
|
|
274
333
|
return None
|
|
275
|
-
|
|
276
|
-
if isinstance(value, (str, int, float)):
|
|
277
|
-
return value
|
|
278
|
-
return None
|
|
334
|
+
return pricing.get(key) # type: ignore[reportUnknownMemberType]
|
|
279
335
|
|
|
280
336
|
# OpenRouter fields are dollars-per-token numeric strings.
|
|
281
|
-
input_per_1k =
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
337
|
+
input_per_1k = _safe_parse_catalog_price_per_1k(
|
|
338
|
+
catalog_name=OpenRouterCatalogResolver.name,
|
|
339
|
+
model_id=model_id,
|
|
340
|
+
category="input",
|
|
341
|
+
value=_opt("prompt"),
|
|
342
|
+
default_unit="token",
|
|
343
|
+
)
|
|
344
|
+
output_per_1k = _safe_parse_catalog_price_per_1k(
|
|
345
|
+
catalog_name=OpenRouterCatalogResolver.name,
|
|
346
|
+
model_id=model_id,
|
|
347
|
+
category="output",
|
|
348
|
+
value=_opt("completion"),
|
|
349
|
+
default_unit="token",
|
|
350
|
+
)
|
|
351
|
+
cache_read = _safe_parse_catalog_microdollars(
|
|
352
|
+
catalog_name=OpenRouterCatalogResolver.name,
|
|
353
|
+
model_id=model_id,
|
|
354
|
+
category="cache_read",
|
|
355
|
+
value=_opt("input_cache_read"),
|
|
356
|
+
default_unit="token",
|
|
285
357
|
)
|
|
286
|
-
cache_write =
|
|
287
|
-
|
|
358
|
+
cache_write = _safe_parse_catalog_microdollars(
|
|
359
|
+
catalog_name=OpenRouterCatalogResolver.name,
|
|
360
|
+
model_id=model_id,
|
|
361
|
+
category="cache_write",
|
|
362
|
+
value=_opt("input_cache_write"),
|
|
363
|
+
default_unit="token",
|
|
288
364
|
)
|
|
289
365
|
return CatalogEntry(
|
|
290
366
|
catalog_model_id=model_id,
|
|
@@ -375,6 +451,15 @@ class CatalogResolverPipeline:
|
|
|
375
451
|
exc,
|
|
376
452
|
)
|
|
377
453
|
continue
|
|
454
|
+
except Exception as exc:
|
|
455
|
+
logger.exception(
|
|
456
|
+
"Catalog %s failed unexpectedly for %s/%s: %s",
|
|
457
|
+
resolver.name,
|
|
458
|
+
provider_id,
|
|
459
|
+
model_id,
|
|
460
|
+
exc,
|
|
461
|
+
)
|
|
462
|
+
continue
|
|
378
463
|
entry = catalog.get(alias.catalog_model_id)
|
|
379
464
|
if entry is None:
|
|
380
465
|
logger.warning(
|
|
@@ -385,10 +470,20 @@ class CatalogResolverPipeline:
|
|
|
385
470
|
model_id,
|
|
386
471
|
)
|
|
387
472
|
continue
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
473
|
+
try:
|
|
474
|
+
return resolver.to_resolved_pricing(
|
|
475
|
+
entry=entry,
|
|
476
|
+
provider_id=provider_id,
|
|
477
|
+
model_id=model_id,
|
|
478
|
+
alias=alias,
|
|
479
|
+
)
|
|
480
|
+
except Exception as exc:
|
|
481
|
+
logger.exception(
|
|
482
|
+
"Catalog %s failed to convert pricing for %s/%s: %s",
|
|
483
|
+
resolver.name,
|
|
484
|
+
provider_id,
|
|
485
|
+
model_id,
|
|
486
|
+
exc,
|
|
487
|
+
)
|
|
488
|
+
continue
|
|
394
489
|
return None
|
|
@@ -531,6 +531,12 @@ def _check_stale_contracts(config: AppConfig, config_path: str) -> list[str]:
|
|
|
531
531
|
|
|
532
532
|
for provider in config.providers.values():
|
|
533
533
|
endpoint = provider.models_endpoint
|
|
534
|
+
raw_section_obj = raw_providers.get(provider.id)
|
|
535
|
+
raw_section: dict[str, object] = (
|
|
536
|
+
cast("dict[str, object]", raw_section_obj)
|
|
537
|
+
if isinstance(raw_section_obj, dict)
|
|
538
|
+
else {}
|
|
539
|
+
)
|
|
534
540
|
|
|
535
541
|
if (
|
|
536
542
|
endpoint is not None
|
|
@@ -553,13 +559,21 @@ def _check_stale_contracts(config: AppConfig, config_path: str) -> list[str]:
|
|
|
553
559
|
"verify.require_models is true; the contract is contradictory"
|
|
554
560
|
)
|
|
555
561
|
|
|
556
|
-
if
|
|
562
|
+
if (
|
|
563
|
+
"anthropic_path" in raw_section
|
|
564
|
+
and provider.anthropic_path
|
|
565
|
+
and "anthropic" not in provider.protocols
|
|
566
|
+
):
|
|
557
567
|
warnings.append(
|
|
558
568
|
f"[{provider.id}] anthropic_path is set but 'anthropic' is "
|
|
559
569
|
"not in protocols; the field will be ignored"
|
|
560
570
|
)
|
|
561
571
|
|
|
562
|
-
if
|
|
572
|
+
if (
|
|
573
|
+
"openai_path" in raw_section
|
|
574
|
+
and provider.openai_path
|
|
575
|
+
and "openai" not in provider.protocols
|
|
576
|
+
):
|
|
563
577
|
warnings.append(
|
|
564
578
|
f"[{provider.id}] openai_path is set but 'openai' is not "
|
|
565
579
|
"in protocols; the field will be ignored"
|
|
@@ -595,9 +609,7 @@ def _check_stale_contracts(config: AppConfig, config_path: str) -> list[str]:
|
|
|
595
609
|
"providers typically use header='x-api-key'"
|
|
596
610
|
)
|
|
597
611
|
|
|
598
|
-
|
|
599
|
-
if isinstance(raw_section_obj, dict):
|
|
600
|
-
raw_section = cast("dict[str, object]", raw_section_obj)
|
|
612
|
+
if raw_section:
|
|
601
613
|
has_legacy_key = (
|
|
602
614
|
"models_method" in raw_section or "models_path" in raw_section
|
|
603
615
|
)
|
|
@@ -15,7 +15,7 @@ from typing import Any, cast
|
|
|
15
15
|
from eggpool.constants import DEFAULT_PROVIDER_ID
|
|
16
16
|
from eggpool.providers.contract import PROVIDER_STATUS_SYMBOLS
|
|
17
17
|
from eggpool.runtime import restart_server as _restart_server
|
|
18
|
-
from eggpool.toml_edit import render_toml_value
|
|
18
|
+
from eggpool.toml_edit import render_toml_value, update_section_value
|
|
19
19
|
|
|
20
20
|
_REGISTRY_METADATA_FIELDS = frozenset(
|
|
21
21
|
{
|
|
@@ -454,10 +454,36 @@ def merge_provider_into_config(
|
|
|
454
454
|
)
|
|
455
455
|
content = _insert_provider_block(content, block)
|
|
456
456
|
|
|
457
|
+
if _provider_needs_transcoder(provider_data):
|
|
458
|
+
content = _ensure_transcoder_enabled(content)
|
|
459
|
+
|
|
457
460
|
path.write_text(content, encoding="utf-8")
|
|
458
461
|
return True
|
|
459
462
|
|
|
460
463
|
|
|
464
|
+
def _provider_needs_transcoder(provider_data: dict[str, Any]) -> bool:
|
|
465
|
+
"""Return whether this provider needs cross-protocol request bridging."""
|
|
466
|
+
protocols_value = provider_data.get("protocols")
|
|
467
|
+
if not isinstance(protocols_value, list):
|
|
468
|
+
return False
|
|
469
|
+
protocol_items = cast("list[object]", protocols_value)
|
|
470
|
+
protocols = {str(protocol) for protocol in protocol_items}
|
|
471
|
+
return bool(protocols) and not {"openai", "anthropic"}.issubset(protocols)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def _ensure_transcoder_enabled(content: str) -> str:
|
|
475
|
+
"""Enable the global transcoder block for single-protocol providers."""
|
|
476
|
+
result = update_section_value(
|
|
477
|
+
content.split("\n"),
|
|
478
|
+
"transcoder",
|
|
479
|
+
"enabled",
|
|
480
|
+
"true",
|
|
481
|
+
insert_missing_key=True,
|
|
482
|
+
append_missing_section=True,
|
|
483
|
+
)
|
|
484
|
+
return "\n".join(result.lines)
|
|
485
|
+
|
|
486
|
+
|
|
461
487
|
def _get_existing_accounts(content: str, provider_id: str) -> list[str] | None:
|
|
462
488
|
"""Get existing account names for a provider. Returns None if not found."""
|
|
463
489
|
# TOML array-of-tables uses [[providers.X.accounts]] syntax
|
|
@@ -82,7 +82,7 @@ class OpenAIToAnthropic:
|
|
|
82
82
|
role = str(msg.get("role", "")) # pyright: ignore[reportUnknownMemberType]
|
|
83
83
|
content = msg.get("content", "") # pyright: ignore[reportUnknownMemberType]
|
|
84
84
|
|
|
85
|
-
if role
|
|
85
|
+
if role in ("system", "developer"):
|
|
86
86
|
if isinstance(content, str):
|
|
87
87
|
system_parts.append(content)
|
|
88
88
|
elif isinstance(content, list):
|
|
@@ -147,6 +147,8 @@ class OpenAIToAnthropic:
|
|
|
147
147
|
out["temperature"] = temperature
|
|
148
148
|
|
|
149
149
|
max_tokens = payload.get("max_tokens")
|
|
150
|
+
if max_tokens is None:
|
|
151
|
+
max_tokens = payload.get("max_completion_tokens")
|
|
150
152
|
if max_tokens is None:
|
|
151
153
|
max_tokens = 4096
|
|
152
154
|
warnings.append(
|
|
@@ -510,6 +510,7 @@ class AnthropicToOpenAIStreaming(_BaseStreamingTranscoder):
|
|
|
510
510
|
self._id = ""
|
|
511
511
|
self._model = ""
|
|
512
512
|
self._emitted_usage = False
|
|
513
|
+
self._done_emitted = False
|
|
513
514
|
|
|
514
515
|
async def feed(self, chunk: bytes) -> list[bytes]:
|
|
515
516
|
self._observer.observe(chunk)
|
|
@@ -525,7 +526,9 @@ class AnthropicToOpenAIStreaming(_BaseStreamingTranscoder):
|
|
|
525
526
|
out: list[bytes] = []
|
|
526
527
|
for event_type, data in frames:
|
|
527
528
|
out.extend(self._translate(event_type, data))
|
|
528
|
-
|
|
529
|
+
done = self._emit_done()
|
|
530
|
+
if done is not None:
|
|
531
|
+
out.append(done)
|
|
529
532
|
return out
|
|
530
533
|
|
|
531
534
|
def _translate(
|
|
@@ -550,7 +553,7 @@ class AnthropicToOpenAIStreaming(_BaseStreamingTranscoder):
|
|
|
550
553
|
msg = str(err_typed.get("message", str(err_typed)))
|
|
551
554
|
else:
|
|
552
555
|
msg = str(err)
|
|
553
|
-
|
|
556
|
+
out = [
|
|
554
557
|
self._openai_frame(
|
|
555
558
|
{
|
|
556
559
|
"error": {
|
|
@@ -561,8 +564,11 @@ class AnthropicToOpenAIStreaming(_BaseStreamingTranscoder):
|
|
|
561
564
|
},
|
|
562
565
|
},
|
|
563
566
|
),
|
|
564
|
-
self._openai_done(),
|
|
565
567
|
]
|
|
568
|
+
done = self._emit_done()
|
|
569
|
+
if done is not None:
|
|
570
|
+
out.append(done)
|
|
571
|
+
return out
|
|
566
572
|
|
|
567
573
|
def _dispatch(
|
|
568
574
|
self,
|
|
@@ -714,9 +720,18 @@ class AnthropicToOpenAIStreaming(_BaseStreamingTranscoder):
|
|
|
714
720
|
},
|
|
715
721
|
),
|
|
716
722
|
)
|
|
717
|
-
|
|
723
|
+
done = self._emit_done()
|
|
724
|
+
if done is not None:
|
|
725
|
+
out.append(done)
|
|
718
726
|
return out
|
|
719
727
|
|
|
728
|
+
def _emit_done(self) -> bytes | None:
|
|
729
|
+
"""Emit the OpenAI terminal marker at most once."""
|
|
730
|
+
if self._done_emitted:
|
|
731
|
+
return None
|
|
732
|
+
self._done_emitted = True
|
|
733
|
+
return self._openai_done()
|
|
734
|
+
|
|
720
735
|
|
|
721
736
|
def select_streaming_transcoder(
|
|
722
737
|
*,
|
|
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
|