diff --git a/.gitignore b/.gitignore index 30431a17..800d9a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,4 @@ auths/* AGENTS.md CLAUDE.md *.exe -temp/* -.serena/ \ No newline at end of file +temp/* \ No newline at end of file diff --git a/internal/provider/gemini-web/auth.go b/internal/provider/gemini-web/auth.go index 05d8bd48..c10f76ee 100644 --- a/internal/provider/gemini-web/auth.go +++ b/internal/provider/gemini-web/auth.go @@ -12,6 +12,8 @@ import ( "regexp" "strings" "time" + + log "github.com/sirupsen/logrus" ) type httpOptions struct { @@ -103,7 +105,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i } trySets = append(trySets, merged) } else if verbose { - Debug("Skipping base cookies: __Secure-1PSIDTS missing") + log.Debug("Skipping base cookies: __Secure-1PSIDTS missing") } } @@ -130,7 +132,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i resp, mergedCookies, err := sendInitRequest(cookies, proxy, insecure) if err != nil { if verbose { - Warning("Failed init request: %v", err) + log.Warnf("Failed init request: %v", err) } continue } @@ -143,7 +145,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i if len(matches) >= 2 { token := matches[1] if verbose { - Success("Gemini access token acquired.") + log.Infof("Gemini access token acquired.") } return token, mergedCookies, nil } @@ -212,3 +214,27 @@ func (r *constReader) Read(p []byte) (int, error) { } func stringsReader(s string) io.Reader { return &constReader{s: s} } + +func MaskToken28(s string) string { + n := len(s) + if n == 0 { + return "" + } + if n < 20 { + return strings.Repeat("*", n) + } + midStart := n/2 - 2 + if midStart < 8 { + midStart = 8 + } + if midStart+4 > n-8 { + midStart = n - 8 - 4 + if midStart < 8 { + midStart = 8 + } + } + prefixByte := s[:8] + middle := s[midStart : midStart+4] + suffix := s[n-8:] + return prefixByte + strings.Repeat("*", 4) + middle + strings.Repeat("*", 4) + suffix +} diff --git a/internal/provider/gemini-web/client.go b/internal/provider/gemini-web/client.go index 8f84eaa3..829f21ee 100644 --- a/internal/provider/gemini-web/client.go +++ b/internal/provider/gemini-web/client.go @@ -10,6 +10,8 @@ import ( "regexp" "strings" "time" + + log "github.com/sirupsen/logrus" ) // GeminiClient is the async http client interface (Go port) @@ -79,7 +81,7 @@ func (c *GeminiClient) Init(timeoutSec float64, verbose bool) error { c.Timeout = time.Duration(timeoutSec * float64(time.Second)) if verbose { - Success("Gemini client initialized successfully.") + log.Infof("Gemini client initialized successfully.") } return nil } diff --git a/internal/provider/gemini-web/logging.go b/internal/provider/gemini-web/logging.go deleted file mode 100644 index fe892d90..00000000 --- a/internal/provider/gemini-web/logging.go +++ /dev/null @@ -1,131 +0,0 @@ -package geminiwebapi - -import ( - "fmt" - "os" - "strings" - - log "github.com/sirupsen/logrus" -) - -// init honors GEMINI_WEBAPI_LOG to keep parity with the Python client. -func init() { - if lvl := os.Getenv("GEMINI_WEBAPI_LOG"); lvl != "" { - SetLogLevel(lvl) - } -} - -// SetLogLevel adjusts logging verbosity using CLI-style strings. -func SetLogLevel(level string) { - switch strings.ToUpper(level) { - case "TRACE": - log.SetLevel(log.TraceLevel) - case "DEBUG": - log.SetLevel(log.DebugLevel) - case "INFO": - log.SetLevel(log.InfoLevel) - case "WARNING", "WARN": - log.SetLevel(log.WarnLevel) - case "ERROR": - log.SetLevel(log.ErrorLevel) - case "CRITICAL", "FATAL": - log.SetLevel(log.FatalLevel) - default: - log.SetLevel(log.InfoLevel) - } -} - -func prefix(format string) string { return "[gemini_webapi] " + format } - -func Debug(format string, v ...any) { log.Debugf(prefix(format), v...) } - -// DebugRaw logs without the module prefix; use sparingly for messages -// that should integrate with global formatting without extra tags. -func DebugRaw(format string, v ...any) { log.Debugf(format, v...) } -func Info(format string, v ...any) { log.Infof(prefix(format), v...) } -func Warning(format string, v ...any) { log.Warnf(prefix(format), v...) } -func Error(format string, v ...any) { log.Errorf(prefix(format), v...) } -func Success(format string, v ...any) { log.Infof(prefix("SUCCESS "+format), v...) } - -// MaskToken28 returns a fixed-length (28) masked representation showing: -// first 8 chars + 8 asterisks + 4 middle chars + last 8 chars. -// If the input is shorter than 20 characters, it returns a fully masked string -// of length min(len(s), 28). -func MaskToken28(s string) string { - n := len(s) - if n == 0 { - return "" - } - if n < 20 { - return strings.Repeat("*", n) - } - // Pick 4 middle characters around the center - midStart := n/2 - 2 - if midStart < 8 { - midStart = 8 - } - if midStart+4 > n-8 { - midStart = n - 8 - 4 - if midStart < 8 { - midStart = 8 - } - } - prefixByte := s[:8] - middle := s[midStart : midStart+4] - suffix := s[n-8:] - return prefixByte + strings.Repeat("*", 4) + middle + strings.Repeat("*", 4) + suffix -} - -// BuildUpstreamRequestLog builds a compact preview string for upstream request logging. -func BuildUpstreamRequestLog(account string, contextOn bool, useTags, explicitContext bool, prompt string, filesCount int, reuse bool, metaLen int, gem *Gem) string { - var sb strings.Builder - sb.WriteString("\n\n=== GEMINI WEB UPSTREAM ===\n") - sb.WriteString(fmt.Sprintf("account: %s\n", account)) - if contextOn { - sb.WriteString("context_mode: on\n") - } else { - sb.WriteString("context_mode: off\n") - } - if reuse { - sb.WriteString("reuseIdx: 1\n") - } else { - sb.WriteString("reuseIdx: 0\n") - } - sb.WriteString(fmt.Sprintf("useTags: %t\n", useTags)) - sb.WriteString(fmt.Sprintf("metadata_len: %d\n", metaLen)) - if explicitContext { - sb.WriteString("explicit_context: true\n") - } else { - sb.WriteString("explicit_context: false\n") - } - if filesCount > 0 { - sb.WriteString(fmt.Sprintf("files: %d\n", filesCount)) - } - - if gem != nil { - sb.WriteString("gem:\n") - if gem.ID != "" { - sb.WriteString(fmt.Sprintf(" id: %s\n", gem.ID)) - } - if gem.Name != "" { - sb.WriteString(fmt.Sprintf(" name: %s\n", gem.Name)) - } - sb.WriteString(fmt.Sprintf(" predefined: %t\n", gem.Predefined)) - } else { - sb.WriteString("gem: none\n") - } - - chunks := ChunkByRunes(prompt, 4096) - preview := prompt - truncated := false - if len(chunks) > 1 { - preview = chunks[0] - truncated = true - } - sb.WriteString("prompt_preview:\n") - sb.WriteString(preview) - if truncated { - sb.WriteString("\n... [truncated]\n") - } - return sb.String() -} diff --git a/internal/provider/gemini-web/media.go b/internal/provider/gemini-web/media.go index 58651453..3c843c62 100644 --- a/internal/provider/gemini-web/media.go +++ b/internal/provider/gemini-web/media.go @@ -20,6 +20,7 @@ import ( "github.com/router-for-me/CLIProxyAPI/v6/internal/interfaces" "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" + log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -58,7 +59,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver filename = m[1] } else { if verbose { - Warning("Invalid filename: %s", filename) + log.Warnf("Invalid filename: %s", filename) } if skipInvalidFilename { return "", nil @@ -125,7 +126,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver return "", fmt.Errorf("error downloading image: %d %s", resp.StatusCode, resp.Status) } if ct := resp.Header.Get("Content-Type"); ct != "" && !strings.Contains(strings.ToLower(ct), "image") { - Warning("Content type of %s is not image, but %s.", filename, ct) + log.Warnf("Content type of %s is not image, but %s.", filename, ct) } if path == "" { path = "temp" @@ -144,7 +145,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver return "", err } if verbose { - Info("Image saved as %s", dest) + log.Infof("Image saved as %s", dest) } abspath, _ := filepath.Abs(dest) return abspath, nil