fastapi-startkit 0.40.0__tar.gz → 0.41.0__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.
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/PKG-INFO +1 -1
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/pyproject.toml +1 -1
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/__init__.py +22 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/ai/audio.py +214 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/ai/audio_factory.py +260 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/config.py +13 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/ai/document.py +139 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/ai/image.py +218 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/ai/image_factory.py +157 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/__init__.py +6 -3
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/auth.py +140 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/channels.py +8 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/drivers/log_driver.py +4 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/event.py +72 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/helpers.py +39 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/manager.py +94 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/provider.py +168 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/stubs/__init__.py +1 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/broadcasting/stubs/channels.py +35 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/__init__.py +0 -1
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/__init__.py +24 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/adapters/__init__.py +7 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/adapters/base.py +49 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/adapters/claude.py +82 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/adapters/gemini.py +102 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/commands/__init__.py +6 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/commands/list.py +73 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/commands/sync.py +91 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/provider.py +51 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/registry.py +126 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/__init__.py +8 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/adapters/__init__.py +6 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/adapters/claude.py +90 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/adapters/gemini.py +74 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/commands/__init__.py +6 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/commands/list.py +57 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/commands/sync.py +81 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/rules/registry.py +164 -0
- fastapi_startkit-0.41.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi-startkit/SKILL.md +109 -0
- fastapi_startkit-0.40.0/src/fastapi_startkit/ai/document.py +0 -43
- fastapi_startkit-0.40.0/src/fastapi_startkit/broadcasting/event.py +0 -14
- fastapi_startkit-0.40.0/src/fastapi_startkit/broadcasting/helpers.py +0 -7
- fastapi_startkit-0.40.0/src/fastapi_startkit/broadcasting/manager.py +0 -19
- fastapi_startkit-0.40.0/src/fastapi_startkit/broadcasting/provider.py +0 -21
- fastapi_startkit-0.40.0/src/fastapi_startkit/facades/Broadcast.py +0 -5
- fastapi_startkit-0.40.0/src/fastapi_startkit/facades/Broadcast.pyi +0 -15
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/.DS_Store +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/agent.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/decorators.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/providers/ai_provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/ai/response.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/application.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/drivers/reverb_driver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/reverb/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/reverb/channel_manager.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/reverb/connection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/broadcasting/reverb/server.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/carbon/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/carbon/carbon.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/config/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/config/app.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/Configuration.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/helpers.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/configuration/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/application.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/can_override_config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/can_override_default_options.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/command.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/console/publish_command.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/container/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/container/container.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/environment/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/environment/environment.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/exceptions/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/exceptions/exceptions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/exceptions/handler.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/AI.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/AI.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Cache.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Config.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Dump.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Dump.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Facade.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Gate.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Gate.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Hash.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Hash.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Loader.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Loader.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Mail.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Mail.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Notification.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Notification.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Queue.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Queue.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/RateLimiter.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/RateLimiter.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Request.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Request.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Response.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Response.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Session.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Session.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Url.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Url.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/View.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/View.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Vite.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/facades/Vite.pyi +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/commands/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/commands/serve_command.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/config/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/config/fastapi.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/exceptions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/providers/fastapi_provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/requests/model.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/routers/router.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/fastapi/testing/test_case.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/helpers/app.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/helpers/dataclass.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/constant.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/context.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/inertia.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/middleware.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/props/props.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/inertia/provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/jsonapi/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/jsonapi/response.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/loader/Loader.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/loader/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/ChannelFactory.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/BaseChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/DailyChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/MultiBaseChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/SingleChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/SlackChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/StackChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/SyslogChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/TerminalChannel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/channels/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/config/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/config/channels.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/config/logging.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/BaseDriver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/LogSingleDriver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/LogSlackDriver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/LogSyslogDriver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/LogTerminalDriver.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/factory.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/file.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/handler.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/listeners.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/logger.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/managers/LoggingManager.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/managers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/logging/providers/log_provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/collection/Collection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/collection/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/DBMigrateCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/DBSeedCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MakeMigrationCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelDocstringCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MakeObserverCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MakeSeedCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MigrateFreshCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MigrateResetCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/MigrateStatusCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/ShellCommand.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_migration.stub +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_seed.stub +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/stubs/model.stub +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/stubs/observer.stub +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/commands/stubs/table_migration.stub +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/config/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/config/config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/config/database.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/connection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/factory.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/manager.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/mysql_connection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/connections/sqlite_connection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/exceptions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/expressions/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/expressions/expressions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/facades/DB.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/facades/Schema.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/facades/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/factory/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/factory/factory.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/helpers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/helpers/misc.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/migrations/Migration.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/migrations/Migrator.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/migrations/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/MigrationModel.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/attribute.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/caster.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/fields.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/model.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/observer.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/pivot.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/registry.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/models/relationship.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/observers/ObservesEvents.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/observers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/pagination/BasePaginator.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/pagination/SimplePaginator.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/pagination/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/providers/DatabaseProvider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/EagerLoadMixin.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/EagerRelation.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/BaseGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/PostgresGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/grammars/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/processors/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/query/support.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/BaseRelationship.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsTo.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsToMany.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/HasMany.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/HasManyThrough.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/HasOne.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/HasOneThrough.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/MorphMany.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/MorphOne.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/MorphToMany.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/relationships/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/Blueprint.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/Column.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/ColumnDiff.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/Constraint.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/Index.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/Table.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/TableDiff.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MSSQLPlatform.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MySQLPlatform.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/Platform.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/PostgresPlatform.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/platforms/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/schema/schema.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/seeds/Seeder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/seeds/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/stubs/create-migration.html +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/stubs/table-migration.html +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm/testing/transaction.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/.gitignore +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/CACHEDIR.TAG +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/README.md +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/lastfailed +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/nodeids +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/config/database.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/config.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/exceptions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/factories/Factory.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/factories/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/schema/Schema.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/BaseScope.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeleteScope.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeletesMixin.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyMixin.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyScope.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/scopes/scope.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/testing/BaseTestCaseSelectGrammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/testing/Database.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/testing/TestCase.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/User.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/connections/test_base_connections.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/eagers/test_eager.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/models/test_models.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder_relationships.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_qmark.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_select_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_update_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_mysql_builder_transaction.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder_scopes.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_transactions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/connections/test_mysql_connection_selects.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_qmark.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_select_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_update_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_accessors_and_mutators.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_model.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_belongs_to_many.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_many_through.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_one_through.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_relationships.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_global_scopes.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_scopes.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_soft_delete.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_query_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_transaction.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_select_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_update_grammar.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/relationships/test_postgres_relationships.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/scopes/test_default_global_scopes.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/seeds/test_seeds.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/masoniteorm.backup/tests/utils.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/argument.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/prompt.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/protocol.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/providers/mcp_provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/request.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/resource.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/response.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/server.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/mcp/tool.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/process/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/process/exception.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/process/fake.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/process/process.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/process/result.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/providers/Provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/providers/app_provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/config/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/config/storage.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/data/mime.types +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/drivers/fake.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/drivers/local.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/drivers/s3.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/file.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/filestream.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/helper.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/providers/provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/storage/storage.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/support/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/support/collection.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/support/string.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/testing/test_case.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/utils/structures.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/__init__.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/config/vite.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/exceptions.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/providers/provider.py +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/package.json +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/resources/css/app.css +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/resources/js/app.ts +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/templates/index.html +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/tsconfig.json +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/stubs/vite.config.ts +0 -0
- {fastapi_startkit-0.40.0 → fastapi_startkit-0.41.0}/src/fastapi_startkit/vite/vite.py +0 -0
|
@@ -2,12 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Provides a LangGraph-powered declarative API for building AI agents backed
|
|
4
4
|
by Anthropic, OpenAI, or Google provider SDKs.
|
|
5
|
+
|
|
6
|
+
Also exposes a Laravel-style fluent API for image generation and text-to-speech::
|
|
7
|
+
|
|
8
|
+
from fastapi_startkit.ai import Image, Audio, Document
|
|
9
|
+
|
|
10
|
+
image = await Image.of("A donut on a counter").generate()
|
|
11
|
+
|
|
12
|
+
# With a photo attachment
|
|
13
|
+
doc = await Document.from_url("https://example.com/photo.jpg")
|
|
14
|
+
image = await Image.of("Make impressionist").attachments([doc]).generate()
|
|
15
|
+
|
|
16
|
+
audio = await Audio.of("Hello world").female().generate()
|
|
5
17
|
"""
|
|
6
18
|
|
|
7
19
|
from .agent import Agent
|
|
20
|
+
from .audio import Audio, AudioResponse
|
|
21
|
+
from .audio_factory import AudioFactory
|
|
8
22
|
from .config import AIConfig, AnthropicConfig, GoogleConfig, OpenAIConfig
|
|
9
23
|
from .decorators import max_steps, max_tokens, memory, model, provider, timeout, top_p
|
|
10
24
|
from .document import Document
|
|
25
|
+
from .image import Image, ImageResponse
|
|
26
|
+
from .image_factory import ImageFactory
|
|
11
27
|
from .providers.ai_provider import AIProvider
|
|
12
28
|
from .response import AgentResponse, AgentSnapshot
|
|
13
29
|
|
|
@@ -18,8 +34,14 @@ __all__ = [
|
|
|
18
34
|
"AIConfig",
|
|
19
35
|
"AIProvider",
|
|
20
36
|
"AnthropicConfig",
|
|
37
|
+
"Audio",
|
|
38
|
+
"AudioResponse",
|
|
39
|
+
"AudioFactory",
|
|
21
40
|
"Document",
|
|
22
41
|
"GoogleConfig",
|
|
42
|
+
"Image",
|
|
43
|
+
"ImageFactory",
|
|
44
|
+
"ImageResponse",
|
|
23
45
|
"OpenAIConfig",
|
|
24
46
|
"max_steps",
|
|
25
47
|
"max_tokens",
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Audio generation API — text-to-speech via a pluggable provider."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import uuid
|
|
7
|
+
from typing import TYPE_CHECKING, Optional
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .audio_factory import AudioFactory
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from fastapi_startkit.storage.storage import Storage
|
|
14
|
+
except Exception: # pragma: no cover
|
|
15
|
+
Storage = None # type: ignore[assignment,misc]
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from fastapi_startkit import Config
|
|
19
|
+
except Exception: # pragma: no cover
|
|
20
|
+
Config = None # type: ignore[assignment,misc]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AudioResponse:
|
|
24
|
+
"""Returned by :meth:`Audio.generate`.
|
|
25
|
+
|
|
26
|
+
Holds raw MP3 (or other format) bytes and provides async helpers to
|
|
27
|
+
persist the audio to any configured storage disk::
|
|
28
|
+
|
|
29
|
+
audio = await Audio.of("Hello world").generate()
|
|
30
|
+
|
|
31
|
+
path = await audio.store() # auto-named, private disk
|
|
32
|
+
path = await audio.storeAs("greeting.mp3") # named, private disk
|
|
33
|
+
path = await audio.storePublicly() # auto-named, public disk
|
|
34
|
+
path = await audio.storePubliclyAs("greeting.mp3")
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, data: bytes, fmt: str = "mp3"):
|
|
38
|
+
self._data = data
|
|
39
|
+
self._fmt = fmt
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def data(self) -> bytes:
|
|
43
|
+
"""Raw audio bytes."""
|
|
44
|
+
return self._data
|
|
45
|
+
|
|
46
|
+
def _auto_filename(self) -> str:
|
|
47
|
+
return f"{uuid.uuid4()}.{self._fmt}"
|
|
48
|
+
|
|
49
|
+
# ── Storage helpers ────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
async def store(self) -> str:
|
|
52
|
+
"""Save to the default private disk with an auto-generated filename."""
|
|
53
|
+
return await self._save(self._auto_filename(), disk="local")
|
|
54
|
+
|
|
55
|
+
async def storeAs(self, name: str) -> str:
|
|
56
|
+
"""Save to the default private disk with a custom filename."""
|
|
57
|
+
return await self._save(name, disk="local")
|
|
58
|
+
|
|
59
|
+
async def storePublicly(self) -> str:
|
|
60
|
+
"""Save to the public disk with an auto-generated filename."""
|
|
61
|
+
return await self._save(self._auto_filename(), disk="public")
|
|
62
|
+
|
|
63
|
+
async def storePubliclyAs(self, name: str) -> str:
|
|
64
|
+
"""Save to the public disk with a custom filename."""
|
|
65
|
+
return await self._save(name, disk="public")
|
|
66
|
+
|
|
67
|
+
# ── Internal ───────────────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
async def _save(self, name: str, disk: str = "local") -> str:
|
|
70
|
+
return await asyncio.to_thread(self._save_sync, name, disk)
|
|
71
|
+
|
|
72
|
+
def _save_sync(self, name: str, disk: str) -> str:
|
|
73
|
+
"""Try the Storage facade first; fall back to a temp file."""
|
|
74
|
+
if Storage is not None:
|
|
75
|
+
try:
|
|
76
|
+
Storage.disk(disk).put(name, self._data)
|
|
77
|
+
return name
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
import os
|
|
81
|
+
import tempfile
|
|
82
|
+
|
|
83
|
+
path = os.path.join(tempfile.gettempdir(), name)
|
|
84
|
+
with open(path, "wb") as f:
|
|
85
|
+
f.write(self._data)
|
|
86
|
+
return path
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class Audio:
|
|
90
|
+
"""Fluent builder for text-to-speech generation.
|
|
91
|
+
|
|
92
|
+
The active backend is selected from :attr:`~fastapi_startkit.ai.AIConfig.audio_provider`
|
|
93
|
+
(env: ``AI_AUDIO_PROVIDER``). Defaults to OpenAI TTS.
|
|
94
|
+
|
|
95
|
+
Usage::
|
|
96
|
+
|
|
97
|
+
audio = await Audio.of("Hello world").generate()
|
|
98
|
+
audio = await Audio.of("Hello world").female().generate()
|
|
99
|
+
audio = await Audio.of("Hello world").male().generate()
|
|
100
|
+
audio = await Audio.of("Hello world").voice("nova").generate()
|
|
101
|
+
|
|
102
|
+
Available OpenAI TTS voices: alloy, echo, fable, onyx, nova, shimmer.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
# OpenAI TTS voice presets
|
|
106
|
+
_DEFAULT_VOICE = "alloy"
|
|
107
|
+
_DEFAULT_FEMALE_VOICE = "nova"
|
|
108
|
+
_DEFAULT_MALE_VOICE = "onyx"
|
|
109
|
+
|
|
110
|
+
def __init__(self, text: str):
|
|
111
|
+
self._text = text
|
|
112
|
+
self._voice: str = self._DEFAULT_VOICE
|
|
113
|
+
self._model: str = "tts-1"
|
|
114
|
+
self._speed: float = 1.0
|
|
115
|
+
self._response_format: str = "mp3"
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def of(cls, text: str) -> "Audio":
|
|
119
|
+
"""Create an :class:`Audio` builder with the given input text."""
|
|
120
|
+
return cls(text)
|
|
121
|
+
|
|
122
|
+
# ── Modifier methods (chainable) ───────────────────────────────────────────
|
|
123
|
+
|
|
124
|
+
def female(self) -> "Audio":
|
|
125
|
+
"""Use a female voice (``nova``)."""
|
|
126
|
+
self._voice = self._DEFAULT_FEMALE_VOICE
|
|
127
|
+
return self
|
|
128
|
+
|
|
129
|
+
def male(self) -> "Audio":
|
|
130
|
+
"""Use a male voice (``onyx``)."""
|
|
131
|
+
self._voice = self._DEFAULT_MALE_VOICE
|
|
132
|
+
return self
|
|
133
|
+
|
|
134
|
+
def voice(self, name: str) -> "Audio":
|
|
135
|
+
"""Set an explicit TTS voice name.
|
|
136
|
+
|
|
137
|
+
OpenAI voices: ``alloy``, ``echo``, ``fable``, ``onyx``, ``nova``,
|
|
138
|
+
``shimmer``.
|
|
139
|
+
"""
|
|
140
|
+
self._voice = name
|
|
141
|
+
return self
|
|
142
|
+
|
|
143
|
+
def model(self, name: str) -> "Audio":
|
|
144
|
+
"""Override the TTS model (default: ``tts-1``).
|
|
145
|
+
|
|
146
|
+
Use ``tts-1-hd`` for higher quality at the cost of latency.
|
|
147
|
+
"""
|
|
148
|
+
self._model = name
|
|
149
|
+
return self
|
|
150
|
+
|
|
151
|
+
def speed(self, value: float) -> "Audio":
|
|
152
|
+
"""Set speech speed (0.25 – 4.0, default: 1.0)."""
|
|
153
|
+
self._speed = value
|
|
154
|
+
return self
|
|
155
|
+
|
|
156
|
+
def format(self, fmt: str) -> "Audio":
|
|
157
|
+
"""Set output format: ``mp3``, ``opus``, ``aac``, or ``flac``."""
|
|
158
|
+
self._response_format = fmt
|
|
159
|
+
return self
|
|
160
|
+
|
|
161
|
+
# ── Generation ─────────────────────────────────────────────────────────────
|
|
162
|
+
|
|
163
|
+
async def generate(self) -> AudioResponse:
|
|
164
|
+
"""Call the configured TTS provider and return an :class:`AudioResponse`."""
|
|
165
|
+
provider = self._resolve_provider()
|
|
166
|
+
data = await provider.synthesize(
|
|
167
|
+
text=self._text,
|
|
168
|
+
voice=self._voice,
|
|
169
|
+
model=self._model,
|
|
170
|
+
speed=self._speed,
|
|
171
|
+
fmt=self._response_format,
|
|
172
|
+
)
|
|
173
|
+
return AudioResponse(data=data, fmt=self._response_format)
|
|
174
|
+
|
|
175
|
+
# ── Internal ───────────────────────────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
def _resolve_provider(self) -> "AudioFactory":
|
|
178
|
+
from .audio_factory import ( # noqa: PLC0415
|
|
179
|
+
ElevenLabsAudioFactory,
|
|
180
|
+
GoogleAudioFactory,
|
|
181
|
+
OpenAIAudioFactory,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
provider_name = "openai"
|
|
185
|
+
api_key: Optional[str] = None
|
|
186
|
+
base_url: Optional[str] = None
|
|
187
|
+
google_key: Optional[str] = None
|
|
188
|
+
elevenlabs_key: Optional[str] = None
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
ai_config = Config.get("ai") if Config is not None else None # type: ignore[union-attr]
|
|
192
|
+
if ai_config is None:
|
|
193
|
+
raise RuntimeError("Config not available")
|
|
194
|
+
provider_name = ai_config.audio_provider
|
|
195
|
+
openai_cfg = ai_config.providers.get("openai")
|
|
196
|
+
if openai_cfg:
|
|
197
|
+
api_key = openai_cfg.key or None
|
|
198
|
+
base_url = openai_cfg.url or None
|
|
199
|
+
google_cfg = ai_config.providers.get("google")
|
|
200
|
+
if google_cfg:
|
|
201
|
+
google_key = google_cfg.key or None
|
|
202
|
+
el_cfg = ai_config.providers.get("elevenlabs")
|
|
203
|
+
if el_cfg:
|
|
204
|
+
elevenlabs_key = el_cfg.key or None
|
|
205
|
+
except Exception:
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
if provider_name == "openai":
|
|
209
|
+
return OpenAIAudioFactory(api_key=api_key, base_url=base_url)
|
|
210
|
+
if provider_name == "google":
|
|
211
|
+
return GoogleAudioFactory(api_key=google_key)
|
|
212
|
+
if provider_name == "elevenlabs":
|
|
213
|
+
return ElevenLabsAudioFactory(api_key=elevenlabs_key)
|
|
214
|
+
raise ValueError(f"Unknown audio provider: {provider_name!r}. Use 'openai', 'google', or 'elevenlabs'.")
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""Audio synthesis provider abstractions.
|
|
2
|
+
|
|
3
|
+
Providers implement the :class:`AudioFactory` ABC so that the
|
|
4
|
+
:class:`~fastapi_startkit.ai.Audio` builder is not hard-wired to a single
|
|
5
|
+
vendor. Select the active provider via ``AI_AUDIO_PROVIDER`` in your
|
|
6
|
+
``.env`` (or ``AIConfig.audio_provider``).
|
|
7
|
+
|
|
8
|
+
Supported providers
|
|
9
|
+
-------------------
|
|
10
|
+
* ``openai`` — OpenAI TTS (tts-1 / tts-1-hd) (default)
|
|
11
|
+
* ``google`` — Google Gemini TTS via the ``google-genai`` SDK
|
|
12
|
+
* ``elevenlabs`` — ElevenLabs TTS via the ``elevenlabs`` SDK
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import struct
|
|
19
|
+
from abc import ABC, abstractmethod
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AudioFactory(ABC):
|
|
23
|
+
"""Abstract base for text-to-speech backends."""
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
async def synthesize(
|
|
27
|
+
self,
|
|
28
|
+
text: str,
|
|
29
|
+
voice: str,
|
|
30
|
+
model: str,
|
|
31
|
+
speed: float,
|
|
32
|
+
fmt: str,
|
|
33
|
+
) -> bytes:
|
|
34
|
+
"""Convert *text* to speech and return raw audio bytes."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class OpenAIAudioFactory(AudioFactory):
|
|
38
|
+
"""OpenAI TTS provider using :class:`openai.AsyncOpenAI`.
|
|
39
|
+
|
|
40
|
+
Supported voices: ``alloy``, ``echo``, ``fable``, ``onyx``, ``nova``,
|
|
41
|
+
``shimmer``. Supported formats: ``mp3``, ``opus``, ``aac``, ``flac``.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, api_key: str | None = None, base_url: str | None = None):
|
|
45
|
+
self._api_key = api_key
|
|
46
|
+
self._base_url = base_url
|
|
47
|
+
|
|
48
|
+
async def synthesize(
|
|
49
|
+
self,
|
|
50
|
+
text: str,
|
|
51
|
+
voice: str,
|
|
52
|
+
model: str,
|
|
53
|
+
speed: float,
|
|
54
|
+
fmt: str,
|
|
55
|
+
) -> bytes:
|
|
56
|
+
from openai import AsyncOpenAI # noqa: PLC0415
|
|
57
|
+
|
|
58
|
+
client = AsyncOpenAI(api_key=self._api_key, base_url=self._base_url)
|
|
59
|
+
response = await client.audio.speech.create(
|
|
60
|
+
model=model,
|
|
61
|
+
voice=voice,
|
|
62
|
+
input=text,
|
|
63
|
+
speed=speed,
|
|
64
|
+
response_format=fmt,
|
|
65
|
+
)
|
|
66
|
+
return response.read()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class GoogleAudioFactory(AudioFactory):
|
|
70
|
+
"""Google Gemini TTS provider via the ``google-genai`` SDK.
|
|
71
|
+
|
|
72
|
+
Requires: ``pip install google-genai``
|
|
73
|
+
|
|
74
|
+
Configure via ``.env``::
|
|
75
|
+
|
|
76
|
+
AI_AUDIO_PROVIDER=google
|
|
77
|
+
GEMINI_API_KEY=your-key # or GOOGLE_API_KEY
|
|
78
|
+
|
|
79
|
+
Default model: ``gemini-2.5-flash-preview-tts``.
|
|
80
|
+
|
|
81
|
+
Google voice names (pass via :meth:`~fastapi_startkit.ai.Audio.voice`):
|
|
82
|
+
``Kore``, ``Aoede``, ``Puck``, ``Charon``, ``Fenrir``, ``Leda``,
|
|
83
|
+
``Orus``, ``Zephyr``.
|
|
84
|
+
|
|
85
|
+
OpenAI-compatible voice aliases are also accepted and mapped
|
|
86
|
+
automatically:
|
|
87
|
+
|
|
88
|
+
+----------+-------------+
|
|
89
|
+
| Alias | Google voice|
|
|
90
|
+
+==========+=============+
|
|
91
|
+
| nova | Aoede |
|
|
92
|
+
| alloy | Kore |
|
|
93
|
+
| echo | Charon |
|
|
94
|
+
| fable | Puck |
|
|
95
|
+
| onyx | Fenrir |
|
|
96
|
+
| shimmer | Leda |
|
|
97
|
+
+----------+-------------+
|
|
98
|
+
|
|
99
|
+
The provider returns **WAV** bytes regardless of the requested format,
|
|
100
|
+
because Gemini TTS yields raw PCM16 which is wrapped in a WAV container.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
# Map OpenAI-style voice aliases → Google Gemini voice names
|
|
104
|
+
_VOICE_MAP: dict[str, str] = {
|
|
105
|
+
"nova": "Aoede",
|
|
106
|
+
"alloy": "Kore",
|
|
107
|
+
"echo": "Charon",
|
|
108
|
+
"fable": "Puck",
|
|
109
|
+
"onyx": "Fenrir",
|
|
110
|
+
"shimmer": "Leda",
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
def __init__(self, api_key: str | None = None):
|
|
114
|
+
self._api_key = api_key
|
|
115
|
+
|
|
116
|
+
async def synthesize(
|
|
117
|
+
self,
|
|
118
|
+
text: str,
|
|
119
|
+
voice: str,
|
|
120
|
+
model: str,
|
|
121
|
+
speed: float,
|
|
122
|
+
fmt: str,
|
|
123
|
+
) -> bytes:
|
|
124
|
+
"""Synthesise *text* via Gemini TTS and return WAV bytes.
|
|
125
|
+
|
|
126
|
+
.. note::
|
|
127
|
+
The ``speed`` parameter is accepted for API compatibility but is
|
|
128
|
+
not currently supported by the Gemini TTS API.
|
|
129
|
+
"""
|
|
130
|
+
from google import genai # noqa: PLC0415
|
|
131
|
+
from google.genai import types # noqa: PLC0415
|
|
132
|
+
|
|
133
|
+
client = genai.Client(api_key=self._api_key)
|
|
134
|
+
google_voice = self._VOICE_MAP.get(voice, voice)
|
|
135
|
+
|
|
136
|
+
response = await asyncio.to_thread(
|
|
137
|
+
client.models.generate_content,
|
|
138
|
+
model=model,
|
|
139
|
+
contents=text,
|
|
140
|
+
config=types.GenerateContentConfig(
|
|
141
|
+
response_modalities=["AUDIO"],
|
|
142
|
+
speech_config=types.SpeechConfig(
|
|
143
|
+
voice_config=types.VoiceConfig(
|
|
144
|
+
prebuilt_voice_config=types.PrebuiltVoiceConfig(
|
|
145
|
+
voice_name=google_voice,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
),
|
|
149
|
+
),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Gemini TTS returns raw PCM16 samples — wrap in WAV container
|
|
153
|
+
pcm_data = response.candidates[0].content.parts[0].inline_data.data
|
|
154
|
+
return _pcm_to_wav(pcm_data)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ElevenLabsAudioFactory(AudioFactory):
|
|
158
|
+
"""ElevenLabs TTS provider via the ``elevenlabs`` SDK.
|
|
159
|
+
|
|
160
|
+
Requires: ``pip install elevenlabs``
|
|
161
|
+
|
|
162
|
+
Configure via ``.env``::
|
|
163
|
+
|
|
164
|
+
AI_AUDIO_PROVIDER=elevenlabs
|
|
165
|
+
ELEVENLABS_API_KEY=your-key
|
|
166
|
+
|
|
167
|
+
Voice names are mapped to ElevenLabs voice IDs. You can pass any
|
|
168
|
+
ElevenLabs voice ID directly via :meth:`~fastapi_startkit.ai.Audio.voice`,
|
|
169
|
+
or use one of the built-in aliases:
|
|
170
|
+
|
|
171
|
+
+----------+----------------+---------+
|
|
172
|
+
| Alias | EL Name | Gender |
|
|
173
|
+
+==========+================+=========+
|
|
174
|
+
| nova | Rachel | female |
|
|
175
|
+
| alloy | Bella | female |
|
|
176
|
+
| shimmer | Elli | female |
|
|
177
|
+
| onyx | Adam | male |
|
|
178
|
+
| echo | Antoni | male |
|
|
179
|
+
| fable | Arnold | male |
|
|
180
|
+
+----------+----------------+---------+
|
|
181
|
+
|
|
182
|
+
Default model: ``eleven_multilingual_v2``.
|
|
183
|
+
Override with :meth:`~fastapi_startkit.ai.Audio.model`.
|
|
184
|
+
|
|
185
|
+
.. note::
|
|
186
|
+
The ``speed`` parameter is accepted for API compatibility but is
|
|
187
|
+
not currently supported by ElevenLabs.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
# Map OpenAI-style aliases → ElevenLabs voice IDs
|
|
191
|
+
_VOICE_MAP: dict[str, str] = {
|
|
192
|
+
"nova": "21m00Tcm4TlvDq8ikWAM", # Rachel — female
|
|
193
|
+
"alloy": "EXAVITQu4vr4xnSDxMaL", # Bella — female
|
|
194
|
+
"shimmer": "MF3mGyEYCl7XYWbV9V6O", # Elli — female
|
|
195
|
+
"onyx": "pNInz6obpgDQGcFmaJgB", # Adam — male
|
|
196
|
+
"echo": "ErXwobaYiN019PkySvjV", # Antoni — male
|
|
197
|
+
"fable": "VR6AewLTigWG4xSOukaG", # Arnold — male
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
def __init__(self, api_key: str | None = None):
|
|
201
|
+
self._api_key = api_key
|
|
202
|
+
|
|
203
|
+
async def synthesize(
|
|
204
|
+
self,
|
|
205
|
+
text: str,
|
|
206
|
+
voice: str,
|
|
207
|
+
model: str,
|
|
208
|
+
speed: float,
|
|
209
|
+
fmt: str,
|
|
210
|
+
) -> bytes:
|
|
211
|
+
from elevenlabs.client import ElevenLabs # noqa: PLC0415
|
|
212
|
+
|
|
213
|
+
voice_id = self._VOICE_MAP.get(voice, voice)
|
|
214
|
+
client = ElevenLabs(api_key=self._api_key)
|
|
215
|
+
|
|
216
|
+
audio_chunks = await asyncio.to_thread(
|
|
217
|
+
client.text_to_speech.convert,
|
|
218
|
+
voice_id=voice_id,
|
|
219
|
+
text=text,
|
|
220
|
+
model_id=model,
|
|
221
|
+
output_format="mp3_44100_128",
|
|
222
|
+
)
|
|
223
|
+
return b"".join(audio_chunks)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# ─── PCM → WAV helper ─────────────────────────────────────────────────────────
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _pcm_to_wav(
|
|
230
|
+
pcm_data: bytes,
|
|
231
|
+
sample_rate: int = 24000,
|
|
232
|
+
channels: int = 1,
|
|
233
|
+
bit_depth: int = 16,
|
|
234
|
+
) -> bytes:
|
|
235
|
+
"""Wrap raw PCM16 samples in a minimal RIFF/WAV container.
|
|
236
|
+
|
|
237
|
+
Gemini TTS returns signed 16-bit little-endian PCM at 24 kHz mono.
|
|
238
|
+
Most audio players and APIs accept WAV, so we wrap it here.
|
|
239
|
+
"""
|
|
240
|
+
data_size = len(pcm_data)
|
|
241
|
+
byte_rate = sample_rate * channels * bit_depth // 8
|
|
242
|
+
block_align = channels * bit_depth // 8
|
|
243
|
+
|
|
244
|
+
header = struct.pack(
|
|
245
|
+
"<4sI4s4sIHHIIHH4sI",
|
|
246
|
+
b"RIFF",
|
|
247
|
+
36 + data_size,
|
|
248
|
+
b"WAVE",
|
|
249
|
+
b"fmt ",
|
|
250
|
+
16,
|
|
251
|
+
1, # PCM
|
|
252
|
+
channels,
|
|
253
|
+
sample_rate,
|
|
254
|
+
byte_rate,
|
|
255
|
+
block_align,
|
|
256
|
+
bit_depth,
|
|
257
|
+
b"data",
|
|
258
|
+
data_size,
|
|
259
|
+
)
|
|
260
|
+
return header + pcm_data
|
|
@@ -33,6 +33,14 @@ class GoogleConfig:
|
|
|
33
33
|
key: str = field(default_factory=lambda: env("GEMINI_API_KEY", "") or env("GOOGLE_API_KEY", ""))
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
@dataclass
|
|
37
|
+
class ElevenLabsConfig:
|
|
38
|
+
"""Configuration for the ElevenLabs provider."""
|
|
39
|
+
|
|
40
|
+
driver: str = "elevenlabs"
|
|
41
|
+
key: str = field(default_factory=lambda: env("ELEVENLABS_API_KEY", ""))
|
|
42
|
+
|
|
43
|
+
|
|
36
44
|
@dataclass
|
|
37
45
|
class AIConfig:
|
|
38
46
|
"""Top-level AI configuration — selects the default provider and holds per-provider configs."""
|
|
@@ -44,5 +52,10 @@ class AIConfig:
|
|
|
44
52
|
"openai": OpenAIConfig(),
|
|
45
53
|
"anthropic": AnthropicConfig(),
|
|
46
54
|
"google": GoogleConfig(),
|
|
55
|
+
"elevenlabs": ElevenLabsConfig(),
|
|
47
56
|
}
|
|
48
57
|
)
|
|
58
|
+
|
|
59
|
+
# Media-generation provider selection
|
|
60
|
+
image_provider: str = field(default_factory=lambda: env("AI_IMAGE_PROVIDER", "openai"))
|
|
61
|
+
audio_provider: str = field(default_factory=lambda: env("AI_AUDIO_PROVIDER", "openai"))
|