@magpie-community/opencode-workbuddy-auth 0.1.15 → 0.1.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/index.mjs +39 -8
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -77,9 +77,27 @@ const SITES = {
|
|
|
77
77
|
platform: "workbuddy-ai",
|
|
78
78
|
ai: true,
|
|
79
79
|
models: AI_MODELS,
|
|
80
|
+
// models whose images WorkBuddy AI drops though its config says they
|
|
81
|
+
// take them (see textOnly)
|
|
82
|
+
noImages: /^glm-/,
|
|
80
83
|
},
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
// textOnly says whether site drops the images sent to model, whatever its
|
|
87
|
+
// config says. On 2026-10-13, with a real WorkBuddy AI account (Yirasumi on
|
|
88
|
+
// Discord), www.workbuddy.ai's /v3/config marked every model
|
|
89
|
+
// supportsImages: true, but a chat to glm-5.3-flash, glm-5.3 or glm-5.2
|
|
90
|
+
// came back saying "[System reminder: the current model does not support
|
|
91
|
+
// images. Content filtered. ...]": the server had taken the image out.
|
|
92
|
+
// Its other models (deepseek-v4.1-flash, kimi, gemini, grok, gpt) read
|
|
93
|
+
// them, and WorkBuddy (China)'s glm-5.3-flash does too, so this is WorkBuddy
|
|
94
|
+
// AI's GLM models alone. Said text-only, magpie's image-describing model
|
|
95
|
+
// reads the image for them; a user who said the model takes images keeps
|
|
96
|
+
// their own answer (magpie's settings, over what this list says).
|
|
97
|
+
function textOnly(site, model) {
|
|
98
|
+
return !!site.noImages?.test(model)
|
|
99
|
+
}
|
|
100
|
+
|
|
83
101
|
const NPM = "@ai-sdk/openai-compatible"
|
|
84
102
|
const hex = () => randomBytes(16).toString("hex")
|
|
85
103
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
|
|
@@ -1180,7 +1198,7 @@ async function liveModels(site, a) {
|
|
|
1180
1198
|
if (d) {
|
|
1181
1199
|
m.context = d.maxInputTokens
|
|
1182
1200
|
m.output = d.maxOutputTokens
|
|
1183
|
-
m.images = d.supportsImages === true
|
|
1201
|
+
m.images = d.supportsImages === true && !textOnly(site, id)
|
|
1184
1202
|
const r = creditsOf(d.credits)
|
|
1185
1203
|
if (r !== undefined) {
|
|
1186
1204
|
m.free = r === 0
|
|
@@ -1332,6 +1350,18 @@ const REFUSED_HINT =
|
|
|
1332
1350
|
"WorkBuddy refuses chats from Codex and Claude Code (their system prompt); use it from Hermes, OpenCode or Pi, or add another provider to this group"
|
|
1333
1351
|
const REFUSED = /unapproved channel|illegal api invocation/i
|
|
1334
1352
|
|
|
1353
|
+
// RESTRICTED_HINT is what the user can do about WorkBuddy's 403 code 11140
|
|
1354
|
+
// "request illegal", whose displayMsg says "Your account has been restricted
|
|
1355
|
+
// due to unusual activity" (magpie #1849): the account is out until WorkBuddy
|
|
1356
|
+
// lifts the restriction, which an appeal asks for. It ends the error's
|
|
1357
|
+
// message as magpie's built-in puts it (provider.WBRestrictedHint), word for
|
|
1358
|
+
// word, so magpie rests the account for hours rather than minutes.
|
|
1359
|
+
const RESTRICTED_HINT =
|
|
1360
|
+
"WorkBuddy restricted this account for unusual activity; it stays out until WorkBuddy lifts that, which an appeal (Submit feedback in WorkBuddy) asks for"
|
|
1361
|
+
const RESTRICTED_CODE = 11140
|
|
1362
|
+
// The code is matched whole, as with 14018: 111400 is another error.
|
|
1363
|
+
const RESTRICTED_TEXT = /account has been restricted due to unusual activity|账号存在异常行为|帳號存在異常行為|["']code["']\s*:\s*["']?11140(?![\d.])/i
|
|
1364
|
+
|
|
1335
1365
|
// EXHAUSTED_HINT explains WorkBuddy's requirement of an active package
|
|
1336
1366
|
// even for 0-rate / free models. When an account has no packages or 0 credits,
|
|
1337
1367
|
// WorkBuddy returns code 14018 ("Credits exhausted...").
|
|
@@ -1349,7 +1379,7 @@ function kept(res) {
|
|
|
1349
1379
|
return new Response(res.body, { status: res.status, statusText: res.statusText, headers })
|
|
1350
1380
|
}
|
|
1351
1381
|
|
|
1352
|
-
// explained is res with REFUSED_HINT or EXHAUSTED_HINT added to that refusal's message.
|
|
1382
|
+
// explained is res with REFUSED_HINT, RESTRICTED_HINT or EXHAUSTED_HINT added to that refusal's message.
|
|
1353
1383
|
// Each refusal says the sign-in is kept: the built-in passed WorkBuddy's
|
|
1354
1384
|
// 401 on and never marked a WorkBuddy account lapsed.
|
|
1355
1385
|
async function explained(res) {
|
|
@@ -1368,8 +1398,9 @@ async function explained(res) {
|
|
|
1368
1398
|
const at = v?.error && typeof v.error === "object" ? v.error : v && typeof v === "object" ? v : null
|
|
1369
1399
|
const code = at?.data?.code ?? at?.code ?? v?.code ?? v?.data?.code
|
|
1370
1400
|
const isRefused = REFUSED.test(text)
|
|
1371
|
-
const
|
|
1372
|
-
|
|
1401
|
+
const isRestricted = !isRefused && (Number(code) === RESTRICTED_CODE || RESTRICTED_TEXT.test(text))
|
|
1402
|
+
const isExhausted = !isRestricted && (code === 14018 || Number(code) === 14018 || EXHAUSTED_TEXT.test(text))
|
|
1403
|
+
if (!isRefused && !isRestricted && !isExhausted) return again(text)
|
|
1373
1404
|
|
|
1374
1405
|
let msg = text.trim()
|
|
1375
1406
|
if (at && typeof at.message === "string") msg = at.message
|
|
@@ -1378,9 +1409,9 @@ async function explained(res) {
|
|
|
1378
1409
|
else if (typeof v?.msg === "string" && v.msg) msg = v.msg // WorkBuddy's own {"code", "msg"}
|
|
1379
1410
|
else if (typeof v?.data?.msg === "string") msg = v.data.msg
|
|
1380
1411
|
|
|
1381
|
-
const hint = isRefused ? REFUSED_HINT : EXHAUSTED_HINT
|
|
1382
|
-
const type = isRefused ? "permission_error" : "insufficient_quota"
|
|
1383
|
-
const errCode = isRefused ? null : 14018
|
|
1412
|
+
const hint = isRefused ? REFUSED_HINT : isRestricted ? RESTRICTED_HINT : EXHAUSTED_HINT
|
|
1413
|
+
const type = isRefused || isRestricted ? "permission_error" : "insufficient_quota"
|
|
1414
|
+
const errCode = isRefused ? null : isRestricted ? RESTRICTED_CODE : 14018
|
|
1384
1415
|
msg = `${msg} — ${hint}`
|
|
1385
1416
|
const headers = new Headers(res.headers)
|
|
1386
1417
|
headers.set("content-type", "application/json")
|
|
@@ -1394,4 +1425,4 @@ export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
|
1394
1425
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
1395
1426
|
|
|
1396
1427
|
// for tests
|
|
1397
|
-
export const _internal = { runsOutOf, packagesOf, endOf, enterpriseHeaders, enterpriseOf, liveModels, browserSignIn, withSystem, normalizeToolChoice, fitTools, fitted, renamed, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, EXHAUSTED_HINT, freeCredits, creditsOf, fresh, SITES, renewing, renewed, SESSION, attend, turnKey, conversationKey, signatureOf }
|
|
1428
|
+
export const _internal = { textOnly, runsOutOf, packagesOf, endOf, enterpriseHeaders, enterpriseOf, liveModels, browserSignIn, withSystem, normalizeToolChoice, fitTools, fitted, renamed, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, RESTRICTED_HINT, EXHAUSTED_HINT, freeCredits, creditsOf, fresh, SITES, renewing, renewed, SESSION, attend, turnKey, conversationKey, signatureOf }
|
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.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",
|