-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
149 lines (127 loc) · 3.67 KB
/
main.go
File metadata and controls
149 lines (127 loc) · 3.67 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
149
package main
import (
"embed"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
"io/fs"
"github.com/smallnest/langchat/pkg/chat"
)
//go:embed static
var staticFS embed.FS
// loadEnv loads environment variables from .env file if it exists
func loadEnv() {
if _, err := os.Stat(".env"); err == nil {
content, err := os.ReadFile(".env")
if err != nil {
log.Printf("Error reading .env file: %v", err)
return
}
lines := strings.SplitSeq(string(content), "\n")
for line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
os.Setenv(key, value)
}
}
}
}
func main() {
// Load environment variables from .env file
loadEnv()
// Load configuration from environment
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
sessionDir := os.Getenv("SESSION_DIR")
if sessionDir == "" {
sessionDir = "./sessions"
}
maxHistory := 50
if maxHistoryStr := os.Getenv("MAX_HISTORY_SIZE"); maxHistoryStr != "" {
if _, err := fmt.Sscanf(maxHistoryStr, "%d", &maxHistory); err != nil {
log.Printf("Warning: Failed to parse MAX_HISTORY_SIZE %q, using default 50: %v", maxHistoryStr, err)
maxHistory = 50
}
}
// Get config file path from environment or use default
configPath := os.Getenv("CONFIG_PATH")
if configPath == "" {
configPath = "configs/config.json"
}
// Create and start server
server, err := chat.NewChatServer(sessionDir, maxHistory, port, configPath)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
// Pre-warm: Initialize tools in background before server starts
// This prevents the first user from experiencing slow tool loading
log.Println("🔄 Pre-warming tools initialization...")
warmupAgent := chat.NewSimpleChatAgent(server.GetLLM(), *server.GetConfig())
warmupAgent.InitializeToolsAsync()
// Store the warmup agent so it can be reused for the first session
server.SetWarmupAgent(warmupAgent)
// Wait for tools to finish loading before starting server
go func() {
for {
// Simple check - in real implementation you might want to add a method to check status
time.Sleep(500 * time.Millisecond)
// For now, we'll just wait a bit and then show ready message
log.Printf("🚀 Server is ready! Access at http://localhost:%s", port)
break
}
}()
// Setup graceful shutdown
serverErr := make(chan error, 1)
// Use local filesystem if static directory exists (for development), otherwise use embedded
var fileSystem fs.FS = staticFS
if _, err := os.Stat("static"); err == nil {
log.Println("📂 Using local static directory")
fileSystem = os.DirFS(".")
}
go func() {
if err := server.Start(fileSystem); err != nil {
serverErr <- err
}
}()
// Wait for interrupt signal or server error
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// Block until signal received or server error
select {
case sig := <-sigChan:
log.Printf("Received shutdown signal: %v", sig)
case err := <-serverErr:
log.Printf("Server error: %v", err)
}
// Graceful shutdown with timeout
log.Println("Starting graceful shutdown...")
shutdownDone := make(chan error, 1)
go func() {
shutdownDone <- server.Close()
}()
// Wait for shutdown to complete with timeout
select {
case err := <-shutdownDone:
if err != nil {
log.Printf("Error during shutdown: %v", err)
os.Exit(1)
}
log.Println("Shutdown complete")
os.Exit(0)
case <-time.After(15 * time.Second):
log.Println("Shutdown timed out after 15 seconds, forcing exit")
os.Exit(1)
}
}