@eddyskywalker/dsh-chatgpt-subscription 0.6.0 → 0.6.5
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/CHANGELOG.md +2 -0
- package/README.md +3 -3
- package/lib/client.js +101 -242
- package/lib/client.js.map +1 -1
- package/lib/index.js +3 -1
- package/lib/types/client/workbuddy/WorkBuddySection.d.ts.map +1 -1
- package/lib/types/client/workbuddy/locales.d.ts +12 -90
- package/lib/types/client/workbuddy/locales.d.ts.map +1 -1
- package/lib/types/client/workbuddy/styles.d.ts +8 -4
- package/lib/types/client/workbuddy/styles.d.ts.map +1 -1
- package/lib/types/host/workbuddy/account-pool.d.ts.map +1 -1
- package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
- package/lib/types/shared/workbuddy-contracts.d.ts +6 -0
- package/lib/types/shared/workbuddy-contracts.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
- **账号 id 与既有设置保持一致**:号池新增 `accountId` 钩子,WorkBuddy 用它返回 `${region}:${identity}` 这个既有公开键,而不是内核默认生成的随机 `acc_xxx`。这样老用户已存下的 `selectedAccountId` / `hiddenAccountIds` 无需迁移即可继续生效。
|
|
28
28
|
- 卡片新增两个可选插槽:`renderLoginActions`(WorkBuddy 需要国区/国际区两个登录入口,单按钮表达不了)与 `renderAccountActions`(桌面账号的隐藏/恢复);`PoolAccountSummaryDto` 新增可选 `removable`(缺省即可删除)。两者对另外四条线路完全向后兼容——既有号池测试全部保持通过。
|
|
29
29
|
- 新增 `test/workbuddy-account-pool.test.ts`(14 条)与卡片/路由回归:身份与快照去重、桌面账号不可删除、隐藏不动文件、固定账号与冷却回退、轮询调度、429 换号、401 标记失效并换号、桌面 token 回写;共享卡片新增 2 条锁定「非本插件账号不出现删除按钮」。
|
|
30
|
+
- **设置页界面与另外四条线路对齐**:接入共享号池内核只统一了数据,卡片本身仍是本线路自己手搓的那套——手写的「本机凭据」账号列表排在共享卡片**前面**,随后还跟一个独立的「账号」分组堆身份字段,分组顺序、标题文案、按钮样式都与四条兄弟线路不一致。现在收敛为与四条线路**逐字一致**的分组序列(账号管理 → 连接 → 模型 → 增强功能 → 上下文窗口 → 用量与额度),标题用共享的「账号管理」,登录入口用共享的 `dsha-btn-primary`;身份信息(UIN、账号类型、区域、认证域名、凭据文件)改由共享卡片的 `renderDetails` 逐账号渲染,独立的「账号」分组整体删除,空态/路由不可达提示也移入卡片(不再与共享空态文案重复);号池摘要 DTO 因此新增 `domain` / `backend` / `accountType` 三个可选字段。
|
|
31
|
+
- **对话页模型选择器只显示模型名**:`listModels` 不再下发 `description`——五条线路里只有它带描述,DSH 的共享模型选择器会因此给这一路多渲染一行「能力说明」。设置页的模型胶囊同步只显示名称(上下文窗口 / 图片 / 思考档位改挂 `title` 提示),与四条兄弟线路的胶囊完全一致。
|
|
30
32
|
- **思考档位下拉跟随模型**:设置页此前固定渲染全部 6 档,即使当前账号的模型一个都不支持。现在选项由该账号模型**实际声明的档位**并集推导(仅部分模型支持的档位会标注,如 `High (2/5)`),没有任何模型声明档位时给出说明而不是空列表;已保存但当前无模型支持的档位会被保留并标注,不会在打开页面时被静默改写。
|
|
31
33
|
- **修正「全部返回 200 即等于全部支持」的误判**:`/v3/config` 对多数模型只报单个 `effort` 默认值(如 `deepseek-v4.1-flash` 的 `{"effort":"high"}`),此前据此推断成完整 6 档,于是 DSH 模型选择器里出现了该模型并不具备的 `minimal`/`xhigh`。逐档实测确认这类模型接受的就是 `low`/`high`/`max`——与网关为 `glm-5.3-flash`、`kimi-k2.8-preview` **显式声明**的档位完全一致,其余取值由上游收敛到最近的档位而非作为独立档位生效——因此内置兜底表与解析逻辑同步收敛为这三档(`WORKBUDDY_STANDARD_EFFORTS`)。**收紧档位后又修掉它带出的一个反向缺陷**:目录给的**默认档**也可能落在档位表之外——`minimax-m3`、`kimi-k3`、国区 `glm-5.3` 等 12 个条目都报 `medium` 却只有三档。这种「默认档不在表内」的值会被档位解析判为不支持而丢弃,于是请求不带 `reasoning_effort`,上游返回**空的 `reasoning_content`**(实测 `minimax-m3`:不带字段三次全为 0 字符,带 `medium` 为 282–659 字符)。现在默认档会收敛到表内最近的档位(`convergeWorkBuddyEffort`,平局向上取,与 kimi-code 线路 `medium`→`high` 的既有映射一致),并在 `resolveWorkBuddyModel` 这个唯一读取口统一归一化,离线兜底表同样覆盖。
|
|
32
34
|
- **合并前代码审查发现并修复的问题**(同源校验、缓存与凭据续期一致性、流式解码):`/quota` 的 POST 与其它写路由一样校验同源;`/connection/test` 与 `/catalog/refresh` 先 `ensureFresh` 续期过期 token,不再对有效账号误报 401;`loadConfigCatalog` 不再把另一区域的缓存快照当成当前区域的结果(那会让模型选择器整个空掉,而不是回落到内置表);续期回写保留原凭据文件的权限位并清理临时文件;流式请求不再附加 300s 墙钟超时(空闲超时由共享看门狗负责,长回答不会被掐断);无参工具调用同样置 `hasToolCall` 并在首个 delta 带上工具名,否则整轮会被当成普通 stop、工具永不执行;流中错误帧抛错而不是当成干净的停止;路由销毁时终止未完成的浏览器登录轮询。每条修复都有对应回归测试。
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
- **桌面账号归 IDE 所有,不可删除**:卡片只对插件自己添加的账号显示「删除」,桌面账号显示「隐藏 / 恢复」——隐藏只把它移出本插件的调度,绝不改动 CodeBuddy 的凭据文件;号池层同样拒绝删除桌面账号(双保险,均有测试);
|
|
76
76
|
- **续期后原子写回**原凭据文件(只改 `auth` 块),以免桌面端掉线——桌面账号的 refresh token 会轮换,若只写进插件自己的加密存储,IDE 手里就只剩一个已作废的 token。同一进程内的并发调用**共用一次刷新**,且不会二次刷新;
|
|
77
77
|
- 上游是 OpenAI 兼容的 `POST {backend}/v2/chat/completions`,但有两条硬约束:**只支持流式**(`stream:false` → 400 `code 11101`),且**首条消息必须是 system**(否则国际区返回 400 `code 11128`)。因此请求构造器始终发送 `stream:true`,并在调用方没给系统提示时补一条中性的,避免手搓的一次性请求踩到这条规则;
|
|
78
|
-
- **区域是凭据属性,不是请求属性**:`*.workbuddy.ai` / `*.codebuddy.ai` 走国际区 `https://www.<apex>`,其余走国区 `https://copilot.tencent.com
|
|
78
|
+
- **区域是凭据属性,不是请求属性**:`*.workbuddy.ai` / `*.codebuddy.ai` 走国际区 `https://www.<apex>`,其余走国区 `https://copilot.tencent.com`。账号卡片逐条标注每个账号的**国区 / 国际区**并允许选择;切换后,模型目录、额度和后续对话都使用该账号。历史凭据快照按账号身份自动去重。插件托管账号可真正删除;桌面扫描账号只能从本插件隐藏/恢复,永不删除 CodeBuddy 的原文件。两区模型清单不同,把模型发到不服务它的区会返回 400 `code 11102`,因此模型选择器**按当前账号区域过滤**;
|
|
79
79
|
- **模型目录取自网关自己的 `/v3/config`**(官方 CLI 启动时读的就是它):每个模型的真实上下文上限、输出上限、是否接受图片、以及可用的思考档位都在这里,不做任何按模型名猜测。`/v1/models` 在这条线路上是 404,所以此前只能靠内置表——现在内置表只作为离线兜底,且是**从真实 `/v3/config` 转录**的(早期手写版本把 `glm-5.3`、`kimi-k3` 的窗口猜成 200K/256K,实际都是 1M);
|
|
80
80
|
- 目录同时区分**默认服务的上下文长度**与**模型上限**(如 `deepseek-v4.1-flash` 默认 300K、最大 1M)。本线路不发送显式长度参数,所以 DSH 的压缩与溢出判断按**默认服务长度**计算,不会让请求越过后端实际接受的窗口;
|
|
81
81
|
- 思考档位**逐模型**取目录声明的档位表,回落顺序为「调用方显式指定 → 用户配置的默认档 → 目录为该模型声明的默认档」。最后一档不能省:上游在请求不带 `reasoning_effort` 时返回**空的 `reasoning_content`**(实测同一提示:不带字段 0 字符,带字段 130–215 字符),不发送就等于静默丢弃模型的思考。目录里的单个 `effort` 字段是**默认值**,既不是完整档位表也不是「只此一档」:实测这类模型接受 `low` / `high` / `max`,其余取值会被上游收敛到最近的档位,因此它们使用这三档的标准表(`WORKBUDDY_STANDARD_EFFORTS`);显式声明了 `supportedEfforts` 的模型则原样采信。目录给出的**默认档**也可能落在档位表之外(如 `minimax-m3`、`kimi-k3`、国区 `glm-5.3` 都报 `medium` 却只有三档),这种值会被收敛到最近的档位——否则默认档会被判为不支持而丢弃,请求不带 `reasoning_effort`,上游返回**空的 `reasoning_content`**。不在该模型档位集合内的取值会被忽略而不是发出去(上游对不支持的档位返回 `code 11150`);
|
|
@@ -307,8 +307,8 @@ DSH 设置页的「Subagent」卡片会把勾选的模型写成会话级的允
|
|
|
307
307
|
|
|
308
308
|
1. 重启 DSH,让 Host 加载本插件;
|
|
309
309
|
2. 打开 **设置 → WorkBuddy**;
|
|
310
|
-
3. 二选一:登录 CodeBuddy
|
|
311
|
-
4.
|
|
310
|
+
3. 二选一:登录 CodeBuddy 桌面端后点「重新扫描」,或点「账号管理」右上角的「添加国区账号 / 添加国际区账号」并在官方页面完成浏览器授权;
|
|
311
|
+
4. 在「账号管理」里选择账号(每条都标注国区 / 国际区),再按需勾选模型、设置默认思考深度与上下文窗口。
|
|
312
312
|
|
|
313
313
|
`workbuddy-subscription` 会像其他 Provider 一样出现在 DSH 模型选择器中,并可与名为 `workbuddy` 的自定义 API 同时存在。**上下文窗口**默认取网关 `/v3/config` 声明的**默认服务长度**,可逐模型覆盖(用于 DSH 的压缩与溢出判断,支持 `1M` / `300K` / `200000` 等写法);**默认思考深度**逐模型生效,选项由当前账号各模型**实际声明的档位**取并集(仅部分模型支持的档位会标注数量),档位不在该模型集合内时不会被发送。
|
|
314
314
|
|
package/lib/client.js
CHANGED
|
@@ -4217,41 +4217,28 @@ window.__ModuleLoader__.load({
|
|
|
4217
4217
|
title: "WorkBuddy",
|
|
4218
4218
|
pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
|
|
4219
4219
|
account: "账号",
|
|
4220
|
-
noAccounts: "
|
|
4221
|
-
signedIn: "已找到凭据",
|
|
4220
|
+
noAccounts: "暂无账号。点击右上角「添加账号」完成浏览器授权,或登录 CodeBuddy 桌面端后重新扫描;桌面账号只能从本插件隐藏,绝不删除 CodeBuddy 的原凭据。",
|
|
4222
4221
|
signedOut: "未找到凭据",
|
|
4223
4222
|
nickname: "昵称",
|
|
4224
|
-
uid: "账号 ID",
|
|
4225
4223
|
uin: "UIN",
|
|
4226
4224
|
region: "区域",
|
|
4227
4225
|
regionCn: "国区",
|
|
4228
4226
|
regionIntl: "国际区",
|
|
4229
4227
|
accountType: "账号类型",
|
|
4230
|
-
backend: "后端地址",
|
|
4231
|
-
domain: "认证域名",
|
|
4232
|
-
tokenExpires: "登录态有效期",
|
|
4233
|
-
tokenExpired: "已过期",
|
|
4234
4228
|
sourceFile: "凭据文件",
|
|
4235
4229
|
authDirectory: "凭据目录",
|
|
4236
4230
|
storage: "凭据存储",
|
|
4237
4231
|
storageNotice: "桌面端账号仍读取 CodeBuddy 自己的凭据文件,插件不会删除这些文件;通过这里添加的账号保存在系统加密存储中(Windows DPAPI / macOS Keychain / Linux Secret Service),token 不进入浏览器。",
|
|
4238
|
-
notFoundTitle: "未找到 WorkBuddy 账号",
|
|
4239
|
-
notFoundHint: "可安装并登录 CodeBuddy 后重新扫描,也可以直接点击下方「添加国区账号」或「添加国际区账号」完成浏览器授权。",
|
|
4240
4232
|
routeUnreachable: "无法读取 WorkBuddy 设置路由",
|
|
4241
4233
|
routeUnreachableHint: "浏览器里加载的插件版本可能比 Host 进程里运行的新(客户端资源是现读磁盘的,Host 只在启动时加载)。请重启 DSH,让两端来自同一份构建。",
|
|
4242
4234
|
rescan: "重新扫描",
|
|
4243
4235
|
rescanning: "扫描中...",
|
|
4244
|
-
accounts: "
|
|
4245
|
-
accountsHint: "按账号地区分组。插件添加的账号可删除;CodeBuddy 桌面账号只能从本插件隐藏,绝不删除桌面端原凭据。点击账号会切换模型目录、额度和后续对话。",
|
|
4246
|
-
useAccount: "使用此账号",
|
|
4247
|
-
selectedAccount: "当前账号",
|
|
4236
|
+
accounts: "账号管理",
|
|
4248
4237
|
addCnAccount: "添加国区账号",
|
|
4249
4238
|
addIntlAccount: "添加国际区账号",
|
|
4250
4239
|
authorizing: "授权中…",
|
|
4251
4240
|
loginWaiting: "请在新打开的浏览器页面完成登录与授权。",
|
|
4252
4241
|
loginFailed: "账号授权失败",
|
|
4253
|
-
pluginAccount: "插件账号",
|
|
4254
|
-
desktopAccount: "桌面账号",
|
|
4255
4242
|
encryptedStorage: "系统加密存储",
|
|
4256
4243
|
hiddenAccount: "已隐藏",
|
|
4257
4244
|
hideAccount: "从插件隐藏",
|
|
@@ -4310,41 +4297,28 @@ window.__ModuleLoader__.load({
|
|
|
4310
4297
|
title: "WorkBuddy",
|
|
4311
4298
|
pageDesc: "Reuse the local CodeBuddy desktop sign-in to manage WorkBuddy (CodeBuddy subscription) models, context windows, and quota.",
|
|
4312
4299
|
account: "Account",
|
|
4313
|
-
noAccounts: "No accounts yet. Add
|
|
4314
|
-
signedIn: "Credential found",
|
|
4300
|
+
noAccounts: "No accounts yet. Use “Add account” above to authorize, or sign in with the CodeBuddy desktop client and rescan; desktop accounts can only be hidden here, never removed from CodeBuddy.",
|
|
4315
4301
|
signedOut: "No credential found",
|
|
4316
4302
|
nickname: "Nickname",
|
|
4317
|
-
uid: "Account ID",
|
|
4318
4303
|
uin: "UIN",
|
|
4319
4304
|
region: "Region",
|
|
4320
4305
|
regionCn: "China",
|
|
4321
4306
|
regionIntl: "International",
|
|
4322
4307
|
accountType: "Account type",
|
|
4323
|
-
backend: "Backend",
|
|
4324
|
-
domain: "Auth domain",
|
|
4325
|
-
tokenExpires: "Sign-in valid until",
|
|
4326
|
-
tokenExpired: "Expired",
|
|
4327
4308
|
sourceFile: "Credential file",
|
|
4328
4309
|
authDirectory: "Credential directory",
|
|
4329
4310
|
storage: "Credential storage",
|
|
4330
4311
|
storageNotice: "Desktop accounts continue to use CodeBuddy’s credential files, which this plugin never deletes. Accounts added here use encrypted OS storage (Windows DPAPI, macOS Keychain, or Linux Secret Service); tokens never enter the browser.",
|
|
4331
|
-
notFoundTitle: "No WorkBuddy account found",
|
|
4332
|
-
notFoundHint: "Install and sign in to CodeBuddy and rescan, or use “Add China account” / “Add international account” below to authorize in the browser.",
|
|
4333
4312
|
routeUnreachable: "The WorkBuddy settings route could not be read",
|
|
4334
4313
|
routeUnreachableHint: "The plugin loaded in the browser may be newer than the one running in the Host: client assets are read from disk on demand, while the Host loads them only at startup. Restart DSH so both halves come from the same build.",
|
|
4335
4314
|
rescan: "Rescan",
|
|
4336
4315
|
rescanning: "Scanning...",
|
|
4337
|
-
accounts: "
|
|
4338
|
-
accountsHint: "Accounts are grouped by region. Plugin-managed accounts can be deleted; CodeBuddy desktop accounts can only be hidden from this plugin and their source files are never deleted. Selecting one switches models, quota, and chats.",
|
|
4339
|
-
useAccount: "Use this account",
|
|
4340
|
-
selectedAccount: "Selected account",
|
|
4316
|
+
accounts: "Account Management",
|
|
4341
4317
|
addCnAccount: "Add China account",
|
|
4342
4318
|
addIntlAccount: "Add international account",
|
|
4343
4319
|
authorizing: "Authorizing…",
|
|
4344
4320
|
loginWaiting: "Complete sign-in and authorization in the newly opened browser page.",
|
|
4345
4321
|
loginFailed: "Account authorization failed",
|
|
4346
|
-
pluginAccount: "Plugin account",
|
|
4347
|
-
desktopAccount: "Desktop account",
|
|
4348
4322
|
encryptedStorage: "Encrypted OS storage",
|
|
4349
4323
|
hiddenAccount: "Hidden",
|
|
4350
4324
|
hideAccount: "Hide from plugin",
|
|
@@ -4421,6 +4395,21 @@ window.__ModuleLoader__.load({
|
|
|
4421
4395
|
};
|
|
4422
4396
|
const API$4 = "/workbuddy/api";
|
|
4423
4397
|
/**
|
|
4398
|
+
* The shared card's label set.
|
|
4399
|
+
*
|
|
4400
|
+
* Only the three labels WorkBuddy genuinely words differently are taken from
|
|
4401
|
+
* this tab's dictionary; everything else is the shared set, so the five
|
|
4402
|
+
* provider tabs cannot drift apart in wording.
|
|
4403
|
+
*/
|
|
4404
|
+
function accountPoolLabels(t) {
|
|
4405
|
+
return {
|
|
4406
|
+
...accountPoolZh,
|
|
4407
|
+
noAccounts: t.noAccounts,
|
|
4408
|
+
storageNotice: t.storageNotice,
|
|
4409
|
+
email: t.nickname
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
/**
|
|
4424
4413
|
* Call one settings route and unwrap its `{ ok, value }` envelope.
|
|
4425
4414
|
*
|
|
4426
4415
|
* The response body is read as text first, because a route that is not mounted
|
|
@@ -4538,24 +4527,6 @@ window.__ModuleLoader__.load({
|
|
|
4538
4527
|
accounts: Array.isArray(data?.accounts) ? data.accounts : []
|
|
4539
4528
|
};
|
|
4540
4529
|
}
|
|
4541
|
-
/**
|
|
4542
|
-
* The shared card's label set, taken from this tab's dictionary.
|
|
4543
|
-
*
|
|
4544
|
-
* Wording is the shared one so the five provider tabs cannot drift apart; the
|
|
4545
|
-
* couple of WorkBuddy-specific words are supplied here.
|
|
4546
|
-
*/
|
|
4547
|
-
function accountPoolLabels(t) {
|
|
4548
|
-
return {
|
|
4549
|
-
...accountPoolZh,
|
|
4550
|
-
accountPool: t.accounts,
|
|
4551
|
-
noAccounts: t.noAccounts,
|
|
4552
|
-
storage: t.storage,
|
|
4553
|
-
storageNotice: t.storageNotice,
|
|
4554
|
-
deleteAccount: t.deleteAccount,
|
|
4555
|
-
email: t.nickname,
|
|
4556
|
-
accountId: t.uid
|
|
4557
|
-
};
|
|
4558
|
-
}
|
|
4559
4530
|
function WorkBuddySection({ onModelChange, loadModelDirectory }) {
|
|
4560
4531
|
const [status, setStatus] = (0, react.useState)(null);
|
|
4561
4532
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
@@ -4563,7 +4534,6 @@ window.__ModuleLoader__.load({
|
|
|
4563
4534
|
const [error, setError] = (0, react.useState)(null);
|
|
4564
4535
|
const [statusFailed, setStatusFailed] = (0, react.useState)(false);
|
|
4565
4536
|
const [connection, setConnection] = (0, react.useState)(null);
|
|
4566
|
-
const [accounts, setAccounts] = (0, react.useState)(null);
|
|
4567
4537
|
const [loginProgress, setLoginProgress] = (0, react.useState)(null);
|
|
4568
4538
|
const loginIntervalRef = (0, react.useRef)(null);
|
|
4569
4539
|
const loginTimeoutRef = (0, react.useRef)(null);
|
|
@@ -4594,24 +4564,10 @@ window.__ModuleLoader__.load({
|
|
|
4594
4564
|
setLoading(false);
|
|
4595
4565
|
}
|
|
4596
4566
|
}, []);
|
|
4597
|
-
const loadAccounts = (0, react.useCallback)(async () => {
|
|
4598
|
-
try {
|
|
4599
|
-
const payload = await fetchApi$4("/accounts");
|
|
4600
|
-
setAccounts({
|
|
4601
|
-
authDirectory: payload?.authDirectory ?? "",
|
|
4602
|
-
managedStoragePath: payload?.managedStoragePath,
|
|
4603
|
-
accounts: Array.isArray(payload?.accounts) ? payload.accounts : []
|
|
4604
|
-
});
|
|
4605
|
-
} catch {}
|
|
4606
|
-
}, []);
|
|
4607
4567
|
(0, react.useEffect)(() => {
|
|
4608
4568
|
loadStatus();
|
|
4609
|
-
loadAccounts();
|
|
4610
4569
|
const refreshWhenVisible = () => {
|
|
4611
|
-
if (document.visibilityState === "visible")
|
|
4612
|
-
loadStatus(true);
|
|
4613
|
-
loadAccounts();
|
|
4614
|
-
}
|
|
4570
|
+
if (document.visibilityState === "visible") loadStatus(true);
|
|
4615
4571
|
};
|
|
4616
4572
|
document.addEventListener("visibilitychange", refreshWhenVisible);
|
|
4617
4573
|
return () => {
|
|
@@ -4619,14 +4575,13 @@ window.__ModuleLoader__.load({
|
|
|
4619
4575
|
if (loginIntervalRef.current !== null) window.clearInterval(loginIntervalRef.current);
|
|
4620
4576
|
if (loginTimeoutRef.current !== null) window.clearTimeout(loginTimeoutRef.current);
|
|
4621
4577
|
};
|
|
4622
|
-
}, [loadStatus
|
|
4578
|
+
}, [loadStatus]);
|
|
4623
4579
|
const handleRescan = async () => {
|
|
4624
4580
|
try {
|
|
4625
4581
|
setBusy("rescan");
|
|
4626
4582
|
setError(null);
|
|
4627
4583
|
const updated = await fetchApi$4("/rescan", { method: "POST" });
|
|
4628
|
-
setStatus(updated);
|
|
4629
|
-
await loadAccounts();
|
|
4584
|
+
setStatus(normalizeStatus(updated));
|
|
4630
4585
|
notifyChange();
|
|
4631
4586
|
} catch (err) {
|
|
4632
4587
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -4663,7 +4618,6 @@ window.__ModuleLoader__.load({
|
|
|
4663
4618
|
body: JSON.stringify({ selectedAccountId: poll.accountId })
|
|
4664
4619
|
});
|
|
4665
4620
|
await loadStatus();
|
|
4666
|
-
await loadAccounts();
|
|
4667
4621
|
notifyChange();
|
|
4668
4622
|
} else if (poll.status === "error") {
|
|
4669
4623
|
window.clearInterval(timer);
|
|
@@ -4707,7 +4661,6 @@ window.__ModuleLoader__.load({
|
|
|
4707
4661
|
})
|
|
4708
4662
|
});
|
|
4709
4663
|
setStatus(normalizeStatus(updated));
|
|
4710
|
-
await loadAccounts();
|
|
4711
4664
|
notifyChange();
|
|
4712
4665
|
} catch (err) {
|
|
4713
4666
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -4728,7 +4681,6 @@ window.__ModuleLoader__.load({
|
|
|
4728
4681
|
body: JSON.stringify({ strategy })
|
|
4729
4682
|
});
|
|
4730
4683
|
setStatus(normalizeStatus(updated));
|
|
4731
|
-
await loadAccounts();
|
|
4732
4684
|
} catch (err) {
|
|
4733
4685
|
setError(err instanceof Error ? err.message : String(err));
|
|
4734
4686
|
} finally {
|
|
@@ -4881,136 +4833,12 @@ window.__ModuleLoader__.load({
|
|
|
4881
4833
|
})
|
|
4882
4834
|
});
|
|
4883
4835
|
const quota = status?.quota;
|
|
4884
|
-
const account = status?.account;
|
|
4885
4836
|
const authenticated = status?.authenticated === true;
|
|
4886
4837
|
const unreachable = statusFailed && status === null;
|
|
4887
4838
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4888
4839
|
className: "dsha-page",
|
|
4889
4840
|
children: [
|
|
4890
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
4891
|
-
className: "dsha-group",
|
|
4892
|
-
children: [
|
|
4893
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4894
|
-
className: "dsha-grouphead",
|
|
4895
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: authenticated ? t.account : t.signedOut }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4896
|
-
className: "dsha-btn",
|
|
4897
|
-
disabled: busy !== null,
|
|
4898
|
-
onClick: () => void handleRescan(),
|
|
4899
|
-
children: busy === "rescan" ? t.rescanning : t.rescan
|
|
4900
|
-
})]
|
|
4901
|
-
}),
|
|
4902
|
-
unreachable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4903
|
-
className: "dsha-empty",
|
|
4904
|
-
children: t.routeUnreachable
|
|
4905
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4906
|
-
className: "dsha-notice",
|
|
4907
|
-
children: t.routeUnreachableHint
|
|
4908
|
-
})] }) : !authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4909
|
-
className: "dsha-empty",
|
|
4910
|
-
children: t.notFoundTitle
|
|
4911
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4912
|
-
className: "dsha-notice",
|
|
4913
|
-
children: t.notFoundHint
|
|
4914
|
-
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4915
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4916
|
-
className: "dsha-row",
|
|
4917
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4918
|
-
className: "dsha-label",
|
|
4919
|
-
children: t.nickname
|
|
4920
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4921
|
-
className: "dsha-value",
|
|
4922
|
-
children: account?.nickname || "—"
|
|
4923
|
-
})]
|
|
4924
|
-
}),
|
|
4925
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4926
|
-
className: "dsha-row",
|
|
4927
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4928
|
-
className: "dsha-label",
|
|
4929
|
-
children: t.uid
|
|
4930
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4931
|
-
className: "dsha-value dshwb-mono",
|
|
4932
|
-
children: account?.uid || "—"
|
|
4933
|
-
})]
|
|
4934
|
-
}),
|
|
4935
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4936
|
-
className: "dsha-row",
|
|
4937
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4938
|
-
className: "dsha-label",
|
|
4939
|
-
children: t.uin
|
|
4940
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4941
|
-
className: "dsha-value dshwb-mono",
|
|
4942
|
-
children: maskUin(account?.uin)
|
|
4943
|
-
})]
|
|
4944
|
-
}),
|
|
4945
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4946
|
-
className: "dsha-row",
|
|
4947
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4948
|
-
className: "dsha-label",
|
|
4949
|
-
children: t.region
|
|
4950
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4951
|
-
className: "dsha-value",
|
|
4952
|
-
children: [account?.region === "intl" ? t.regionIntl : t.regionCn, account?.accountType ? ` · ${account.accountType}` : ""]
|
|
4953
|
-
})]
|
|
4954
|
-
}),
|
|
4955
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4956
|
-
className: "dsha-row",
|
|
4957
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4958
|
-
className: "dsha-label",
|
|
4959
|
-
children: t.domain
|
|
4960
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4961
|
-
className: "dsha-value dshwb-mono",
|
|
4962
|
-
children: account?.domain || "—"
|
|
4963
|
-
})]
|
|
4964
|
-
}),
|
|
4965
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4966
|
-
className: "dsha-row",
|
|
4967
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4968
|
-
className: "dsha-label",
|
|
4969
|
-
children: t.backend
|
|
4970
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4971
|
-
className: "dsha-value dshwb-mono",
|
|
4972
|
-
children: account?.backend || "—"
|
|
4973
|
-
})]
|
|
4974
|
-
}),
|
|
4975
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4976
|
-
className: "dsha-row",
|
|
4977
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4978
|
-
className: "dsha-label",
|
|
4979
|
-
children: t.tokenExpires
|
|
4980
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4981
|
-
className: "dsha-value",
|
|
4982
|
-
children: account?.expiresAt === null || account?.expiresAt === void 0 ? "—" : account.expiresAt <= Date.now() ? t.tokenExpired : formatDate(account.expiresAt)
|
|
4983
|
-
})]
|
|
4984
|
-
}),
|
|
4985
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4986
|
-
className: "dsha-row",
|
|
4987
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4988
|
-
className: "dsha-label",
|
|
4989
|
-
children: t.sourceFile
|
|
4990
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4991
|
-
className: "dsha-value dshwb-mono",
|
|
4992
|
-
title: account?.sourceFile ?? status?.managedStoragePath ?? "",
|
|
4993
|
-
children: account?.source === "managed" ? t.encryptedStorage : displayFile(account?.sourceFile)
|
|
4994
|
-
})]
|
|
4995
|
-
})
|
|
4996
|
-
] }),
|
|
4997
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4998
|
-
className: "dsha-row",
|
|
4999
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5000
|
-
className: "dsha-label",
|
|
5001
|
-
children: t.authDirectory
|
|
5002
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5003
|
-
className: "dsha-value dshwb-mono",
|
|
5004
|
-
children: status?.authDirectory || "—"
|
|
5005
|
-
})]
|
|
5006
|
-
}),
|
|
5007
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5008
|
-
className: "dsha-notice",
|
|
5009
|
-
children: t.storageNotice
|
|
5010
|
-
})
|
|
5011
|
-
]
|
|
5012
|
-
}),
|
|
5013
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
|
|
4841
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
|
|
5014
4842
|
accounts: poolAccounts,
|
|
5015
4843
|
activeAccountId: status?.activeAccountId,
|
|
5016
4844
|
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
@@ -5026,12 +4854,12 @@ window.__ModuleLoader__.load({
|
|
|
5026
4854
|
renderLoginActions: () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5027
4855
|
className: "dsha-account-add-actions",
|
|
5028
4856
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5029
|
-
className: "dsha-btn",
|
|
4857
|
+
className: "dsha-btn dsha-btn-primary",
|
|
5030
4858
|
disabled: busy !== null,
|
|
5031
4859
|
onClick: () => void handleAddAccount("cn"),
|
|
5032
4860
|
children: busy === "login:cn" ? t.authorizing : t.addCnAccount
|
|
5033
4861
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5034
|
-
className: "dsha-btn",
|
|
4862
|
+
className: "dsha-btn dsha-btn-primary",
|
|
5035
4863
|
disabled: busy !== null,
|
|
5036
4864
|
onClick: () => void handleAddAccount("intl"),
|
|
5037
4865
|
children: busy === "login:intl" ? t.authorizing : t.addIntlAccount
|
|
@@ -5049,27 +4877,67 @@ window.__ModuleLoader__.load({
|
|
|
5049
4877
|
children: t.hideAccount
|
|
5050
4878
|
})] }),
|
|
5051
4879
|
renderDetails: (candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5052
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5053
|
-
t.region,
|
|
5054
|
-
": ",
|
|
5055
|
-
candidate.region === "intl" ? t.regionIntl : t.regionCn
|
|
5056
|
-
] }),
|
|
5057
4880
|
candidate.uin ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5058
4881
|
t.uin,
|
|
5059
4882
|
": ",
|
|
5060
4883
|
maskUin(candidate.uin)
|
|
5061
4884
|
] }) : null,
|
|
4885
|
+
candidate.accountType ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4886
|
+
t.accountType,
|
|
4887
|
+
": ",
|
|
4888
|
+
candidate.accountType
|
|
4889
|
+
] }) : null,
|
|
4890
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4891
|
+
t.region,
|
|
4892
|
+
": ",
|
|
4893
|
+
candidate.region === "intl" ? t.regionIntl : t.regionCn
|
|
4894
|
+
] }),
|
|
4895
|
+
candidate.domain ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4896
|
+
className: "dshwb-mono",
|
|
4897
|
+
title: `${candidate.domain} · ${candidate.backend ?? ""}`,
|
|
4898
|
+
children: candidate.domain
|
|
4899
|
+
}) : null,
|
|
5062
4900
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5063
4901
|
className: "dshwb-mono",
|
|
5064
4902
|
children: candidate.source === "managed" ? t.encryptedStorage : displayFile(candidate.sourceFile)
|
|
5065
4903
|
}),
|
|
5066
4904
|
candidate.hidden === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.hiddenAccount }) : null
|
|
5067
|
-
] })
|
|
4905
|
+
] }),
|
|
4906
|
+
children: [
|
|
4907
|
+
unreachable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4908
|
+
className: "dsha-empty",
|
|
4909
|
+
children: t.routeUnreachable
|
|
4910
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4911
|
+
className: "dsha-notice",
|
|
4912
|
+
children: t.routeUnreachableHint
|
|
4913
|
+
})] }) : null,
|
|
4914
|
+
loginProgress ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4915
|
+
className: "dsha-notice",
|
|
4916
|
+
children: loginProgress
|
|
4917
|
+
}) : null,
|
|
4918
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4919
|
+
className: "dsha-row",
|
|
4920
|
+
style: { marginTop: 12 },
|
|
4921
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4922
|
+
className: "dsha-label",
|
|
4923
|
+
children: t.authDirectory
|
|
4924
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4925
|
+
className: "dsha-value dshwb-mono",
|
|
4926
|
+
title: status?.authDirectory || "",
|
|
4927
|
+
children: status?.authDirectory || "—"
|
|
4928
|
+
})]
|
|
4929
|
+
}),
|
|
4930
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4931
|
+
className: "dsha-actions",
|
|
4932
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4933
|
+
className: "dsha-btn",
|
|
4934
|
+
disabled: busy !== null,
|
|
4935
|
+
onClick: () => void handleRescan(),
|
|
4936
|
+
children: busy === "rescan" ? t.rescanning : t.rescan
|
|
4937
|
+
})
|
|
4938
|
+
})
|
|
4939
|
+
]
|
|
5068
4940
|
}),
|
|
5069
|
-
loginProgress ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5070
|
-
className: "dsha-notice",
|
|
5071
|
-
children: loginProgress
|
|
5072
|
-
}) : null,
|
|
5073
4941
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5074
4942
|
className: "dsha-group",
|
|
5075
4943
|
children: [
|
|
@@ -5145,26 +5013,22 @@ window.__ModuleLoader__.load({
|
|
|
5145
5013
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5146
5014
|
className: "dsha-models",
|
|
5147
5015
|
"aria-label": "WorkBuddy Models",
|
|
5148
|
-
children: status?.models.map((model) =>
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
]
|
|
5165
|
-
})]
|
|
5166
|
-
})]
|
|
5167
|
-
}, model.id))
|
|
5016
|
+
children: status?.models.map((model) => {
|
|
5017
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5018
|
+
title: [
|
|
5019
|
+
model.id,
|
|
5020
|
+
formatCapacity(model.contextWindow),
|
|
5021
|
+
model.supportsImage ? t.imageSupport : t.textOnly,
|
|
5022
|
+
...model.reasoningEfforts && model.reasoningEfforts.length > 0 ? [model.reasoningEfforts.join("/")] : []
|
|
5023
|
+
].join(" · "),
|
|
5024
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5025
|
+
type: "checkbox",
|
|
5026
|
+
checked: model.enabled,
|
|
5027
|
+
disabled: busy !== null,
|
|
5028
|
+
onChange: (event) => void toggleModel(model.id, event.currentTarget.checked)
|
|
5029
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name })]
|
|
5030
|
+
}, model.id);
|
|
5031
|
+
})
|
|
5168
5032
|
}),
|
|
5169
5033
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5170
5034
|
className: "dsha-actions",
|
|
@@ -6488,29 +6352,24 @@ window.__ModuleLoader__.load({
|
|
|
6488
6352
|
/**
|
|
6489
6353
|
* WorkBuddy-only additions to the shared settings design system.
|
|
6490
6354
|
*
|
|
6491
|
-
* The base control styles (`.dsha-page`, `.dsha-group`, `.dsha-models`,
|
|
6492
|
-
* from the stylesheet the sibling routes install,
|
|
6493
|
-
*
|
|
6494
|
-
*
|
|
6355
|
+
* The base control styles (`.dsha-page`, `.dsha-group`, `.dsha-models`, the
|
|
6356
|
+
* account card, …) come from the stylesheet the sibling routes install, in the
|
|
6357
|
+
* same order the client installs them, so this file declares only what stays
|
|
6358
|
+
* unique to this card: the mono credential paths and the login-progress line.
|
|
6359
|
+
*
|
|
6360
|
+
* Everything this tab used to declare locally — the per-model capability line
|
|
6361
|
+
* and the account-region headings — is gone: the model pill is name-only like
|
|
6362
|
+
* every sibling tab, and the account card is the shared one.
|
|
6495
6363
|
*/
|
|
6496
6364
|
function installWorkBuddyStyles() {
|
|
6497
6365
|
if (typeof document === "undefined" || document.getElementById("dsh-workbuddy-settings-style")) return;
|
|
6498
6366
|
const style = document.createElement("style");
|
|
6499
6367
|
style.id = STYLE_ID;
|
|
6500
6368
|
style.textContent = `
|
|
6501
|
-
.dshwb-model{display:flex;flex-direction:column;gap:2px;min-width:0}
|
|
6502
|
-
.dshwb-model-meta{color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400;line-height:1.3;white-space:nowrap}
|
|
6503
|
-
.dsha-models input:checked+span .dshwb-model-meta{color:var(--dsw-alias-label-secondary)}
|
|
6504
|
-
.dshwb-region{display:inline-flex;align-items:center;gap:4px}
|
|
6505
|
-
.dshwb-muted-note{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;margin:8px 0 0}
|
|
6506
6369
|
.dshwb-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
|
|
6507
|
-
.dsha-account-region{margin-top:14px}
|
|
6508
|
-
.dsha-account-region h4{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:650;margin:0 0 8px}
|
|
6509
6370
|
.dsha-account-add-actions{display:flex;flex-wrap:wrap;gap:8px}
|
|
6510
|
-
.dsha-account-
|
|
6511
|
-
.
|
|
6512
|
-
.dshwb-account-select:disabled{cursor:default}
|
|
6513
|
-
.dshwb-account-select:hover:not(:disabled) .dsha-account-title{color:var(--dsw-alias-label-link,#397ee8)}
|
|
6371
|
+
.dsha-account-add-actions .dsha-btn{background:var(--dsw-alias-button-info-fill,#397ee8);border-color:transparent;color:var(--dsw-alias-button-info-label,#fff)}
|
|
6372
|
+
.dsha-account-add-actions .dsha-btn:hover:not(:disabled){opacity:.9;background:var(--dsw-alias-button-info-fill,#397ee8)}
|
|
6514
6373
|
`;
|
|
6515
6374
|
document.head.append(style);
|
|
6516
6375
|
}
|