@magpie-community/opencode-workbuddy-auth 0.2.10 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/index.mjs +71 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -344,6 +344,17 @@ client reads. The daily Free Plan slice isn't counted: it ends at the same
|
|
|
344
344
|
midnight on every account. magpie's smart routing spends the account whose
|
|
345
345
|
credits run out first.
|
|
346
346
|
|
|
347
|
+
The plan's own credits and the rest are two windows. "Credits" is the
|
|
348
|
+
packages whose credits come back each cycle, as WorkBuddy's client lists
|
|
349
|
+
them (Pro monthly or yearly, youth, advanced, flagship, the plan's bonus,
|
|
350
|
+
the free plan's monthly base, the Pro trials, or the subscription the
|
|
351
|
+
summary names), with the plan's cycle, so its pace line is the month's.
|
|
352
|
+
"Extra credits" is the packages that only lapse: gifted and activity
|
|
353
|
+
credits (赠送积分) and bought credit packs. Only one of the two stops the
|
|
354
|
+
account, since WorkBuddy serves it while any credits are left: the extra
|
|
355
|
+
window is set aside until the plan's credits are spent. A summary with
|
|
356
|
+
only one kind keeps the one "Credits" window (akic404 on Discord).
|
|
357
|
+
|
|
347
358
|
An enterprise (team) account's resource summary lists no packages. Its
|
|
348
359
|
credits are read from the enterprise meter
|
|
349
360
|
(`/billing/meter/get-enterprise-user-usage`), the one WorkBuddy's own usage
|
package/index.mjs
CHANGED
|
@@ -2776,20 +2776,49 @@ function pinned(rows, account) {
|
|
|
2776
2776
|
// CycleRemainCapacity at all leaves the window out. TotalCredits is not a
|
|
2777
2777
|
// fallback: an account with no packages at all keeps its unknown allowance,
|
|
2778
2778
|
// as before, so its free models are not skipped.
|
|
2779
|
-
|
|
2779
|
+
//
|
|
2780
|
+
// The plan's own credits and the rest are two windows (akic404 on
|
|
2781
|
+
// Discord): summed, the gifted and activity packages' credits used long
|
|
2782
|
+
// ago put the card at most of its allowance on the first day of the
|
|
2783
|
+
// month, and the plan's pace line said nothing. "Credits" is the packages
|
|
2784
|
+
// whose credits come back each cycle — WorkBuddy's client's own
|
|
2785
|
+
// onlyRefreshCodes (PLAN_CODES), or the subscription the summary names —
|
|
2786
|
+
// and "Extra credits" the ones that only lapse (gift, activity, bought
|
|
2787
|
+
// credit packs, any code the client doesn't list). A summary with only
|
|
2788
|
+
// one kind keeps the one "Credits" window, as before.
|
|
2789
|
+
//
|
|
2790
|
+
// Only one of the two stops the account at a time: WorkBuddy serves it
|
|
2791
|
+
// while any credits are left, so the one set aside is the one whose
|
|
2792
|
+
// running out doesn't stop it — "Extra credits", until the plan's are
|
|
2793
|
+
// spent and extra ones are left.
|
|
2794
|
+
function usageOf(sum, plan, site) {
|
|
2780
2795
|
const out = { plan: plan || (sum?.IsPaidUser ? "Pro" : "Free plan"), windows: [] }
|
|
2781
|
-
|
|
2796
|
+
const ofPlan = planCodes(sum, site)
|
|
2797
|
+
const kinds = { plan: { total: 0, used: 0 }, extra: { total: 0, used: 0 } }
|
|
2798
|
+
let left = 0, bags = 0
|
|
2782
2799
|
for (const p of sum?.Packages ?? []) {
|
|
2783
2800
|
const hasTotal = p?.CycleTotalCapacity != null && p.CycleTotalCapacity !== ""
|
|
2784
2801
|
if (hasTotal) {
|
|
2785
|
-
|
|
2786
|
-
|
|
2802
|
+
const k = kinds[ofPlan(p?.PackageCode) ? "plan" : "extra"]
|
|
2803
|
+
k.total += capacity(p.CycleTotalCapacity)
|
|
2804
|
+
k.used += capacity(p?.CycleUsedCapacity)
|
|
2787
2805
|
} else if (p?.CycleRemainCapacity != null && p.CycleRemainCapacity !== "") {
|
|
2788
2806
|
left += capacity(p.CycleRemainCapacity)
|
|
2789
2807
|
bags++
|
|
2790
2808
|
}
|
|
2791
2809
|
}
|
|
2792
|
-
|
|
2810
|
+
const window = (name, { used, total }) => ({ name, used: (100 * used) / total, display: `${compact(used)} / ${compact(total)}`, amount: used, limit: total, unit: "credits" })
|
|
2811
|
+
const { plan: mine, extra } = kinds
|
|
2812
|
+
if (mine.total > 0 && extra.total > 0) {
|
|
2813
|
+
const credits = window("Credits", mine), more = window("Extra credits", extra)
|
|
2814
|
+
if (mine.used >= mine.total && extra.used < extra.total) credits.aside = true
|
|
2815
|
+
else more.aside = true
|
|
2816
|
+
out.windows.push(credits, more)
|
|
2817
|
+
} else {
|
|
2818
|
+
const total = mine.total + extra.total, used = mine.used + extra.used
|
|
2819
|
+
if (total > 0) out.windows.push(window("Credits", { used, total }))
|
|
2820
|
+
}
|
|
2821
|
+
const total = mine.total + extra.total
|
|
2793
2822
|
if (bags > 0 && (total === 0 || left > 0)) out.windows.push({ name: "Prepaid credits", balance: left, display: `${compact(left)} credits`, unit: "credits" })
|
|
2794
2823
|
return out
|
|
2795
2824
|
}
|
|
@@ -2845,6 +2874,26 @@ const FREE_CODES = [DAILY_CODE, CODE("008", "cfWoLwvjU4"), CODE("035", "ArVxJcGD
|
|
|
2845
2874
|
// lost at the same midnight on every account, so they tell none apart
|
|
2846
2875
|
const SLICE = "4"
|
|
2847
2876
|
|
|
2877
|
+
// PLAN_CODES are the packages whose credits come back each cycle, as
|
|
2878
|
+
// WorkBuddy's client (5.9.x) lists them (onlyRefreshCodes): Pro monthly,
|
|
2879
|
+
// Pro monthly plus, Pro yearly, youth, advanced, flagship, the plan's
|
|
2880
|
+
// bonus (bonus28; bonusIntl, "Plan Bonus Quota"), the international free
|
|
2881
|
+
// plan (freeMonIntl), the Pro trials, and on the China build alone the
|
|
2882
|
+
// free plan's monthly base (freeMon, 套餐基础积分). Every other code only
|
|
2883
|
+
// lapses: gift (006, "Bonus Pack" / Pro trial), activity (007, 赠送积分),
|
|
2884
|
+
// bonus29/30, and the credit packs (009, 036, 038).
|
|
2885
|
+
const PLAN_CODES = [CODE("002", "AkiJS3ZHF5"), CODE("005", "maRGyrHhw1"), CODE("003", "FAnt7lcmRT"), CODE("023", "4xbGhMrE6q"),
|
|
2886
|
+
CODE("026", "BaESVICNoi"), CODE("027", "0FCGVA6vSa"), CODE("028", "NtpWi0jzXs"), CODE("035", "ArVxJcGDsm"),
|
|
2887
|
+
CODE("039", "KRcQj7wUat"), CODE("040", "mi9rCYg46x"), CODE("037", "WxOD3MpI2o")]
|
|
2888
|
+
const FREE_MON = CODE("008", "cfWoLwvjU4")
|
|
2889
|
+
|
|
2890
|
+
// planCodes says whether a package of the summary is the plan's own: one
|
|
2891
|
+
// of PLAN_CODES on that site, or the subscription the summary names.
|
|
2892
|
+
function planCodes(sum, site) {
|
|
2893
|
+
const sub = sum?.SubscriptionPackageCode
|
|
2894
|
+
return (code) => !!code && (code === sub || PLAN_CODES.includes(code) || (!site?.ai && code === FREE_MON))
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2848
2897
|
// beijing is WorkBuddy's own time ("2026-10-13 00:39:27" is UTC+8, as its
|
|
2849
2898
|
// DeductionEndTime for the same package says).
|
|
2850
2899
|
const beijing = (ms) => new Date(ms + 8 * 3600_000).toISOString().slice(0, 19).replace("T", " ")
|
|
@@ -2887,11 +2936,12 @@ function endOf(p) {
|
|
|
2887
2936
|
// packages are lost, and how many (cdredfox on X): smart routing spends
|
|
2888
2937
|
// the account whose credits expire first. Only packages the summary
|
|
2889
2938
|
// counts, with credits left, and not the daily slice; null when none.
|
|
2890
|
-
|
|
2939
|
+
// only narrows it to the packages of one window (the split's, usageOf).
|
|
2940
|
+
function runsOutOf(sum, packages, now = Date.now(), only = () => true) {
|
|
2891
2941
|
const counted = new Set((sum?.Packages ?? []).map((p) => p?.PackageCode))
|
|
2892
2942
|
let at = 0, amount = 0
|
|
2893
2943
|
for (const p of packages ?? []) {
|
|
2894
|
-
if (!counted.has(p?.PackageCode) || p?.PackageCode === DAILY_CODE || String(p?.CapacityType) === SLICE) continue
|
|
2944
|
+
if (!counted.has(p?.PackageCode) || !only(p?.PackageCode) || p?.PackageCode === DAILY_CODE || String(p?.CapacityType) === SLICE) continue
|
|
2895
2945
|
const left = capacity(p?.CycleCapacityRemainPrecise ?? p?.CycleCapacityRemain)
|
|
2896
2946
|
const end = endOf(p)
|
|
2897
2947
|
if (!(left > 0) || end <= now) continue
|
|
@@ -3626,7 +3676,7 @@ function makePlugin(site) {
|
|
|
3626
3676
|
}
|
|
3627
3677
|
said = "renewed"
|
|
3628
3678
|
}
|
|
3629
|
-
const out = usageOf(sum, auth.plan)
|
|
3679
|
+
const out = usageOf(sum, auth.plan, site)
|
|
3630
3680
|
// an enterprise account's summary has no packages: its credits
|
|
3631
3681
|
// are the enterprise meter's (#1904). A personal account's
|
|
3632
3682
|
// refusal of it (10001 "uid or enterpriseID is empty") leaves
|
|
@@ -3641,11 +3691,22 @@ function makePlugin(site) {
|
|
|
3641
3691
|
// when the plan's credits start again (cycleOf), and when the credits
|
|
3642
3692
|
// left run out, for routing to spend them first (runsOutOf);
|
|
3643
3693
|
// a list that can't be read leaves it unknown, the card stands
|
|
3694
|
+
//
|
|
3695
|
+
// Split (usageOf), the plan's cycle is the plan window's alone;
|
|
3696
|
+
// the soonest credits to lapse, of any package, stay on the window
|
|
3697
|
+
// that stops the account, as routing reads none set aside, and
|
|
3698
|
+
// the window set aside says its own.
|
|
3644
3699
|
const credits = out.windows.find((w) => w.name === "Credits")
|
|
3700
|
+
const extra = out.windows.find((w) => w.name === "Extra credits")
|
|
3645
3701
|
if (credits) {
|
|
3646
3702
|
try {
|
|
3647
3703
|
const packages = await packagesOf(site, a)
|
|
3648
|
-
Object.assign(credits, cycleOf(sum, packages) ?? {}
|
|
3704
|
+
Object.assign(credits, cycleOf(sum, packages) ?? {})
|
|
3705
|
+
const ofPlan = planCodes(sum, site)
|
|
3706
|
+
const stops = extra && !extra.aside ? extra : credits
|
|
3707
|
+
Object.assign(stops, runsOutOf(sum, packages) ?? {})
|
|
3708
|
+
const aside = extra ? (stops === credits ? extra : credits) : null
|
|
3709
|
+
if (aside) Object.assign(aside, runsOutOf(sum, packages, Date.now(), (code) => ofPlan(code) === (aside === credits)) ?? {})
|
|
3649
3710
|
} catch {}
|
|
3650
3711
|
}
|
|
3651
3712
|
await spareFree(site, a, out.windows)
|
|
@@ -3801,4 +3862,4 @@ export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
|
3801
3862
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
3802
3863
|
|
|
3803
3864
|
// for tests
|
|
3804
|
-
export const _internal = { idFor, OFF_TAKEN, replyAfterToolsOn, withDefaultEffort, defaultEffortOf, gzipped, FREE_ONLY, PRICE_TTL, keyAccount, remoteConfig, cycleOf, typeUnions, systemAsUser, systemKey, DEFAULT_SYSTEM, EDGE_READS, fitShape, replyAfterTools, AFTER_TOOLS_REFUSED, enterpriseUsageOf, accountName, notDesktop, textOnly, runsOutOf, packagesOf, endOf, enterpriseHeaders, enterpriseOf, liveModels, browserSignIn, withSystem, asReasoning, normalizeToolChoice, fitTools, fitted, renamed, unsaid, FILTER_SAYS, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, RESTRICTED_HINT, EXHAUSTED_HINT, REFUSED_DOC, commaPaused, commaPausedOn, opened, freeCredits, creditsOf, priceOf, fresh, SITES, renewing, renewed, SESSION, attend, scopeOf, turnKey, conversationKey, signatureOf, isMessages, withoutUnsigned, withoutSignedThinking, prepared, answeredBefore, nativeOf, modelOf, configModels, freeWindowOf, tokensShort, freeWindowRows, freeWindowLedger, readLedgerTail, pinned, rowTime, rowAccount, ofAccount, windowOffset, windowReset, FREE_WINDOW_MODELS, FREE_WINDOW_SPAN, FREE_WINDOW_GAP, FREE_WINDOW_LEAD, checkinOf, API_MESSAGES: NPM_MESSAGES, API_CHAT: NPM }
|
|
3865
|
+
export const _internal = { planCodes, idFor, OFF_TAKEN, replyAfterToolsOn, withDefaultEffort, defaultEffortOf, gzipped, FREE_ONLY, PRICE_TTL, keyAccount, remoteConfig, cycleOf, typeUnions, systemAsUser, systemKey, DEFAULT_SYSTEM, EDGE_READS, fitShape, replyAfterTools, AFTER_TOOLS_REFUSED, enterpriseUsageOf, accountName, notDesktop, textOnly, runsOutOf, packagesOf, endOf, enterpriseHeaders, enterpriseOf, liveModels, browserSignIn, withSystem, asReasoning, normalizeToolChoice, fitTools, fitted, renamed, unsaid, FILTER_SAYS, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, RESTRICTED_HINT, EXHAUSTED_HINT, REFUSED_DOC, commaPaused, commaPausedOn, opened, freeCredits, creditsOf, priceOf, fresh, SITES, renewing, renewed, SESSION, attend, scopeOf, turnKey, conversationKey, signatureOf, isMessages, withoutUnsigned, withoutSignedThinking, prepared, answeredBefore, nativeOf, modelOf, configModels, freeWindowOf, tokensShort, freeWindowRows, freeWindowLedger, readLedgerTail, pinned, rowTime, rowAccount, ofAccount, windowOffset, windowReset, FREE_WINDOW_MODELS, FREE_WINDOW_SPAN, FREE_WINDOW_GAP, FREE_WINDOW_LEAD, checkinOf, API_MESSAGES: NPM_MESSAGES, API_CHAT: NPM }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magpie-community/opencode-workbuddy-auth",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "OpenCode provider plugins for WorkBuddy's plans: WorkBuddy (CodeBuddy, copilot.tencent.com) and WorkBuddy AI (www.workbuddy.ai)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|