zcode: an old plan with no monthly cap is no longer taken as used up (#366) — the quota reply's TIME_LIMIT is the month's MCP tool calls, which ZCode only shows and never stops the models on, but magpie read it as the account's monthly allowance, so an old plan reporting it at 100% had its ZCode models skipped with the 5 hours full. It is now shown as MCP · Month and set aside, as a pasted Zhipu key's already was, and a limit whose whole is 0 (no cap) counts as unused. TestZCodeNoMonthlyCap fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (the Claude account tests pass alone).

This commit is contained in:
yetone committed 2026-10-01 02:58:29 +08:00
1 parent 49f40b463f
commit df019e18e7
2 files changed
+64 -1

No files matched your search

+10 -1
View File
@@ -381,15 +381,24 @@ type zhipuLimits struct {
// windows are the limits as windows: what is used of the whole when both
// are told (the whole less what remains, or the current value), else the
// percentage the vendor gives.
// percentage the vendor gives. TIME_LIMIT is the month's MCP tool calls,
// which ZCode shows but never stops the models on, so it is set aside, as
// is a limit whose whole is told as 0: no cap (an older plan's), which
// the vendor may still give as 100% used.
func (d zhipuLimits) windows() []QuotaWindow {
out := []QuotaWindow{}
for _, x := range d.Limits {
span := zcodeSpan(x.Unit, x.Number)
w := QuotaWindow{Name: zcodeWindowName(span), Span: span}
if strings.EqualFold(x.Type, "TIME_LIMIT") {
w.Name, w.Aside = "MCP · Month", true
}
if x.Percent != nil {
w.Used = *x.Percent
}
if x.Usage != nil && *x.Usage == 0 {
w.Used, w.Aside = 0, true
}
if x.Usage != nil && *x.Usage > 0 {
total := *x.Usage
switch {
+54
View File
@@ -0,0 +1,54 @@
package provider
import (
"encoding/json"
"strconv"
"testing"
"time"
)
// TestZCodeNoMonthlyCap: an older GLM Coding plan's reply (#366) — the
// five hours untouched, no week, and the month's MCP tool calls with no
// cap given as 100% used. The account is not out: only the five hours
// count, and the uncapped month reads as nothing used.
func TestZCodeNoMonthlyCap(t *testing.T) {
now := time.Now()
reset := now.Add(3 * time.Hour).UnixMilli()
month := now.Add(20 * 24 * time.Hour).UnixMilli()
var d zhipuLimits
if err := json.Unmarshal([]byte(`{"level":"pro","limits":[
{"type":"TOKENS_LIMIT","unit":3,"number":5,"percentage":0,"nextResetTime":`+strconv.FormatInt(reset, 10)+`},
{"type":"TIME_LIMIT","unit":5,"number":1,"usage":0,"currentValue":0,"remaining":0,"percentage":100,"nextResetTime":`+strconv.FormatInt(month, 10)+`}]}`), &d); err != nil {
t.Fatal(err)
}
ws := d.windows()
if len(ws) != 2 || ws[0].Name != "5 hours" || ws[0].Aside || ws[1].Name != "MCP · Month" || !ws[1].Aside || ws[1].Used != 0 {
t.Fatalf("windows: %+v", ws)
}
a := allowanceOf(ws, now)
if used, _ := a.For("glm-5.1", now); used != 0 {
t.Fatalf("used %v, want 0", used)
}
if full := a.Full("glm-5.1", 100, now); !full.IsZero() {
t.Fatalf("full until %v", full)
}
// the MCP calls used up on a plan that caps them don't stop the models
// either, and still show as used
d = zhipuLimits{}
json.Unmarshal([]byte(`{"limits":[
{"type":"TOKENS_LIMIT","unit":3,"number":5,"percentage":10,"nextResetTime":`+strconv.FormatInt(reset, 10)+`},
{"type":"TOKENS_LIMIT","unit":6,"number":1,"percentage":30,"nextResetTime":`+strconv.FormatInt(month, 10)+`},
{"type":"TIME_LIMIT","unit":5,"number":1,"usage":100,"currentValue":100,"remaining":0,"percentage":100,"nextResetTime":`+strconv.FormatInt(month, 10)+`}]}`), &d)
ws = d.windows()
if len(ws) != 3 || ws[2].Used != 100 || !ws[2].Aside || ws[1].Aside {
t.Fatalf("capped: %+v", ws)
}
a = allowanceOf(ws, now)
if used, _ := a.For("glm-5.1", now); used != 30 {
t.Fatalf("capped used %v, want 30", used)
}
if full := a.Full("glm-5.1", 100, now); !full.IsZero() {
t.Fatalf("capped full until %v", full)
}
}