dsh-llm-codebuddy-power 1.2.0 → 1.3.0
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 +4 -5
- package/README.zh.md +4 -5
- package/lib/cli-login.js +110 -107
- package/lib/client.js +127 -144
- package/lib/index.js +121 -104
- package/lib/types/auth-service.d.ts +11 -12
- package/lib/types/cli/login.d.ts +1 -2
- package/lib/types/client/AccountSwitcher.d.ts +1 -2
- package/lib/types/client/CodeBuddySection.d.ts +3 -5
- package/lib/types/client/TurnCreditPill.d.ts +5 -4
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/locales.d.ts +5 -3
- package/lib/types/client/store.d.ts +3 -5
- package/lib/types/client/wire.d.ts +2 -2
- package/lib/types/constants.d.ts +7 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/session-store.d.ts +1 -1
- package/lib/types/session.d.ts +57 -27
- package/lib/types/storage.d.ts +4 -11
- package/lib/types/usage.d.ts +4 -2
- package/package.json +15 -15
package/lib/index.js
CHANGED
|
@@ -87,6 +87,13 @@ const LOGIN_POLL_INTERVAL_MS = 1e3;
|
|
|
87
87
|
const LOGIN_RESULT_RETENTION_MS = 60 * 1e3;
|
|
88
88
|
/** 含义为“浏览器登录尚未完成”的服务码。 */
|
|
89
89
|
const AUTH_PENDING_CODE = 11217;
|
|
90
|
+
/**
|
|
91
|
+
* 一次性赠送活动所用的子产品编码。
|
|
92
|
+
*
|
|
93
|
+
* "裂变包"与"拉新权益包"两类赠送活动各有自己的 `PackageCode`,却共用这一个子产品
|
|
94
|
+
* 编码,而可续期主套餐用的是另一个,因此它是区分赠送与主体的稳定依据。
|
|
95
|
+
*/
|
|
96
|
+
const CODEBUDDY_GIFT_SUB_PRODUCT_CODE = "sp_tcaca_codebuddyide_bonus_pack";
|
|
90
97
|
//#endregion
|
|
91
98
|
//#region lib/types/codebuddy.js
|
|
92
99
|
/**
|
|
@@ -533,16 +540,19 @@ function normalizeResetTime(raw) {
|
|
|
533
540
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
534
541
|
}
|
|
535
542
|
/**
|
|
536
|
-
*
|
|
543
|
+
* 判断某个计量窗口是否是一次性赠送额度。
|
|
537
544
|
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
545
|
+
* 依据是子产品编码:{@link CODEBUDDY_GIFT_SUB_PRODUCT_CODE} 由全部赠送活动共用,
|
|
546
|
+
* 而可续期主套餐用另一个编码。套餐显示名不能独立作依据 —— 两类赠送活动的
|
|
547
|
+
* `PackageCode` 不同、显示名也不同,只有一类名字里带“裂变”,另一类叫“拉新权益包”,
|
|
548
|
+
* 按名匹配会把后者错算进主池。显示名与子产品名因此只作兜底,供未来换了子产品编码
|
|
549
|
+
* 却仍在名字里沿用“裂变/赠送”字样的赠送活动使用。
|
|
550
|
+
* @param resource - `Accounts` 数组里的一项。
|
|
551
|
+
* @returns 赠送窗口返回 true。
|
|
543
552
|
*/
|
|
544
|
-
function
|
|
545
|
-
|
|
553
|
+
function isGiftResource(resource) {
|
|
554
|
+
if (string(resource, "SubProductCode") === "sp_tcaca_codebuddyide_bonus_pack") return true;
|
|
555
|
+
return /裂变|赠送/.test(string(resource, "PackageName") ?? "") || /裂变|赠送/.test(string(resource, "SubProductName") ?? "");
|
|
546
556
|
}
|
|
547
557
|
/**
|
|
548
558
|
* 把有可用容量的窗口聚合成一个池(used/limit 求和)。
|
|
@@ -571,13 +581,13 @@ function liveGiftWindows(windows) {
|
|
|
571
581
|
/**
|
|
572
582
|
* 构建个人快照的主池/赠送池划分,以及提示框的赠送明细(最早过期的有效赠送
|
|
573
583
|
* 在前,最多 5 个)。
|
|
574
|
-
* @param windows -
|
|
584
|
+
* @param windows - 已解析的窗口,各自带 {@link UsageWindow.gift} 归属。
|
|
575
585
|
* @returns 该划分,仅当对应池有可用 limit 时才包含 `main`/`gift`。
|
|
576
586
|
*/
|
|
577
587
|
function splitPools(windows) {
|
|
578
588
|
const mainWindows = [];
|
|
579
589
|
const giftWindows = [];
|
|
580
|
-
for (const window of windows) if (
|
|
590
|
+
for (const window of windows) if (window.gift) giftWindows.push(window);
|
|
581
591
|
else mainWindows.push(window);
|
|
582
592
|
const main = poolOf(mainWindows);
|
|
583
593
|
const live = liveGiftWindows(giftWindows);
|
|
@@ -616,14 +626,17 @@ function personalUsage(accounts) {
|
|
|
616
626
|
const name = string(resource, "PackageName") ?? string(resource, "PackageCode") ?? string(resource, "ResourceId") ?? `resource_${index}`;
|
|
617
627
|
const rawReset = string(resource, "CycleEndTime");
|
|
618
628
|
const resetsAt = rawReset === void 0 ? void 0 : normalizeResetTime(rawReset);
|
|
629
|
+
const gift = isGiftResource(resource);
|
|
619
630
|
if (limit <= 0) return {
|
|
620
631
|
name,
|
|
632
|
+
gift,
|
|
621
633
|
...resetsAt === void 0 ? {} : { resetsAt }
|
|
622
634
|
};
|
|
623
635
|
return {
|
|
624
636
|
name,
|
|
625
637
|
used,
|
|
626
638
|
limit,
|
|
639
|
+
gift,
|
|
627
640
|
...resetsAt === void 0 ? {} : { resetsAt }
|
|
628
641
|
};
|
|
629
642
|
});
|
|
@@ -653,6 +666,7 @@ function enterpriseUsage(data) {
|
|
|
653
666
|
name: "enterprise",
|
|
654
667
|
used,
|
|
655
668
|
limit,
|
|
669
|
+
gift: false,
|
|
656
670
|
...reset === void 0 ? {} : { resetsAt: reset }
|
|
657
671
|
};
|
|
658
672
|
const main = poolOf([window]);
|
|
@@ -916,10 +930,14 @@ function isAccountRef(value) {
|
|
|
916
930
|
/**
|
|
917
931
|
* 文件读出的记录是否合法。
|
|
918
932
|
*
|
|
919
|
-
* `
|
|
920
|
-
*
|
|
921
|
-
*
|
|
922
|
-
*
|
|
933
|
+
* `credit` 与 `accounts` 同为必填:一条记录说不出这一轮扣了多少、用的是哪个账号,
|
|
934
|
+
* 就答不了它存在的唯一问题,与"没有这条记录"没有区别,因此不完整即整条丢弃。引用
|
|
935
|
+
* 还必须能在同一份文件的账号表里解析到 —— 一个悬空引用渲染不出账号,与缺字段是同
|
|
936
|
+
* 一种残缺。
|
|
937
|
+
*
|
|
938
|
+
* `requestId` 则允许缺失:它是后加的字段,已发布的旧版本写下的记录没有它。那些轮次
|
|
939
|
+
* 照常显示积分,只是拿不出请求 id,因此不值得为它丢掉整轮积分。存在时必须是字符串,
|
|
940
|
+
* 否则是损坏内容而不是旧格式。
|
|
923
941
|
* @param value - 文件里的一条轮次记录。
|
|
924
942
|
* @param table - 同一份文件的账号表。
|
|
925
943
|
* @returns 该记录是否可用。
|
|
@@ -927,7 +945,7 @@ function isAccountRef(value) {
|
|
|
927
945
|
function isCreditRecord(value, table) {
|
|
928
946
|
if (typeof value !== "object" || value === null) return false;
|
|
929
947
|
const record = value;
|
|
930
|
-
return typeof record.credit === "number" && Number.isFinite(record.credit) && Array.isArray(record.accounts) && record.accounts.length > 0 && record.accounts.every((key) => typeof key === "string" && isAccountRef(table[key]));
|
|
948
|
+
return typeof record.credit === "number" && Number.isFinite(record.credit) && Array.isArray(record.accounts) && record.accounts.length > 0 && record.accounts.every((key) => typeof key === "string" && isAccountRef(table[key])) && (record.requestId === void 0 || typeof record.requestId === "string");
|
|
931
949
|
}
|
|
932
950
|
/**
|
|
933
951
|
* 读取一个会话的信息。
|
|
@@ -1088,9 +1106,8 @@ function trimEmptyAccountFields(account) {
|
|
|
1088
1106
|
* 把解析出的 JSON 归一化为账号集合。
|
|
1089
1107
|
*
|
|
1090
1108
|
* 同时接受当前形态与仅有一个账号的旧形态(顶层 `auth` + `account`):旧文件
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1093
|
-
* 指针,留着会让“有没有默认账号”与实际情况相反。
|
|
1109
|
+
* 迁移成单元素列表,于是升级不会改变用户下一次请求用的是谁。`lastUid` 指向已不
|
|
1110
|
+
* 存在的账号时丢弃 —— 它只是个指针,留着会让兜底落到一个用不了的账号上。
|
|
1094
1111
|
* @param parsed - 解析出的 JSON 值。
|
|
1095
1112
|
* @returns 归一化后的账号集合。
|
|
1096
1113
|
*/
|
|
@@ -1106,22 +1123,17 @@ function normalizeStorage(parsed) {
|
|
|
1106
1123
|
if (typeof value !== "string") return void 0;
|
|
1107
1124
|
return accounts.some((a) => a.account.uid === value) ? value : void 0;
|
|
1108
1125
|
};
|
|
1109
|
-
const defaultUid = pick(record.defaultUid);
|
|
1110
1126
|
const lastUid = pick(record.lastUid);
|
|
1111
1127
|
return {
|
|
1112
1128
|
accounts,
|
|
1113
|
-
...defaultUid === void 0 ? {} : { defaultUid },
|
|
1114
1129
|
...lastUid === void 0 ? {} : { lastUid }
|
|
1115
1130
|
};
|
|
1116
1131
|
}
|
|
1117
1132
|
if (!isAccountEntry(record)) return emptyStorage();
|
|
1118
|
-
return {
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
}],
|
|
1123
|
-
defaultUid: record.account.uid
|
|
1124
|
-
};
|
|
1133
|
+
return { accounts: [{
|
|
1134
|
+
auth: record.auth,
|
|
1135
|
+
account: trimEmptyAccountFields(record.account)
|
|
1136
|
+
}] };
|
|
1125
1137
|
}
|
|
1126
1138
|
/**
|
|
1127
1139
|
* 读取已存储的账号集合。
|
|
@@ -1168,11 +1180,10 @@ async function upsertAccount(entry) {
|
|
|
1168
1180
|
await updateStorage((current) => {
|
|
1169
1181
|
const uid = entry.account.uid;
|
|
1170
1182
|
const accounts = current.accounts.some((a) => a.account.uid === uid) ? current.accounts.map((a) => a.account.uid === uid ? entry : a) : [...current.accounts, entry];
|
|
1171
|
-
const
|
|
1183
|
+
const lastUid = current.lastUid ?? (current.accounts.length === 0 ? uid : void 0);
|
|
1172
1184
|
return {
|
|
1173
1185
|
accounts,
|
|
1174
|
-
...
|
|
1175
|
-
...current.lastUid === void 0 ? {} : { lastUid: current.lastUid }
|
|
1186
|
+
...lastUid === void 0 ? {} : { lastUid }
|
|
1176
1187
|
};
|
|
1177
1188
|
});
|
|
1178
1189
|
}
|
|
@@ -1206,39 +1217,22 @@ async function reorderAccounts(uids) {
|
|
|
1206
1217
|
});
|
|
1207
1218
|
}
|
|
1208
1219
|
/**
|
|
1209
|
-
*
|
|
1220
|
+
* 移除若干账号,并清掉指向它们的“最后一次手动切换”的账号。
|
|
1210
1221
|
* @param uids - 要移除的账号 uid。
|
|
1211
1222
|
*/
|
|
1212
1223
|
async function removeAccounts(uids) {
|
|
1213
1224
|
const removed = new Set(uids);
|
|
1214
1225
|
await updateStorage((current) => {
|
|
1215
1226
|
const accounts = current.accounts.filter((a) => !removed.has(a.account.uid));
|
|
1216
|
-
const
|
|
1217
|
-
const defaultUid = gone(current.defaultUid);
|
|
1218
|
-
const lastUid = gone(current.lastUid);
|
|
1227
|
+
const lastUid = current.lastUid !== void 0 && removed.has(current.lastUid) ? void 0 : current.lastUid;
|
|
1219
1228
|
return {
|
|
1220
1229
|
accounts,
|
|
1221
|
-
...defaultUid === void 0 ? {} : { defaultUid },
|
|
1222
1230
|
...lastUid === void 0 ? {} : { lastUid }
|
|
1223
1231
|
};
|
|
1224
1232
|
});
|
|
1225
1233
|
}
|
|
1226
1234
|
/**
|
|
1227
|
-
*
|
|
1228
|
-
* @param uid - 默认账号的 uid;传 `undefined` 取消默认账号。
|
|
1229
|
-
*/
|
|
1230
|
-
async function setDefaultAccount(uid) {
|
|
1231
|
-
await updateStorage((current) => {
|
|
1232
|
-
const next = {
|
|
1233
|
-
accounts: current.accounts,
|
|
1234
|
-
...current.lastUid === void 0 ? {} : { lastUid: current.lastUid }
|
|
1235
|
-
};
|
|
1236
|
-
if (uid !== void 0 && current.accounts.some((a) => a.account.uid === uid)) next.defaultUid = uid;
|
|
1237
|
-
return next;
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
/**
|
|
1241
|
-
* 记下最后一次被手动切换到的账号(没有默认账号时作为兜底)。
|
|
1235
|
+
* 记下最后一次被手动切换到的账号,作为未选用账号的会话的兜底。
|
|
1242
1236
|
* @param uid - 被切换到的账号 uid。
|
|
1243
1237
|
*/
|
|
1244
1238
|
async function setLastAccount(uid) {
|
|
@@ -1273,7 +1267,8 @@ async function storageFreshness() {
|
|
|
1273
1267
|
* 并发调用会互相取到对方的刷新结果,其中一个的 token 永远停留过期。
|
|
1274
1268
|
*
|
|
1275
1269
|
* 账号由会话决定:某个会话显式选了账号就用它,否则顺延到派生它的会话(子代理、
|
|
1276
|
-
* fork)
|
|
1270
|
+
* fork),再落到账号级兜底(最后一次手动切换的账号,其次是列表第一个)。会话在
|
|
1271
|
+
* 第一次真正发请求时把解析到的账号固定下来,此后不再跟随兜底。目录与计量快照
|
|
1277
1272
|
* 也按账号分别缓存,因为不同账号的可用模型与额度本就可以不同。
|
|
1278
1273
|
*
|
|
1279
1274
|
* @module dsh-llm-codebuddy-power/session
|
|
@@ -1318,7 +1313,8 @@ function resolveCreditRecord(record, table) {
|
|
|
1318
1313
|
}
|
|
1319
1314
|
return {
|
|
1320
1315
|
credit: record.credit,
|
|
1321
|
-
accounts
|
|
1316
|
+
accounts,
|
|
1317
|
+
...record.requestId === void 0 ? {} : { requestId: record.requestId }
|
|
1322
1318
|
};
|
|
1323
1319
|
}
|
|
1324
1320
|
/**
|
|
@@ -1388,7 +1384,7 @@ var CodeBuddySession = class {
|
|
|
1388
1384
|
*
|
|
1389
1385
|
* 集合只由**带会话身份的**读取填充(聊天请求、模型面板),并供拿不到会话身份的
|
|
1390
1386
|
* 调用方({@link knownModel}、`listModels`)查询:那些调用方无法知道该用哪个账号
|
|
1391
|
-
*
|
|
1387
|
+
* 的目录,主动读取只能落在账号级兜底上 —— 而当前会话用的可能正是另一个账号。
|
|
1392
1388
|
*/
|
|
1393
1389
|
knownCatalog = /* @__PURE__ */ new Map();
|
|
1394
1390
|
/** 按账号 uid 单飞的目录读取。 */
|
|
@@ -1505,12 +1501,14 @@ var CodeBuddySession = class {
|
|
|
1505
1501
|
const existing = track.credits.get(turn);
|
|
1506
1502
|
const accounts = existing?.accounts ?? [];
|
|
1507
1503
|
const known = accounts.some((entry) => entry.uid === account.uid);
|
|
1504
|
+
const requestId = existing?.requestId ?? track.turnRequestId;
|
|
1508
1505
|
const merged = {
|
|
1509
1506
|
credit: (existing?.credit ?? 0) + credit,
|
|
1510
1507
|
accounts: known ? accounts : [...accounts, {
|
|
1511
1508
|
nickname: account.nickname,
|
|
1512
1509
|
uid: account.uid
|
|
1513
|
-
}]
|
|
1510
|
+
}],
|
|
1511
|
+
requestId
|
|
1514
1512
|
};
|
|
1515
1513
|
track.credits.set(turn, merged);
|
|
1516
1514
|
updateSessionInfo(sessionId, (info) => {
|
|
@@ -1530,7 +1528,8 @@ var CodeBuddySession = class {
|
|
|
1530
1528
|
...info.credits,
|
|
1531
1529
|
[String(turn)]: {
|
|
1532
1530
|
credit: merged.credit,
|
|
1533
|
-
accounts: keys
|
|
1531
|
+
accounts: keys,
|
|
1532
|
+
...merged.requestId === void 0 ? {} : { requestId: merged.requestId }
|
|
1534
1533
|
}
|
|
1535
1534
|
}
|
|
1536
1535
|
};
|
|
@@ -1579,7 +1578,7 @@ var CodeBuddySession = class {
|
|
|
1579
1578
|
/**
|
|
1580
1579
|
* 由当前缓存的各账号目录重建合并目录。
|
|
1581
1580
|
*
|
|
1582
|
-
* 账号退出后的处理必须是"重建"而不是"清空"
|
|
1581
|
+
* 账号退出后的处理必须是"重建"而不是"清空":清空会让官方列表塌回账号级兜底,
|
|
1583
1582
|
* 而其余仍登录账号的目录本来就在手上 —— 继续并着才是"退出后重新合并当前已有的
|
|
1584
1583
|
* 列表"。重建同时确定性地解决同 id 的归属:只剩下仍在的账号参与竞争。
|
|
1585
1584
|
*/
|
|
@@ -1615,7 +1614,7 @@ var CodeBuddySession = class {
|
|
|
1615
1614
|
* 或每记一次“最后切换的账号”都会被当成账号变更,从而丢掉按账号缓存的计量快照并
|
|
1616
1615
|
* 广播一次模型变更 —— 那些都不是账号增删。真的增删时才会丢弃已退出账号的缓存并
|
|
1617
1616
|
* 重建合并目录:退出一个账号后官方列表应当继续并着其余账号已读到的目录,而不是
|
|
1618
|
-
*
|
|
1617
|
+
* 塌回账号级兜底那一个。
|
|
1619
1618
|
*/
|
|
1620
1619
|
async refreshIfChanged() {
|
|
1621
1620
|
const storageKey = await storageFreshness();
|
|
@@ -1637,8 +1636,9 @@ var CodeBuddySession = class {
|
|
|
1637
1636
|
* 该会话自身及其派生祖先显式选用的账号,由近及远。读取某个会话的信息可能要碰盘,
|
|
1638
1637
|
* 因此本方法是异步的。
|
|
1639
1638
|
*
|
|
1640
|
-
* 走到祖先是因为子代理与 fork
|
|
1641
|
-
*
|
|
1639
|
+
* 走到祖先是因为子代理与 fork 出来的会话在**固定之前**还没有自己的账号:子代理
|
|
1640
|
+
* 界面上从来就没有账号按钮,若不沿用父会话就会静默改用账号级兜底,把一次派发记到
|
|
1641
|
+
* 另一个账号头上;fork 有自己的按钮,但它在被切换之前也应当跟着父会话走。
|
|
1642
1642
|
*/
|
|
1643
1643
|
async accountChain(sessionId) {
|
|
1644
1644
|
const chain = [];
|
|
@@ -1655,17 +1655,39 @@ var CodeBuddySession = class {
|
|
|
1655
1655
|
/**
|
|
1656
1656
|
* 该会话此刻生效的账号 uid。
|
|
1657
1657
|
*
|
|
1658
|
-
* 顺序:会话(或其派生祖先)显式选用的账号 →
|
|
1659
|
-
*
|
|
1660
|
-
*
|
|
1658
|
+
* 顺序:会话(或其派生祖先)显式选用的账号 → 最后一次手动切换的账号 → 列表第一个。
|
|
1659
|
+
* 指向已退出账号的选择会被跳过,而不是当成“没有账号”;全部落空时返回
|
|
1660
|
+
* `undefined`,调用方据此报未登录。
|
|
1661
1661
|
*/
|
|
1662
1662
|
async accountUidFor(sessionId) {
|
|
1663
1663
|
if (sessionId !== void 0) {
|
|
1664
1664
|
for (const uid of await this.accountChain(sessionId)) if (this.accountEntry(uid) !== void 0) return uid;
|
|
1665
1665
|
}
|
|
1666
|
-
|
|
1666
|
+
const last = this.storage?.lastUid;
|
|
1667
|
+
if (this.accountEntry(last) !== void 0) return last;
|
|
1667
1668
|
return this.storage?.accounts[0]?.account.uid;
|
|
1668
1669
|
}
|
|
1670
|
+
/**
|
|
1671
|
+
* 把该会话此刻解析到的账号写进它自己的文件,使它从此不再跟随账号级兜底。
|
|
1672
|
+
*
|
|
1673
|
+
* 已有选择就不再动它。那有两种可能,而两种都不该被覆盖:早已固定的会话重写只是
|
|
1674
|
+
* 同一份事实的重复落盘;而记录指向一个已退出账号时,读取侧按"没有选择"处理它,
|
|
1675
|
+
* 磁盘上的记录则只增不删 —— 覆盖掉它会让该账号重新登录后不再回到这个会话。
|
|
1676
|
+
* @param sessionId - dsh 会话身份。
|
|
1677
|
+
* @param uid - 本次请求实际使用的账号 uid。
|
|
1678
|
+
*/
|
|
1679
|
+
async pinAccount(sessionId, uid) {
|
|
1680
|
+
const info = await this.infoOf(sessionId);
|
|
1681
|
+
if (info.uid !== void 0) return;
|
|
1682
|
+
await updateSessionInfo(sessionId, (current) => current.uid === void 0 ? {
|
|
1683
|
+
...current,
|
|
1684
|
+
uid
|
|
1685
|
+
} : current);
|
|
1686
|
+
this.infos.set(sessionId, {
|
|
1687
|
+
...info,
|
|
1688
|
+
uid
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1669
1691
|
identityOf(entry) {
|
|
1670
1692
|
return {
|
|
1671
1693
|
accessToken: entry.auth.accessToken,
|
|
@@ -1694,13 +1716,21 @@ var CodeBuddySession = class {
|
|
|
1694
1716
|
}
|
|
1695
1717
|
/**
|
|
1696
1718
|
* 已存账号条目,在首次使用、失效之后以及文件被外部改动时从磁盘读取。
|
|
1697
|
-
*
|
|
1719
|
+
*
|
|
1720
|
+
* 解析出的账号在返回前固定进该会话自己的文件,因此"这个会话用哪个账号"只在它
|
|
1721
|
+
* 第一次真正发请求时从全局兜底取一次;此后用户别处切换账号不会再改变它。固定
|
|
1722
|
+
* 挂在这里而不是账号解析处(见 {@link accountUidFor}),是因为本方法只被
|
|
1723
|
+
* {@link requestIdentity} 调用,即只有真实请求经过 —— 界面上打开一个空会话所
|
|
1724
|
+
* 触发的用量与目录读取不会落下任何记录。
|
|
1725
|
+
* @param sessionId - 用哪个会话的账号;会话未选用时按账号级兜底解析。
|
|
1698
1726
|
* @throws NotLoggedInError 未存有任何凭据时。
|
|
1699
1727
|
*/
|
|
1700
1728
|
async require(sessionId) {
|
|
1701
1729
|
await this.refreshIfChanged();
|
|
1702
|
-
const
|
|
1730
|
+
const uid = await this.accountUidFor(sessionId);
|
|
1731
|
+
const entry = this.accountEntry(uid);
|
|
1703
1732
|
if (entry === void 0) throw new NotLoggedInError("CodeBuddy is not signed in. Run `dsh plugin --profile web codebuddy-power` to sign in through your browser; no API key is required.");
|
|
1733
|
+
if (sessionId !== void 0 && uid !== void 0) await this.pinAccount(sessionId, uid);
|
|
1704
1734
|
return entry;
|
|
1705
1735
|
}
|
|
1706
1736
|
/**
|
|
@@ -1760,7 +1790,7 @@ var CodeBuddySession = class {
|
|
|
1760
1790
|
* 两者在**同一次**身份解析中一起给出:分开解析会有两次账号选择,而账号是每次请求
|
|
1761
1791
|
* 解析的(用户可在同一步里切换),两次解析可能落到不同账号上 —— 那样记进这一轮的
|
|
1762
1792
|
* 账号名就与实际发出去的请求不符。缩写由落盘侧按同一规则算出,故此处给出完整账号。
|
|
1763
|
-
* @param sessionId -
|
|
1793
|
+
* @param sessionId - 请求所属的会话;决定用哪个账号,缺省时按账号级兜底。
|
|
1764
1794
|
* @returns 身份请求头与发起该请求的账号。
|
|
1765
1795
|
*/
|
|
1766
1796
|
async requestIdentity(sessionId) {
|
|
@@ -1782,19 +1812,16 @@ var CodeBuddySession = class {
|
|
|
1782
1812
|
return (this.storage?.accounts.length ?? 0) > 0;
|
|
1783
1813
|
}
|
|
1784
1814
|
/**
|
|
1785
|
-
*
|
|
1786
|
-
* @returns 账号列表(顺序与磁盘一致)
|
|
1815
|
+
* 已存账号,供配置页与会话切换按钮展示。
|
|
1816
|
+
* @returns 账号列表(顺序与磁盘一致);未登录时列表为空。
|
|
1787
1817
|
*/
|
|
1788
1818
|
async accountList() {
|
|
1789
1819
|
await this.refreshIfChanged();
|
|
1790
|
-
return
|
|
1791
|
-
accounts: (this.storage?.accounts ?? []).map(accountInfo),
|
|
1792
|
-
...this.storage?.defaultUid === void 0 ? {} : { defaultUid: this.storage.defaultUid }
|
|
1793
|
-
};
|
|
1820
|
+
return (this.storage?.accounts ?? []).map(accountInfo);
|
|
1794
1821
|
}
|
|
1795
1822
|
/**
|
|
1796
1823
|
* 某会话此刻生效的账号 uid。
|
|
1797
|
-
* @param sessionId - dsh
|
|
1824
|
+
* @param sessionId - dsh 会话身份;缺省时按账号级兜底。
|
|
1798
1825
|
* @returns 账号 uid;一个账号也没有时为 `undefined`。
|
|
1799
1826
|
*/
|
|
1800
1827
|
async activeUid(sessionId) {
|
|
@@ -1803,6 +1830,10 @@ var CodeBuddySession = class {
|
|
|
1803
1830
|
}
|
|
1804
1831
|
/**
|
|
1805
1832
|
* 把某会话的账号切换为指定账号,并把它记为最后一次手动切换的账号。
|
|
1833
|
+
*
|
|
1834
|
+
* 该会话已有持久记录才写它自己的文件;一个还从未落过盘的新会话只更新账号级的
|
|
1835
|
+
* `lastUid` —— 它可能永远不会被发过第一条消息,为它建文件会在磁盘上留下无人
|
|
1836
|
+
* 认领的残留文件。这类会话在真正发请求时由 {@link require} 固定下来。
|
|
1806
1837
|
* @param sessionId - dsh 会话身份。
|
|
1807
1838
|
* @param uid - 要使用的账号 uid。
|
|
1808
1839
|
* @returns 该 uid 是已存账号时为 true;否则不做任何改动并返回 false。
|
|
@@ -1810,7 +1841,9 @@ var CodeBuddySession = class {
|
|
|
1810
1841
|
async activate(sessionId, uid) {
|
|
1811
1842
|
await this.refreshIfChanged();
|
|
1812
1843
|
if (this.accountEntry(uid) === void 0) return false;
|
|
1844
|
+
await setLastAccount(uid);
|
|
1813
1845
|
const info = await this.infoOf(sessionId);
|
|
1846
|
+
if (info.uid === void 0 && Object.keys(info.credits).length === 0) return true;
|
|
1814
1847
|
await updateSessionInfo(sessionId, (current) => ({
|
|
1815
1848
|
...current,
|
|
1816
1849
|
uid
|
|
@@ -1819,13 +1852,12 @@ var CodeBuddySession = class {
|
|
|
1819
1852
|
...info,
|
|
1820
1853
|
uid
|
|
1821
1854
|
});
|
|
1822
|
-
await setLastAccount(uid);
|
|
1823
1855
|
return true;
|
|
1824
1856
|
}
|
|
1825
1857
|
/**
|
|
1826
1858
|
* CodeBuddy 模型目录,短暂缓存,并在并发读取者之间共享。
|
|
1827
1859
|
* @param signal - 底层读取的可选取消信号。
|
|
1828
|
-
* @param sessionId -
|
|
1860
|
+
* @param sessionId - 用哪个会话的账号;缺省时按账号级兜底解析。
|
|
1829
1861
|
* @returns 目录中的模型,按服务自身的顺序。
|
|
1830
1862
|
*/
|
|
1831
1863
|
async models(signal, sessionId) {
|
|
@@ -1835,7 +1867,7 @@ var CodeBuddySession = class {
|
|
|
1835
1867
|
* 目录及其推广与档位,在同一个 TTL 下按账号一起缓存,并按账号单飞,使列表与
|
|
1836
1868
|
* 面板富化共享同一次读取。
|
|
1837
1869
|
* @param signal - 底层读取的可选取消信号。
|
|
1838
|
-
* @param sessionId -
|
|
1870
|
+
* @param sessionId - 用哪个会话的账号;缺省时按账号级兜底解析。
|
|
1839
1871
|
* @returns 模型、推广与档位。
|
|
1840
1872
|
*/
|
|
1841
1873
|
async catalogData(signal, sessionId) {
|
|
@@ -1881,7 +1913,7 @@ var CodeBuddySession = class {
|
|
|
1881
1913
|
* 从各账号已读到的目录的并集里查一个模型,**不发起任何请求**。
|
|
1882
1914
|
*
|
|
1883
1915
|
* 供拿不到会话身份的调用方使用(适配器的 `resolveModel`):它无法知道该用哪个
|
|
1884
|
-
*
|
|
1916
|
+
* 账号的目录,主动读取只能落在账号级兜底上,而当前会话用的可能正是另一个账号 ——
|
|
1885
1917
|
* 那会把一个账号独有的模型解析成保守的默认能力(上下文窗口、输出上限、图片输入
|
|
1886
1918
|
* 全部按最保守处理)。并集由带会话身份的读取填充,因此这个查询零成本、也不改变
|
|
1887
1919
|
* "谁在读目录"这件事。
|
|
@@ -1906,7 +1938,7 @@ var CodeBuddySession = class {
|
|
|
1906
1938
|
* 目录及其推广/档位;读不到时返回空值 —— 供面板使用的
|
|
1907
1939
|
* {@link catalogData} 建议性读取孪生体。
|
|
1908
1940
|
* @param signal - 可选取消信号。
|
|
1909
|
-
* @param sessionId -
|
|
1941
|
+
* @param sessionId - 用哪个会话的账号;缺省时按账号级兜底解析。
|
|
1910
1942
|
* @returns 目录与活动,或空列表。
|
|
1911
1943
|
*/
|
|
1912
1944
|
async catalogDataOrEmpty(signal, sessionId) {
|
|
@@ -1933,7 +1965,7 @@ var CodeBuddySession = class {
|
|
|
1933
1965
|
* 列出模型是配置页上的浏览动作,所以失败必须降级为“没有可显示的内容”,
|
|
1934
1966
|
* 而不是让页面崩掉。请求路径直接使用 {@link models} 并保留真实失败。
|
|
1935
1967
|
* @param signal - 可选取消信号。
|
|
1936
|
-
* @param sessionId -
|
|
1968
|
+
* @param sessionId - 用哪个会话的账号;缺省时按账号级兜底解析。
|
|
1937
1969
|
* @returns 目录,或空列表。
|
|
1938
1970
|
*/
|
|
1939
1971
|
async modelsOrEmpty(signal, sessionId) {
|
|
@@ -1954,7 +1986,7 @@ var CodeBuddySession = class {
|
|
|
1954
1986
|
* 其他每种失败(传输、解析、刷新过期)都在一条警告之后解析为
|
|
1955
1987
|
* `undefined`。身份通过与聊天请求相同的按账号单飞刷新解析,所以并发的计量
|
|
1956
1988
|
* 读取绝不会消耗两次刷新 token。
|
|
1957
|
-
* @param sessionId -
|
|
1989
|
+
* @param sessionId - 用哪个会话的账号;缺省时按账号级兜底解析。
|
|
1958
1990
|
* @param signal - 可选取消信号。
|
|
1959
1991
|
* @returns 该快照;未存有任何凭据或计量平面不可达时为 `undefined`。
|
|
1960
1992
|
*/
|
|
@@ -3552,7 +3584,7 @@ function enrichModel(model, promotions, tiers, withOverrides) {
|
|
|
3552
3584
|
* `startLogin` 生成握手并返回用户必须打开的 URL,`pollLogin` 检查该握手是否已完成,
|
|
3553
3585
|
* `pendingLogin` 报出仍在轮询的握手(浏览器刷新后据此接回);
|
|
3554
3586
|
* 一次完成的登录会**追加**一个账号,而不是取代已有的。`accounts`、`activate`、
|
|
3555
|
-
* `
|
|
3587
|
+
* `logout`、`reorder` 是配置页与会话账号按钮其余时间驱动的读写组合。
|
|
3556
3588
|
*
|
|
3557
3589
|
* @module dsh-llm-codebuddy-power/auth-service
|
|
3558
3590
|
*/
|
|
@@ -3594,6 +3626,7 @@ const CREDIT_UID_DISPLAY_CHARS = 8;
|
|
|
3594
3626
|
*
|
|
3595
3627
|
* uid 在**呈现边界**才截断:存储与解析都保留完整值,截断只影响这一个提示行。把它放在
|
|
3596
3628
|
* 这里而不是存储层,是因为存储层丢掉的信息无法再恢复,而显示层的取舍可以随时改。
|
|
3629
|
+
* 请求 id 不截断,因为它要整个被复制出去。
|
|
3597
3630
|
* @param record - 已按账号表展开的轮次记录。
|
|
3598
3631
|
* @returns 对客户端安全的投影。
|
|
3599
3632
|
*/
|
|
@@ -3603,7 +3636,8 @@ function projectCreditRecord(record) {
|
|
|
3603
3636
|
accounts: record.accounts.map((account) => ({
|
|
3604
3637
|
nickname: account.nickname,
|
|
3605
3638
|
uidPrefix: account.uid.slice(0, CREDIT_UID_DISPLAY_CHARS)
|
|
3606
|
-
}))
|
|
3639
|
+
})),
|
|
3640
|
+
...record.requestId === void 0 ? {} : { requestId: record.requestId }
|
|
3607
3641
|
};
|
|
3608
3642
|
}
|
|
3609
3643
|
/**
|
|
@@ -3650,10 +3684,6 @@ var CodeBuddyAuthService = class {
|
|
|
3650
3684
|
case "cancelLogin": return this.cancelLogin(stringField(payload, "state")) ? ok(void 0) : err("bad-request", "a login handshake id is required");
|
|
3651
3685
|
case "sessionAccount": return ok(await this.sessionAccount(stringField(payload, "sessionId")));
|
|
3652
3686
|
case "activate": return await this.activate(stringField(payload, "sessionId"), stringField(payload, "uid")) ? ok(void 0) : err("unknown-account", "the requested account is not stored");
|
|
3653
|
-
case "setDefault": {
|
|
3654
|
-
const uid = stringField(payload, "uid");
|
|
3655
|
-
return await this.setDefault(uid.length === 0 ? void 0 : uid) ? ok(void 0) : err("unknown-account", "the requested account is not stored");
|
|
3656
|
-
}
|
|
3657
3687
|
case "logout":
|
|
3658
3688
|
await this.logout(stringListField(payload, "uids"));
|
|
3659
3689
|
return ok(void 0);
|
|
@@ -3676,12 +3706,12 @@ var CodeBuddyAuthService = class {
|
|
|
3676
3706
|
}
|
|
3677
3707
|
}
|
|
3678
3708
|
/**
|
|
3679
|
-
*
|
|
3709
|
+
* 读取已存账号,不要求必须存在。
|
|
3680
3710
|
* @returns 账号集合;未存任何内容时为空列表。
|
|
3681
3711
|
*/
|
|
3682
3712
|
async accounts() {
|
|
3683
3713
|
if (this.session === void 0) return { accounts: [] };
|
|
3684
|
-
return this.session.accountList();
|
|
3714
|
+
return { accounts: await this.session.accountList() };
|
|
3685
3715
|
}
|
|
3686
3716
|
/**
|
|
3687
3717
|
* 发起一次浏览器登录握手。
|
|
@@ -3789,19 +3819,6 @@ var CodeBuddyAuthService = class {
|
|
|
3789
3819
|
return true;
|
|
3790
3820
|
}
|
|
3791
3821
|
/**
|
|
3792
|
-
* 指定或取消默认账号。
|
|
3793
|
-
* @param uid - 默认账号 uid;`undefined` 表示取消默认账号。
|
|
3794
|
-
* @returns 指定时该账号已存、或取消成功时为 true。
|
|
3795
|
-
*/
|
|
3796
|
-
async setDefault(uid) {
|
|
3797
|
-
if (uid !== void 0) {
|
|
3798
|
-
if (!(await this.accounts()).accounts.some((account) => account.uid === uid)) return false;
|
|
3799
|
-
}
|
|
3800
|
-
await setDefaultAccount(uid);
|
|
3801
|
-
this.session?.invalidate();
|
|
3802
|
-
return true;
|
|
3803
|
-
}
|
|
3804
|
-
/**
|
|
3805
3822
|
* 移除若干账号。
|
|
3806
3823
|
* @param uids - 要移除的账号 uid。
|
|
3807
3824
|
*/
|
|
@@ -3813,7 +3830,7 @@ var CodeBuddyAuthService = class {
|
|
|
3813
3830
|
/**
|
|
3814
3831
|
* 按给定顺序重排账号。
|
|
3815
3832
|
*
|
|
3816
|
-
*
|
|
3833
|
+
* 顺序即展示顺序,也是没有手动切换记录时的兜底账号,因此这里真的
|
|
3817
3834
|
* 改变"用谁"。重排会让输入区控件组读到的账号集合顺序变化,故同样使会话缓存失效。
|
|
3818
3835
|
* @param uids - 目标顺序上的账号 uid。
|
|
3819
3836
|
*/
|
|
@@ -3893,7 +3910,7 @@ var CodeBuddyAuthService = class {
|
|
|
3893
3910
|
}
|
|
3894
3911
|
/**
|
|
3895
3912
|
* 供客户端面板使用的增强版 CodeBuddy 目录:应用了促销/等级展示信息与覆盖配置的模型。
|
|
3896
|
-
* @param sessionId -
|
|
3913
|
+
* @param sessionId - 用哪个会话的账号读目录;为空时按账号级兜底。
|
|
3897
3914
|
* @returns 增强结果;会话不可用或该账号没有目录时为空行。
|
|
3898
3915
|
*/
|
|
3899
3916
|
async enrichedModels(sessionId) {
|
|
@@ -4103,4 +4120,4 @@ function apply(ctx, config) {
|
|
|
4103
4120
|
}).catch(() => {});
|
|
4104
4121
|
}
|
|
4105
4122
|
//#endregion
|
|
4106
|
-
export { AUTH_PENDING_CODE, BLOCKED_MODEL_IDS, CODEBUDDY_AUTH_CHANNEL, CODEBUDDY_AXIOS_USER_AGENT, CODEBUDDY_CHAT_BASE, CODEBUDDY_DISPLAY_NAME, CODEBUDDY_ENDPOINT, CODEBUDDY_IDE_VERSION, CODEBUDDY_PRODUCT_NAME, CODEBUDDY_PROVIDER, CodeBuddyAdapter, CodeBuddyAuthService, CodeBuddySession, Config, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, LOGIN_POLL_INTERVAL_MS, LOGIN_RESULT_RETENTION_MS, LOGIN_TIMEOUT_MS, NotLoggedInError, REQUEST_IMAGE_DIMENSION_LADDER, REQUEST_IMAGE_MAX_BYTES, apply, fetchEnterpriseUsage, fetchPersonalUsage, fetchUsage, getStoragePath, hasDisclosedCapacity, httpErrorCode, inject, isBlockedModelId, loadSessionInfo, loadStorage, login, name, parseUsage, removeAccounts, resolveConnectionOptions, resolvePrefs,
|
|
4123
|
+
export { AUTH_PENDING_CODE, BLOCKED_MODEL_IDS, CODEBUDDY_AUTH_CHANNEL, CODEBUDDY_AXIOS_USER_AGENT, CODEBUDDY_CHAT_BASE, CODEBUDDY_DISPLAY_NAME, CODEBUDDY_ENDPOINT, CODEBUDDY_GIFT_SUB_PRODUCT_CODE, CODEBUDDY_IDE_VERSION, CODEBUDDY_PRODUCT_NAME, CODEBUDDY_PROVIDER, CodeBuddyAdapter, CodeBuddyAuthService, CodeBuddySession, Config, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, LOGIN_POLL_INTERVAL_MS, LOGIN_RESULT_RETENTION_MS, LOGIN_TIMEOUT_MS, NotLoggedInError, REQUEST_IMAGE_DIMENSION_LADDER, REQUEST_IMAGE_MAX_BYTES, apply, fetchEnterpriseUsage, fetchPersonalUsage, fetchUsage, getStoragePath, hasDisclosedCapacity, httpErrorCode, inject, isBlockedModelId, loadSessionInfo, loadStorage, login, name, parseUsage, removeAccounts, resolveConnectionOptions, resolvePrefs, setLastAccount, updateSessionInfo, updateStorage, upsertAccount };
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `startLogin` 生成握手并返回用户必须打开的 URL,`pollLogin` 检查该握手是否已完成,
|
|
6
6
|
* `pendingLogin` 报出仍在轮询的握手(浏览器刷新后据此接回);
|
|
7
7
|
* 一次完成的登录会**追加**一个账号,而不是取代已有的。`accounts`、`activate`、
|
|
8
|
-
* `
|
|
8
|
+
* `logout`、`reorder` 是配置页与会话账号按钮其余时间驱动的读写组合。
|
|
9
9
|
*
|
|
10
10
|
* @module dsh-llm-codebuddy-power/auth-service
|
|
11
11
|
*/
|
|
@@ -19,8 +19,6 @@ export declare const CODEBUDDY_AUTH_CHANNEL = "/codebuddy";
|
|
|
19
19
|
export interface CodeBuddyAccountsResult {
|
|
20
20
|
/** 已存账号,顺序与磁盘一致。 */
|
|
21
21
|
accounts: CodeBuddyAccountInfo[];
|
|
22
|
-
/** 用户显式指定的默认账号;未指定或缺省时缺省。 */
|
|
23
|
-
defaultUid?: string;
|
|
24
22
|
}
|
|
25
23
|
/** `startLogin` 返回给客户端的结构。 */
|
|
26
24
|
export interface CodeBuddyLoginStart {
|
|
@@ -89,6 +87,13 @@ export interface CodeBuddyTurnCreditResult {
|
|
|
89
87
|
credit: number;
|
|
90
88
|
/** 本轮扣分用过的账号,按首次使用排序;一轮里切换过账号时会有多个。 */
|
|
91
89
|
accounts: CodeBuddyTurnCreditAccount[];
|
|
90
|
+
/**
|
|
91
|
+
* 本轮的 CodeBuddy 请求 id,完整值。
|
|
92
|
+
*
|
|
93
|
+
* 与 uid 不同,它不在这里截断:客户端要把它整个复制出来,截断就会复制到一个查不到的
|
|
94
|
+
* id。显示几位由呈现层决定,那里才是可以改的取舍。
|
|
95
|
+
*/
|
|
96
|
+
requestId?: string;
|
|
92
97
|
}
|
|
93
98
|
/** `creditOf` 返回给客户端的一个账号。 */
|
|
94
99
|
export interface CodeBuddyTurnCreditAccount {
|
|
@@ -116,7 +121,7 @@ export declare class CodeBuddyAuthService {
|
|
|
116
121
|
/** 把一次 RPC endpoint 调用路由到对应的处理器。 */
|
|
117
122
|
private dispatch;
|
|
118
123
|
/**
|
|
119
|
-
*
|
|
124
|
+
* 读取已存账号,不要求必须存在。
|
|
120
125
|
* @returns 账号集合;未存任何内容时为空列表。
|
|
121
126
|
*/
|
|
122
127
|
accounts(): Promise<CodeBuddyAccountsResult>;
|
|
@@ -174,12 +179,6 @@ export declare class CodeBuddyAuthService {
|
|
|
174
179
|
* @returns 该握手是否已被放弃(未知 state 同样是 true)。
|
|
175
180
|
*/
|
|
176
181
|
cancelLogin(state: string): boolean;
|
|
177
|
-
/**
|
|
178
|
-
* 指定或取消默认账号。
|
|
179
|
-
* @param uid - 默认账号 uid;`undefined` 表示取消默认账号。
|
|
180
|
-
* @returns 指定时该账号已存、或取消成功时为 true。
|
|
181
|
-
*/
|
|
182
|
-
setDefault(uid: string | undefined): Promise<boolean>;
|
|
183
182
|
/**
|
|
184
183
|
* 移除若干账号。
|
|
185
184
|
* @param uids - 要移除的账号 uid。
|
|
@@ -188,7 +187,7 @@ export declare class CodeBuddyAuthService {
|
|
|
188
187
|
/**
|
|
189
188
|
* 按给定顺序重排账号。
|
|
190
189
|
*
|
|
191
|
-
*
|
|
190
|
+
* 顺序即展示顺序,也是没有手动切换记录时的兜底账号,因此这里真的
|
|
192
191
|
* 改变"用谁"。重排会让输入区控件组读到的账号集合顺序变化,故同样使会话缓存失效。
|
|
193
192
|
* @param uids - 目标顺序上的账号 uid。
|
|
194
193
|
*/
|
|
@@ -225,7 +224,7 @@ export declare class CodeBuddyAuthService {
|
|
|
225
224
|
private settle;
|
|
226
225
|
/**
|
|
227
226
|
* 供客户端面板使用的增强版 CodeBuddy 目录:应用了促销/等级展示信息与覆盖配置的模型。
|
|
228
|
-
* @param sessionId -
|
|
227
|
+
* @param sessionId - 用哪个会话的账号读目录;为空时按账号级兜底。
|
|
229
228
|
* @returns 增强结果;会话不可用或该账号没有目录时为空行。
|
|
230
229
|
*/
|
|
231
230
|
enrichedModels(sessionId: string): Promise<{
|
package/lib/types/cli/login.d.ts
CHANGED
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* 用法:
|
|
11
11
|
* codebuddy-power 登录并追加账号
|
|
12
|
-
* codebuddy-power --status
|
|
13
|
-
* codebuddy-power --default <账号> 把某个账号设为默认
|
|
12
|
+
* codebuddy-power --status 列出全部账号
|
|
14
13
|
* codebuddy-power --logout <账号> 退出一个账号
|
|
15
14
|
* codebuddy-power --logout --all 退出全部账号
|
|
16
15
|
* codebuddy-power --no-open 只打印 URL,不打开浏览器
|
|
@@ -27,10 +27,9 @@ export interface AccountSwitcherInjected {
|
|
|
27
27
|
/** 三个界面偏好的当前值,与设置页同源。 */
|
|
28
28
|
prefs: HostObservable<CodeBuddyPrefs>;
|
|
29
29
|
};
|
|
30
|
-
/**
|
|
30
|
+
/** 读取账号集合。 */
|
|
31
31
|
fetchAccounts: () => Promise<{
|
|
32
32
|
accounts: CodeBuddyAccountView[];
|
|
33
|
-
defaultUid: string | null;
|
|
34
33
|
} | null>;
|
|
35
34
|
/** 读取该会话此刻生效的账号 uid;没有账号时为 null。 */
|
|
36
35
|
fetchSessionAccount: () => Promise<string | null>;
|