@magpie-community/opencode-workbuddy-auth 0.1.42 → 0.1.44
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 +10 -1
- package/index.mjs +174 -44
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -235,7 +235,16 @@ is used.
|
|
|
235
235
|
- Kimi-K3, Kimi-K2.6
|
|
236
236
|
- MiniMax-M3
|
|
237
237
|
|
|
238
|
-
A model's reasoning levels are its variants (`reasoningEffort`).
|
|
238
|
+
A model's reasoning levels are its variants (`reasoningEffort`). A chat
|
|
239
|
+
that names no level goes at the model's own default from the config
|
|
240
|
+
(`reasoning.defaultEffort`, "high" for DeepSeek-V4.1-Flash), as WorkBuddy's
|
|
241
|
+
client sends it: WorkBuddy doesn't think when a chat names none, so
|
|
242
|
+
OpenCode's default variant got answers without thinking. An effort the
|
|
243
|
+
client names, `none` too, goes as it came.
|
|
244
|
+
|
|
245
|
+
A chat goes gzipped (`Content-Encoding: gzip`), as WorkBuddy's own client
|
|
246
|
+
sends its model requests (`RequestBodyGzip` in both builds' product.json).
|
|
247
|
+
Claude's Messages route goes as it came.
|
|
239
248
|
|
|
240
249
|
A model's price is its `credits` ("x0.29") and the config's
|
|
241
250
|
`modelPromotions`. A discount for whole days (Step-5-Preview's 独家限免) is
|
package/index.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import { createHash, randomBytes } from "node:crypto"
|
|
|
13
13
|
import { readFileSync } from "node:fs"
|
|
14
14
|
import { homedir } from "node:os"
|
|
15
15
|
import { join } from "node:path"
|
|
16
|
+
import { gzipSync } from "node:zlib"
|
|
16
17
|
|
|
17
18
|
const APP_VERSION = "2.0.0" // the version WorkBuddy's sign-in page is opened with
|
|
18
19
|
const POLL_MS = 1000
|
|
@@ -458,8 +459,28 @@ const SALT = randomBytes(16).toString("hex")
|
|
|
458
459
|
|
|
459
460
|
// idFor is the 32 hex digits WorkBuddy's own ids are made of, made of a
|
|
460
461
|
// name of the thing the id is for (a turn, a conversation) and what names it.
|
|
462
|
+
// key is a string, or the pieces it is made of: the digest is the same
|
|
463
|
+
// either way, and a key made of a 45 MiB message is never joined into one
|
|
464
|
+
// string to be hashed (plugins#461). Each piece goes to the hash whole:
|
|
465
|
+
// Bun reads a one-byte string's bytes in place, where a piece cut into
|
|
466
|
+
// slices was measured costing a copy of each slice.
|
|
461
467
|
function idFor(kind, key) {
|
|
462
|
-
|
|
468
|
+
const h = createHash("sha256").update(`${SALT}|${kind}|`)
|
|
469
|
+
// a surrogate pair's first half ending one piece waits for the next, as
|
|
470
|
+
// the joined key would hold the pair together
|
|
471
|
+
let held = ""
|
|
472
|
+
for (let piece of typeof key === "string" ? [key] : key) {
|
|
473
|
+
if (held) piece = held + piece
|
|
474
|
+
held = ""
|
|
475
|
+
const c = piece.charCodeAt(piece.length - 1)
|
|
476
|
+
if (c >= 0xd800 && c <= 0xdbff) {
|
|
477
|
+
held = piece.slice(-1)
|
|
478
|
+
piece = piece.slice(0, -1)
|
|
479
|
+
}
|
|
480
|
+
h.update(piece)
|
|
481
|
+
}
|
|
482
|
+
if (held) h.update(held)
|
|
483
|
+
return h.digest("hex").slice(0, 32)
|
|
463
484
|
}
|
|
464
485
|
|
|
465
486
|
// signatureOf is a message content's signature: its text, and a digest of
|
|
@@ -468,14 +489,20 @@ function idFor(kind, key) {
|
|
|
468
489
|
// clients of Anthropic's shape — is left out: it is not what the user said,
|
|
469
490
|
// and it changes with every step of the send.
|
|
470
491
|
function signatureOf(content) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
492
|
+
return signatureParts(content).join("")
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// signatureParts is signatureOf in the pieces it is joined from, none empty
|
|
496
|
+
function signatureParts(content) {
|
|
497
|
+
if (typeof content === "string") return content ? [content] : []
|
|
498
|
+
if (!Array.isArray(content)) return []
|
|
499
|
+
const out = []
|
|
474
500
|
for (const part of content) {
|
|
475
501
|
const type = part?.type ?? ""
|
|
476
|
-
if (type === "" || type === "text")
|
|
477
|
-
|
|
478
|
-
|
|
502
|
+
if (type === "" || type === "text") {
|
|
503
|
+
if (typeof part?.text === "string" && part.text) out.push(part.text)
|
|
504
|
+
} else if (type !== "tool_result" && type !== "tool-result") {
|
|
505
|
+
out.push(`[${type}:${createHash("sha256").update(JSON.stringify(part)).digest("hex").slice(0, 8)}]`)
|
|
479
506
|
}
|
|
480
507
|
}
|
|
481
508
|
return out
|
|
@@ -521,13 +548,18 @@ function hasBlock(m, type) {
|
|
|
521
548
|
// has none at all: the caller then makes a fresh id for that request, as
|
|
522
549
|
// before these were derived at all.
|
|
523
550
|
function turnKey(chat) {
|
|
551
|
+
return turnParts(chat).join("")
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// turnParts is turnKey in pieces (idFor takes them): [] for ""
|
|
555
|
+
function turnParts(chat) {
|
|
524
556
|
const msgs = Array.isArray(chat?.messages) ? chat.messages : []
|
|
525
557
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
526
558
|
if (msgs[i]?.role !== "user" || answeredBefore(msgs, i)) continue
|
|
527
|
-
const sig =
|
|
528
|
-
return sig ? `u${i}
|
|
559
|
+
const sig = signatureParts(msgs[i].content)
|
|
560
|
+
return sig.length ? [`u${i}:`, ...sig] : []
|
|
529
561
|
}
|
|
530
|
-
return
|
|
562
|
+
return []
|
|
531
563
|
}
|
|
532
564
|
|
|
533
565
|
// conversationKey names the conversation a chat belongs to: the session
|
|
@@ -537,14 +569,19 @@ function turnKey(chat) {
|
|
|
537
569
|
// conversation id is sent then: a made-up one would be a conversation of the
|
|
538
570
|
// request's own, which is what fragments the usage detail in the first place.
|
|
539
571
|
function conversationKey(chat, session) {
|
|
540
|
-
|
|
572
|
+
return conversationParts(chat, session).join("")
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// conversationParts is conversationKey in pieces (idFor takes them): [] for ""
|
|
576
|
+
function conversationParts(chat, session) {
|
|
577
|
+
if (session) return [`session:${session}`]
|
|
541
578
|
const msgs = Array.isArray(chat?.messages) ? chat.messages : []
|
|
542
579
|
for (const m of msgs) {
|
|
543
580
|
if (m?.role !== "user") continue
|
|
544
|
-
const sig =
|
|
545
|
-
if (sig) return
|
|
581
|
+
const sig = signatureParts(m.content)
|
|
582
|
+
if (sig.length) return ["first:", ...sig]
|
|
546
583
|
}
|
|
547
|
-
return
|
|
584
|
+
return []
|
|
548
585
|
}
|
|
549
586
|
|
|
550
587
|
// isMessages says whether a request is an Anthropic Messages one, which
|
|
@@ -683,17 +720,17 @@ function attend(headers, body, session) {
|
|
|
683
720
|
}
|
|
684
721
|
|
|
685
722
|
function attendChat(headers, chat, session) {
|
|
686
|
-
const conv =
|
|
723
|
+
const conv = conversationParts(chat, session)
|
|
687
724
|
const msg = hex()
|
|
688
725
|
headers.set("X-Conversation-Message-ID", msg)
|
|
689
726
|
headers.set("X-Request-ID", msg)
|
|
690
727
|
if (!headers.has("X-Conversation-Request-ID")) {
|
|
691
|
-
const turn =
|
|
728
|
+
const turn = turnParts(chat)
|
|
692
729
|
// a turn is a conversation's own: two conversations whose user message
|
|
693
730
|
// reads the same are still two sends, not one
|
|
694
|
-
headers.set("X-Conversation-Request-ID", turn ? idFor("turn",
|
|
731
|
+
headers.set("X-Conversation-Request-ID", turn.length ? idFor("turn", [...conv, "|", ...turn]) : hex())
|
|
695
732
|
}
|
|
696
|
-
if (conv && !headers.has("X-Conversation-ID")) headers.set("X-Conversation-ID", idFor("conversation", conv))
|
|
733
|
+
if (conv.length && !headers.has("X-Conversation-ID")) headers.set("X-Conversation-ID", idFor("conversation", conv))
|
|
697
734
|
}
|
|
698
735
|
|
|
699
736
|
// FLAGGED are the words WorkBuddy refuses a chat for, "Illegal API
|
|
@@ -1289,6 +1326,24 @@ function fitted(body) {
|
|
|
1289
1326
|
}
|
|
1290
1327
|
}
|
|
1291
1328
|
|
|
1329
|
+
// gzipped is a chat's body compressed, as WorkBuddy's own client sends its
|
|
1330
|
+
// model requests: its CLI's GzipRequestProcessor (WorkBuddy 5.9.3, CLI
|
|
1331
|
+
// 2.165.0; WorkBuddy AI 5.8.4 the same) gzips each POST's body and sets
|
|
1332
|
+
// Content-Encoding: gzip when the product's RequestBodyGzip feature is on,
|
|
1333
|
+
// which both builds' product.json turn on and /v3/config (merged over it)
|
|
1334
|
+
// doesn't turn off. Sent as plain JSON, a long agent conversation went up
|
|
1335
|
+
// whole on every step: runmiNeverstop on X saw 2.89 GB up to
|
|
1336
|
+
// copilot.tencent.com against 258 MB down. Measured 2026-10-28 on
|
|
1337
|
+
// www.workbuddy.ai: a gzipped chat answers as the plain one does. A
|
|
1338
|
+
// Messages request (Claude on the China build) goes as it came: that route
|
|
1339
|
+
// wasn't tried gzipped. null when the body isn't sent gzipped.
|
|
1340
|
+
function gzipped(native, b) {
|
|
1341
|
+
if (native) return null
|
|
1342
|
+
if (typeof b === "string") return gzipSync(Buffer.from(b))
|
|
1343
|
+
if (b instanceof ArrayBuffer || ArrayBuffer.isView(b)) return gzipSync(b)
|
|
1344
|
+
return null
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1292
1347
|
// prepared is a request's body read once for every change the loader makes
|
|
1293
1348
|
// to it and everything it reads off it (plugins#461): a long chat, 45 MiB
|
|
1294
1349
|
// of history, was parsed six times on its way, once by each step, and
|
|
@@ -2119,6 +2174,37 @@ function effortsOf(d, site, id) {
|
|
|
2119
2174
|
return EFFORT_ORDER.filter((e) => set.has(e))
|
|
2120
2175
|
}
|
|
2121
2176
|
|
|
2177
|
+
// defaultEffortOf is the level WorkBuddy's own client asks a model for when
|
|
2178
|
+
// the user picked none: its CLI's configureThinkingSettings (WorkBuddy
|
|
2179
|
+
// 5.9.3, CLI 2.165.0) takes the session's effort, else the settings', else
|
|
2180
|
+
// the config's reasoning.defaultEffort, else reasoning.effort, and sends it
|
|
2181
|
+
// as reasoning_effort unless thinking was turned off. A request with no
|
|
2182
|
+
// reasoning_effort is not thinking on WorkBuddy's side: measured 2026-10-28
|
|
2183
|
+
// on www.workbuddy.ai, deepseek-v4.1-flash (defaultEffort "high") answered
|
|
2184
|
+
// with 0 reasoning tokens without one, and thought at low and high
|
|
2185
|
+
// (troilus1011 on X, OpenCode's default variant). A default the model's
|
|
2186
|
+
// levels don't hold is left out, as the CLI clamps it to one they do.
|
|
2187
|
+
function defaultEffortOf(d, efforts) {
|
|
2188
|
+
const own = d.reasoning?.defaultEffort ?? d.reasoning?.effort
|
|
2189
|
+
return typeof own === "string" && efforts.includes(own) ? own : undefined
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
// withDefaultEffort gives a chat that names no effort the model's default
|
|
2193
|
+
// (defaultEffortOf), as WorkBuddy's client sends it; true when it did. An
|
|
2194
|
+
// effort the client named, "none" too, goes as it came.
|
|
2195
|
+
function withDefaultEffort(chat, list) {
|
|
2196
|
+
if (!chat || typeof chat !== "object" || namesEffort(chat)) return false
|
|
2197
|
+
const m = list?.find((x) => x.id === chat.model)
|
|
2198
|
+
if (!m?.effort) return false
|
|
2199
|
+
chat.reasoning_effort = m.effort
|
|
2200
|
+
return true
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
// namesEffort is whether a chat names its effort itself, in either spelling
|
|
2204
|
+
function namesEffort(chat) {
|
|
2205
|
+
return chat.reasoning_effort !== undefined || (!!chat.reasoning && typeof chat.reasoning === "object" && chat.reasoning.effort !== undefined)
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2122
2208
|
async function liveModels(site, a) {
|
|
2123
2209
|
const headers = new Headers()
|
|
2124
2210
|
sign(site, a, headers)
|
|
@@ -2145,6 +2231,8 @@ async function liveModels(site, a) {
|
|
|
2145
2231
|
if (es.length) {
|
|
2146
2232
|
const canOff = d.reasoning?.canDisableThinking
|
|
2147
2233
|
m.efforts = [...(!d.onlyReasoning && (canOff == null || canOff) ? ["none"] : []), ...es]
|
|
2234
|
+
const def = defaultEffortOf(d, es)
|
|
2235
|
+
if (def) m.effort = def
|
|
2148
2236
|
}
|
|
2149
2237
|
}
|
|
2150
2238
|
out.push(m)
|
|
@@ -2185,13 +2273,19 @@ const AFTER_TOOLS_REFUSED = /must end with a user message|["']code["']\s*:\s*["'
|
|
|
2185
2273
|
// ending with the assistant's message is a prefill, refused as it is.
|
|
2186
2274
|
function replyAfterTools(body) {
|
|
2187
2275
|
const b = chatOf(body)
|
|
2276
|
+
return replyAfterToolsOn(b) ? JSON.stringify(b) : null
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
// replyAfterToolsOn makes replyAfterTools's change on a chat's object; false
|
|
2280
|
+
// for a chat it doesn't take
|
|
2281
|
+
function replyAfterToolsOn(b) {
|
|
2188
2282
|
const msgs = b?.messages
|
|
2189
|
-
if (!Array.isArray(msgs)) return
|
|
2283
|
+
if (!Array.isArray(msgs)) return false
|
|
2190
2284
|
let i = msgs.length - 1
|
|
2191
2285
|
while (i >= 0 && msgs[i]?.role === "user") i--
|
|
2192
|
-
if (i === msgs.length - 1 || i < 0 || msgs[i]?.role !== "tool") return
|
|
2286
|
+
if (i === msgs.length - 1 || i < 0 || msgs[i]?.role !== "tool") return false
|
|
2193
2287
|
msgs.splice(i + 1, 0, { role: "assistant", content: "" })
|
|
2194
|
-
return
|
|
2288
|
+
return true
|
|
2195
2289
|
}
|
|
2196
2290
|
|
|
2197
2291
|
// FREE_ONLY is the switch that keeps an account off credits (#430): its
|
|
@@ -2238,6 +2332,24 @@ function makePlugin(site) {
|
|
|
2238
2332
|
if (lists.size > 64) lists.delete(lists.keys().next().value)
|
|
2239
2333
|
return list
|
|
2240
2334
|
}
|
|
2335
|
+
// effortList is the list a chat's default effort is read from
|
|
2336
|
+
// (withDefaultEffort): listed's, or null when there is none to read — a
|
|
2337
|
+
// key WorkBuddy's CLI reads no config with (as models does), or a read
|
|
2338
|
+
// that failed within PRICE_TTL, so a config that can't be read costs a
|
|
2339
|
+
// chat one try a minute, not one each
|
|
2340
|
+
const unlisted = new Map()
|
|
2341
|
+
const effortList = async (a) => {
|
|
2342
|
+
if (a.source === "key" && !remoteConfig(a.key)) return null
|
|
2343
|
+
const k = listKey(a)
|
|
2344
|
+
if (Date.now() - (unlisted.get(k) ?? 0) < PRICE_TTL) return null
|
|
2345
|
+
try {
|
|
2346
|
+
return await listed(a)
|
|
2347
|
+
} catch {
|
|
2348
|
+
unlisted.set(k, Date.now())
|
|
2349
|
+
if (unlisted.size > 64) unlisted.delete(unlisted.keys().next().value)
|
|
2350
|
+
return null
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2241
2353
|
const freeOnly = () => magpie?.option?.(site.id, FREE_ONLY) === true
|
|
2242
2354
|
// onlyFree is a list with the switch on: its free models, or a failure
|
|
2243
2355
|
// when there are none to tell (magpie then keeps the list it had)
|
|
@@ -2341,18 +2453,6 @@ function makePlugin(site) {
|
|
|
2341
2453
|
sign(site, a, headers)
|
|
2342
2454
|
let body = init?.body
|
|
2343
2455
|
if (body === undefined && req) body = await req.clone().text()
|
|
2344
|
-
// the switch is checked before anything is sent: a model not
|
|
2345
|
-
// free, or one whose price can't be read, never reaches WorkBuddy
|
|
2346
|
-
if (freeOnly()) {
|
|
2347
|
-
const model = chatOf(typeof body === "string" ? body : bodyString(body))?.model
|
|
2348
|
-
let list
|
|
2349
|
-
try {
|
|
2350
|
-
list = await listed(a)
|
|
2351
|
-
} catch (e) {
|
|
2352
|
-
return notFree(site, model, e?.message ?? String(e))
|
|
2353
|
-
}
|
|
2354
|
-
if (!list.some((m) => m.id === model && m.free)) return notFree(site, model)
|
|
2355
|
-
}
|
|
2356
2456
|
// An Anthropic request goes as the agent sent it: WorkBuddy
|
|
2357
2457
|
// serves these models on Messages itself, and the rewrites
|
|
2358
2458
|
// below (a default system message, the chat endpoint's
|
|
@@ -2363,16 +2463,40 @@ function makePlugin(site) {
|
|
|
2363
2463
|
// Codex's and DeepSeek Harness's openings all answer on
|
|
2364
2464
|
// /v1/messages, where a chat is refused 11128.
|
|
2365
2465
|
const native = isMessages(req ? req.url : String(input), body)
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
let changed
|
|
2370
|
-
body =
|
|
2371
|
-
if (
|
|
2466
|
+
// read once (prepared): nothing below parses the body again on
|
|
2467
|
+
// its way out, and nothing keeps the parsed chat once it is
|
|
2468
|
+
// written (plugins#461)
|
|
2469
|
+
let chat, changed, names
|
|
2470
|
+
;({ body, chat, changed, names } = prepared(body, native))
|
|
2471
|
+
if (native) names = {}
|
|
2472
|
+
// the switch is checked before anything is sent: a model not
|
|
2473
|
+
// free, or one whose price can't be read, never reaches
|
|
2474
|
+
// WorkBuddy. The model is read off the chat parsed above; a body
|
|
2475
|
+
// prepared leaves unread (bytes on Messages) is read for it.
|
|
2476
|
+
if (freeOnly()) {
|
|
2477
|
+
const model = (chat ?? chatOf(typeof body === "string" ? body : bodyString(body)))?.model
|
|
2478
|
+
let list
|
|
2479
|
+
try {
|
|
2480
|
+
list = await listed(a)
|
|
2481
|
+
} catch (e) {
|
|
2482
|
+
return notFree(site, model, e?.message ?? String(e))
|
|
2483
|
+
}
|
|
2484
|
+
if (!list.some((m) => m.id === model && m.free)) return notFree(site, model)
|
|
2485
|
+
}
|
|
2486
|
+
// a chat that names no effort is asked at the model's default,
|
|
2487
|
+
// as WorkBuddy's client asks it (withDefaultEffort); with no
|
|
2488
|
+
// list to read (effortList) the chat goes as it came
|
|
2489
|
+
if (!native && chat && !namesEffort(chat) && withDefaultEffort(chat, await effortList(a))) changed = true
|
|
2372
2490
|
chatHeaders(site, headers)
|
|
2373
2491
|
attendChat(headers, chat, session)
|
|
2374
|
-
const post = (b) =>
|
|
2375
|
-
|
|
2492
|
+
const post = (b) => {
|
|
2493
|
+
// a chat goes gzipped, as WorkBuddy's client sends it
|
|
2494
|
+
// (gzipped); its size on the wire is what unanswered weighs
|
|
2495
|
+
const z = gzipped(native, b)
|
|
2496
|
+
if (z) headers.set("Content-Encoding", "gzip")
|
|
2497
|
+
else headers.delete("Content-Encoding")
|
|
2498
|
+
return fetch(req ? req.url : input, { ...init, method: init?.method ?? req?.method, headers, body: z ?? b }).catch((e) => unanswered(site, a, z ?? b, e, init?.signal))
|
|
2499
|
+
}
|
|
2376
2500
|
// a 401 is answered once, on whichever try meets it: by a
|
|
2377
2501
|
// sign-in with another access token (reissued), the request
|
|
2378
2502
|
// sent once more with it, never again after that; else, or
|
|
@@ -2422,10 +2546,16 @@ function makePlugin(site) {
|
|
|
2422
2546
|
// words at once (see systemAsUser)
|
|
2423
2547
|
const sysKey = native ? "" : systemKeyOf(chat)
|
|
2424
2548
|
if (sysKey && refusedSystems.has(sysKey) && systemAsUserOn(chat)) changed = true
|
|
2549
|
+
// shaped is a body as such a model takes it. The first try's
|
|
2550
|
+
// is made on the chat already parsed, after the move above,
|
|
2551
|
+
// as shaped would make it of the body written; a resend with
|
|
2552
|
+
// the system prompt moved (below) is shaped again, and a body
|
|
2553
|
+
// that has the reply already is left as it is.
|
|
2554
|
+
const shaped = (b) => (!native && endsAfterTools.has(model) ? replyAfterTools(b) ?? b : b)
|
|
2555
|
+
if (!native && endsAfterTools.has(model) && replyAfterToolsOn(chat)) changed = true
|
|
2425
2556
|
if (changed) body = JSON.stringify(chat)
|
|
2426
2557
|
chat = null
|
|
2427
|
-
|
|
2428
|
-
let res = await send(shaped(body))
|
|
2558
|
+
let res = await send(body)
|
|
2429
2559
|
// a signature WorkBuddy's own signing didn't make — a session
|
|
2430
2560
|
// moved here from another provider keeps its thinking blocks,
|
|
2431
2561
|
// and a truncated or altered one reads the same way — is 11159
|
|
@@ -2653,4 +2783,4 @@ export const WorkBuddyAuthPlugin = makePlugin(SITES.workbuddy)
|
|
|
2653
2783
|
export const WorkBuddyAIAuthPlugin = makePlugin(SITES["workbuddy-ai"])
|
|
2654
2784
|
|
|
2655
2785
|
// for tests
|
|
2656
|
-
export const _internal = { 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, turnKey, conversationKey, signatureOf, isMessages, withoutUnsigned, withoutSignedThinking, prepared, answeredBefore, nativeOf, modelOf, configModels, API_MESSAGES: NPM_MESSAGES, API_CHAT: NPM }
|
|
2786
|
+
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, turnKey, conversationKey, signatureOf, isMessages, withoutUnsigned, withoutSignedThinking, prepared, answeredBefore, nativeOf, modelOf, configModels, 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.1.
|
|
3
|
+
"version": "0.1.44",
|
|
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",
|