@magpie-community/opencode-workbuddy-auth 0.2.15 → 0.2.17
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 -7
- package/index.mjs +105 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -349,15 +349,19 @@ midnight on every account. magpie's smart routing spends the account whose
|
|
|
349
349
|
credits run out first.
|
|
350
350
|
|
|
351
351
|
The plan's own credits and the rest are two windows. "Credits" is the
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
352
|
+
plan's base credits: what the subscription grants each cycle (Pro monthly
|
|
353
|
+
or yearly, youth, advanced, flagship, the Pro trials, the free plan's
|
|
354
|
+
monthly base, or the subscription the summary names), with the plan's
|
|
355
|
+
cycle, so its pace line is the month's. "Extra credits" is every other
|
|
356
|
+
kind WorkBuddy's own usage panel lists: the plan's bonus, top-ups (bought
|
|
357
|
+
credit packs) and platform rewards (gifted and activity credits,
|
|
358
|
+
赠送积分). The summary's CreditGroups say which is which (plan_base
|
|
359
|
+
against plan_bonus, addon and benefit); a summary without them is split
|
|
360
|
+
by package code as WorkBuddy's client does. Only one of the two stops the
|
|
358
361
|
account, since WorkBuddy serves it while any credits are left: the extra
|
|
359
362
|
window is set aside until the plan's credits are spent. A summary with
|
|
360
|
-
only one kind keeps the one "Credits" window (akic404 on Discord
|
|
363
|
+
only one kind keeps the one "Credits" window (akic404 on Discord; since
|
|
364
|
+
0.2.16 the plan's bonus is extra too, Jiabubu on Discord).
|
|
361
365
|
|
|
362
366
|
An enterprise (team) account's resource summary lists no packages. Its
|
|
363
367
|
credits are read from the enterprise meter
|
package/index.mjs
CHANGED
|
@@ -2868,12 +2868,15 @@ function pinning() {
|
|
|
2868
2868
|
// The plan's own credits and the rest are two windows (akic404 on
|
|
2869
2869
|
// Discord): summed, the gifted and activity packages' credits used long
|
|
2870
2870
|
// ago put the card at most of its allowance on the first day of the
|
|
2871
|
-
// month, and the plan's pace line said nothing. "Credits" is the
|
|
2872
|
-
//
|
|
2873
|
-
//
|
|
2874
|
-
//
|
|
2875
|
-
//
|
|
2876
|
-
//
|
|
2871
|
+
// month, and the plan's pace line said nothing. "Credits" is the plan's
|
|
2872
|
+
// base credits and "Extra credits" every other kind, as WorkBuddy's own
|
|
2873
|
+
// usage panel breaks them down (Jiabubu on Discord: a plan's bonus and
|
|
2874
|
+
// bought credits were nowhere on the card). The summary's CreditGroups
|
|
2875
|
+
// say it in WorkBuddy's words: plan_base ("Plan Base Credits") is the
|
|
2876
|
+
// plan's, plan_bonus, addon ("Top-up Credits") and benefit ("Platform
|
|
2877
|
+
// Reward Credits") are extra. A summary without them is split by code as
|
|
2878
|
+
// the client's resolveCreditGroup does (PLAN_CODES, see planCodes). A
|
|
2879
|
+
// summary with only one kind keeps the one "Credits" window, as before.
|
|
2877
2880
|
//
|
|
2878
2881
|
// Only one of the two stops the account at a time: WorkBuddy serves it
|
|
2879
2882
|
// while any credits are left, so the one set aside is the one whose
|
|
@@ -2881,36 +2884,79 @@ function pinning() {
|
|
|
2881
2884
|
// spent and extra ones are left.
|
|
2882
2885
|
function usageOf(sum, plan, site) {
|
|
2883
2886
|
const out = { plan: plan || (sum?.IsPaidUser ? "Pro" : "Free plan"), windows: [] }
|
|
2884
|
-
const
|
|
2885
|
-
const kinds = { plan: { total: 0, used: 0 }, extra: { total: 0, used: 0 } }
|
|
2886
|
-
let left = 0, bags = 0
|
|
2887
|
-
for (const p of sum?.Packages ?? []) {
|
|
2888
|
-
const hasTotal = p?.CycleTotalCapacity != null && p.CycleTotalCapacity !== ""
|
|
2889
|
-
if (hasTotal) {
|
|
2890
|
-
const k = kinds[ofPlan(p?.PackageCode) ? "plan" : "extra"]
|
|
2891
|
-
k.total += capacity(p.CycleTotalCapacity)
|
|
2892
|
-
k.used += capacity(p?.CycleUsedCapacity)
|
|
2893
|
-
} else if (p?.CycleRemainCapacity != null && p.CycleRemainCapacity !== "") {
|
|
2894
|
-
left += capacity(p.CycleRemainCapacity)
|
|
2895
|
-
bags++
|
|
2896
|
-
}
|
|
2897
|
-
}
|
|
2898
|
-
const window = (name, { used, total }) => ({ name, used: (100 * used) / total, display: `${compact(used)} / ${compact(total)}`, amount: used, limit: total, unit: "credits" })
|
|
2899
|
-
const { plan: mine, extra } = kinds
|
|
2887
|
+
const { plan: mine, extra, left, bags } = kindsOf(sum, site)
|
|
2900
2888
|
if (mine.total > 0 && extra.total > 0) {
|
|
2901
|
-
const credits =
|
|
2889
|
+
const credits = creditWindow("Credits", mine), more = creditWindow("Extra credits", extra)
|
|
2902
2890
|
if (mine.used >= mine.total && extra.used < extra.total) credits.aside = true
|
|
2903
2891
|
else more.aside = true
|
|
2904
2892
|
out.windows.push(credits, more)
|
|
2905
2893
|
} else {
|
|
2906
2894
|
const total = mine.total + extra.total, used = mine.used + extra.used
|
|
2907
|
-
if (total > 0) out.windows.push(
|
|
2895
|
+
if (total > 0) out.windows.push(creditWindow("Credits", { used, total }))
|
|
2908
2896
|
}
|
|
2909
2897
|
const total = mine.total + extra.total
|
|
2910
2898
|
if (bags > 0 && (total === 0 || left > 0)) out.windows.push({ name: "Prepaid credits", balance: left, display: `${compact(left)} credits`, unit: "credits" })
|
|
2911
2899
|
return out
|
|
2912
2900
|
}
|
|
2913
2901
|
|
|
2902
|
+
// creditWindow is a window of credits used of a total.
|
|
2903
|
+
const creditWindow = (name, { used, total }) => ({ name, used: (100 * used) / total, display: `${compact(used)} / ${compact(total)}`, amount: used, limit: total, unit: "credits" })
|
|
2904
|
+
|
|
2905
|
+
// kindsOf is the summary's credits, the plan's and the extra ones (see
|
|
2906
|
+
// usageOf), and what is left in its packages with no total (a prepaid
|
|
2907
|
+
// balance).
|
|
2908
|
+
function kindsOf(sum, site) {
|
|
2909
|
+
const ofPlan = planCodes(sum, site)
|
|
2910
|
+
const kinds = { plan: { total: 0, used: 0 }, extra: { total: 0, used: 0 }, left: 0, bags: 0 }
|
|
2911
|
+
const hasTotal = (p) => p?.CycleTotalCapacity != null && p.CycleTotalCapacity !== ""
|
|
2912
|
+
const add = (k, p) => ((k.total += capacity(p.CycleTotalCapacity)), (k.used += capacity(p?.CycleUsedCapacity)))
|
|
2913
|
+
const groups = (Array.isArray(sum?.CreditGroups) ? sum.CreditGroups : []).filter(hasTotal)
|
|
2914
|
+
for (const g of groups) add(kinds[g?.Kind === "plan_base" ? "plan" : "extra"], g)
|
|
2915
|
+
for (const p of sum?.Packages ?? []) {
|
|
2916
|
+
if (hasTotal(p)) {
|
|
2917
|
+
if (!groups.length) add(kinds[ofPlan(p?.PackageCode) ? "plan" : "extra"], p)
|
|
2918
|
+
} else if (p?.CycleRemainCapacity != null && p.CycleRemainCapacity !== "") {
|
|
2919
|
+
kinds.left += capacity(p.CycleRemainCapacity)
|
|
2920
|
+
kinds.bags++
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
return kinds
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// listedExtra is the extra credits of the detail lists (packagesOf) that
|
|
2927
|
+
// the summary doesn't list at all, as WorkBuddy's own usage panel counts
|
|
2928
|
+
// them (jiabubu on Discord, magpie 0.1.2774, a China-site free account:
|
|
2929
|
+
// magpie's card read "0 / 500" alone, while the panel shows the extra
|
|
2930
|
+
// kinds beside the plan's). The panel's groups come from the detail
|
|
2931
|
+
// lists, not the summary (buildCreditGroups over fetchUserResources' paid
|
|
2932
|
+
// and free lists), and leave out a package past its end; a slice package
|
|
2933
|
+
// (CapacityType 4) counts the day's slice, as resolveResourceCapacity
|
|
2934
|
+
// does. null when there are none with credits.
|
|
2935
|
+
function listedExtra(sum, packages, site, now = Date.now()) {
|
|
2936
|
+
const summed = new Set((sum?.Packages ?? []).map((p) => p?.PackageCode))
|
|
2937
|
+
const codes = site?.ai ? [...EXTRA_CODES, ...EXTRA_AI] : EXTRA_CODES
|
|
2938
|
+
let total = 0, left = 0, at = 0, lapsing = 0
|
|
2939
|
+
for (const p of packages ?? []) {
|
|
2940
|
+
const code = p?.PackageCode
|
|
2941
|
+
if (!codes.includes(code) || summed.has(code)) continue
|
|
2942
|
+
const end = endOf(p)
|
|
2943
|
+
if (end > 0 && end <= now) continue
|
|
2944
|
+
const slice = String(p?.CapacityType) === SLICE ? p?.SlicePeriodUsageDetails?.[0] : null
|
|
2945
|
+
const of = (v) => { const n = Number(v); return Number.isFinite(n) && n > 0 ? n : 0 }
|
|
2946
|
+
const t = of(slice ? slice.SlicePeriodCapacitySizePrecise : p?.CycleCapacitySizePrecise)
|
|
2947
|
+
const l = Math.min(t, of(slice ? slice.SlicePeriodCapacityRemainPrecise : p?.CycleCapacityRemainPrecise))
|
|
2948
|
+
if (!(t > 0)) continue
|
|
2949
|
+
total += t
|
|
2950
|
+
left += l
|
|
2951
|
+
if (l > 0 && end > 0 && !slice) {
|
|
2952
|
+
if (!at || end < at) at = end, lapsing = l
|
|
2953
|
+
else if (end === at) lapsing += l
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
if (!(total > 0)) return null
|
|
2957
|
+
return { total, used: total - left, ...(at ? { runsOutAt: new Date(at).toISOString(), runsOut: lapsing } : {}) }
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2914
2960
|
// enterpriseUsageOf is an enterprise (team) account's credits, from
|
|
2915
2961
|
// /billing/meter/get-enterprise-user-usage, the meter WorkBuddy's own usage
|
|
2916
2962
|
// page (www.workbuddy.cn/profile/usage) reads for one (magpie #1904,
|
|
@@ -2953,7 +2999,7 @@ async function spareFree(site, a, windows) {
|
|
|
2953
2999
|
// detail list without them (10001 "PackageCodes required").
|
|
2954
3000
|
const CODE = (n, s) => `TCACA_code_${n}_${s}`
|
|
2955
3001
|
const PAID_CODES = [CODE("002", "AkiJS3ZHF5"), CODE("005", "maRGyrHhw1"), CODE("003", "FAnt7lcmRT"), CODE("023", "4xbGhMrE6q"),
|
|
2956
|
-
CODE("026", "BaESVICNoi"), CODE("027", "0FCGVA6vSa"), CODE("009", "0XmEQc2xOf"), CODE("038", "OhvqZtiPKr"), CODE("036", "lupO5WgNdG")]
|
|
3002
|
+
CODE("026", "BaESVICNoi"), CODE("027", "0FCGVA6vSa"), CODE("043", "6oIkxT7Z0S"), CODE("009", "0XmEQc2xOf"), CODE("038", "OhvqZtiPKr"), CODE("036", "lupO5WgNdG")]
|
|
2957
3003
|
const DAILY_CODE = CODE("001", "PqouKr6QWV")
|
|
2958
3004
|
const FREE_CODES = [DAILY_CODE, CODE("008", "cfWoLwvjU4"), CODE("035", "ArVxJcGDsm"), CODE("006", "DbXS0lrypC"), CODE("039", "KRcQj7wUat"),
|
|
2959
3005
|
CODE("040", "mi9rCYg46x"), CODE("007", "nzdH5h4Nl0"), CODE("028", "NtpWi0jzXs"), CODE("037", "WxOD3MpI2o"), CODE("029", "6wCGEWquYy"),
|
|
@@ -2962,19 +3008,30 @@ const FREE_CODES = [DAILY_CODE, CODE("008", "cfWoLwvjU4"), CODE("035", "ArVxJcGD
|
|
|
2962
3008
|
// lost at the same midnight on every account, so they tell none apart
|
|
2963
3009
|
const SLICE = "4"
|
|
2964
3010
|
|
|
2965
|
-
// PLAN_CODES are the
|
|
2966
|
-
//
|
|
2967
|
-
// Pro monthly plus, Pro yearly, youth, advanced,
|
|
2968
|
-
//
|
|
2969
|
-
//
|
|
2970
|
-
//
|
|
2971
|
-
//
|
|
2972
|
-
//
|
|
3011
|
+
// PLAN_CODES are the plan's base credits, as WorkBuddy's client (WorkBuddy
|
|
3012
|
+
// AI 5.9.4) groups them in its usage panel (resolveCreditGroup's
|
|
3013
|
+
// planBase): Pro monthly, Pro monthly plus, Pro yearly, youth, advanced,
|
|
3014
|
+
// flagship, buddyOneVip, the international free plan (freeMonIntl), the
|
|
3015
|
+
// Pro trials, and on the China build alone the free plan's monthly base
|
|
3016
|
+
// (freeMon, 套餐基础积分). The plan's bonus (bonus28; bonusIntl, "Plan
|
|
3017
|
+
// Bonus Quota") comes back each cycle too, but the client says it apart
|
|
3018
|
+
// (planBonus), as it does the credit packs (009, 036, 038: addon) and
|
|
3019
|
+
// activity, bonus29/30 and gift (benefit).
|
|
2973
3020
|
const PLAN_CODES = [CODE("002", "AkiJS3ZHF5"), CODE("005", "maRGyrHhw1"), CODE("003", "FAnt7lcmRT"), CODE("023", "4xbGhMrE6q"),
|
|
2974
|
-
CODE("026", "BaESVICNoi"), CODE("027", "0FCGVA6vSa"), CODE("
|
|
2975
|
-
CODE("039", "KRcQj7wUat"), CODE("040", "mi9rCYg46x")
|
|
3021
|
+
CODE("026", "BaESVICNoi"), CODE("027", "0FCGVA6vSa"), CODE("043", "6oIkxT7Z0S"), CODE("035", "ArVxJcGDsm"),
|
|
3022
|
+
CODE("039", "KRcQj7wUat"), CODE("040", "mi9rCYg46x")]
|
|
2976
3023
|
const FREE_MON = CODE("008", "cfWoLwvjU4")
|
|
2977
3024
|
|
|
3025
|
+
// EXTRA_CODES are the kinds of extra credits WorkBuddy's own usage panel
|
|
3026
|
+
// shows beside the plan's base (WorkBuddy 5.5.6, the China build's
|
|
3027
|
+
// resolveCreditGroup): the plan's bonus (bonus28, bonusIntl), top-ups
|
|
3028
|
+
// (extra 009, extra38 038, extraIntl 036) and platform rewards (activity
|
|
3029
|
+
// 007, bonus29, bonus30), and on WorkBuddy AI the free month (008) and
|
|
3030
|
+
// gift (006) too. The China build puts gift in no group, so it shows none.
|
|
3031
|
+
const EXTRA_CODES = [CODE("028", "NtpWi0jzXs"), CODE("037", "WxOD3MpI2o"), CODE("009", "0XmEQc2xOf"), CODE("038", "OhvqZtiPKr"),
|
|
3032
|
+
CODE("036", "lupO5WgNdG"), CODE("007", "nzdH5h4Nl0"), CODE("029", "6wCGEWquYy"), CODE("030", "BjSt89qTvr")]
|
|
3033
|
+
const EXTRA_AI = [FREE_MON, CODE("006", "DbXS0lrypC")]
|
|
3034
|
+
|
|
2978
3035
|
// planCodes says whether a package of the summary is the plan's own: one
|
|
2979
3036
|
// of PLAN_CODES on that site, or the subscription the summary names.
|
|
2980
3037
|
function planCodes(sum, site) {
|
|
@@ -3811,6 +3868,18 @@ function makePlugin(site) {
|
|
|
3811
3868
|
Object.assign(stops, runsOutOf(sum, packages) ?? {})
|
|
3812
3869
|
const aside = extra ? (stops === credits ? extra : credits) : null
|
|
3813
3870
|
if (aside) Object.assign(aside, runsOutOf(sum, packages, Date.now(), (code) => ofPlan(code) === (aside === credits)) ?? {})
|
|
3871
|
+
// the summary of the plan's credits alone: the extra ones
|
|
3872
|
+
// only the detail lists have (listedExtra) are their window,
|
|
3873
|
+
// always set aside. Whether WorkBuddy spends them once the
|
|
3874
|
+
// plan's are gone isn't seen, so the plan's window stops the
|
|
3875
|
+
// account as it did before.
|
|
3876
|
+
const kinds = !extra && kindsOf(sum, site)
|
|
3877
|
+
const more = kinds && kinds.plan.total > 0 && kinds.extra.total === 0 ? listedExtra(sum, packages, site) : null
|
|
3878
|
+
if (more) {
|
|
3879
|
+
const { runsOutAt, runsOut, ...counts } = more
|
|
3880
|
+
const w = { ...creditWindow("Extra credits", counts), aside: true, ...(runsOutAt ? { runsOutAt, runsOut } : {}) }
|
|
3881
|
+
out.windows.splice(out.windows.indexOf(credits) + 1, 0, w)
|
|
3882
|
+
}
|
|
3814
3883
|
} catch {}
|
|
3815
3884
|
}
|
|
3816
3885
|
await spareFree(site, a, out.windows)
|
|
@@ -3968,4 +4037,4 @@ export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
|
3968
4037
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
3969
4038
|
|
|
3970
4039
|
// for tests
|
|
3971
|
-
export const _internal = { planCodes, idFor, OFF_TAKEN, replyAfterToolsOn, withDefaultEffort, SMALL_BUDGET, 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, pinning, rowTime, rowAccount, ofAccount, windowOffset, windowReset, FREE_WINDOW_MODELS, FREE_WINDOW_CN, FREE_WINDOW_AI, FREE_WINDOW_SPAN, FREE_WINDOW_GAP, FREE_WINDOW_LEAD, checkinOf, API_MESSAGES: NPM_MESSAGES, API_CHAT: NPM }
|
|
4040
|
+
export const _internal = { planCodes, listedExtra, idFor, OFF_TAKEN, replyAfterToolsOn, withDefaultEffort, SMALL_BUDGET, 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, pinning, rowTime, rowAccount, ofAccount, windowOffset, windowReset, FREE_WINDOW_MODELS, FREE_WINDOW_CN, FREE_WINDOW_AI, 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.17",
|
|
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",
|