build / build (push) Successful in 2m34s
- New internal/stats (types) and internal/store (SQLite owner: requests + credentials tables, WAL); store implements stats.Recorder. - Stream (SSE tee) and non-stream chat paths parse upstream usage incl. cached_tokens and record per-request; add /api/stats, /api/stats/reset, /admin/stats HTML with cache hit rate. - Drop credentials.json: remove auth file I/O and ZHANLU_CREDENTIALS_FILE; credential precedence is env vars > db row.
38 lines
927 B
Go
38 lines
927 B
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
|
|
"git.misaka.ren/M1saka/zhanlu_proxy/internal/config"
|
|
"git.misaka.ren/M1saka/zhanlu_proxy/internal/server"
|
|
"git.misaka.ren/M1saka/zhanlu_proxy/internal/store"
|
|
)
|
|
|
|
func main() {
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
st, err := store.Open(cfg.DBPath)
|
|
if err != nil {
|
|
log.Fatalf("open store: %v", err)
|
|
}
|
|
defer st.Close()
|
|
|
|
// Credential precedence at startup: environment variables > db row.
|
|
if cfg.Credentials.Validate() != nil && !cfg.Credentials.HasAPIKey() {
|
|
if dbCreds, derr := st.LoadCredentials(); derr == nil && (dbCreds.HasAPIKey() || dbCreds.Validate() == nil) {
|
|
cfg.Credentials = dbCreds
|
|
}
|
|
}
|
|
|
|
h := server.New(cfg, st)
|
|
log.Printf("zhanlu proxy listening on %s", cfg.ListenAddr)
|
|
log.Printf("login page: http://127.0.0.1%s/login", cfg.ListenAddr)
|
|
if err := http.ListenAndServe(cfg.ListenAddr, h); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|