feat: show all accounts with full status in serve startup banner
- Startup banner now prints every account's complete status (nickname, UID, enterprise, domain, cooldown state, token validity, expiry) instead of a single-line summary - Extracted shared formatAccountStatus() used by both status command and serve startup output, keeping them consistent - Shows disabled accounts with reason and re-login hint at startup
This commit is contained in:
@@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
version = "1.4.0"
|
||||
version = "1.4.1"
|
||||
upstreamBase = "https://copilot.tencent.com"
|
||||
clientUA = "CLI/2.143.1 CodeBuddy/2.143.1"
|
||||
originReferer = "https://www.codebuddy.cn"
|
||||
@@ -778,6 +778,57 @@ func refreshTokenPayload(sa *StoredAuth) (int, error) {
|
||||
// CLI 子命令实现: login, status, refresh
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// formatAccountStatus 生成单个账号的完整状态文本(status 命令与 serve 启动横幅共用)。
|
||||
// idx 从 1 开始的账号序号;now 为当前时间(用于冷却/过期判定)。
|
||||
func formatAccountStatus(acc *Account, idx int, now time.Time) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("\n--- 账号 #%d ---\n", idx))
|
||||
sb.WriteString(fmt.Sprintf("凭据文件: %s\n", acc.Path))
|
||||
|
||||
if acc.Disabled {
|
||||
// 失效账号(Auth 可能为 nil:凭据文件已删除,信息来自失效标记)
|
||||
nickname := acc.Nickname
|
||||
uid := acc.UID
|
||||
if acc.Auth != nil {
|
||||
nickname = acc.Auth.Account.Nickname
|
||||
uid = acc.Auth.Account.UID
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("用户昵称: %s\n", ifEmpty(nickname, "(未知)")))
|
||||
sb.WriteString(fmt.Sprintf("用户 UID: %s\n", ifEmpty(uid, "(未知)")))
|
||||
sb.WriteString("账号状态: ❌ 授权失效(禁止调度)\n")
|
||||
sb.WriteString(fmt.Sprintf("失效原因: %s\n", truncate(acc.DisabledReason, 200)))
|
||||
sb.WriteString(fmt.Sprintf("处理建议: ⚠️ 凭据文件已删除,请重新执行: workbuddy-gateway login -auth %s\n", acc.Path))
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
if acc.Auth == nil {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
expTime := time.Unix(acc.Auth.Auth.ExpiresAt, 0)
|
||||
remaining := time.Until(expTime)
|
||||
statusStr := "有效"
|
||||
if remaining <= 0 {
|
||||
statusStr = "已过期"
|
||||
}
|
||||
|
||||
sb.WriteString(fmt.Sprintf("用户昵称: %s\n", acc.Auth.Account.Nickname))
|
||||
sb.WriteString(fmt.Sprintf("用户 UID: %s\n", acc.Auth.Account.UID))
|
||||
sb.WriteString(fmt.Sprintf("企业 ID: %s\n", ifEmpty(acc.Auth.Account.EnterpriseID, "(个人账号)")))
|
||||
sb.WriteString(fmt.Sprintf("认证域名: %s\n", ifEmpty(acc.Auth.Auth.Domain, "www.codebuddy.cn")))
|
||||
if acc.CooldownUntil.After(now) {
|
||||
sb.WriteString(fmt.Sprintf("冷却状态: 🔒 冷却中 (解封: %s, 剩余 %v)\n",
|
||||
acc.CooldownUntil.Format("2006-01-02 15:04:05"),
|
||||
time.Until(acc.CooldownUntil).Round(time.Minute)))
|
||||
sb.WriteString(fmt.Sprintf("冷却原因: %s\n", truncate(acc.CooldownMsg, 120)))
|
||||
} else {
|
||||
sb.WriteString("冷却状态: ✅ 可用\n")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("Token 状态: %s\n", statusStr))
|
||||
sb.WriteString(fmt.Sprintf("过期时间: %s (剩余 %v)\n", expTime.Format("2006-01-02 15:04:05"), remaining.Round(time.Minute)))
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func runStatus() {
|
||||
if err := loadAccounts(); err != nil {
|
||||
fmt.Printf("未找到有效凭据: %v\n请先执行: workbuddy-gateway login 扫码登录。\n", err)
|
||||
@@ -791,50 +842,7 @@ func runStatus() {
|
||||
fmt.Printf("账号总数: %d\n", len(accounts))
|
||||
now := time.Now()
|
||||
for i, acc := range accounts {
|
||||
fmt.Printf("\n--- 账号 #%d ---\n", i+1)
|
||||
fmt.Printf("凭据文件: %s\n", acc.Path)
|
||||
|
||||
if acc.Disabled {
|
||||
// 失效账号(Auth 可能为 nil:凭据文件已删除,信息来自失效标记)
|
||||
nickname := acc.Nickname
|
||||
uid := acc.UID
|
||||
if acc.Auth != nil {
|
||||
nickname = acc.Auth.Account.Nickname
|
||||
uid = acc.Auth.Account.UID
|
||||
}
|
||||
fmt.Printf("用户昵称: %s\n", ifEmpty(nickname, "(未知)"))
|
||||
fmt.Printf("用户 UID: %s\n", ifEmpty(uid, "(未知)"))
|
||||
fmt.Printf("账号状态: ❌ 授权失效(禁止调度)\n")
|
||||
fmt.Printf("失效原因: %s\n", truncate(acc.DisabledReason, 200))
|
||||
fmt.Printf("处理建议: ⚠️ 凭据文件已删除,请重新执行: workbuddy-gateway login -auth %s\n", acc.Path)
|
||||
continue
|
||||
}
|
||||
|
||||
if acc.Auth == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
expTime := time.Unix(acc.Auth.Auth.ExpiresAt, 0)
|
||||
remaining := time.Until(expTime)
|
||||
statusStr := "有效"
|
||||
if remaining <= 0 {
|
||||
statusStr = "已过期"
|
||||
}
|
||||
|
||||
fmt.Printf("用户昵称: %s\n", acc.Auth.Account.Nickname)
|
||||
fmt.Printf("用户 UID: %s\n", acc.Auth.Account.UID)
|
||||
fmt.Printf("企业 ID: %s\n", ifEmpty(acc.Auth.Account.EnterpriseID, "(个人账号)"))
|
||||
fmt.Printf("认证域名: %s\n", ifEmpty(acc.Auth.Auth.Domain, "www.codebuddy.cn"))
|
||||
if acc.CooldownUntil.After(now) {
|
||||
fmt.Printf("冷却状态: 🔒 冷却中 (解封: %s, 剩余 %v)\n",
|
||||
acc.CooldownUntil.Format("2006-01-02 15:04:05"),
|
||||
time.Until(acc.CooldownUntil).Round(time.Minute))
|
||||
fmt.Printf("冷却原因: %s\n", truncate(acc.CooldownMsg, 120))
|
||||
} else {
|
||||
fmt.Printf("冷却状态: ✅ 可用\n")
|
||||
}
|
||||
fmt.Printf("Token 状态: %s\n", statusStr)
|
||||
fmt.Printf("过期时间: %s (剩余 %v)\n", expTime.Format("2006-01-02 15:04:05"), remaining.Round(time.Minute))
|
||||
fmt.Print(formatAccountStatus(acc, i+1, now))
|
||||
}
|
||||
fmt.Println("\n=======================================================")
|
||||
}
|
||||
@@ -972,28 +980,13 @@ func runServe() {
|
||||
fmt.Printf("警告: 未检测到有效凭据 (%v)。\n请先执行: workbuddy-gateway login 扫码登录,或确保凭据文件存在。\n\n", err)
|
||||
} else {
|
||||
accountMu.Lock()
|
||||
accCount := len(accounts)
|
||||
activeCount := 0
|
||||
disabledCount := 0
|
||||
for _, acc := range accounts {
|
||||
if acc.Disabled || acc.Auth == nil {
|
||||
disabledCount++
|
||||
continue
|
||||
}
|
||||
activeCount++
|
||||
_ = ensureValidTokenFor(acc)
|
||||
}
|
||||
accountMu.Unlock()
|
||||
fmt.Printf("已就绪账号池: %d 个账号 (有效 %d, 失效 %d)\n", accCount, activeCount, disabledCount)
|
||||
for i, acc := range accounts {
|
||||
if acc.Disabled || acc.Auth == nil {
|
||||
fmt.Printf(" #%d ❌ %s (授权失效,凭据文件已删除,请重新登录)\n", i+1, acc.Path)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" #%d ✅ %s (UID: %s, 有效期至: %s)\n",
|
||||
i+1, acc.Auth.Account.Nickname, acc.Auth.Account.UID,
|
||||
time.Unix(acc.Auth.Auth.ExpiresAt, 0).Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
// 启动后台自动刷新协程
|
||||
@@ -1030,6 +1023,30 @@ func runServe() {
|
||||
if cfg.ProxyURL != "" {
|
||||
fmt.Printf(" 上游出口代理: %s\n", cfg.ProxyURL)
|
||||
}
|
||||
|
||||
// 启动时展示所有账号状态(与 status 命令一致)
|
||||
accountMu.Lock()
|
||||
accCount := len(accounts)
|
||||
activeCount := 0
|
||||
disabledCount := 0
|
||||
now := time.Now()
|
||||
for _, acc := range accounts {
|
||||
if acc.Disabled || acc.Auth == nil {
|
||||
disabledCount++
|
||||
} else {
|
||||
activeCount++
|
||||
}
|
||||
}
|
||||
fmt.Printf(" 账号池: %d 个账号 (有效 %d, 失效 %d)\n", accCount, activeCount, disabledCount)
|
||||
if accCount > 0 {
|
||||
fmt.Println(" ----------------------------------------------------------")
|
||||
for i, acc := range accounts {
|
||||
fmt.Print(formatAccountStatus(acc, i+1, now))
|
||||
}
|
||||
fmt.Println(" ----------------------------------------------------------")
|
||||
}
|
||||
accountMu.Unlock()
|
||||
|
||||
fmt.Println("================================================================")
|
||||
fmt.Println("等待客户端请求中 (按 Ctrl+C 安全停止)...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user