@magpie-community/opencode-workbuddy-auth 0.2.0 → 0.2.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/README.md +13 -0
- package/index.mjs +47 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,19 @@ as WorkBuddy's own client sends them; without them WorkBuddy answers as the
|
|
|
61
61
|
personal account, with the personal plan's models. A browser sign-in made
|
|
62
62
|
before 0.1.13 has no enterprise id kept: sign in again.
|
|
63
63
|
|
|
64
|
+
Which account a browser sign-in gives is chosen on WorkBuddy's own sign-in
|
|
65
|
+
page. After a phone sign-in it lists the person's accounts (personal, a
|
|
66
|
+
team, 「WorkBuddy 教育公益版」…) and binds the one picked to the sign-in, so
|
|
67
|
+
to add an education or team account, pick it there. Its account is named
|
|
68
|
+
with the enterprise too (`nickname · enterprise name`, or the end of the
|
|
69
|
+
enterprise id when WorkBuddy names none): one person's personal and
|
|
70
|
+
enterprise accounts share the uid and the nickname, and magpie keeps one
|
|
71
|
+
account per name and uid, so before 0.2.1 signing in to the enterprise
|
|
72
|
+
account replaced the personal one. An enterprise account signed in before
|
|
73
|
+
0.2.1 keeps its old name until its Sign in again, which renames it in
|
|
74
|
+
place; its free-model window, read from usage rows kept under the old
|
|
75
|
+
name, starts again from the new one.
|
|
76
|
+
|
|
64
77
|
Desktop's sign-in is refreshed only when the app hasn't refreshed it
|
|
65
78
|
itself, and the new token is kept in memory, never written back, as magpie's
|
|
66
79
|
built-in WorkBuddy does.
|
package/index.mjs
CHANGED
|
@@ -415,16 +415,26 @@ function enterpriseHeaders(a) {
|
|
|
415
415
|
return id ? { "X-Enterprise-Id": id, "X-Tenant-Id": id } : {}
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
// enterpriseOf is the enterprise the account a sign-in gave belongs to
|
|
419
|
-
// the one /login/account names, else, for an account that
|
|
420
|
-
// the one WorkBuddy's account list has for it — the same
|
|
421
|
-
// own client makes (mergeCurrentAccountDetails): the
|
|
422
|
-
// type, or the only one it last signed in to. None
|
|
418
|
+
// enterpriseOf is the enterprise the account a sign-in gave belongs to,
|
|
419
|
+
// { id, name }: the one /login/account names, else, for an account that
|
|
420
|
+
// isn't personal, the one WorkBuddy's account list has for it — the same
|
|
421
|
+
// choice WorkBuddy's own client makes (mergeCurrentAccountDetails): the
|
|
422
|
+
// uid's only entry of that type, or the only one it last signed in to. None
|
|
423
|
+
// found is personal ({ id: "" }).
|
|
424
|
+
//
|
|
425
|
+
// Which account that is was chosen on WorkBuddy's sign-in page: after a
|
|
426
|
+
// phone sign-in it lists the person's accounts (personal, a team,
|
|
427
|
+
// 「WorkBuddy 教育公益版」…) and binds the one picked to the sign-in's state
|
|
428
|
+
// (POST /console/login/enterprise/<id>?state=…), so the token and
|
|
429
|
+
// /login/account this plugin reads by that state are the chosen account's.
|
|
423
430
|
async function enterpriseOf(site, a, who) {
|
|
431
|
+
const name = (x) => (typeof x?.enterpriseName === "string" ? x.enterpriseName.trim() : "")
|
|
424
432
|
const own = typeof who?.enterpriseId === "string" ? who.enterpriseId.trim() : ""
|
|
425
|
-
if (own) return own
|
|
426
433
|
const type = String(who?.type ?? "").trim().toLowerCase()
|
|
427
|
-
if (!type || type === "personal") return ""
|
|
434
|
+
if (!own && (!type || type === "personal")) return { id: "", name: "" }
|
|
435
|
+
// a name /login/account leaves out is the account list's, as the
|
|
436
|
+
// client merges the two
|
|
437
|
+
if (own && name(who)) return { id: own, name: name(who) }
|
|
428
438
|
let list
|
|
429
439
|
try {
|
|
430
440
|
list = await call(site, "GET", "/v2/plugin/accounts", {
|
|
@@ -432,13 +442,29 @@ async function enterpriseOf(site, a, who) {
|
|
|
432
442
|
"X-Domain": domainOf(site, a),
|
|
433
443
|
})
|
|
434
444
|
} catch {
|
|
435
|
-
return ""
|
|
445
|
+
return { id: own, name: "" }
|
|
436
446
|
}
|
|
437
447
|
const mine = (list?.accounts ?? []).filter((x) => x?.uid === who.uid && typeof x.enterpriseId === "string" && x.enterpriseId.trim())
|
|
448
|
+
if (own) return { id: own, name: name(mine.find((x) => x.enterpriseId.trim() === own)) }
|
|
438
449
|
const same = mine.filter((x) => String(x.type ?? "").trim().toLowerCase() === type)
|
|
439
450
|
const last = mine.filter((x) => x.lastLogin)
|
|
440
451
|
const pick = same.length === 1 ? same[0] : last.length === 1 ? last[0] : mine.length === 1 ? mine[0] : undefined
|
|
441
|
-
return pick ? pick.enterpriseId.trim() : ""
|
|
452
|
+
return pick ? { id: pick.enterpriseId.trim(), name: name(pick) } : { id: "", name: "" }
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// accountName is what magpie lists an account a sign-in gave as: the
|
|
456
|
+
// person's name, and for an enterprise (team, education) account the
|
|
457
|
+
// enterprise's too. One person's personal account and their enterprise one
|
|
458
|
+
// share the uid and the nickname, and magpie's plugin host keeps one
|
|
459
|
+
// account per name and uid (settle in host.js): named alike, signing in to
|
|
460
|
+
// 「WorkBuddy 教育公益版」 took the place of the same person's personal
|
|
461
|
+
// account, and the two could never be in one pool. An enterprise WorkBuddy
|
|
462
|
+
// names no name for is told by the end of its id.
|
|
463
|
+
function accountName(who, ent) {
|
|
464
|
+
const person = who?.nickname || who?.phoneNumber || who?.uid || ""
|
|
465
|
+
if (!ent?.id) return person
|
|
466
|
+
const team = ent.name || `enterprise ${ent.id.slice(-6)}`
|
|
467
|
+
return person ? `${person} · ${team}` : team
|
|
442
468
|
}
|
|
443
469
|
|
|
444
470
|
// WorkBuddy's own client names each chat to its gateway four ways: the
|
|
@@ -793,8 +819,14 @@ const FLAGGED = [
|
|
|
793
819
|
[/(?<!the )Codex CLI is an open source project led by OpenAI\./gi, "The Codex CLI is an open source project led by OpenAI."],
|
|
794
820
|
// DeepSeek Harness (DSH) opens its system prompt with this line, which
|
|
795
821
|
// WorkBuddy refuses as 11128 (magpie-community/plugins#279; the same
|
|
796
|
-
// refusal traced in smart-open/TraeWorkAssistant#125).
|
|
797
|
-
|
|
822
|
+
// refusal traced in smart-open/TraeWorkAssistant#125). WorkBuddy matches
|
|
823
|
+
// the line whole and exactly, so a comma is enough to pass: measured on
|
|
824
|
+
// 2026-10-30 against copilot.tencent.com, one account, streamed, the line
|
|
825
|
+
// as DSH writes it answered 400 code 11128 and the same line with the
|
|
826
|
+
// comma answered 200. Saying it in another agent's terms passed too, but
|
|
827
|
+
// took the harness's own name out of the only line that says which agent
|
|
828
|
+
// runs here, and that name is what the rest of the prompt refers back to.
|
|
829
|
+
[/You are an AI agent powered by DeepSeek Harness\.?/gi, "You are an AI agent, powered by DeepSeek Harness."],
|
|
798
830
|
// A line WorkBuddy refuses in a long DeepSeek Harness chat, measured 400
|
|
799
831
|
// then 200 with this wording by tearslee (magpie-community/plugins#291). The
|
|
800
832
|
// model can quote it back into an assistant message, which the move to
|
|
@@ -1541,8 +1573,9 @@ async function browserSignIn(site) {
|
|
|
1541
1573
|
"X-No-Enterprise-Id": "true",
|
|
1542
1574
|
}, [12151], deadline)
|
|
1543
1575
|
a.uid = who.uid ?? ""
|
|
1544
|
-
|
|
1545
|
-
|
|
1576
|
+
const ent = await enterpriseOf(site, a, who)
|
|
1577
|
+
a.enterpriseId = ent.id
|
|
1578
|
+
return success(site, a, accountName(who, ent))
|
|
1546
1579
|
} catch (e) {
|
|
1547
1580
|
return { type: "failed", error: e.message }
|
|
1548
1581
|
}
|
|
@@ -3504,4 +3537,4 @@ export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
|
3504
3537
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
3505
3538
|
|
|
3506
3539
|
// for tests
|
|
3507
|
-
export const _internal = { idFor, replyAfterToolsOn, withDefaultEffort, defaultEffortOf, gzipped, FREE_ONLY, PRICE_TTL, keyAccount, remoteConfig, cycleOf, typeUnions, systemAsUser, systemKey, DEFAULT_SYSTEM, EDGE_READS, fitShape, replyAfterTools, AFTER_TOOLS_REFUSED, enterpriseUsageOf, notDesktop, textOnly, runsOutOf, packagesOf, endOf, enterpriseHeaders, enterpriseOf, liveModels, browserSignIn, withSystem, asReasoning, normalizeToolChoice, fitTools, fitted, renamed, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, RESTRICTED_HINT, EXHAUSTED_HINT, 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 }
|
|
3540
|
+
export const _internal = { idFor, 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, unflagged, usageOf, desktopHeld, explained, REFUSED_HINT, RESTRICTED_HINT, EXHAUSTED_HINT, 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.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",
|