@magpie-community/opencode-workbuddy-auth 0.1.39 → 0.1.40
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 +14 -2
- package/index.mjs +60 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,7 +124,11 @@ estimate.
|
|
|
124
124
|
|
|
125
125
|
Each chat carries WorkBuddy's headers:
|
|
126
126
|
- `Authorization`, `X-User-Id`, `X-Domain`, `X-Product: SaaS`, `X-IDE-Type: WorkBuddy`;
|
|
127
|
-
- `User-Agent
|
|
127
|
+
- the desktop CLI's `User-Agent`, `WorkBuddy/<app> <appName>/<app> CLI/<cli>`:
|
|
128
|
+
`WorkBuddy/5.9.3 WorkBuddy/5.9.3 CLI/2.165.0` on the China build and
|
|
129
|
+
`WorkBuddy/5.8.4 workbuddy-ai/5.8.4 CLI/2.161.0` on WorkBuddy AI, each
|
|
130
|
+
build's current app on 2026-10-28; `X-IDE-Version` is the app's version.
|
|
131
|
+
A User-Agent not starting `WorkBuddy/<version>` is answered error 10085;
|
|
128
132
|
- the client's, which WorkBuddy's usage list shows as the client that asked
|
|
129
133
|
(使用端): `X-Agent-Purpose: conversation`, `X-IDE-Name: WorkBuddy`,
|
|
130
134
|
`X-IDE-Version`, `X-Agent-Intent: craft`, `X-Requested-With`. Both builds
|
|
@@ -139,7 +143,15 @@ Each chat carries WorkBuddy's headers:
|
|
|
139
143
|
else the chat's first user message; nothing is made up when neither names
|
|
140
144
|
one, a made-up conversation of the request's own being what splits one
|
|
141
145
|
conversation into many in the usage detail;
|
|
142
|
-
-
|
|
146
|
+
- what the CLI adds to a model request alone: `X-Agent-Type: main` on both
|
|
147
|
+
builds, `X-Agent-Runtime: local-agent` on the China build (new in 5.9),
|
|
148
|
+
`Accept: application/json`, and the `X-Stainless-*` headers of the OpenAI
|
|
149
|
+
SDK it sends through (openai 6.25.0 on Electron 37's Node v22.21.1, a
|
|
150
|
+
1200s timeout, no retries).
|
|
151
|
+
|
|
152
|
+
Not sent: `X-Device-Token`, which the desktop app gets from Tencent's
|
|
153
|
+
native device SDK before each prompt, and a `traceparent`, which the CLI
|
|
154
|
+
adds only while its server-side tracing is on.
|
|
143
155
|
|
|
144
156
|
A chat that doesn't open with a system message is given WorkBuddy's
|
|
145
157
|
default one, as the app does.
|
package/index.mjs
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
// the token as WorkBuddy's desktop app does) or is taken from WorkBuddy
|
|
7
7
|
// desktop's own sign-in. Its chats are chat completions at <endpoint>/v2,
|
|
8
8
|
// streamed only, with WorkBuddy's headers: a request whose User-Agent isn't
|
|
9
|
-
// WorkBuddy/<version> is refused (error 10085).
|
|
9
|
+
// WorkBuddy/<version> is refused (error 10085). Each build's headers are
|
|
10
|
+
// those of its current desktop app (see SITES' app, cli and appName).
|
|
10
11
|
|
|
11
12
|
import { createHash, randomBytes } from "node:crypto"
|
|
12
13
|
import { readFileSync } from "node:fs"
|
|
@@ -14,7 +15,6 @@ import { homedir } from "node:os"
|
|
|
14
15
|
import { join } from "node:path"
|
|
15
16
|
|
|
16
17
|
const APP_VERSION = "2.0.0" // the version WorkBuddy's sign-in page is opened with
|
|
17
|
-
const UA_VERSION = "5.5.6" // WorkBuddy/<this> is the User-Agent the API takes
|
|
18
18
|
const POLL_MS = 1000
|
|
19
19
|
const SIGN_IN_MS = 5 * 60 * 1000
|
|
20
20
|
const EARLY_MS = 60 * 1000 // a token this close to its end is refreshed before a request
|
|
@@ -67,6 +67,16 @@ const SITES = {
|
|
|
67
67
|
authID: "workbuddy-desktop",
|
|
68
68
|
platform: "workbuddy",
|
|
69
69
|
ai: false,
|
|
70
|
+
// the desktop app the requests are WorkBuddy's own client's of: its
|
|
71
|
+
// version, its bundled CLI's (@genie/agent-cli), and the CLI's
|
|
72
|
+
// product.json applicationName. Read from WorkBuddy 5.9.3.42398134,
|
|
73
|
+
// the update feed's current build on 2026-10-28.
|
|
74
|
+
app: "5.9.3",
|
|
75
|
+
cli: "2.165.0",
|
|
76
|
+
appName: "WorkBuddy",
|
|
77
|
+
// 5.9's CLI says on each chat where the agent runs; the desktop's own
|
|
78
|
+
// is "local-agent" (X-Agent-Runtime, absent in 5.8)
|
|
79
|
+
runtime: "local-agent",
|
|
70
80
|
// where this build's API keys are made (see keyAccount)
|
|
71
81
|
keys: "https://www.workbuddy.cn/profile/keys",
|
|
72
82
|
models: CN_MODELS,
|
|
@@ -81,6 +91,11 @@ const SITES = {
|
|
|
81
91
|
authID: "workbuddy-desktop-ai",
|
|
82
92
|
platform: "workbuddy-ai",
|
|
83
93
|
ai: true,
|
|
94
|
+
// WorkBuddy AI 5.8.4.41366630, its update feed's current build on
|
|
95
|
+
// 2026-10-28 (see the China build's)
|
|
96
|
+
app: "5.8.4",
|
|
97
|
+
cli: "2.161.0",
|
|
98
|
+
appName: "workbuddy-ai",
|
|
84
99
|
keys: "https://www.workbuddy.ai/profile/keys",
|
|
85
100
|
models: AI_MODELS,
|
|
86
101
|
// models whose images WorkBuddy AI drops though its config says they
|
|
@@ -155,7 +170,7 @@ async function call(site, method, path, headers = {}, body) {
|
|
|
155
170
|
headers: {
|
|
156
171
|
"Content-Type": "application/json",
|
|
157
172
|
Accept: "application/json",
|
|
158
|
-
"User-Agent": "WorkBuddy/" +
|
|
173
|
+
"User-Agent": "WorkBuddy/" + site.app,
|
|
159
174
|
...headers,
|
|
160
175
|
},
|
|
161
176
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
@@ -312,15 +327,51 @@ function sign(site, a, headers) {
|
|
|
312
327
|
}
|
|
313
328
|
headers.set("X-Product", "SaaS")
|
|
314
329
|
headers.set("X-IDE-Type", "WorkBuddy")
|
|
315
|
-
headers.set("User-Agent",
|
|
330
|
+
headers.set("User-Agent", cliAgent(site))
|
|
316
331
|
headers.set("X-Requested-With", "XMLHttpRequest")
|
|
317
332
|
headers.set("X-Agent-Intent", "craft")
|
|
318
333
|
headers.set("X-Agent-Purpose", "conversation")
|
|
319
334
|
headers.set("X-IDE-Name", "WorkBuddy")
|
|
320
|
-
headers.set("X-IDE-Version",
|
|
335
|
+
headers.set("X-IDE-Version", site.app)
|
|
321
336
|
for (const [k, v] of Object.entries(enterpriseHeaders(a))) headers.set(k, v)
|
|
322
|
-
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// cliAgent is the User-Agent WorkBuddy's desktop CLI sends its API calls
|
|
340
|
+
// (a chat, the product config) with: UserAgentHttpInterceptor's
|
|
341
|
+
// buildUserAgent puts the platform (CLIENT_INFO_PLATFORM "WorkBuddy", at
|
|
342
|
+
// the app's version) first, then the CLI's applicationName at the same
|
|
343
|
+
// version, then CLIENT_INFO_USER_AGENT_EXTENSION, "CLI/<its version>".
|
|
344
|
+
function cliAgent(site) {
|
|
345
|
+
return `WorkBuddy/${site.app} ${site.appName}/${site.app} CLI/${site.cli}`
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// OPENAI_SDK and NODE are what the CLI's chats go out through: the OpenAI
|
|
349
|
+
// SDK it bundles (openai 6.25.0) and the Node its Electron runs it on
|
|
350
|
+
// (Electron 37.10.3, ELECTRON_RUN_AS_NODE).
|
|
351
|
+
const OPENAI_SDK = "6.25.0"
|
|
352
|
+
const NODE = "v22.21.1"
|
|
353
|
+
const SDK_OS = { darwin: "MacOS", win32: "Windows", linux: "Linux", freebsd: "FreeBSD", openbsd: "OpenBSD", android: "Android" }
|
|
354
|
+
const SDK_ARCH = { x64: "x64", arm64: "arm64", arm: "arm", ia32: "x32", x32: "x32" }
|
|
355
|
+
|
|
356
|
+
// chatHeaders sets on a chat what WorkBuddy's CLI adds to its model
|
|
357
|
+
// requests alone (axiosToFetchAdapter, both builds): the agent type
|
|
358
|
+
// (resolveModelCallAgentType, "main" for the conversation's own agent),
|
|
359
|
+
// the runtime where a build sends one, and the OpenAI SDK's own headers,
|
|
360
|
+
// which the CLI's fetch passes on. Its client has a 1200s timeout and
|
|
361
|
+
// no retries of its own.
|
|
362
|
+
function chatHeaders(site, headers) {
|
|
323
363
|
headers.set("X-Agent-Type", "main")
|
|
364
|
+
if (site.runtime) headers.set("X-Agent-Runtime", site.runtime)
|
|
365
|
+
else headers.delete("X-Agent-Runtime")
|
|
366
|
+
headers.set("Accept", "application/json")
|
|
367
|
+
headers.set("X-Stainless-Retry-Count", "0")
|
|
368
|
+
headers.set("X-Stainless-Timeout", "1200")
|
|
369
|
+
headers.set("X-Stainless-Lang", "js")
|
|
370
|
+
headers.set("X-Stainless-Package-Version", OPENAI_SDK)
|
|
371
|
+
headers.set("X-Stainless-OS", SDK_OS[process.platform] ?? (process.platform ? `Other:${process.platform}` : "Unknown"))
|
|
372
|
+
headers.set("X-Stainless-Arch", SDK_ARCH[process.arch] ?? (process.arch ? `other:${process.arch}` : "unknown"))
|
|
373
|
+
headers.set("X-Stainless-Runtime", "node")
|
|
374
|
+
headers.set("X-Stainless-Runtime-Version", NODE)
|
|
324
375
|
}
|
|
325
376
|
|
|
326
377
|
// keyAccount is the account an API key (OpenCode's {type: "api", key}) is
|
|
@@ -1459,7 +1510,7 @@ const statusText = (n) => STATUS_TEXT[n] || `HTTP ${n}`
|
|
|
1459
1510
|
function meterAsked(site, a, path, body = {}, signal = AbortSignal.timeout(20000)) {
|
|
1460
1511
|
return fetch(site.endpoint + path, {
|
|
1461
1512
|
method: "POST",
|
|
1462
|
-
headers: { "Content-Type": "application/json", Accept: "application/json", "User-Agent": "WorkBuddy/" +
|
|
1513
|
+
headers: { "Content-Type": "application/json", Accept: "application/json", "User-Agent": "WorkBuddy/" + site.app,
|
|
1463
1514
|
Authorization: "Bearer " + a.access, "X-User-Id": a.uid ?? "", "X-Domain": domainOf(site, a), "X-Product": "SaaS",
|
|
1464
1515
|
"X-IDE-Type": "WorkBuddy", ...enterpriseHeaders(a) },
|
|
1465
1516
|
body: JSON.stringify(body),
|
|
@@ -1992,7 +2043,7 @@ function effortsOf(d, site, id) {
|
|
|
1992
2043
|
async function liveModels(site, a) {
|
|
1993
2044
|
const headers = new Headers()
|
|
1994
2045
|
sign(site, a, headers)
|
|
1995
|
-
headers.set("User-Agent",
|
|
2046
|
+
headers.set("User-Agent", cliAgent(site))
|
|
1996
2047
|
headers.set("X-Requested-With", "XMLHttpRequest")
|
|
1997
2048
|
headers.set("Accept", "application/json")
|
|
1998
2049
|
const res = await fetch(site.endpoint + "/v3/config", { headers, signal: AbortSignal.timeout(15000) })
|
|
@@ -2242,6 +2293,7 @@ function makePlugin(site) {
|
|
|
2242
2293
|
} else {
|
|
2243
2294
|
body = withoutUnsigned(body)
|
|
2244
2295
|
}
|
|
2296
|
+
chatHeaders(site, headers)
|
|
2245
2297
|
attend(headers, body, session)
|
|
2246
2298
|
const post = (b) =>
|
|
2247
2299
|
fetch(req ? req.url : input, { ...init, method: init?.method ?? req?.method, headers, body: b }).catch((e) => unanswered(site, a, b, e, init?.signal))
|
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.40",
|
|
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",
|