Skip to content

Commit 4935f1e

Browse files
author
joo
committed
fix: align usage query formatting
1 parent b39d44a commit 4935f1e

9 files changed

Lines changed: 248 additions & 116 deletions

File tree

core/cmd/profiles_cmd.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"github.com/spf13/cobra"
1010

1111
"github.com/clovapi/switcher/internal/desktop"
12-
"github.com/clovapi/switcher/internal/usage"
1312
)
1413

1514
func cmdProfilesGroup() *cobra.Command {
@@ -152,7 +151,7 @@ func cmdProfilesUsage() *cobra.Command {
152151
}
153152
return fmt.Errorf("usage query failed")
154153
}
155-
fmt.Printf("Usage for %s:\n%s\n", strings.TrimSpace(result.Vendor), usage.FormatResult(result.Usage))
154+
fmt.Printf("Usage for %s:\n%s\n", strings.TrimSpace(result.Vendor), strings.TrimSpace(result.Text))
156155
return nil
157156
},
158157
}

core/internal/buildinfo/buildinfo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import "strings"
44

55
// Set at link time via -ldflags (see .goreleaser.yaml).
66
var (
7-
Version = "dev0.1.69"
7+
Version = "dev0.1.71"
88
Commit = "none"
99
Date = "unknown"
1010
)

core/internal/desktop/usage.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func QueryVendorUsage(vendorName string) VendorUsageResult {
103103
OK: result.Success,
104104
Vendor: name,
105105
Template: "subscription",
106-
Text: usage.FormatResult(result),
106+
Text: strings.TrimSpace(result.Text),
107107
Usage: result,
108108
Error: result.Error,
109109
}
@@ -117,7 +117,7 @@ func QueryVendorUsage(vendorName string) VendorUsageResult {
117117
OK: result.Success,
118118
Vendor: name,
119119
Template: templateType,
120-
Text: usage.FormatResult(result),
120+
Text: strings.TrimSpace(result.Text),
121121
Usage: result,
122122
Error: result.Error,
123123
}

core/internal/usage/balance.go

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,7 @@ func queryDeepSeek(apiKey string) Result {
142142
})
143143
}
144144
}
145-
res := Result{Success: true, Kind: "balance"}
146-
if len(out) > 0 {
147-
res.Data = out
148-
}
149-
return res
145+
return resultWithBalanceData(out)
150146
}
151147

152148
func queryStepFun(apiKey string) Result {
@@ -169,16 +165,12 @@ func queryStepFun(apiKey string) Result {
169165
}
170166
balance := parseFloatField(payload, "balance")
171167
valid := true
172-
return Result{
173-
Success: true,
174-
Kind: "balance",
175-
Data: []Data{{
176-
PlanName: "StepFun",
177-
Remaining: balance,
178-
Unit: "CNY",
179-
IsValid: &valid,
180-
}},
181-
}
168+
return resultWithBalanceData([]Data{{
169+
PlanName: "StepFun",
170+
Remaining: balance,
171+
Unit: "CNY",
172+
IsValid: &valid,
173+
}})
182174
}
183175

184176
func querySiliconFlow(apiKey string, cn bool) Result {
@@ -213,16 +205,12 @@ func querySiliconFlow(apiKey string, cn bool) Result {
213205
}
214206
remaining := parseFloatField(data, "totalBalance")
215207
valid := true
216-
return Result{
217-
Success: true,
218-
Kind: "balance",
219-
Data: []Data{{
220-
PlanName: plan,
221-
Remaining: remaining,
222-
Unit: unit,
223-
IsValid: &valid,
224-
}},
225-
}
208+
return resultWithBalanceData([]Data{{
209+
PlanName: plan,
210+
Remaining: remaining,
211+
Unit: unit,
212+
IsValid: &valid,
213+
}})
226214
}
227215

228216
func queryOpenRouter(apiKey string) Result {
@@ -259,19 +247,15 @@ func queryOpenRouter(apiKey string) Result {
259247
if remaining != nil && *remaining <= 0 {
260248
invalidMsg = "No credits remaining"
261249
}
262-
return Result{
263-
Success: true,
264-
Kind: "balance",
265-
Data: []Data{{
266-
PlanName: "OpenRouter",
267-
Remaining: remaining,
268-
Total: total,
269-
Used: used,
270-
Unit: "USD",
271-
IsValid: &valid,
272-
InvalidMessage: invalidMsg,
273-
}},
274-
}
250+
return resultWithBalanceData([]Data{{
251+
PlanName: "OpenRouter",
252+
Remaining: remaining,
253+
Total: total,
254+
Used: used,
255+
Unit: "USD",
256+
IsValid: &valid,
257+
InvalidMessage: invalidMsg,
258+
}})
275259
}
276260

277261
func queryNovita(apiKey string) Result {
@@ -303,17 +287,31 @@ func queryNovita(apiKey string) Result {
303287
if remaining != nil && *remaining <= 0 {
304288
invalidMsg = "No balance remaining"
305289
}
306-
return Result{
307-
Success: true,
308-
Kind: "balance",
309-
Data: []Data{{
310-
PlanName: "Novita AI",
311-
Remaining: remaining,
312-
Unit: "USD",
313-
IsValid: &valid,
314-
InvalidMessage: invalidMsg,
315-
}},
290+
return resultWithBalanceData([]Data{{
291+
PlanName: "Novita AI",
292+
Remaining: remaining,
293+
Unit: "USD",
294+
IsValid: &valid,
295+
InvalidMessage: invalidMsg,
296+
}})
297+
}
298+
299+
func formatBalanceUsageText(rows []Data) string {
300+
parts := make([]string, 0, len(rows))
301+
for _, row := range rows {
302+
if text := strings.TrimSpace(FormatDataRow(row)); text != "" {
303+
parts = append(parts, text)
304+
}
316305
}
306+
return strings.Join(parts, " · ")
307+
}
308+
309+
func resultWithBalanceData(rows []Data) Result {
310+
res := Result{Success: true, Kind: "balance", Text: formatBalanceUsageText(rows)}
311+
if len(rows) > 0 {
312+
res.Data = rows
313+
}
314+
return res
317315
}
318316

319317
// QueryBalance queries vendor account balance when base_url matches a known provider.

core/internal/usage/coding_plan.go

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ func extractResetTime(raw any) string {
6767
return ""
6868
}
6969

70+
func formatCodingPlanReset(tierName, raw string) string {
71+
resetAt, ok := parseRFC3339ResetTime(raw)
72+
if !ok {
73+
return ""
74+
}
75+
switch strings.ToLower(strings.TrimSpace(tierName)) {
76+
case tierFiveHour:
77+
return formatResetDuration(resetAt.Sub(usageTextNow()))
78+
case tierWeeklyLimit:
79+
return resetAt.Format("01-02")
80+
default:
81+
return ""
82+
}
83+
}
84+
7085
func parseZhipuTokenTiers(data map[string]any) []Tier {
7186
type row struct {
7287
resetMS *int64
@@ -116,7 +131,7 @@ func parseZhipuTokenTiers(data map[string]any) []Tier {
116131
if rows[j].resetMS != nil {
117132
rightVal = *rows[j].resetMS
118133
}
119-
if (!leftHas && rightHas) || (leftHas && rightHas && leftVal > rightVal) {
134+
if (leftHas && !rightHas) || (leftHas && rightHas && leftVal > rightVal) {
120135
rows[i], rows[j] = rows[j], rows[i]
121136
}
122137
}
@@ -196,7 +211,7 @@ func queryKimiCodingPlan(apiKey string) Result {
196211
})
197212
}
198213
}
199-
return Result{Success: true, Kind: "token_plan", Tiers: tiers}
214+
return resultWithCodingPlanTiers(tiers)
200215
}
201216

202217
func queryZhipuCodingPlan(apiKey string) Result {
@@ -229,7 +244,7 @@ func queryZhipuCodingPlan(apiKey string) Result {
229244
if data == nil {
230245
return Result{Success: false, Kind: "token_plan", Error: "Missing 'data' field in response"}
231246
}
232-
return Result{Success: true, Kind: "token_plan", Tiers: parseZhipuTokenTiers(data)}
247+
return resultWithCodingPlanTiers(parseZhipuTokenTiers(data))
233248
}
234249

235250
func queryMiniMaxCodingPlan(apiKey string, cn bool) Result {
@@ -297,7 +312,7 @@ func queryMiniMaxCodingPlan(apiKey string, cn bool) Result {
297312
}
298313
}
299314
}
300-
return Result{Success: true, Kind: "token_plan", Tiers: tiers}
315+
return resultWithCodingPlanTiers(tiers)
301316
}
302317

303318
// QueryCodingPlan queries token-plan utilization for Kimi / Zhipu / MiniMax coding endpoints.
@@ -350,3 +365,30 @@ func TiersToUsageData(tiers []Tier) []Data {
350365
}
351366
return out
352367
}
368+
369+
func formatCodingPlanUsageText(tiers []Tier) string {
370+
parts := make([]string, 0, len(tiers))
371+
for _, tier := range tiers {
372+
name := TierDisplayName(tier.Name)
373+
if name == "" {
374+
name = strings.TrimSpace(tier.Name)
375+
}
376+
if name == "" {
377+
continue
378+
}
379+
body := name + " " + formatNumber(tier.Utilization) + "%"
380+
if reset := formatCodingPlanReset(tier.Name, tier.ResetsAt); reset != "" {
381+
body += "(" + reset + ")"
382+
}
383+
parts = append(parts, body)
384+
}
385+
return strings.Join(parts, " · ")
386+
}
387+
388+
func resultWithCodingPlanTiers(tiers []Tier) Result {
389+
res := Result{Success: true, Kind: "token_plan", Text: formatCodingPlanUsageText(tiers), Tiers: tiers}
390+
if len(tiers) > 0 {
391+
res.Data = TiersToUsageData(tiers)
392+
}
393+
return res
394+
}

core/internal/usage/format.go

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -86,37 +86,16 @@ func FormatDataRow(row Data) string {
8686
return name
8787
}
8888

89-
func formatTierRow(tier Tier) string {
90-
name := TierDisplayName(tier.Name)
91-
body := formatNumber(tier.Utilization) + "%"
92-
if name == "" {
93-
return body
94-
}
95-
return name + " " + body
96-
}
97-
9889
// FormatResult renders a complete usage query result as plain text.
9990
func FormatResult(result Result) string {
91+
if text := strings.TrimSpace(result.Text); text != "" {
92+
return text
93+
}
10094
if !result.Success {
10195
if err := strings.TrimSpace(result.Error); err != "" {
10296
return err
10397
}
10498
return "usage query failed"
10599
}
106-
rows := result.Data
107-
if len(rows) == 0 && len(result.Tiers) > 0 {
108-
parts := make([]string, 0, len(result.Tiers))
109-
for _, tier := range result.Tiers {
110-
parts = append(parts, formatTierRow(tier))
111-
}
112-
return strings.Join(parts, " · ")
113-
}
114-
if len(rows) == 0 {
115-
return "no usage details"
116-
}
117-
parts := make([]string, 0, len(rows))
118-
for _, row := range rows {
119-
parts = append(parts, FormatDataRow(row))
120-
}
121-
return strings.Join(parts, " · ")
100+
return ""
122101
}

0 commit comments

Comments
 (0)