eggpool 0.1.2__tar.gz → 0.1.3__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.
Files changed (193) hide show
  1. {eggpool-0.1.2 → eggpool-0.1.3}/CHANGELOG.md +15 -0
  2. {eggpool-0.1.2 → eggpool-0.1.3}/PKG-INFO +1 -1
  3. {eggpool-0.1.2 → eggpool-0.1.3}/pyproject.toml +1 -1
  4. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/install.sh +1 -1
  5. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/cli.py +17 -10
  6. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/onboard.py +51 -3
  7. {eggpool-0.1.2 → eggpool-0.1.3}/uv.lock +1 -1
  8. {eggpool-0.1.2 → eggpool-0.1.3}/.env.example +0 -0
  9. {eggpool-0.1.2 → eggpool-0.1.3}/.github/workflows/ci.yml +0 -0
  10. {eggpool-0.1.2 → eggpool-0.1.3}/.github/workflows/release.yml +0 -0
  11. {eggpool-0.1.2 → eggpool-0.1.3}/.gitignore +0 -0
  12. {eggpool-0.1.2 → eggpool-0.1.3}/AGENTS.md +0 -0
  13. {eggpool-0.1.2 → eggpool-0.1.3}/LICENSE +0 -0
  14. {eggpool-0.1.2 → eggpool-0.1.3}/README.md +0 -0
  15. {eggpool-0.1.2 → eggpool-0.1.3}/architecture/README.md +0 -0
  16. {eggpool-0.1.2 → eggpool-0.1.3}/config-examples/claude-code.env +0 -0
  17. {eggpool-0.1.2 → eggpool-0.1.3}/config-examples/opencode.jsonc +0 -0
  18. {eggpool-0.1.2 → eggpool-0.1.3}/config.example.toml +0 -0
  19. {eggpool-0.1.2 → eggpool-0.1.3}/deploy/eggpool-logrotate.conf +0 -0
  20. {eggpool-0.1.2 → eggpool-0.1.3}/deploy/eggpool.service +0 -0
  21. {eggpool-0.1.2 → eggpool-0.1.3}/deploy/env.example +0 -0
  22. {eggpool-0.1.2 → eggpool-0.1.3}/docs/backup-restore.md +0 -0
  23. {eggpool-0.1.2 → eggpool-0.1.3}/docs/deployment.md +0 -0
  24. {eggpool-0.1.2 → eggpool-0.1.3}/docs/filesystem-layout.md +0 -0
  25. {eggpool-0.1.2 → eggpool-0.1.3}/docs/firewall.md +0 -0
  26. {eggpool-0.1.2 → eggpool-0.1.3}/docs/model-limits.md +0 -0
  27. {eggpool-0.1.2 → eggpool-0.1.3}/docs/providers.md +0 -0
  28. {eggpool-0.1.2 → eggpool-0.1.3}/docs/proxy.md +0 -0
  29. {eggpool-0.1.2 → eggpool-0.1.3}/docs/raspberry-pi.md +0 -0
  30. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/__init__.py +0 -0
  31. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/check_database.py +0 -0
  32. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/install_prompt.py +0 -0
  33. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/smoke_test.py +0 -0
  34. {eggpool-0.1.2 → eggpool-0.1.3}/scripts/verify_upstream_auth.py +0 -0
  35. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/__init__.py +0 -0
  36. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/__main__.py +0 -0
  37. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/_share/.env.example +0 -0
  38. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/_share/config.example.toml +0 -0
  39. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/accounts/__init__.py +0 -0
  40. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/accounts/registry.py +0 -0
  41. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/accounts/state.py +0 -0
  42. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/__init__.py +0 -0
  43. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/chat_completions.py +0 -0
  44. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/errors.py +0 -0
  45. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/messages.py +0 -0
  46. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/models.py +0 -0
  47. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/proxy_request.py +0 -0
  48. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/api/stats.py +0 -0
  49. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/app.py +0 -0
  50. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/auth.py +0 -0
  51. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/background/__init__.py +0 -0
  52. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/background/cleanup.py +0 -0
  53. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/__init__.py +0 -0
  54. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/cache.py +0 -0
  55. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/fetcher.py +0 -0
  56. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/limits.py +0 -0
  57. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/normalizer.py +0 -0
  58. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/pricing.py +0 -0
  59. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/protocols.py +0 -0
  60. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/catalog/service.py +0 -0
  61. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/constants.py +0 -0
  62. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/__init__.py +0 -0
  63. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/_resources.py +0 -0
  64. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/escape.py +0 -0
  65. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/render.py +0 -0
  66. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/routes.py +0 -0
  67. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/static/chart.umd.min.js +0 -0
  68. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/static/dashboard.css +0 -0
  69. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/static/favicon.svg +0 -0
  70. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/theme.py +0 -0
  71. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Booberry.toml +0 -0
  72. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Catppuccin Latte.toml +0 -0
  73. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Catppuccin Macchiato.toml +0 -0
  74. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Catppuccin Mocha.toml +0 -0
  75. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Cyber Red.toml +0 -0
  76. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Cyberpunk.toml +0 -0
  77. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Dark Green.toml +0 -0
  78. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Discord (80_ Saturation).toml +0 -0
  79. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Discord.toml +0 -0
  80. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Dracula.toml +0 -0
  81. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Ferra Light.toml +0 -0
  82. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Flexor Dark.toml +0 -0
  83. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Gruvbox.toml +0 -0
  84. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Halcyon Dark.toml +0 -0
  85. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/IntelliJ Light.toml +0 -0
  86. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Kanagawa.toml +0 -0
  87. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Macaw Dark.toml +0 -0
  88. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Macaw Light.toml +0 -0
  89. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Matrix.toml +0 -0
  90. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Noctis Lilac.toml +0 -0
  91. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Nord.toml +0 -0
  92. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Nostromo Terminal.toml +0 -0
  93. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/One Dark.toml +0 -0
  94. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Oxocarbon.toml +0 -0
  95. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Rose Pine Dawn.toml +0 -0
  96. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Rose Pine Moon.toml +0 -0
  97. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Rose Pine.toml +0 -0
  98. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Solarized Dark.toml +0 -0
  99. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Sonokai.toml +0 -0
  100. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Tokyo Night Storm.toml +0 -0
  101. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/VESPER.toml +0 -0
  102. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/Zenburn.toml +0 -0
  103. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/acton.toml +0 -0
  104. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/bam.toml +0 -0
  105. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/base16-atelier-forest-light.toml +0 -0
  106. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/berlin.toml +0 -0
  107. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/black but with important highlights.toml +0 -0
  108. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/broc.toml +0 -0
  109. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/cork.toml +0 -0
  110. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/ferra.toml +0 -0
  111. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/forest.toml +0 -0
  112. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/lisbon.toml +0 -0
  113. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/midnight.toml +0 -0
  114. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/oslo.toml +0 -0
  115. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/plum.toml +0 -0
  116. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/portland.toml +0 -0
  117. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/sunset.toml +0 -0
  118. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/tofino.toml +0 -0
  119. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/vanimo.toml +0 -0
  120. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/dashboard/themes/vik.toml +0 -0
  121. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/__init__.py +0 -0
  122. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/connection.py +0 -0
  123. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/migrations.py +0 -0
  124. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/repositories.py +0 -0
  125. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0001_initial.sql +0 -0
  126. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0002_indexes.sql +0 -0
  127. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0003_request_attempts.sql +0 -0
  128. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0004_integration_hardening.sql +0 -0
  129. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0005_price_microdollars.sql +0 -0
  130. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0006_correct_price_microdollars.sql +0 -0
  131. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0007_price_cache_rates.sql +0 -0
  132. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0008_proxy_request_identity.sql +0 -0
  133. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0009_model_protocol_source.sql +0 -0
  134. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0010_health_probe.sql +0 -0
  135. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0011_model_resolution_status.sql +0 -0
  136. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0012_drop_reservations_estimated_microdollars.sql +0 -0
  137. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0013_request_attempts_account_id_index.sql +0 -0
  138. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0014_bandwidth_tracking.sql +0 -0
  139. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0015_multi_provider.sql +0 -0
  140. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0016_requests_provider_id.sql +0 -0
  141. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0017_price_snapshots_provider_id.sql +0 -0
  142. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0018_provider_pings.sql +0 -0
  143. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0019_client_ip.sql +0 -0
  144. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0020_performance_indexes.sql +0 -0
  145. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0021_provider_model_metadata.sql +0 -0
  146. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/0022_dashboard_indexes.sql +0 -0
  147. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/db/schema/checksums.json +0 -0
  148. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/deploy/__init__.py +0 -0
  149. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/errors.py +0 -0
  150. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/health/__init__.py +0 -0
  151. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/health/circuit_breaker.py +0 -0
  152. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/health/health_manager.py +0 -0
  153. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/integrations/__init__.py +0 -0
  154. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/integrations/opencode.py +0 -0
  155. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/logging.py +0 -0
  156. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/models/__init__.py +0 -0
  157. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/models/api.py +0 -0
  158. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/models/config.py +0 -0
  159. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/models/database.py +0 -0
  160. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/models/domain.py +0 -0
  161. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/__init__.py +0 -0
  162. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/_templates.toml +0 -0
  163. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/client_pool.py +0 -0
  164. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/connect.py +0 -0
  165. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/contract.py +0 -0
  166. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/providers/pproxy_transport.py +0 -0
  167. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/proxy/__init__.py +0 -0
  168. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/proxy/client.py +0 -0
  169. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/proxy/sse_observer.py +0 -0
  170. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/proxy/usage.py +0 -0
  171. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/py.typed +0 -0
  172. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/quota/__init__.py +0 -0
  173. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/quota/estimation.py +0 -0
  174. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/quota/reservation.py +0 -0
  175. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/quota/scorer.py +0 -0
  176. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/__init__.py +0 -0
  177. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/attempt_finalizer.py +0 -0
  178. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/body.py +0 -0
  179. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/coordinator.py +0 -0
  180. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/finalizer.py +0 -0
  181. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/request/limits.py +0 -0
  182. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/retry/__init__.py +0 -0
  183. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/retry/classification.py +0 -0
  184. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/routing/__init__.py +0 -0
  185. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/routing/eligibility.py +0 -0
  186. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/routing/provider.py +0 -0
  187. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/routing/router.py +0 -0
  188. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/security/__init__.py +0 -0
  189. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/security/redaction.py +0 -0
  190. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/stats/__init__.py +0 -0
  191. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/stats/queries.py +0 -0
  192. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/stats/service.py +0 -0
  193. {eggpool-0.1.2 → eggpool-0.1.3}/src/eggpool/toml_edit.py +0 -0
@@ -5,6 +5,21 @@ All notable changes to EggPool are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.3] - 2026-06-23
9
+
10
+ ### Changed
11
+
12
+ - `eggpool onboard` now creates a minimal config and generates a server
13
+ API key on fresh installs, eliminating the need for `init-config`.
14
+ - Install script recommends `eggpool onboard` instead of `init-config`.
15
+ - `init-config` shows a helpful warning when config exists, recommending
16
+ `eggpool onboard` for provider setup.
17
+
18
+ ### Fixed
19
+
20
+ - Onboard flow now works deterministically on fresh installs without
21
+ requiring manual config creation first.
22
+
8
23
  ## [0.1.2] - 2026-06-23
9
24
 
10
25
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eggpool
3
- Version: 0.1.2
3
+ Version: 0.1.3
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "eggpool"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  description = "A lightweight proxy that aggregates multiple LLM provider accounts behind one OpenAI-compatible endpoint"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -89,7 +89,7 @@ echo "Checking for pipx..."
89
89
  if command -v pipx >/dev/null 2>&1; then
90
90
  echo "Installing eggpool via pipx..."
91
91
  pipx install eggpool
92
- echo "Installation complete. Run 'eggpool init-config' to start."
92
+ echo "Installation complete. Run 'eggpool onboard' to start."
93
93
  exec eggpool accounts status
94
94
  fi
95
95
 
@@ -334,7 +334,7 @@ def edit(ctx: click.Context) -> None:
334
334
  sys.exit(1)
335
335
 
336
336
 
337
- def _generate_api_key() -> str:
337
+ def generate_api_key() -> str:
338
338
  """Generate a cryptographically secure API key."""
339
339
  import secrets
340
340
 
@@ -383,7 +383,7 @@ def _detect_lan_ip() -> str:
383
383
  return "127.0.0.1"
384
384
 
385
385
 
386
- def _write_server_api_key(config_path: str, new_key: str) -> None:
386
+ def write_server_api_key(config_path: str, new_key: str) -> None:
387
387
  """Write a server API key to the [server] section of the config.
388
388
 
389
389
  If the [server] section declares ``api_key_env`` instead of an inline
@@ -443,8 +443,8 @@ def newkey(ctx: click.Context) -> None:
443
443
 
444
444
  config_path: str = ctx.obj["config_path"]
445
445
  old_key = _read_server_api_key(config_path)
446
- new_key = _generate_api_key()
447
- _write_server_api_key(config_path, new_key)
446
+ new_key = generate_api_key()
447
+ write_server_api_key(config_path, new_key)
448
448
 
449
449
  if old_key:
450
450
  click.echo(f"Old key (expired): {old_key}")
@@ -633,8 +633,8 @@ def configsetup_opencode(ctx: click.Context) -> None:
633
633
  key = _read_server_api_key(config_path)
634
634
  if not key:
635
635
  try:
636
- key = _generate_api_key()
637
- _write_server_api_key(config_path, key)
636
+ key = generate_api_key()
637
+ write_server_api_key(config_path, key)
638
638
  click.echo("Generated new server API key.", err=True)
639
639
  except OSError as exc:
640
640
  click.echo(
@@ -828,8 +828,8 @@ def configsetup_claude_code(ctx: click.Context) -> None:
828
828
  key = _read_server_api_key(config_path)
829
829
  if not key:
830
830
  try:
831
- key = _generate_api_key()
832
- _write_server_api_key(config_path, key)
831
+ key = generate_api_key()
832
+ write_server_api_key(config_path, key)
833
833
  click.echo("Generated new server API key.", err=True)
834
834
  except OSError as exc:
835
835
  click.echo(
@@ -1740,7 +1740,11 @@ def restart(ctx: click.Context, timeout: float) -> None:
1740
1740
  @click.option("--force", is_flag=True, help="Overwrite existing config file.")
1741
1741
  @click.pass_context
1742
1742
  def init_config(ctx: click.Context, target: str | None, force: bool) -> None:
1743
- """Write config.example.toml into the current directory (or TARGET)."""
1743
+ """Write config.example.toml into the current directory (or TARGET).
1744
+
1745
+ For fresh installs, prefer 'eggpool onboard' which handles
1746
+ config creation, API key generation, and provider setup.
1747
+ """
1744
1748
  from importlib.resources import as_file, files
1745
1749
 
1746
1750
  ref = files("eggpool._share").joinpath("config.example.toml")
@@ -1753,7 +1757,10 @@ def init_config(ctx: click.Context, target: str | None, force: bool) -> None:
1753
1757
 
1754
1758
  if target_path.exists() and not force:
1755
1759
  click.echo(
1756
- f"Error: {target_path} already exists. Use --force to overwrite.",
1760
+ f"Warning: {target_path} already exists.\n"
1761
+ "This will overwrite your configuration.\n"
1762
+ "For a fresh config, use --force.\n"
1763
+ "For provider setup, use 'eggpool onboard' instead.",
1757
1764
  err=True,
1758
1765
  )
1759
1766
  sys.exit(1)
@@ -54,15 +54,63 @@ def _prompt_add_another() -> bool:
54
54
  return _prompt_yn("Add another provider?")
55
55
 
56
56
 
57
+ def _ensure_config_with_api_key(config_path: str) -> None:
58
+ """Create config if missing and ensure a server API key exists.
59
+
60
+ This is called at the start of onboarding so fresh installs get a
61
+ working config with a real API key before any provider is connected.
62
+ """
63
+ from pathlib import Path
64
+
65
+ path = Path(config_path)
66
+
67
+ if not path.exists():
68
+ minimal = (
69
+ "[server]\n"
70
+ 'host = "0.0.0.0"\n'
71
+ "port = 11300\n"
72
+ 'log_level = "INFO"\n'
73
+ "\n"
74
+ "[database]\n"
75
+ 'path = "usage.sqlite3"\n'
76
+ "\n"
77
+ "[models]\n"
78
+ "refresh_interval_s = 300\n"
79
+ )
80
+ path.write_text(minimal, encoding="utf-8")
81
+ sys.stdout.write(f" Created {config_path}\n")
82
+
83
+ # Generate a server API key if one doesn't exist
84
+ import tomllib
85
+
86
+ with open(path, "rb") as f:
87
+ raw = tomllib.load(f)
88
+
89
+ server = raw.get("server", {})
90
+ existing_key = server.get("api_key", "")
91
+
92
+ if not existing_key:
93
+ from eggpool.cli import generate_api_key, write_server_api_key
94
+
95
+ new_key = generate_api_key()
96
+ write_server_api_key(config_path, new_key)
97
+ sys.stdout.write(" Generated server API key\n")
98
+
99
+
57
100
  def run_onboarding(config_path: str, providers_path: str | None = None) -> None:
58
101
  """Run the interactive onboarding flow.
59
102
 
60
- 1. Loop: connect a provider, ask if they want another
61
- 2. Run check-config
62
- 3. Start the server (if not already running)
103
+ 1. Ensure config exists with a server API key
104
+ 2. Loop: connect a provider, ask if they want another
105
+ 3. Run check-config
106
+ 4. Start the server (if not already running)
63
107
  """
64
108
  sys.stdout.write("\n=== EggPool Onboarding ===\n\n")
65
109
 
110
+ # Ensure we have a config file with a server API key
111
+ sys.stdout.write("--- Setting Up Configuration ---\n")
112
+ _ensure_config_with_api_key(config_path)
113
+
66
114
  from eggpool.providers.connect import connect as do_connect
67
115
 
68
116
  # Interactive provider connection loop
@@ -196,7 +196,7 @@ wheels = [
196
196
 
197
197
  [[package]]
198
198
  name = "eggpool"
199
- version = "0.1.2"
199
+ version = "0.1.3"
200
200
  source = { editable = "." }
201
201
  dependencies = [
202
202
  { name = "aiosqlite" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes