@magpie-community/opencode-workbuddy-auth 0.1.1 → 0.1.2
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/index.mjs +74 -0
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -342,6 +342,65 @@ async function current(site, client, auth) {
|
|
|
342
342
|
return a
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
// ---- allowance ----------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
// STATUS_TEXT is Go's http.StatusText for the answers WorkBuddy gives.
|
|
348
|
+
const STATUS_TEXT = { 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed",
|
|
349
|
+
408: "Request Timeout", 429: "Too Many Requests", 500: "Internal Server Error", 502: "Bad Gateway", 503: "Service Unavailable",
|
|
350
|
+
504: "Gateway Timeout" }
|
|
351
|
+
|
|
352
|
+
// meter asks the billing API as magpie's built-in did, its errors said
|
|
353
|
+
// the same: WorkBuddy's message, else its code, else the HTTP status.
|
|
354
|
+
async function meter(site, a, path) {
|
|
355
|
+
const res = await fetch(site.endpoint + path, {
|
|
356
|
+
method: "POST",
|
|
357
|
+
headers: { "Content-Type": "application/json", Accept: "application/json", "User-Agent": "WorkBuddy/" + UA_VERSION,
|
|
358
|
+
Authorization: "Bearer " + a.access, "X-User-Id": a.uid ?? "", "X-Domain": domainOf(site, a), "X-Product": "SaaS",
|
|
359
|
+
"X-IDE-Type": "WorkBuddy" },
|
|
360
|
+
body: "{}",
|
|
361
|
+
signal: AbortSignal.timeout(20000),
|
|
362
|
+
})
|
|
363
|
+
let env = {}
|
|
364
|
+
try {
|
|
365
|
+
env = JSON.parse(await res.text()) ?? {}
|
|
366
|
+
} catch {}
|
|
367
|
+
const code = Number.parseInt(env.code, 10) || 0
|
|
368
|
+
if (!res.ok) {
|
|
369
|
+
if (code) throw new Error(env.msg || `error ${code}`)
|
|
370
|
+
if (env.msg) throw new Error(env.msg)
|
|
371
|
+
throw new Error(STATUS_TEXT[res.status] ?? "")
|
|
372
|
+
}
|
|
373
|
+
if (code) throw new Error(env.msg || `error ${code}`)
|
|
374
|
+
return env.data ?? null
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// capacity is a capacity the billing API sends, as a string ("438.88")
|
|
378
|
+
// or now and then a number; empty is 0.
|
|
379
|
+
function capacity(v) {
|
|
380
|
+
if (v == null || v === "") return 0
|
|
381
|
+
if (typeof v === "number") return v
|
|
382
|
+
const s = String(v)
|
|
383
|
+
const n = Number(s)
|
|
384
|
+
if (s.trim() !== s || Number.isNaN(n)) throw new Error(`strconv.ParseFloat: parsing ${JSON.stringify(s)}: invalid syntax`)
|
|
385
|
+
return n
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// compact is a count as magpie says one: whole, else to two places.
|
|
389
|
+
const compact = (n) => (Number.isInteger(n) ? String(n) : n.toFixed(2).replace(/0+$/, "").replace(/\.$/, ""))
|
|
390
|
+
|
|
391
|
+
// usageOf is the account's credits, from its resource summary: the plan's
|
|
392
|
+
// credits used against what the cycle grants, as magpie's built-in said.
|
|
393
|
+
function usageOf(sum, plan) {
|
|
394
|
+
const out = { plan: plan || (sum?.IsPaidUser ? "Pro" : "Free"), windows: [] }
|
|
395
|
+
let total = 0, used = 0
|
|
396
|
+
for (const p of sum?.Packages ?? []) {
|
|
397
|
+
total += capacity(p?.CycleTotalCapacity)
|
|
398
|
+
used += capacity(p?.CycleUsedCapacity)
|
|
399
|
+
}
|
|
400
|
+
if (total > 0) out.windows.push({ name: "Credits", used: (100 * used) / total, display: `${compact(used)} / ${compact(total)}` })
|
|
401
|
+
return out
|
|
402
|
+
}
|
|
403
|
+
|
|
345
404
|
// ---- models -----------------------------------------------------------------
|
|
346
405
|
|
|
347
406
|
// variants are the reasoning levels as OpenCode gives them to the AI SDK.
|
|
@@ -484,6 +543,18 @@ function makePlugin(site) {
|
|
|
484
543
|
},
|
|
485
544
|
}
|
|
486
545
|
},
|
|
546
|
+
// the account's credits, as magpie's built-in showed them
|
|
547
|
+
async usage(getAuth) {
|
|
548
|
+
const auth = await getAuth()
|
|
549
|
+
if (auth?.type !== "oauth" || !(auth.access || auth.source)) return { error: "not signed in" }
|
|
550
|
+
try {
|
|
551
|
+
const a = await current(site, client, auth)
|
|
552
|
+
// the meter has no /v2 prefix, on either site
|
|
553
|
+
return usageOf(await meter(site, a, "/billing/meter/get-user-resource-summary"), auth.plan)
|
|
554
|
+
} catch (e) {
|
|
555
|
+
return { error: e?.message ?? String(e) }
|
|
556
|
+
}
|
|
557
|
+
},
|
|
487
558
|
methods: [
|
|
488
559
|
{
|
|
489
560
|
type: "oauth",
|
|
@@ -502,3 +573,6 @@ function makePlugin(site) {
|
|
|
502
573
|
|
|
503
574
|
export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
504
575
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
576
|
+
|
|
577
|
+
// for tests
|
|
578
|
+
export const _internal = { usageOf, desktopHeld }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magpie-community/opencode-workbuddy-auth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
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",
|