feat: integrate AI candidate review and automatic publication
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"git.sundynix.cn/Blizzard/Veyra/internal/llm"
|
||||
"git.sundynix.cn/Blizzard/Veyra/internal/logging"
|
||||
"git.sundynix.cn/Blizzard/Veyra/internal/market"
|
||||
"git.sundynix.cn/Blizzard/Veyra/internal/research"
|
||||
@@ -41,8 +42,8 @@ func main() {
|
||||
func run(ctx context.Context, args []string) (err error) {
|
||||
flags := flag.NewFlagSet("veyra", flag.ContinueOnError)
|
||||
envFile := flags.String("env-file", "configs/.env", "environment file (empty disables file loading)")
|
||||
command := flags.String("command", "serve", "serve, db-create, db-migrate, user-create, or admin-set")
|
||||
previousLogin := flags.String("previous-login", "", "current administrator login for admin-set (defaults to ADMIN_LOGIN)")
|
||||
command := flags.String("command", "serve", "serve, db-create, db-migrate, user-create, admin-set, or user-set")
|
||||
previousLogin := flags.String("previous-login", "", "current identity login for admin-set/user-set (defaults to configured login)")
|
||||
role := flags.String("role", "ADMIN", "ADMIN or USER for user-create")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return err
|
||||
@@ -51,7 +52,7 @@ func run(ctx context.Context, args []string) (err error) {
|
||||
return fmt.Errorf("unexpected positional arguments")
|
||||
}
|
||||
switch *command {
|
||||
case "serve", "db-create", "db-migrate", "user-create", "admin-set":
|
||||
case "serve", "db-create", "db-migrate", "user-create", "admin-set", "user-set":
|
||||
default:
|
||||
return fmt.Errorf("unsupported command")
|
||||
}
|
||||
@@ -79,6 +80,8 @@ func run(ctx context.Context, args []string) (err error) {
|
||||
switch *command {
|
||||
case "db-create", "db-migrate":
|
||||
return maintainDatabase(ctx, c, *command, logger)
|
||||
case "user-set":
|
||||
return setDevelopmentUser(ctx, c, *previousLogin, logger)
|
||||
case "admin-set":
|
||||
return setAdministrator(ctx, c, *previousLogin, logger)
|
||||
case "user-create":
|
||||
@@ -101,6 +104,7 @@ func serve(ctx context.Context, c config.Config, logger *zap.Logger) error {
|
||||
var backtestRepo service.BacktestRepository
|
||||
var marketRepo service.MarketRepository
|
||||
var screeningRepo service.ScreeningRepository
|
||||
var analysisRepo service.CandidateAnalysisRepository
|
||||
vault, err := secret.NewVault(c.SecretEncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -126,6 +130,7 @@ func serve(ctx context.Context, c config.Config, logger *zap.Logger) error {
|
||||
backtestRepo = repository.NewBacktestRepository(pool)
|
||||
marketRepo = repository.NewMarketRepository(pool)
|
||||
screeningRepo = repository.NewScreeningRepository(pool)
|
||||
analysisRepo = repository.NewCandidateAnalysisRepository(pool)
|
||||
}
|
||||
redisClient := redis.NewClient(&redis.Options{Addr: c.RedisAddr, Username: c.RedisUsername, Password: c.RedisPassword, DB: c.RedisDB, DialTimeout: time.Second, ReadTimeout: time.Second, WriteTimeout: time.Second, MaxRetries: -1, ContextTimeoutEnabled: true})
|
||||
defer redisClient.Close()
|
||||
@@ -137,6 +142,7 @@ func serve(ctx context.Context, c config.Config, logger *zap.Logger) error {
|
||||
development := c.Environment == "local" || c.Environment == "test"
|
||||
marketService := service.NewMarketService(marketRepo, providerRepo, market.New(), development)
|
||||
screenings := service.NewScreeningService(screeningRepo, marketService, development)
|
||||
analyses := service.NewCandidateAnalysisService(analysisRepo, providerRepo, vault, llm.New(), development)
|
||||
notifications := service.NewNotificationService(notificationRepo, development)
|
||||
backtests := service.NewBacktestService(backtestRepo, research.New(c.PythonExecutable), development, marketService)
|
||||
workerContext, workerCancel := context.WithCancel(ctx)
|
||||
@@ -148,8 +154,17 @@ func serve(ctx context.Context, c config.Config, logger *zap.Logger) error {
|
||||
go func() { defer close(marketDone); marketService.Run(workerContext, logger) }()
|
||||
screeningDone := make(chan struct{})
|
||||
go func() { defer close(screeningDone); screenings.Run(workerContext, logger) }()
|
||||
defer func() { workerCancel(); <-workerDone; <-researchDone; <-marketDone; <-screeningDone }()
|
||||
identityOptions := handler.IdentityOptions{Screenings: screenings, Market: marketService, Backtests: backtests, Strategies: service.NewStrategyService(strategyRepo, development), Notifications: notifications, Auth: auth, Fills: service.NewTradeFillService(fillRepo, development), Plans: service.NewTradePlanService(planRepo, development), Candidates: service.NewCandidateService(candidateRepo, development), Providers: service.NewProviderService(providerRepo, vault), Accounts: service.NewAccountService(accountRepo), Limiter: ratelimit.NewRedis(redisClient), DevelopmentLogin: development, SecureCookie: !development || strings.HasPrefix(c.PublicOrigin, "https://"), PublicOrigin: c.PublicOrigin}
|
||||
analysisDone := make(chan struct{})
|
||||
go func() { defer close(analysisDone); analyses.Run(workerContext, logger) }()
|
||||
defer func() {
|
||||
workerCancel()
|
||||
<-workerDone
|
||||
<-researchDone
|
||||
<-marketDone
|
||||
<-screeningDone
|
||||
<-analysisDone
|
||||
}()
|
||||
identityOptions := handler.IdentityOptions{Analyses: analyses, Screenings: screenings, Market: marketService, Backtests: backtests, Strategies: service.NewStrategyService(strategyRepo, development), Notifications: notifications, Auth: auth, Fills: service.NewTradeFillService(fillRepo, development), Plans: service.NewTradePlanService(planRepo, development), Candidates: service.NewCandidateService(candidateRepo, development), Providers: service.NewProviderService(providerRepo, vault), Accounts: service.NewAccountService(accountRepo), Limiter: ratelimit.NewRedis(redisClient), DevelopmentLogin: development, SecureCookie: !development || strings.HasPrefix(c.PublicOrigin, "https://"), PublicOrigin: c.PublicOrigin}
|
||||
server := &http.Server{Addr: c.HTTPAddr, Handler: handler.NewRouter(health, logger, identityOptions), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, MaxHeaderBytes: 1 << 20}
|
||||
result := make(chan error, 1)
|
||||
go func() { result <- server.ListenAndServe() }()
|
||||
@@ -258,3 +273,27 @@ func setAdministrator(ctx context.Context, c config.Config, previousLogin string
|
||||
logger.Info("administrator credential updated", zap.String("user_id", userID))
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDevelopmentUser(ctx context.Context, c config.Config, previousLogin string, logger *zap.Logger) error {
|
||||
if c.Environment != "local" && c.Environment != "test" {
|
||||
return fmt.Errorf("development user setup is disabled outside local/test")
|
||||
}
|
||||
login, password := os.Getenv("DEV_USER_LOGIN"), os.Getenv("DEV_USER_PASSWORD")
|
||||
if previousLogin == "" {
|
||||
previousLogin = login
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer cancel()
|
||||
pool, err := database.Open(ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pool.Close()
|
||||
updater := service.NewDevelopmentUserCredentialService(repository.NewIdentityRepository(pool), true)
|
||||
userID, err := updater.Set(ctx, previousLogin, login, password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info("development user credential updated", zap.String("user_id", userID))
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user