forked from diillson/chatcli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
148 lines (125 loc) · 3.92 KB
/
main.go
File metadata and controls
148 lines (125 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* ChatCLI - Command Line Interface for LLM interaction
* Copyright (c) 2024 Edilson Freitas
* License: MIT
*/
package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/diillson/chatcli/cli"
"github.com/diillson/chatcli/config"
"github.com/diillson/chatcli/llm/manager"
"github.com/diillson/chatcli/utils"
"github.com/diillson/chatcli/version"
"github.com/joho/godotenv"
"go.uber.org/zap"
)
func main() {
// Parse das flags
args := cli.PreprocessArgs(os.Args[1:])
opts, err := cli.Parse(args)
if err != nil {
fmt.Println(err)
os.Exit(2)
}
// Saída antecipada para --version
if opts.Version {
versionInfo := version.GetCurrentVersion()
// Checagem com timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
latest, hasUpdate, err := version.CheckLatestVersionWithContext(ctx)
fmt.Println(version.FormatVersionInfo(versionInfo, latest, hasUpdate, err))
return
}
// Mensagem de versão no startup
//version.PrintStartupVersionInfo()
// Carregar variáveis de ambiente do arquivo .env
envFilePath := os.Getenv("CHATCLI_DOTENV")
if envFilePath == "" {
envFilePath = ".env"
} else {
expanded, err := utils.ExpandPath(envFilePath)
if err == nil {
envFilePath = expanded
} else {
fmt.Printf("Aviso: não foi possível expandir o caminho '%s': %v\n", envFilePath, err)
}
}
if err := godotenv.Load(envFilePath); err != nil && !os.IsNotExist(err) {
fmt.Printf("Não foi encontrado o arquivo .env em %s\n", envFilePath)
}
// Inicializar o logger
logger, err := utils.InitializeLogger()
if err != nil {
fmt.Printf("Não foi possível inicializar o logger: %v\n", err)
os.Exit(1) // Encerrar a aplicação em caso de erro crítico
}
utils.LogStartupInfo(logger)
defer func() {
if err := logger.Sync(); err != nil {
fmt.Printf("Erro ao fechar logger: %v\n", err)
}
}()
// Configurar o contexto para o shutdown gracioso
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Verificar variáveis de ambiente e informar o usuário
utils.CheckEnvVariables(logger)
// Inicializar o LLMManager com as constantes do pacote config
slugName := utils.GetEnvOrDefault("SLUG_NAME", config.DefaultSlugName)
tenantName := utils.GetEnvOrDefault("TENANT_NAME", config.DefaultTenantName)
llmManager, err := manager.NewLLMManager(logger, slugName, tenantName)
if err != nil {
logger.Fatal("Erro ao inicializar o LLMManager", zap.Error(err))
}
// Verificar se há provedores disponíveis
availableProviders := llmManager.GetAvailableProviders()
if len(availableProviders) == 0 {
fmt.Println("Nenhum provedor LLM está configurado. Verifique suas variáveis de ambiente.")
os.Exit(1)
}
// Inicializar e iniciar o ChatCLI
chatCLI, err := cli.NewChatCLI(llmManager, logger)
if err != nil {
logger.Fatal("Erro ao inicializar o ChatCLI", zap.Error(err))
}
// Configurar manipulador de sinais DEPOIS de criar chatCLI
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT)
go func() {
for range sigChan {
// Este é o truque: verificamos se está executando
if chatCLI.IsExecuting() {
logger.Info("Cancelando operação em andamento")
chatCLI.CancelOperation()
// NÃO sair do programa, apenas cancelar a operação
} else {
logger.Info("Encerrando aplicação")
os.Exit(0)
}
}
}()
// Modo one-shot: se acionado, tratar e sair
if chatCLI.HandleOneShotOrFatal(ctx, opts) {
return
}
handleGracefulShutdown(cancel, logger)
// Caso não for oneshot, segue no modo interativo
chatCLI.Start(ctx)
}
func handleGracefulShutdown(cancelFunc context.CancelFunc, logger *zap.Logger) {
signals := make(chan os.Signal, 1)
// Capturar sinais de interrupção e término
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
go func() {
sig := <-signals
logger.Info("Recebido sinal para finalizar a aplicação", zap.String("sinal", sig.String()))
cancelFunc()
}()
}