fastapi-startkit 0.40.1__tar.gz → 0.42.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.1 → fastapi_startkit-0.42.0}/PKG-INFO +1 -1
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/pyproject.toml +1 -1
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/manager.py +1 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/__init__.py +7 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/adapters/__init__.py +7 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/adapters/base.py +57 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/adapters/claude.py +91 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/adapters/gemini.py +110 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/commands/__init__.py +5 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/commands/skills.py +80 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/parser.py +74 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/provider.py +17 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/registry.py +158 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/database/SKILL.md +107 -0
- fastapi_startkit-0.42.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +109 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/.DS_Store +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/agent.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/audio.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/audio_factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/decorators.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/document.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/image.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/image_factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/providers/ai_provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/ai/response.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/application.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/auth.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/channels.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/drivers/log_driver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/drivers/reverb_driver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/event.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/helpers.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/manager.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/reverb/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/reverb/channel_manager.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/reverb/connection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/reverb/server.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/stubs/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/broadcasting/stubs/channels.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/carbon/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/carbon/carbon.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/config/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/config/app.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/Configuration.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/helpers.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/configuration/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/application.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/can_override_config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/can_override_default_options.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/command.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/console/publish_command.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/container/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/container/container.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/environment/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/environment/environment.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/exceptions/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/exceptions/exceptions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/exceptions/handler.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/AI.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/AI.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Cache.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Config.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Dump.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Dump.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Facade.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Gate.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Gate.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Hash.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Hash.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Loader.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Loader.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Mail.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Mail.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Notification.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Notification.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Queue.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Queue.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/RateLimiter.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/RateLimiter.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Request.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Request.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Response.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Response.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Session.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Session.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Url.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Url.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/View.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/View.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Vite.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/Vite.pyi +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/facades/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/commands/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/commands/serve_command.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/config/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/config/fastapi.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/exceptions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/providers/fastapi_provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/requests/model.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/routers/router.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/fastapi/testing/test_case.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/helpers/app.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/helpers/dataclass.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/constant.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/context.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/inertia.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/middleware.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/props/props.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/inertia/provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/jsonapi/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/jsonapi/response.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/loader/Loader.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/loader/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/ChannelFactory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/BaseChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/DailyChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/MultiBaseChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/SingleChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/SlackChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/StackChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/SyslogChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/TerminalChannel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/channels/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/config/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/config/channels.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/config/logging.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/BaseDriver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/LogSingleDriver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/LogSlackDriver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/LogSyslogDriver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/LogTerminalDriver.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/file.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/handler.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/listeners.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/logger.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/managers/LoggingManager.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/managers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/logging/providers/log_provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/collection/Collection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/collection/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/DBMigrateCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/DBSeedCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MakeMigrationCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelDocstringCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MakeObserverCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MakeSeedCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MigrateFreshCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MigrateResetCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/MigrateStatusCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/ShellCommand.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_migration.stub +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_seed.stub +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/stubs/model.stub +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/stubs/observer.stub +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/commands/stubs/table_migration.stub +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/config/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/config/config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/config/database.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/connection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/mysql_connection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/connections/sqlite_connection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/exceptions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/expressions/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/expressions/expressions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/facades/DB.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/facades/Schema.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/facades/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/factory/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/factory/factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/helpers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/helpers/misc.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/migrations/Migration.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/migrations/Migrator.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/migrations/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/MigrationModel.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/attribute.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/caster.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/fields.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/model.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/observer.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/pivot.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/registry.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/models/relationship.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/observers/ObservesEvents.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/observers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/pagination/BasePaginator.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/pagination/SimplePaginator.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/pagination/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/providers/DatabaseProvider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/EagerLoadMixin.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/EagerRelation.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/BaseGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/PostgresGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/grammars/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/processors/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/query/support.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/BaseRelationship.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsTo.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsToMany.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/HasMany.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/HasManyThrough.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/HasOne.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/HasOneThrough.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/MorphMany.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/MorphOne.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/MorphToMany.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/relationships/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/Blueprint.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/Column.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/ColumnDiff.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/Constraint.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/Index.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/Table.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/TableDiff.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MSSQLPlatform.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MySQLPlatform.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/Platform.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/PostgresPlatform.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/platforms/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/schema/schema.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/seeds/Seeder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/seeds/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/stubs/create-migration.html +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/stubs/table-migration.html +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm/testing/transaction.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/.gitignore +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/CACHEDIR.TAG +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/README.md +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/lastfailed +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/nodeids +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/config/database.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/config.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/exceptions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/factories/Factory.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/factories/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/schema/Schema.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/BaseScope.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeleteScope.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeletesMixin.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyMixin.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyScope.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/scopes/scope.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/testing/BaseTestCaseSelectGrammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/testing/Database.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/testing/TestCase.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/User.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/connections/test_base_connections.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/eagers/test_eager.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/models/test_models.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder_relationships.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_qmark.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_select_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_update_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_mysql_builder_transaction.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder_scopes.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_transactions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/connections/test_mysql_connection_selects.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_qmark.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_select_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_update_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_accessors_and_mutators.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_model.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_belongs_to_many.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_many_through.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_one_through.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_relationships.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_global_scopes.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_scopes.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_soft_delete.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_query_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_transaction.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_delete_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_insert_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_select_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_update_grammar.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/relationships/test_postgres_relationships.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/scopes/test_default_global_scopes.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/seeds/test_seeds.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/masoniteorm.backup/tests/utils.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/argument.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/prompt.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/protocol.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/providers/mcp_provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/request.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/resource.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/response.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/server.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/mcp/tool.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/process/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/process/exception.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/process/fake.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/process/process.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/process/result.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/providers/Provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/providers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/providers/app_provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/config/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/config/storage.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/data/mime.types +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/drivers/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/drivers/fake.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/drivers/local.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/drivers/s3.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/file.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/filestream.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/helper.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/providers/provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/storage/storage.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/support/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/support/collection.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/support/string.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/testing/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/testing/test_case.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/utils/structures.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/__init__.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/config/vite.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/exceptions.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/providers/provider.py +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/package.json +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/resources/css/app.css +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/resources/js/app.ts +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/templates/index.html +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/tsconfig.json +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/stubs/vite.config.ts +0 -0
- {fastapi_startkit-0.40.1 → fastapi_startkit-0.42.0}/src/fastapi_startkit/vite/vite.py +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""BaseAdapter — abstract base class for all skill adapters.
|
|
2
|
+
|
|
3
|
+
New adapters (e.g. Codex) only need to subclass :class:`BaseAdapter` and
|
|
4
|
+
implement :meth:`render` and :meth:`prune`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Callable, Sequence
|
|
12
|
+
|
|
13
|
+
from fastapi_startkit.skills.registry import Skill
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseAdapter(ABC):
|
|
17
|
+
"""Abstract base for skill adapters.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
base_path:
|
|
22
|
+
Root of the project (where ``.claude/``, ``GEMINI.md``, etc. live).
|
|
23
|
+
Defaults to the current working directory.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
#: Short identifier shown in CLI output (e.g. "claude", "gemini").
|
|
27
|
+
name: str = ""
|
|
28
|
+
|
|
29
|
+
def __init__(self, base_path: Path | str | None = None) -> None:
|
|
30
|
+
self.base_path = Path(base_path) if base_path else Path.cwd()
|
|
31
|
+
|
|
32
|
+
# ------------------------------------------------------------------
|
|
33
|
+
# Abstract interface
|
|
34
|
+
# ------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def render(
|
|
38
|
+
self,
|
|
39
|
+
skills: Sequence[Skill],
|
|
40
|
+
force: bool = False,
|
|
41
|
+
confirm: Callable[..., bool] | None = None,
|
|
42
|
+
) -> list[str]:
|
|
43
|
+
"""Write *skills* to the target format.
|
|
44
|
+
|
|
45
|
+
Existing files are preserved unless *force* is true or *confirm*
|
|
46
|
+
returns true for the overwrite prompt — mirroring ``provider:publish``.
|
|
47
|
+
|
|
48
|
+
Returns a list of human-readable lines describing what was written
|
|
49
|
+
(suitable for printing in the ``ai:skills`` command).
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def prune(self, skills: Sequence[Skill]) -> list[str]:
|
|
54
|
+
"""Remove previously-synced skills that are *not* in *skills*.
|
|
55
|
+
|
|
56
|
+
Returns a list of human-readable lines describing what was removed.
|
|
57
|
+
"""
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""ClaudeAdapter — renders skills into ``.claude/skills/<name>/SKILL.md``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Callable, Sequence
|
|
7
|
+
|
|
8
|
+
from fastapi_startkit.skills.registry import Skill
|
|
9
|
+
from .base import BaseAdapter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ClaudeAdapter(BaseAdapter):
|
|
13
|
+
"""Writes canonical skills into Claude Code's skill directory.
|
|
14
|
+
|
|
15
|
+
Each skill is rendered as ``.claude/skills/<skill-name>/SKILL.md`` with a
|
|
16
|
+
YAML front-matter block followed by the original body. Publishing follows
|
|
17
|
+
the same rules as ``provider:publish``: a missing file is written, an
|
|
18
|
+
existing file is left untouched unless ``force`` is set or the caller
|
|
19
|
+
confirms the overwrite.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
name = "claude"
|
|
23
|
+
|
|
24
|
+
# ------------------------------------------------------------------
|
|
25
|
+
# Public API
|
|
26
|
+
# ------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
def render(
|
|
29
|
+
self,
|
|
30
|
+
skills: Sequence[Skill],
|
|
31
|
+
force: bool = False,
|
|
32
|
+
confirm: Callable[..., bool] | None = None,
|
|
33
|
+
) -> list[str]:
|
|
34
|
+
messages: list[str] = []
|
|
35
|
+
for skill in skills:
|
|
36
|
+
dest = self._skill_path(skill.name)
|
|
37
|
+
rel = f".claude/skills/{skill.name}/SKILL.md"
|
|
38
|
+
content = self._build_content(skill)
|
|
39
|
+
|
|
40
|
+
if dest.exists() and not force:
|
|
41
|
+
if not self._confirm_overwrite(confirm, rel):
|
|
42
|
+
messages.append(f"[claude] Skipped <comment>{rel}</comment> (already exists)")
|
|
43
|
+
continue
|
|
44
|
+
verb = "Overwrote"
|
|
45
|
+
else:
|
|
46
|
+
verb = "Overwrote" if dest.exists() else "Published"
|
|
47
|
+
|
|
48
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
dest.write_text(content, encoding="utf-8")
|
|
50
|
+
messages.append(f"[claude] {verb} <info>{rel}</info>")
|
|
51
|
+
return messages
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def _confirm_overwrite(confirm: Callable[..., bool] | None, rel: str) -> bool:
|
|
55
|
+
"""Ask the caller whether to overwrite *rel*; default to no."""
|
|
56
|
+
if confirm is None:
|
|
57
|
+
return False
|
|
58
|
+
return bool(confirm(f" <comment>{rel}</comment> already exists. Overwrite?", default=False))
|
|
59
|
+
|
|
60
|
+
def prune(self, skills: Sequence[Skill]) -> list[str]:
|
|
61
|
+
"""Remove ``.claude/skills/<name>/`` dirs not represented in *skills*."""
|
|
62
|
+
messages: list[str] = []
|
|
63
|
+
known_names = {s.name for s in skills}
|
|
64
|
+
skills_root = self.base_path / ".claude" / "skills"
|
|
65
|
+
if not skills_root.is_dir():
|
|
66
|
+
return messages
|
|
67
|
+
|
|
68
|
+
for child in sorted(skills_root.iterdir()):
|
|
69
|
+
if child.is_dir() and child.name not in known_names:
|
|
70
|
+
import shutil
|
|
71
|
+
|
|
72
|
+
shutil.rmtree(child)
|
|
73
|
+
messages.append(f"[claude] Pruned .claude/skills/{child.name}/")
|
|
74
|
+
return messages
|
|
75
|
+
|
|
76
|
+
# ------------------------------------------------------------------
|
|
77
|
+
# Internal helpers
|
|
78
|
+
# ------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
def _skill_path(self, skill_name: str) -> Path:
|
|
81
|
+
return self.base_path / ".claude" / "skills" / skill_name / "SKILL.md"
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def _build_content(skill: Skill) -> str:
|
|
85
|
+
"""Render the SKILL.md content for *skill*."""
|
|
86
|
+
lines = ["---", f"name: {skill.name}", f"description: {skill.description}", "---"]
|
|
87
|
+
if skill.body:
|
|
88
|
+
lines.append("")
|
|
89
|
+
lines.append(skill.body)
|
|
90
|
+
lines.append("")
|
|
91
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""GeminiAdapter — renders skills into ``GEMINI.md`` via marker blocks.
|
|
2
|
+
|
|
3
|
+
The adapter manages only the region of ``GEMINI.md`` that lies between the
|
|
4
|
+
``<!-- skills:start -->`` and ``<!-- skills:end -->`` markers. Content
|
|
5
|
+
outside those markers is **never** modified, making the adapter safe to use
|
|
6
|
+
even when the user has hand-edited the rest of the file.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Callable, Sequence
|
|
13
|
+
|
|
14
|
+
from fastapi_startkit.skills.registry import Skill
|
|
15
|
+
from .base import BaseAdapter
|
|
16
|
+
|
|
17
|
+
_MARKER_START = "<!-- skills:start -->"
|
|
18
|
+
_MARKER_END = "<!-- skills:end -->"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class GeminiAdapter(BaseAdapter):
|
|
22
|
+
"""Writes canonical skills into ``GEMINI.md`` with HTML comment markers.
|
|
23
|
+
|
|
24
|
+
If ``GEMINI.md`` does not exist it is created from scratch. If it exists
|
|
25
|
+
the content between the markers is replaced; everything outside is left
|
|
26
|
+
unchanged. The write is idempotent.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
name = "gemini"
|
|
30
|
+
|
|
31
|
+
# ------------------------------------------------------------------
|
|
32
|
+
# Public API
|
|
33
|
+
# ------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
def render(
|
|
36
|
+
self,
|
|
37
|
+
skills: Sequence[Skill],
|
|
38
|
+
force: bool = False,
|
|
39
|
+
confirm: Callable[..., bool] | None = None,
|
|
40
|
+
) -> list[str]:
|
|
41
|
+
# GEMINI.md edits are confined to the skills marker block, so user
|
|
42
|
+
# content is never clobbered — force/confirm are accepted for a uniform
|
|
43
|
+
# adapter interface but the block is always kept in sync.
|
|
44
|
+
gemini_md = self.base_path / "GEMINI.md"
|
|
45
|
+
new_section = self._build_section(skills)
|
|
46
|
+
changed = self._update_file(gemini_md, new_section)
|
|
47
|
+
verb = "Updated" if changed else "Unchanged"
|
|
48
|
+
return [f"[gemini] {verb} <info>GEMINI.md</info> ({len(skills)} skill(s))"]
|
|
49
|
+
|
|
50
|
+
def prune(self, skills: Sequence[Skill]) -> list[str]:
|
|
51
|
+
"""For Gemini, pruning just re-renders with the current skill list.
|
|
52
|
+
|
|
53
|
+
Since everything lives in a single file within a marked block,
|
|
54
|
+
rendering the new (shorter) list is equivalent to pruning.
|
|
55
|
+
"""
|
|
56
|
+
return self.render(skills)
|
|
57
|
+
|
|
58
|
+
# ------------------------------------------------------------------
|
|
59
|
+
# Internal helpers
|
|
60
|
+
# ------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
def _build_section(self, skills: Sequence[Skill]) -> str:
|
|
63
|
+
"""Return the full marker block to inject into GEMINI.md."""
|
|
64
|
+
parts = [_MARKER_START]
|
|
65
|
+
for skill in skills:
|
|
66
|
+
parts.append(f"\n## {skill.name}\n")
|
|
67
|
+
if skill.description:
|
|
68
|
+
parts.append(f"{skill.description}\n")
|
|
69
|
+
if skill.body:
|
|
70
|
+
parts.append(f"\n{skill.body}\n")
|
|
71
|
+
parts.append(_MARKER_END)
|
|
72
|
+
return "\n".join(parts)
|
|
73
|
+
|
|
74
|
+
def _update_file(self, path: Path, section: str) -> bool:
|
|
75
|
+
"""Inject *section* into *path*, preserving content outside markers.
|
|
76
|
+
|
|
77
|
+
Returns *True* when the file was (re)written, *False* when unchanged.
|
|
78
|
+
"""
|
|
79
|
+
if path.exists():
|
|
80
|
+
original = path.read_text(encoding="utf-8")
|
|
81
|
+
else:
|
|
82
|
+
original = ""
|
|
83
|
+
|
|
84
|
+
new_content = self._splice(original, section)
|
|
85
|
+
|
|
86
|
+
if original == new_content:
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
path.write_text(new_content, encoding="utf-8")
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def _splice(original: str, section: str) -> str:
|
|
95
|
+
"""Replace the skills block inside *original* with *section*.
|
|
96
|
+
|
|
97
|
+
If the markers do not exist yet the section is appended to the file
|
|
98
|
+
(separated by a blank line).
|
|
99
|
+
"""
|
|
100
|
+
start_idx = original.find(_MARKER_START)
|
|
101
|
+
end_idx = original.find(_MARKER_END)
|
|
102
|
+
|
|
103
|
+
if start_idx != -1 and end_idx != -1 and end_idx > start_idx:
|
|
104
|
+
before = original[:start_idx]
|
|
105
|
+
after = original[end_idx + len(_MARKER_END) :]
|
|
106
|
+
return before + section + after
|
|
107
|
+
else:
|
|
108
|
+
# No markers yet — append
|
|
109
|
+
separator = "\n\n" if original and not original.endswith("\n\n") else ""
|
|
110
|
+
return original + separator + section + "\n"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""ai:skills — list or sync provider-declared AI skills.
|
|
2
|
+
|
|
3
|
+
Examples::
|
|
4
|
+
|
|
5
|
+
artisan ai:skills --list
|
|
6
|
+
artisan ai:skills --sync
|
|
7
|
+
artisan ai:skills --sync --target=claude --prune
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from cleo.helpers import option
|
|
13
|
+
|
|
14
|
+
from fastapi_startkit.console import Command
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SkillsCommand(Command):
|
|
18
|
+
name = "ai:skills"
|
|
19
|
+
description = "List or sync provider-declared AI skills."
|
|
20
|
+
|
|
21
|
+
options = [
|
|
22
|
+
option("list", "l", flag=True, description="List providers that declare skills (default)."),
|
|
23
|
+
option("sync", "s", flag=True, description="Publish skills and sync them to AI agents."),
|
|
24
|
+
option(
|
|
25
|
+
"target",
|
|
26
|
+
"t",
|
|
27
|
+
flag=False,
|
|
28
|
+
description="Sync target: claude | gemini | all. Prompts if omitted.",
|
|
29
|
+
),
|
|
30
|
+
option(
|
|
31
|
+
"prune",
|
|
32
|
+
None,
|
|
33
|
+
flag=True,
|
|
34
|
+
description="Remove skill files no longer declared by any provider.",
|
|
35
|
+
),
|
|
36
|
+
option(
|
|
37
|
+
"force",
|
|
38
|
+
"f",
|
|
39
|
+
flag=True,
|
|
40
|
+
description="Overwrite existing files without prompting.",
|
|
41
|
+
),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
def handle(self) -> int:
|
|
45
|
+
from fastapi_startkit.skills.registry import SkillRegistry
|
|
46
|
+
|
|
47
|
+
registry: SkillRegistry = self.container.make("ai_skill.skills.registry")
|
|
48
|
+
|
|
49
|
+
# --target / --prune only make sense when syncing, so they imply --sync.
|
|
50
|
+
if self.option("sync") or self.option("prune") or self.option("target"):
|
|
51
|
+
return self._sync(registry)
|
|
52
|
+
|
|
53
|
+
return self._list(registry)
|
|
54
|
+
|
|
55
|
+
def _list(self, registry) -> int:
|
|
56
|
+
providers = registry.get_providers()
|
|
57
|
+
|
|
58
|
+
if providers.is_empty():
|
|
59
|
+
self.line("<comment>No skills found in any registered provider.</comment>")
|
|
60
|
+
return 0
|
|
61
|
+
|
|
62
|
+
self.info("Skill(s) found for the following provider(s):")
|
|
63
|
+
for index, provider_key in enumerate(providers, start=1):
|
|
64
|
+
self.info(f"{index}. {provider_key}")
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
def _sync(self, registry) -> int:
|
|
68
|
+
choices = ["all", "claude", "gemini"]
|
|
69
|
+
target = self.option("target")
|
|
70
|
+
if not target:
|
|
71
|
+
answer = self.choice("Which agent do you want to publish for?", choices, default=0)
|
|
72
|
+
# Interactive returns the value; non-interactive returns the default index.
|
|
73
|
+
target = choices[answer] if isinstance(answer, int) else answer
|
|
74
|
+
target = target.lower()
|
|
75
|
+
prune = bool(self.option("prune"))
|
|
76
|
+
force = bool(self.option("force"))
|
|
77
|
+
|
|
78
|
+
for message in registry.publish(target=target, prune=prune, force=force, confirm=self.confirm):
|
|
79
|
+
self.line(f" {message}")
|
|
80
|
+
return 0
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Skill:
|
|
9
|
+
name: str
|
|
10
|
+
description: str
|
|
11
|
+
path: Path
|
|
12
|
+
provider_key: str = "fastapi-startkit"
|
|
13
|
+
body: str = field(default="", repr=False)
|
|
14
|
+
metadata: dict = field(default_factory=dict, repr=False)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SkillParser:
|
|
18
|
+
"""Parses SKILL.md files into :class:`Skill` objects."""
|
|
19
|
+
|
|
20
|
+
def parse(self, path: Path, provider_key: str = "fastapi-startkit") -> "Skill | None":
|
|
21
|
+
"""Read and parse *path* into a Skill, or ``None`` if it can't be read
|
|
22
|
+
or has no name."""
|
|
23
|
+
try:
|
|
24
|
+
text = path.read_text(encoding="utf-8")
|
|
25
|
+
except OSError:
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
meta, body = self.parse_frontmatter(text)
|
|
29
|
+
name = (meta.get("name") or path.parent.name or "").strip()
|
|
30
|
+
if not name:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
description = (meta.get("description") or "").strip()
|
|
34
|
+
extra = {k: v for k, v in meta.items() if k not in ("name", "description")}
|
|
35
|
+
return Skill(
|
|
36
|
+
name=name,
|
|
37
|
+
description=description,
|
|
38
|
+
path=path,
|
|
39
|
+
provider_key=provider_key,
|
|
40
|
+
body=body.strip(),
|
|
41
|
+
metadata=extra,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def parse_frontmatter(text: str) -> tuple[dict, str]:
|
|
46
|
+
"""Split YAML front-matter from the body. Returns (meta_dict, body_str)."""
|
|
47
|
+
lines = text.splitlines(keepends=True)
|
|
48
|
+
if not lines or lines[0].strip() != "---":
|
|
49
|
+
return {}, text
|
|
50
|
+
|
|
51
|
+
end_idx = None
|
|
52
|
+
for i, line in enumerate(lines[1:], start=1):
|
|
53
|
+
if line.strip() == "---":
|
|
54
|
+
end_idx = i
|
|
55
|
+
break
|
|
56
|
+
|
|
57
|
+
if end_idx is None:
|
|
58
|
+
return {}, text
|
|
59
|
+
|
|
60
|
+
fm_text = "".join(lines[1:end_idx])
|
|
61
|
+
body = "".join(lines[end_idx + 1 :])
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
import yaml
|
|
65
|
+
|
|
66
|
+
meta = yaml.safe_load(fm_text) or {}
|
|
67
|
+
except ModuleNotFoundError:
|
|
68
|
+
meta = {}
|
|
69
|
+
for line in lines[1:end_idx]:
|
|
70
|
+
if ":" in line:
|
|
71
|
+
k, _, v = line.partition(":")
|
|
72
|
+
meta[k.strip()] = v.strip()
|
|
73
|
+
|
|
74
|
+
return meta, body
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fastapi_startkit.providers import Provider
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AISkillProvider(Provider):
|
|
7
|
+
provider_key = "ai_skill"
|
|
8
|
+
|
|
9
|
+
def register(self) -> None:
|
|
10
|
+
from fastapi_startkit.skills.registry import SkillRegistry
|
|
11
|
+
|
|
12
|
+
self.app.bind(f"{self.provider_key}.skills.registry", SkillRegistry(self.app))
|
|
13
|
+
|
|
14
|
+
def boot(self) -> None:
|
|
15
|
+
from fastapi_startkit.skills.commands import SkillsCommand
|
|
16
|
+
|
|
17
|
+
self.commands([SkillsCommand])
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""SkillRegistry — maps providers to their skill files and publishes them.
|
|
2
|
+
|
|
3
|
+
Each provider key in :attr:`SkillRegistry.skills` points at one or more
|
|
4
|
+
``SKILL.md`` destinations under ``.ai/fastapi-startkit/``. The framework ships a
|
|
5
|
+
matching stub for each at ``skills/stubs/<dest>``.
|
|
6
|
+
|
|
7
|
+
* ``get_providers()`` — registered providers that declare skills (used by list).
|
|
8
|
+
* ``publish()`` — copy stubs into the project then render to AI agents.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Callable, TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from fastapi_startkit.skills.parser import Skill, SkillParser
|
|
17
|
+
from fastapi_startkit.support.collection import collect
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from fastapi_startkit.application import Application
|
|
21
|
+
from fastapi_startkit.support.collection import Collection
|
|
22
|
+
|
|
23
|
+
__all__ = ["Skill", "SkillRegistry", "STUBS_BASE_PATH"]
|
|
24
|
+
|
|
25
|
+
#: Source location of framework-shipped skill stubs, organised by provider key:
|
|
26
|
+
#: stubs/.ai/fastapi-startkit/<provider_key>/SKILL.md
|
|
27
|
+
STUBS_BASE_PATH = Path(__file__).resolve().parent / "stubs" / ".ai" / "fastapi-startkit"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SkillRegistry:
|
|
31
|
+
skills = {
|
|
32
|
+
"fastapi": [
|
|
33
|
+
".ai/fastapi-startkit/fastapi/SKILL.md",
|
|
34
|
+
],
|
|
35
|
+
"database": [
|
|
36
|
+
".ai/fastapi-startkit/database/SKILL.md",
|
|
37
|
+
],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def __init__(self, app: "Application") -> None:
|
|
41
|
+
self.application = app
|
|
42
|
+
self.parser = SkillParser()
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def base_path(self) -> Path:
|
|
46
|
+
return Path(self.application.base_path)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def stubs_root(self) -> Path:
|
|
50
|
+
return STUBS_BASE_PATH.parent.parent # .../skills/stubs
|
|
51
|
+
|
|
52
|
+
def get_providers(self) -> "Collection":
|
|
53
|
+
"""Registered providers that declare skills (keyed by provider key)."""
|
|
54
|
+
return (
|
|
55
|
+
collect(self.application.providers)
|
|
56
|
+
.map(lambda provider: provider.provider_key)
|
|
57
|
+
.filter(lambda key: key in self.skills)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def discover(self) -> list[Skill]:
|
|
61
|
+
"""Load a Skill for every declared file of every registered provider.
|
|
62
|
+
|
|
63
|
+
Prefers the project copy under ``.ai/`` (so user edits flow through) and
|
|
64
|
+
falls back to the bundled stub when the project hasn't published it yet.
|
|
65
|
+
"""
|
|
66
|
+
skills: list[Skill] = []
|
|
67
|
+
for provider_key in self.get_providers():
|
|
68
|
+
for dest in self.skills.get(provider_key, []):
|
|
69
|
+
source = self.base_path / dest
|
|
70
|
+
if not source.is_file():
|
|
71
|
+
source = self.stubs_root / dest
|
|
72
|
+
skill = self.parser.parse(source, provider_key)
|
|
73
|
+
if skill is not None:
|
|
74
|
+
skills.append(skill)
|
|
75
|
+
|
|
76
|
+
return skills
|
|
77
|
+
|
|
78
|
+
def publish(
|
|
79
|
+
self,
|
|
80
|
+
target: str = "all",
|
|
81
|
+
prune: bool = False,
|
|
82
|
+
force: bool = False,
|
|
83
|
+
confirm: Callable[..., bool] | None = None,
|
|
84
|
+
) -> list[str]:
|
|
85
|
+
"""Copy stubs into the project, then render skills to the AI agent(s).
|
|
86
|
+
|
|
87
|
+
Existing destination files are preserved unless *force* is set or
|
|
88
|
+
*confirm* approves the overwrite — matching ``provider:publish``.
|
|
89
|
+
|
|
90
|
+
Returns human-readable log lines for the calling command to print.
|
|
91
|
+
"""
|
|
92
|
+
messages = self._publish_stubs(force=force, confirm=confirm)
|
|
93
|
+
|
|
94
|
+
skills = self.discover()
|
|
95
|
+
if not skills:
|
|
96
|
+
messages.append("<comment>No skills found in any registered provider.</comment>")
|
|
97
|
+
return messages
|
|
98
|
+
|
|
99
|
+
adapters = self._resolve_adapters(target)
|
|
100
|
+
if not adapters:
|
|
101
|
+
messages.append(f"<error>Unknown target '{target}'. Use: claude, gemini, all.</error>")
|
|
102
|
+
return messages
|
|
103
|
+
|
|
104
|
+
messages.append(f"<info>Syncing {len(skills)} skill(s) to: {target}…</info>")
|
|
105
|
+
for adapter in adapters:
|
|
106
|
+
messages.extend(adapter.render(skills, force=force, confirm=confirm))
|
|
107
|
+
if prune:
|
|
108
|
+
messages.extend(adapter.prune(skills))
|
|
109
|
+
return messages
|
|
110
|
+
|
|
111
|
+
def _publish_stubs(
|
|
112
|
+
self,
|
|
113
|
+
force: bool = False,
|
|
114
|
+
confirm: Callable[..., bool] | None = None,
|
|
115
|
+
) -> list[str]:
|
|
116
|
+
"""Copy bundled stubs into the project's ``.ai/``.
|
|
117
|
+
|
|
118
|
+
A missing file is always written. An existing file is left untouched
|
|
119
|
+
(preserving user edits) unless *force* is set or *confirm* approves the
|
|
120
|
+
overwrite — so framework stub updates can be pulled in deliberately.
|
|
121
|
+
"""
|
|
122
|
+
import shutil
|
|
123
|
+
|
|
124
|
+
messages: list[str] = []
|
|
125
|
+
for provider_key in self.get_providers():
|
|
126
|
+
for dest in self.skills.get(provider_key, []):
|
|
127
|
+
source = self.stubs_root / dest
|
|
128
|
+
if not source.is_file():
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
dest_path = self.base_path / dest
|
|
132
|
+
existed = dest_path.exists()
|
|
133
|
+
if existed and not force:
|
|
134
|
+
if confirm is None or not confirm(
|
|
135
|
+
f" <comment>{dest}</comment> already exists. Overwrite?", default=False
|
|
136
|
+
):
|
|
137
|
+
messages.append(f"Skipped <comment>{dest}</comment> (already exists)")
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
dest_path.parent.mkdir(parents=True, exist_ok=True)
|
|
141
|
+
shutil.copy2(source, dest_path)
|
|
142
|
+
verb = "Overwrote" if existed else "Published"
|
|
143
|
+
messages.append(f"{verb} <info>{dest}</info>")
|
|
144
|
+
return messages
|
|
145
|
+
|
|
146
|
+
def _resolve_adapters(self, target: str) -> list:
|
|
147
|
+
from fastapi_startkit.skills.adapters import ClaudeAdapter, GeminiAdapter
|
|
148
|
+
|
|
149
|
+
all_adapters = {
|
|
150
|
+
"claude": ClaudeAdapter,
|
|
151
|
+
"gemini": GeminiAdapter,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if target == "all":
|
|
155
|
+
return [cls(self.base_path) for cls in all_adapters.values()]
|
|
156
|
+
|
|
157
|
+
cls = all_adapters.get(target)
|
|
158
|
+
return [cls(self.base_path)] if cls else []
|