dsh-codearts 1.2.9 → 1.2.10

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 CHANGED
@@ -3,6 +3,18 @@
3
3
  本文件记录本插件的重要改动。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
4
4
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
5
5
 
6
+ ## [1.2.10] - 2026-11-06
7
+
8
+ ### 新增
9
+
10
+ - **每个账号都能「重新登录」,凭证写回原条目**:以前账号过期时卡片上只有「删除」,
11
+ 要先删掉再加回来,账号的展示顺序和备注全丢。现在账号行多了「重新登录」按钮
12
+ (过期的账号显示为主色按钮),走一遍浏览器 OAuth 就把新凭证写回同一条,id、顺序、
13
+ 备注都保留。手工粘贴 token 的账号同样适用。
14
+ - 点了 A 账号的重登却登成了 B 账号时,B 会作为新账号添加,A 原样不动,并提示
15
+ 「你登录的是另一个账号,已作为新账号添加;原账号保持不变」——不会把 A 的凭证
16
+ 悄悄换成别人的。
17
+
6
18
  ## [1.2.9] - 2026-11-06
7
19
 
8
20
  ### 变更
package/lib/bin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { R as isBenefitModel, V as CodeArtsAccountStore, W as codeartsAccountsPath, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-B2LNsUuR.mjs";
2
+ import { R as isBenefitModel, V as CodeArtsAccountStore, W as codeartsAccountsPath, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-CjPd0Gok.mjs";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  //#region src/version.ts
5
- const CODEARTS_VERSION = "1.2.9";
5
+ const CODEARTS_VERSION = "1.2.10";
6
6
  //#endregion
7
7
  //#region src/bin.ts
8
8
  /**
@@ -32,6 +32,12 @@ interface CodeArtsSettingsKey {
32
32
  expiredHint: string;
33
33
  accountsTitle: string;
34
34
  accountRemove: string;
35
+ /** 重新登录这个账号:新凭证写回原条目,不会多出一条。 */
36
+ accountRelogin: string;
37
+ /** 该账号正在浏览器里授权。 */
38
+ reloginPending: string;
39
+ /** 「重新登录」却登了另一个账号:已作为新账号添加,原账号未动。 */
40
+ reloginOtherAccount: string;
35
41
  addAccount: string;
36
42
  pasteTokenAdd: string;
37
43
  accountsRotateHint: string;
@@ -62,7 +62,7 @@ function subscribeSidebarPanelWanted(listener) {
62
62
  }
63
63
  //#endregion
64
64
  //#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPluginCard.module.css.mjs
65
- const css$1 = ".xoziZG_card{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-settings-card-fill);max-width:720px}.xoziZG_header{align-items:flex-start;gap:12px;padding:14px 16px;display:flex}.xoziZG_headText{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.xoziZG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:22px}.xoziZG_desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.xoziZG_statusLine{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;font-size:14px;font-weight:500;line-height:22px;display:inline-flex}.xoziZG_meta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.xoziZG_body{border-top:.5px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 16px}.xoziZG_tabs{margin-top:12px}.xoziZG_tabPanel{padding-top:2px}.xoziZG_accountToolbar{gap:8px;margin-top:12px;display:flex}.xoziZG_accountToolbar>*{flex:1}.xoziZG_manualForm{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:12px}.xoziZG_accountCard{flex-direction:column;gap:10px;margin-top:12px;display:flex}.xoziZG_accountEntry{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}.xoziZG_accountRow{align-items:center;gap:10px;padding:12px;display:flex}.xoziZG_claimAllRow{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:flex-end;padding:10px 12px 0;display:flex}.xoziZG_avatar{background:var(--dsw-alias-bg-layer-3);width:32px;height:32px;color:var(--dsw-alias-label-primary);border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:inline-flex}.xoziZG_accountInfo{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.xoziZG_accountNameRow{align-items:center;gap:6px;min-width:0;display:flex}.xoziZG_accountName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.xoziZG_accountRowActions{flex:none;gap:6px;display:flex}.xoziZG_accountHint{color:var(--dsw-alias-label-tertiary);margin:0;padding:0 12px 12px;font-size:12px;line-height:18px}.xoziZG_creditBlock{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px}.xoziZG_balanceRow{flex-wrap:wrap;align-items:baseline;gap:6px;display:flex}.xoziZG_balance{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:28px;font-weight:600;line-height:34px}.xoziZG_balanceUnit{color:var(--dsw-alias-label-secondary);font-size:12px}.xoziZG_balanceMeta{color:var(--dsw-alias-label-tertiary);margin-left:2px;font-size:12px}.xoziZG_updated{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:12px}.xoziZG_creditRows{flex-direction:column;gap:4px;margin-top:8px;display:flex}.xoziZG_creditRow{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;font-size:12px;line-height:18px;display:flex}.xoziZG_usageBar{background:var(--dsw-alias-border-l2);border-radius:2px;height:4px;margin-top:4px;display:block;overflow:hidden}.xoziZG_usageFill{background:var(--dsw-alias-brand-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.xoziZG_expiryRow{margin-top:2px}.xoziZG_expiryLabel{color:var(--dsw-alias-state-warn-label)}.xoziZG_bar{background:var(--dsw-alias-bg-layer-3);border-radius:2px;height:4px;margin-top:6px;display:block;overflow:hidden}.xoziZG_barFill{background:var(--dsw-alias-state-warn-primary);border-radius:2px;height:100%;display:block}.xoziZG_creditLink{margin-top:8px;display:inline-block}.xoziZG_creditFooter{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:8px;margin-top:12px;padding-top:10px;display:flex}.xoziZG_creditHint{color:var(--dsw-alias-label-tertiary);margin:8px 0 0;font-size:12px;line-height:18px}.xoziZG_section{margin-top:16px}.xoziZG_sectionHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.xoziZG_sectionLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500}.xoziZG_count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.xoziZG_hint{color:var(--dsw-alias-label-secondary);margin:8px 0 0;font-size:13px;line-height:20px}.xoziZG_error{color:var(--dsw-alias-state-error-primary);margin:10px 0 0;font-size:13px;line-height:20px}.xoziZG_actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;display:flex}.xoziZG_danger{color:var(--dsw-alias-state-error-primary)}.xoziZG_link{appearance:none;color:var(--dsw-alias-brand-text);font:inherit;text-align:left;word-break:break-all;cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.xoziZG_link:hover{text-decoration:underline}.xoziZG_choices{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_choiceRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;margin:0 -6px;padding:5px 6px;display:flex}.xoziZG_choiceRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_statGrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:10px 0 14px;display:grid}.xoziZG_statCard{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);flex-direction:column;gap:1px;padding:8px 10px;display:flex}.xoziZG_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.xoziZG_statValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:15px;line-height:20px}.xoziZG_statSub{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.xoziZG_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;border-radius:6px;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid;position:relative}.xoziZG_modelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_usageTip{z-index:5;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);min-width:180px;max-width:260px;color:var(--dsw-alias-label-secondary);text-align:left;font-variant-numeric:tabular-nums;pointer-events:none;padding:8px 10px;font-size:12px;line-height:1.9;position:absolute;bottom:calc(100% + 6px);right:0;box-shadow:0 10px 28px #00000073}.xoziZG_usageTip[data-float=true]{z-index:40;position:fixed;bottom:auto;right:auto}.xoziZG_usageTipName{max-width:240px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_usageTipSep{background:var(--dsw-alias-border-l2);height:1px;margin:4px 0}.xoziZG_usageTipRow{justify-content:space-between;gap:24px;display:flex}.xoziZG_usageTipRow span:last-child{color:var(--dsw-alias-label-primary);font-weight:600}.xoziZG_modelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.xoziZG_modelTrack{background:var(--dsw-alias-border-l2);border-radius:4px;height:8px;display:block;overflow:hidden}.xoziZG_modelFill{background:var(--dsw-alias-brand-primary);border-radius:4px;height:100%;transition:width .16s;display:block}.xoziZG_modelTokens,.xoziZG_modelShare,.xoziZG_modelRequests{color:var(--dsw-alias-label-secondary);text-align:right;white-space:nowrap;font-size:11px;line-height:16px}.xoziZG_modelRequests{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatGrid{grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin:8px 0 2px;display:grid}.xoziZG_heatWeekday{color:var(--dsw-alias-label-tertiary);text-align:center;font-size:10px;line-height:14px}.xoziZG_heatCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);height:36px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;border:0;border-radius:8px;outline:0;justify-content:center;align-items:center;font-size:12px;transition:background .12s ease-out;display:flex}.xoziZG_heatCell[data-tone=empty]{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatCell[data-tone=pad]{background:0 0}.xoziZG_heatCell[data-tone=out]{color:var(--dsw-alias-label-tertiary);opacity:.45;background:0 0}.xoziZG_heatCell[data-tone=lv1]{color:#0f1115;background:#ddf4e7}.xoziZG_heatCell[data-tone=lv2]{color:#0f1115;background:#b3e8cc}.xoziZG_heatCell[data-tone=lv3]{color:#0f1115;background:#7dd8ac}.xoziZG_heatCell[data-tone=lv4]{color:#fff;background:#40c584}.xoziZG_heatCell[data-tone=lv5]{color:#fff;background:#16a34a}.xoziZG_heatCell[data-today=true]{font-weight:700;box-shadow:inset 0 -2px}.xoziZG_heatHours{grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;margin:8px 0 0;display:grid}.xoziZG_heatHourCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);border-radius:4px;height:26px;transition:background .12s ease-out}.xoziZG_heatHourCell[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatHourCell[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatHourCell[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatHourCell[data-tone=lv4]{background:#40c584}.xoziZG_heatHourCell[data-tone=lv5]{background:#16a34a}.xoziZG_heatAxis{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;font-size:10px;line-height:14px;display:grid}.xoziZG_heatAxisSlot{text-align:center;white-space:nowrap;overflow:hidden}.xoziZG_heatLegend{color:var(--dsw-alias-label-tertiary);justify-content:flex-start;align-items:center;gap:3px;margin:0 0 6px;font-size:10px;display:flex}.xoziZG_heatLegendChip{border-radius:3px;width:10px;height:10px}.xoziZG_heatLegendChip[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatLegendChip[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatLegendChip[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatLegendChip[data-tone=lv4]{background:#40c584}.xoziZG_heatLegendChip[data-tone=lv5]{background:#16a34a}.xoziZG_trendTip{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;margin:2px 0 0;font-size:11px;line-height:16px}.xoziZG_check{flex:1;min-width:0}.xoziZG_check>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_manual{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:0 12px}.xoziZG_manual[open]{padding-bottom:12px}.xoziZG_manualSummary{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;padding:9px 0;font-size:13px;list-style:none;display:flex}.xoziZG_manualSummary::-webkit-details-marker{display:none}.xoziZG_field{flex-direction:column;gap:5px;margin-top:10px;display:flex}.xoziZG_fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px}.xoziZG_area{box-sizing:border-box;resize:vertical;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px}.xoziZG_area::placeholder{color:var(--dsw-alias-label-dimmed)}.xoziZG_area:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.xoziZG_skeleton{flex-direction:column;gap:10px;padding:4px 0;display:flex}.xoziZG_skeletonRow{border-radius:var(--dsw-radius-sm,4px);background:var(--dsw-alias-border-l2);height:12px;animation:1.4s ease-in-out infinite xoziZG_skeletonBreath}.xoziZG_skeletonRow:nth-child(2){width:72%}.xoziZG_skeletonRow:nth-child(3){width:46%}@keyframes xoziZG_skeletonBreath{0%,to{opacity:.45}50%{opacity:.9}}@media (prefers-reduced-motion:reduce){.xoziZG_skeletonRow{animation:none}}";
65
+ const css$1 = ".xoziZG_card{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-settings-card-fill);max-width:720px}.xoziZG_header{align-items:flex-start;gap:12px;padding:14px 16px;display:flex}.xoziZG_headText{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.xoziZG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:22px}.xoziZG_desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.xoziZG_statusLine{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;font-size:14px;font-weight:500;line-height:22px;display:inline-flex}.xoziZG_meta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.xoziZG_body{border-top:.5px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 16px}.xoziZG_tabs{margin-top:12px}.xoziZG_tabPanel{padding-top:2px}.xoziZG_accountToolbar{gap:8px;margin-top:12px;display:flex}.xoziZG_accountToolbar>*{flex:1}.xoziZG_manualForm{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:12px}.xoziZG_accountCard{flex-direction:column;gap:10px;margin-top:12px;display:flex}.xoziZG_accountEntry{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}.xoziZG_accountRow{align-items:center;gap:10px;padding:12px;display:flex}.xoziZG_claimAllRow{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:flex-end;padding:10px 12px 0;display:flex}.xoziZG_avatar{background:var(--dsw-alias-bg-layer-3);width:32px;height:32px;color:var(--dsw-alias-label-primary);border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:inline-flex}.xoziZG_accountInfo{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.xoziZG_accountNameRow{align-items:center;gap:6px;min-width:0;display:flex}.xoziZG_accountName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.xoziZG_accountRowActions{flex-wrap:wrap;flex:none;justify-content:flex-end;gap:6px;display:flex}.xoziZG_accountHint{color:var(--dsw-alias-label-tertiary);margin:0;padding:0 12px 12px;font-size:12px;line-height:18px}.xoziZG_creditBlock{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px}.xoziZG_balanceRow{flex-wrap:wrap;align-items:baseline;gap:6px;display:flex}.xoziZG_balance{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:28px;font-weight:600;line-height:34px}.xoziZG_balanceUnit{color:var(--dsw-alias-label-secondary);font-size:12px}.xoziZG_balanceMeta{color:var(--dsw-alias-label-tertiary);margin-left:2px;font-size:12px}.xoziZG_updated{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:12px}.xoziZG_creditRows{flex-direction:column;gap:4px;margin-top:8px;display:flex}.xoziZG_creditRow{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;font-size:12px;line-height:18px;display:flex}.xoziZG_usageBar{background:var(--dsw-alias-border-l2);border-radius:2px;height:4px;margin-top:4px;display:block;overflow:hidden}.xoziZG_usageFill{background:var(--dsw-alias-brand-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.xoziZG_expiryRow{margin-top:2px}.xoziZG_expiryLabel{color:var(--dsw-alias-state-warn-label)}.xoziZG_bar{background:var(--dsw-alias-bg-layer-3);border-radius:2px;height:4px;margin-top:6px;display:block;overflow:hidden}.xoziZG_barFill{background:var(--dsw-alias-state-warn-primary);border-radius:2px;height:100%;display:block}.xoziZG_creditLink{margin-top:8px;display:inline-block}.xoziZG_creditFooter{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:8px;margin-top:12px;padding-top:10px;display:flex}.xoziZG_creditHint{color:var(--dsw-alias-label-tertiary);margin:8px 0 0;font-size:12px;line-height:18px}.xoziZG_section{margin-top:16px}.xoziZG_sectionHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.xoziZG_sectionLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500}.xoziZG_count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.xoziZG_hint{color:var(--dsw-alias-label-secondary);margin:8px 0 0;font-size:13px;line-height:20px}.xoziZG_error{color:var(--dsw-alias-state-error-primary);margin:10px 0 0;font-size:13px;line-height:20px}.xoziZG_actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;display:flex}.xoziZG_danger{color:var(--dsw-alias-state-error-primary)}.xoziZG_link{appearance:none;color:var(--dsw-alias-brand-text);font:inherit;text-align:left;word-break:break-all;cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.xoziZG_link:hover{text-decoration:underline}.xoziZG_choices{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_choiceRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;margin:0 -6px;padding:5px 6px;display:flex}.xoziZG_choiceRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_statGrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:10px 0 14px;display:grid}.xoziZG_statCard{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);flex-direction:column;gap:1px;padding:8px 10px;display:flex}.xoziZG_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.xoziZG_statValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:15px;line-height:20px}.xoziZG_statSub{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.xoziZG_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;border-radius:6px;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid;position:relative}.xoziZG_modelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_usageTip{z-index:5;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);min-width:180px;max-width:260px;color:var(--dsw-alias-label-secondary);text-align:left;font-variant-numeric:tabular-nums;pointer-events:none;padding:8px 10px;font-size:12px;line-height:1.9;position:absolute;bottom:calc(100% + 6px);right:0;box-shadow:0 10px 28px #00000073}.xoziZG_usageTip[data-float=true]{z-index:40;position:fixed;bottom:auto;right:auto}.xoziZG_usageTipName{max-width:240px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_usageTipSep{background:var(--dsw-alias-border-l2);height:1px;margin:4px 0}.xoziZG_usageTipRow{justify-content:space-between;gap:24px;display:flex}.xoziZG_usageTipRow span:last-child{color:var(--dsw-alias-label-primary);font-weight:600}.xoziZG_modelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.xoziZG_modelTrack{background:var(--dsw-alias-border-l2);border-radius:4px;height:8px;display:block;overflow:hidden}.xoziZG_modelFill{background:var(--dsw-alias-brand-primary);border-radius:4px;height:100%;transition:width .16s;display:block}.xoziZG_modelTokens,.xoziZG_modelShare,.xoziZG_modelRequests{color:var(--dsw-alias-label-secondary);text-align:right;white-space:nowrap;font-size:11px;line-height:16px}.xoziZG_modelRequests{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatGrid{grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin:8px 0 2px;display:grid}.xoziZG_heatWeekday{color:var(--dsw-alias-label-tertiary);text-align:center;font-size:10px;line-height:14px}.xoziZG_heatCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);height:36px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;border:0;border-radius:8px;outline:0;justify-content:center;align-items:center;font-size:12px;transition:background .12s ease-out;display:flex}.xoziZG_heatCell[data-tone=empty]{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatCell[data-tone=pad]{background:0 0}.xoziZG_heatCell[data-tone=out]{color:var(--dsw-alias-label-tertiary);opacity:.45;background:0 0}.xoziZG_heatCell[data-tone=lv1]{color:#0f1115;background:#ddf4e7}.xoziZG_heatCell[data-tone=lv2]{color:#0f1115;background:#b3e8cc}.xoziZG_heatCell[data-tone=lv3]{color:#0f1115;background:#7dd8ac}.xoziZG_heatCell[data-tone=lv4]{color:#fff;background:#40c584}.xoziZG_heatCell[data-tone=lv5]{color:#fff;background:#16a34a}.xoziZG_heatCell[data-today=true]{font-weight:700;box-shadow:inset 0 -2px}.xoziZG_heatHours{grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;margin:8px 0 0;display:grid}.xoziZG_heatHourCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);border-radius:4px;height:26px;transition:background .12s ease-out}.xoziZG_heatHourCell[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatHourCell[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatHourCell[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatHourCell[data-tone=lv4]{background:#40c584}.xoziZG_heatHourCell[data-tone=lv5]{background:#16a34a}.xoziZG_heatAxis{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;font-size:10px;line-height:14px;display:grid}.xoziZG_heatAxisSlot{text-align:center;white-space:nowrap;overflow:hidden}.xoziZG_heatLegend{color:var(--dsw-alias-label-tertiary);justify-content:flex-start;align-items:center;gap:3px;margin:0 0 6px;font-size:10px;display:flex}.xoziZG_heatLegendChip{border-radius:3px;width:10px;height:10px}.xoziZG_heatLegendChip[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatLegendChip[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatLegendChip[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatLegendChip[data-tone=lv4]{background:#40c584}.xoziZG_heatLegendChip[data-tone=lv5]{background:#16a34a}.xoziZG_trendTip{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;margin:2px 0 0;font-size:11px;line-height:16px}.xoziZG_check{flex:1;min-width:0}.xoziZG_check>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_manual{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:0 12px}.xoziZG_manual[open]{padding-bottom:12px}.xoziZG_manualSummary{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;padding:9px 0;font-size:13px;list-style:none;display:flex}.xoziZG_manualSummary::-webkit-details-marker{display:none}.xoziZG_field{flex-direction:column;gap:5px;margin-top:10px;display:flex}.xoziZG_fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px}.xoziZG_area{box-sizing:border-box;resize:vertical;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px}.xoziZG_area::placeholder{color:var(--dsw-alias-label-dimmed)}.xoziZG_area:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.xoziZG_skeleton{flex-direction:column;gap:10px;padding:4px 0;display:flex}.xoziZG_skeletonRow{border-radius:var(--dsw-radius-sm,4px);background:var(--dsw-alias-border-l2);height:12px;animation:1.4s ease-in-out infinite xoziZG_skeletonBreath}.xoziZG_skeletonRow:nth-child(2){width:72%}.xoziZG_skeletonRow:nth-child(3){width:46%}@keyframes xoziZG_skeletonBreath{0%,to{opacity:.45}50%{opacity:.9}}@media (prefers-reduced-motion:reduce){.xoziZG_skeletonRow{animation:none}}";
66
66
  const tagId$1 = "dsh-codearts/CodeArtsPluginCard.module.css";
67
67
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
68
68
  const tag = document.createElement("style");
@@ -72,92 +72,92 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
72
72
  document.head.appendChild(tag);
73
73
  }
74
74
  var CodeArtsPluginCard_module_css_default = {
75
- "statValue": "xoziZG_statValue",
76
- "statSub": "xoziZG_statSub",
77
- "check": "xoziZG_check",
78
- "body": "xoziZG_body",
79
- "barFill": "xoziZG_barFill",
80
- "statCard": "xoziZG_statCard",
81
- "heatWeekday": "xoziZG_heatWeekday",
75
+ "accountHint": "xoziZG_accountHint",
76
+ "heatLegendChip": "xoziZG_heatLegendChip",
77
+ "balance": "xoziZG_balance",
78
+ "claimAllRow": "xoziZG_claimAllRow",
79
+ "balanceUnit": "xoziZG_balanceUnit",
80
+ "heatAxisSlot": "xoziZG_heatAxisSlot",
82
81
  "creditBlock": "xoziZG_creditBlock",
82
+ "statusLine": "xoziZG_statusLine",
83
+ "modelChart": "xoziZG_modelChart",
84
+ "sectionHead": "xoziZG_sectionHead",
85
+ "usageBar": "xoziZG_usageBar",
83
86
  "accountCard": "xoziZG_accountCard",
84
- "card": "xoziZG_card",
85
- "sectionLabel": "xoziZG_sectionLabel",
86
- "error": "xoziZG_error",
87
- "desc": "xoziZG_desc",
88
- "accountRowActions": "xoziZG_accountRowActions",
87
+ "usageTipName": "xoziZG_usageTipName",
88
+ "choiceRow": "xoziZG_choiceRow",
89
+ "fieldLabel": "xoziZG_fieldLabel",
89
90
  "modelRow": "xoziZG_modelRow",
90
- "balanceUnit": "xoziZG_balanceUnit",
91
- "balance": "xoziZG_balance",
92
- "usageTipRow": "xoziZG_usageTipRow",
93
- "bar": "xoziZG_bar",
94
- "accountRow": "xoziZG_accountRow",
91
+ "expiryRow": "xoziZG_expiryRow",
92
+ "headText": "xoziZG_headText",
93
+ "modelTrack": "xoziZG_modelTrack",
95
94
  "heatHourCell": "xoziZG_heatHourCell",
96
95
  "header": "xoziZG_header",
97
- "meta": "xoziZG_meta",
98
- "tabs": "xoziZG_tabs",
99
- "modelChart": "xoziZG_modelChart",
100
- "usageTipName": "xoziZG_usageTipName",
101
- "accountName": "xoziZG_accountName",
102
- "heatCell": "xoziZG_heatCell",
103
- "heatLegend": "xoziZG_heatLegend",
104
- "section": "xoziZG_section",
105
- "modelFill": "xoziZG_modelFill",
106
- "accountNameRow": "xoziZG_accountNameRow",
107
- "claimAllRow": "xoziZG_claimAllRow",
108
- "creditLink": "xoziZG_creditLink",
109
- "choiceRow": "xoziZG_choiceRow",
110
- "updated": "xoziZG_updated",
96
+ "accountToolbar": "xoziZG_accountToolbar",
111
97
  "statGrid": "xoziZG_statGrid",
98
+ "skeletonBreath": "xoziZG_skeletonBreath",
99
+ "balanceRow": "xoziZG_balanceRow",
100
+ "modelFill": "xoziZG_modelFill",
101
+ "heatAxis": "xoziZG_heatAxis",
102
+ "accountRow": "xoziZG_accountRow",
103
+ "heatGrid": "xoziZG_heatGrid",
112
104
  "field": "xoziZG_field",
113
- "creditRows": "xoziZG_creditRows",
114
- "modelRequests": "xoziZG_modelRequests",
115
- "manual": "xoziZG_manual",
116
- "skeletonRow": "xoziZG_skeletonRow",
117
- "expiryRow": "xoziZG_expiryRow",
105
+ "link": "xoziZG_link",
106
+ "heatHours": "xoziZG_heatHours",
107
+ "tabPanel": "xoziZG_tabPanel",
108
+ "choices": "xoziZG_choices",
109
+ "desc": "xoziZG_desc",
110
+ "creditHint": "xoziZG_creditHint",
111
+ "creditFooter": "xoziZG_creditFooter",
112
+ "accountInfo": "xoziZG_accountInfo",
118
113
  "manualForm": "xoziZG_manualForm",
119
- "name": "xoziZG_name",
120
- "usageTip": "xoziZG_usageTip",
121
- "avatar": "xoziZG_avatar",
122
- "heatAxisSlot": "xoziZG_heatAxisSlot",
114
+ "card": "xoziZG_card",
115
+ "actions": "xoziZG_actions",
116
+ "usageFill": "xoziZG_usageFill",
117
+ "usageTipRow": "xoziZG_usageTipRow",
123
118
  "modelTokens": "xoziZG_modelTokens",
124
- "expiryLabel": "xoziZG_expiryLabel",
125
- "heatHours": "xoziZG_heatHours",
126
- "heatLegendChip": "xoziZG_heatLegendChip",
127
- "heatGrid": "xoziZG_heatGrid",
128
- "accountEntry": "xoziZG_accountEntry",
119
+ "trendTip": "xoziZG_trendTip",
120
+ "section": "xoziZG_section",
121
+ "tabs": "xoziZG_tabs",
122
+ "meta": "xoziZG_meta",
123
+ "bar": "xoziZG_bar",
124
+ "barFill": "xoziZG_barFill",
125
+ "modelRequests": "xoziZG_modelRequests",
126
+ "skeleton": "xoziZG_skeleton",
129
127
  "modelName": "xoziZG_modelName",
130
- "heatAxis": "xoziZG_heatAxis",
131
- "fieldLabel": "xoziZG_fieldLabel",
132
- "hint": "xoziZG_hint",
133
- "creditRow": "xoziZG_creditRow",
134
- "creditFooter": "xoziZG_creditFooter",
135
- "creditHint": "xoziZG_creditHint",
128
+ "updated": "xoziZG_updated",
136
129
  "manualSummary": "xoziZG_manualSummary",
137
- "skeleton": "xoziZG_skeleton",
138
- "headText": "xoziZG_headText",
139
- "usageTipSep": "xoziZG_usageTipSep",
140
- "accountInfo": "xoziZG_accountInfo",
141
- "link": "xoziZG_link",
130
+ "area": "xoziZG_area",
131
+ "statCard": "xoziZG_statCard",
132
+ "heatWeekday": "xoziZG_heatWeekday",
133
+ "creditRow": "xoziZG_creditRow",
134
+ "check": "xoziZG_check",
135
+ "accountNameRow": "xoziZG_accountNameRow",
136
+ "skeletonRow": "xoziZG_skeletonRow",
142
137
  "balanceMeta": "xoziZG_balanceMeta",
143
- "danger": "xoziZG_danger",
144
- "trendTip": "xoziZG_trendTip",
145
- "skeletonBreath": "xoziZG_skeletonBreath",
138
+ "statSub": "xoziZG_statSub",
146
139
  "count": "xoziZG_count",
140
+ "name": "xoziZG_name",
141
+ "accountRowActions": "xoziZG_accountRowActions",
142
+ "danger": "xoziZG_danger",
143
+ "statLabel": "xoziZG_statLabel",
144
+ "usageTipSep": "xoziZG_usageTipSep",
147
145
  "modelShare": "xoziZG_modelShare",
148
- "statusLine": "xoziZG_statusLine",
149
- "usageFill": "xoziZG_usageFill",
150
- "usageBar": "xoziZG_usageBar",
151
- "choices": "xoziZG_choices",
152
- "balanceRow": "xoziZG_balanceRow",
153
- "actions": "xoziZG_actions",
154
- "modelTrack": "xoziZG_modelTrack",
155
- "accountHint": "xoziZG_accountHint",
156
- "tabPanel": "xoziZG_tabPanel",
157
- "accountToolbar": "xoziZG_accountToolbar",
158
- "sectionHead": "xoziZG_sectionHead",
159
- "area": "xoziZG_area",
160
- "statLabel": "xoziZG_statLabel"
146
+ "heatCell": "xoziZG_heatCell",
147
+ "heatLegend": "xoziZG_heatLegend",
148
+ "manual": "xoziZG_manual",
149
+ "avatar": "xoziZG_avatar",
150
+ "error": "xoziZG_error",
151
+ "body": "xoziZG_body",
152
+ "creditLink": "xoziZG_creditLink",
153
+ "accountName": "xoziZG_accountName",
154
+ "statValue": "xoziZG_statValue",
155
+ "expiryLabel": "xoziZG_expiryLabel",
156
+ "hint": "xoziZG_hint",
157
+ "usageTip": "xoziZG_usageTip",
158
+ "accountEntry": "xoziZG_accountEntry",
159
+ "sectionLabel": "xoziZG_sectionLabel",
160
+ "creditRows": "xoziZG_creditRows"
161
161
  };
162
162
  //#endregion
163
163
  //#region src/client/CodeArtsPluginCard.tsx
@@ -887,6 +887,8 @@ function CodeArtsPluginCard({ t }) {
887
887
  const [msg, setMsg] = (0, react.useState)(null);
888
888
  const [loginUrl, setLoginUrl] = (0, react.useState)(null);
889
889
  const [loginPending, setLoginPending] = (0, react.useState)(false);
890
+ /** 正在进行的是哪个账号的「重新登录」(无则 null)。用来只让那一行的按钮变「登录中」。 */
891
+ const [reloginId, setReloginId] = (0, react.useState)(null);
890
892
  const [selection, setSelection] = (0, react.useState)(null);
891
893
  const [draft, setDraft] = (0, react.useState)([]);
892
894
  const [savingModels, setSavingModels] = (0, react.useState)(false);
@@ -1211,16 +1213,29 @@ function CodeArtsPluginCard({ t }) {
1211
1213
  setRefreshing(false);
1212
1214
  }
1213
1215
  }
1214
- async function startOAuthLogin() {
1216
+ /**
1217
+ * 开始一次浏览器登录。
1218
+ *
1219
+ * 不带 `targetId` 是「添加账号」;带 `targetId` 是「重新登录这个账号」——
1220
+ * 服务端会把新凭证写回原条目(保留顺序与备注),而不是又长出一条。
1221
+ */
1222
+ async function startOAuthLogin(targetId) {
1215
1223
  setBusy(true);
1216
1224
  setMsg(null);
1217
1225
  setLoginPending(true);
1226
+ if (targetId !== void 0) setReloginId(targetId);
1227
+ const finish = () => {
1228
+ setLoginUrl(null);
1229
+ setLoginPending(false);
1230
+ setReloginId(null);
1231
+ };
1218
1232
  try {
1219
- const res = await fetch("/api/codearts/login", { method: "POST" });
1233
+ const query = targetId === void 0 ? "" : `?account=${encodeURIComponent(targetId)}`;
1234
+ const res = await fetch(`/api/codearts/login${query}`, { method: "POST" });
1220
1235
  const data = await res.json().catch(() => ({}));
1221
1236
  if (!res.ok || typeof data.url !== "string") {
1222
1237
  setMsg(data.error ?? `HTTP ${res.status}`);
1223
- setLoginPending(false);
1238
+ finish();
1224
1239
  return;
1225
1240
  }
1226
1241
  setLoginUrl(data.url);
@@ -1228,20 +1243,18 @@ function CodeArtsPluginCard({ t }) {
1228
1243
  const poll = async () => {
1229
1244
  const st = await (await fetch(`/api/codearts/login/status?url=${encodeURIComponent(data.url)}`, { headers: { Accept: "application/json" } })).json().catch(() => ({ status: "pending" }));
1230
1245
  if (st.status === "done") {
1231
- setLoginUrl(null);
1232
- setLoginPending(false);
1246
+ finish();
1247
+ if (st.conflict === true) setMsg(t("reloginOtherAccount"));
1233
1248
  await refresh();
1234
1249
  return;
1235
1250
  }
1236
1251
  if (st.status === "error") {
1237
- setLoginUrl(null);
1238
- setLoginPending(false);
1252
+ finish();
1239
1253
  setMsg(t("loginFailed"));
1240
1254
  return;
1241
1255
  }
1242
1256
  if (st.status === "idle") {
1243
- setLoginUrl(null);
1244
- setLoginPending(false);
1257
+ finish();
1245
1258
  await refresh();
1246
1259
  return;
1247
1260
  }
@@ -1250,7 +1263,7 @@ function CodeArtsPluginCard({ t }) {
1250
1263
  poll();
1251
1264
  } catch (err) {
1252
1265
  setMsg(err instanceof Error ? err.message : String(err));
1253
- setLoginPending(false);
1266
+ finish();
1254
1267
  } finally {
1255
1268
  setBusy(false);
1256
1269
  }
@@ -1500,16 +1513,22 @@ function CodeArtsPluginCard({ t }) {
1500
1513
  children: accountLine
1501
1514
  })]
1502
1515
  }),
1503
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1516
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1504
1517
  className: CodeArtsPluginCard_module_css_default.accountRowActions,
1505
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1518
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1519
+ variant: account.stale ? "primary" : "outline",
1520
+ size: "sm",
1521
+ disabled: busy || loginPending,
1522
+ onClick: () => void startOAuthLogin(account.id),
1523
+ children: reloginId === account.id && loginPending ? t("reloginPending") : t("accountRelogin")
1524
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1506
1525
  variant: "outline",
1507
1526
  size: "sm",
1508
1527
  className: CodeArtsPluginCard_module_css_default.danger,
1509
- disabled: busy,
1528
+ disabled: busy || loginPending,
1510
1529
  onClick: () => void removeAccount(account.id),
1511
1530
  children: t("accountRemove")
1512
- })
1531
+ })]
1513
1532
  })
1514
1533
  ]
1515
1534
  }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
@@ -2412,13 +2431,13 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
2412
2431
  }
2413
2432
  var CodeArtsPanel_module_css_default = {
2414
2433
  "head": "Z66cgG_head",
2434
+ "body": "Z66cgG_body",
2435
+ "title": "Z66cgG_title",
2415
2436
  "desc": "Z66cgG_desc",
2437
+ "back": "Z66cgG_back",
2416
2438
  "icon": "Z66cgG_icon",
2417
2439
  "page": "Z66cgG_page",
2418
- "backCaret": "Z66cgG_backCaret",
2419
- "body": "Z66cgG_body",
2420
- "back": "Z66cgG_back",
2421
- "title": "Z66cgG_title"
2440
+ "backCaret": "Z66cgG_backCaret"
2422
2441
  };
2423
2442
  //#endregion
2424
2443
  //#region src/client/CodeArtsPanel.tsx
@@ -2519,6 +2538,9 @@ const zh = {
2519
2538
  expiredHint: "凭证已过期,请重新登录以继续使用;已勾选的模型设置会保留。",
2520
2539
  accountsTitle: "账号",
2521
2540
  accountRemove: "删除",
2541
+ accountRelogin: "重新登录",
2542
+ reloginPending: "登录中…",
2543
+ reloginOtherAccount: "你登录的是另一个账号,已作为新账号添加;原账号保持不变。",
2522
2544
  addAccount: "添加账号",
2523
2545
  pasteTokenAdd: "粘贴 Token 添加",
2524
2546
  accountsRotateHint: "已存多个账号:请求会自动轮转,某个账号忙时改用下一个,不用干等。",
@@ -2669,6 +2691,9 @@ const en = {
2669
2691
  expiredHint: "Your credential has expired. Sign in again to continue; your model selection is kept.",
2670
2692
  accountsTitle: "Accounts",
2671
2693
  accountRemove: "Remove",
2694
+ accountRelogin: "Sign in again",
2695
+ reloginPending: "Signing in…",
2696
+ reloginOtherAccount: "That was a different account, so it was added as a new one; the original stayed unchanged.",
2672
2697
  addAccount: "Add account",
2673
2698
  pasteTokenAdd: "Paste a token",
2674
2699
  accountsRotateHint: "Multiple accounts stored: requests rotate automatically, so a busy account hands over to the next one instead of making you wait.",
package/lib/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as upstreamErrorMessage, B as modelUnavailableReason, C as isWelfareClaimedStatus, D as prepareChatBody, E as pickDailyWelfareCampaign, F as filterEnabledModels, G as codeartsAuthPath, H as CodeArtsCredentialStore, I as forgetModelUnavailable, K as startLogin, L as isBenefitBlocked, M as FALLBACK_CODEARTS_MODELS, N as clearBenefitBlocked, O as rateLimitFrame, P as creditRatioLabel, R as isBenefitModel, S as isTpmLimit, T as modelUnavailableReasonText, U as MANUAL_ACCOUNT_ID, V as CodeArtsAccountStore, W as codeartsAccountsPath, _ as isIamTokenError, a as SNAP_HOST, b as isParamInvalidFrame, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isConcurrencyCap, h as firstFrameError, i as refreshCatalog, j as CodeArtsCatalog, k as signedGet, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isModelNotAccessible, w as maxTokensCeilingFor, x as isQueueableRate, y as isNotMultimodal, z as markModelUnavailable } from "./usage-B2LNsUuR.mjs";
1
+ import { A as upstreamErrorMessage, B as modelUnavailableReason, C as isWelfareClaimedStatus, D as prepareChatBody, E as pickDailyWelfareCampaign, F as filterEnabledModels, G as codeartsAuthPath, H as CodeArtsCredentialStore, I as forgetModelUnavailable, K as credentialFromOAuth, L as isBenefitBlocked, M as FALLBACK_CODEARTS_MODELS, N as clearBenefitBlocked, O as rateLimitFrame, P as creditRatioLabel, R as isBenefitModel, S as isTpmLimit, T as modelUnavailableReasonText, U as MANUAL_ACCOUNT_ID, V as CodeArtsAccountStore, W as codeartsAccountsPath, _ as isIamTokenError, a as SNAP_HOST, b as isParamInvalidFrame, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isConcurrencyCap, h as firstFrameError, i as refreshCatalog, j as CodeArtsCatalog, k as signedGet, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, q as startLogin, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isModelNotAccessible, w as maxTokensCeilingFor, x as isQueueableRate, y as isNotMultimodal, z as markModelUnavailable } from "./usage-CjPd0Gok.mjs";
2
2
  import { i as lazyApi, r as createProvider } from "./models-CgKCibpk.mjs";
3
3
  import z from "@deepseek-ai/schemastery";
4
4
  import { randomBytes, timingSafeEqual } from "node:crypto";
@@ -1609,6 +1609,58 @@ async function probeIdentity(token) {
1609
1609
  clearTimeout(timer);
1610
1610
  }
1611
1611
  }
1612
+ /**
1613
+ * 落一次 OAuth 登录的凭证。
1614
+ *
1615
+ * 不带 `targetId` 是「添加账号」:同一账号更新,别的账号新增。
1616
+ *
1617
+ * 带 `targetId` 是「重新登录这个账号」:凭证写回原条目(保留 id、展示顺序和
1618
+ * 备注),而不是又长出一条 —— 以前卡片上只有「删除」,用户遇到凭证过期只能
1619
+ * 先把账号删掉再加回来,顺序和备注都丢。
1620
+ *
1621
+ * 上游只在 `fetchCallerIdentity` 成功时才给稳定 `userId`,拿不到身份就判断不了
1622
+ * 「是不是同一个人」。此时按用户意图替换(他点的就是这个账号的重登),并沿用
1623
+ * 旧条目的身份字段;只有两边 `userId` 都非空且不同,才判为登了另一个账号,
1624
+ * 退回「新增」,原账号原样不动。
1625
+ */
1626
+ async function settleLogin(deps, token, targetId) {
1627
+ const identity = await probeIdentity(token);
1628
+ const target = targetId === void 0 ? void 0 : await deps.store.credential(targetId);
1629
+ if (targetId !== void 0 && target !== void 0) {
1630
+ const known = typeof target.userId === "string" && target.userId !== "";
1631
+ if (!(identity !== null && known && target.userId !== identity.userId)) {
1632
+ const cred = credentialFromOAuth(token, target.label);
1633
+ cred.userId = cred.userId || target.userId;
1634
+ cred.userName = cred.userName || target.userName;
1635
+ cred.domainId = cred.domainId || target.domainId;
1636
+ const id = await deps.store.upsert(cred, targetId);
1637
+ deps.reviveAccount?.(id);
1638
+ if (identity !== null && identity.userId !== "") {
1639
+ if (identity.userId !== id) await deps.store.adoptIdentity(id, identity);
1640
+ deps.reviveAccount?.(identity.userId);
1641
+ return {
1642
+ id: identity.userId,
1643
+ replaced: true,
1644
+ conflict: false
1645
+ };
1646
+ }
1647
+ return {
1648
+ id,
1649
+ replaced: true,
1650
+ conflict: false
1651
+ };
1652
+ }
1653
+ }
1654
+ const id = await deps.store.upsertFromOAuth(token, void 0, identity ?? void 0);
1655
+ if (identity !== null && id !== identity.userId) await deps.store.adoptIdentity(id, identity);
1656
+ deps.reviveAccount?.(id);
1657
+ if (identity !== null && identity.userId !== id) deps.reviveAccount?.(identity.userId);
1658
+ return {
1659
+ id: identity?.userId ?? id,
1660
+ replaced: false,
1661
+ conflict: target !== void 0
1662
+ };
1663
+ }
1612
1664
  /** 账号还能用吗(没被标 stale、也没过期)。 */
1613
1665
  function accountUsable(summary) {
1614
1666
  if (summary.stale) return false;
@@ -2169,6 +2221,8 @@ function registerCodeArtsStatusRoute(ctx, deps) {
2169
2221
  const activeLogins = /* @__PURE__ */ new Map();
2170
2222
  /** 已结束登录的终态,供迟到的轮询读取。被读一次即删。 */
2171
2223
  const recentLogins = /* @__PURE__ */ new Map();
2224
+ /** 本次登录是「重新登录」时,授权 URL → 目标账号 id。终态落库后即删。 */
2225
+ const reloginTargets = /* @__PURE__ */ new Map();
2172
2226
  const disposeStatus = ctx.webServer.register({
2173
2227
  kind: "exact",
2174
2228
  path: CODEARTS_STATUS_PATH,
@@ -2192,7 +2246,7 @@ function registerCodeArtsStatusRoute(ctx, deps) {
2192
2246
  const disposeLoginStart = ctx.webServer.register({
2193
2247
  kind: "exact",
2194
2248
  path: CODEARTS_LOGIN_PATH,
2195
- handler: loginStartHandler(deps, activeLogins, recentLogins)
2249
+ handler: loginStartHandler(deps, activeLogins, recentLogins, reloginTargets)
2196
2250
  });
2197
2251
  const disposeLoginStatus = ctx.webServer.register({
2198
2252
  kind: "exact",
@@ -2250,6 +2304,7 @@ function registerCodeArtsStatusRoute(ctx, deps) {
2250
2304
  disposeDebug();
2251
2305
  for (const s of activeLogins.values()) s.close();
2252
2306
  activeLogins.clear();
2307
+ reloginTargets.clear();
2253
2308
  };
2254
2309
  }, "dsh-codearts: Web status route");
2255
2310
  }
@@ -2267,8 +2322,12 @@ function recordLoginOutcome(recent, url, outcome) {
2267
2322
  }
2268
2323
  recent.set(url, outcome);
2269
2324
  }
2270
- /** POST /api/codearts/login — 启动本地 OAuth 回调,返回授权 URL。 */
2271
- function loginStartHandler(deps, active, recent) {
2325
+ /**
2326
+ * POST /api/codearts/login — 启动本地 OAuth 回调,返回授权 URL。
2327
+ *
2328
+ * `?account=<id>` 表示「重新登录这个账号」(见 settleLogin);省略就是添加账号。
2329
+ */
2330
+ function loginStartHandler(deps, active, recent, targets) {
2272
2331
  return async (req, res) => {
2273
2332
  if (req.method !== "POST") {
2274
2333
  json(res, 405, { error: "method not allowed" });
@@ -2278,28 +2337,33 @@ function loginStartHandler(deps, active, recent) {
2278
2337
  json(res, 403, { error: "request-not-trusted" });
2279
2338
  return;
2280
2339
  }
2340
+ const targetId = (new URL(req.url ?? "", "http://localhost").searchParams.get("account") ?? "").trim();
2281
2341
  try {
2282
2342
  const session = await startLogin();
2283
2343
  active.set(session.url, session);
2344
+ if (targetId !== "") targets.set(session.url, targetId);
2284
2345
  session.promise.then(async (token) => {
2285
2346
  active.delete(session.url);
2347
+ const reloginId = targets.get(session.url);
2348
+ targets.delete(session.url);
2286
2349
  try {
2287
- const identity = await probeIdentity(token);
2288
- const id = await deps.store.upsertFromOAuth(token, void 0, identity ?? void 0);
2289
- if (identity !== null && id !== identity.userId) await deps.store.adoptIdentity(id, identity);
2290
- deps.reviveAccount?.(id);
2291
- if (identity !== null && identity.userId !== id) deps.reviveAccount?.(identity.userId);
2292
- recordLoginOutcome(recent, session.url, "done");
2350
+ const result = await settleLogin(deps, token, reloginId);
2351
+ recordLoginOutcome(recent, session.url, {
2352
+ status: "done",
2353
+ ...result
2354
+ });
2293
2355
  } catch {
2294
- recordLoginOutcome(recent, session.url, "error");
2356
+ recordLoginOutcome(recent, session.url, { status: "error" });
2295
2357
  }
2296
2358
  }, () => {
2297
2359
  active.delete(session.url);
2298
- recordLoginOutcome(recent, session.url, "error");
2360
+ targets.delete(session.url);
2361
+ recordLoginOutcome(recent, session.url, { status: "error" });
2299
2362
  });
2300
2363
  const timer = setTimeout(() => {
2301
2364
  session.close();
2302
- if (active.delete(session.url)) recordLoginOutcome(recent, session.url, "error");
2365
+ targets.delete(session.url);
2366
+ if (active.delete(session.url)) recordLoginOutcome(recent, session.url, { status: "error" });
2303
2367
  }, 3e5);
2304
2368
  session.promise.finally(() => clearTimeout(timer)).catch(() => {});
2305
2369
  json(res, 200, {
@@ -2330,7 +2394,7 @@ function loginPollHandler(_deps, active, recent) {
2330
2394
  const outcome = recent.get(key);
2331
2395
  if (outcome !== void 0) {
2332
2396
  recent.delete(key);
2333
- json(res, 200, { status: outcome });
2397
+ json(res, 200, { ...outcome });
2334
2398
  return;
2335
2399
  }
2336
2400
  json(res, 200, { status: "idle" });
@@ -3052,4 +3052,4 @@ function sumOf(store) {
3052
3052
  return out;
3053
3053
  }
3054
3054
  //#endregion
3055
- export { upstreamErrorMessage as A, modelUnavailableReason as B, isWelfareClaimedStatus as C, prepareChatBody as D, pickDailyWelfareCampaign as E, filterEnabledModels as F, codeartsAuthPath as G, CodeArtsCredentialStore as H, forgetModelUnavailable as I, startLogin as K, isBenefitBlocked as L, FALLBACK_CODEARTS_MODELS as M, clearBenefitBlocked as N, rateLimitFrame as O, creditRatioLabel as P, isBenefitModel as R, isTpmLimit as S, modelUnavailableReasonText as T, MANUAL_ACCOUNT_ID as U, CodeArtsAccountStore as V, codeartsAccountsPath as W, isIamTokenError as _, SNAP_HOST as a, isParamInvalidFrame as b, claimDailyWelfare as c, fetchCallerIdentity as d, fetchModels as f, isConcurrencyCap as g, firstFrameError as h, refreshCatalog as i, CodeArtsCatalog as j, signedGet as k, clearQueueStatus as l, fetchWelfareCampaigns as m, codeartsUsagePath as n, canonicalModel as o, fetchQueueStatus as p, discoverModels as r, chatStream as s, CodeArtsUsageTracker as t, degradeTokenCeiling as u, isModelNotAccessible as v, maxTokensCeilingFor as w, isQueueableRate as x, isNotMultimodal as y, markModelUnavailable as z };
3055
+ export { upstreamErrorMessage as A, modelUnavailableReason as B, isWelfareClaimedStatus as C, prepareChatBody as D, pickDailyWelfareCampaign as E, filterEnabledModels as F, codeartsAuthPath as G, CodeArtsCredentialStore as H, forgetModelUnavailable as I, credentialFromOAuth as K, isBenefitBlocked as L, FALLBACK_CODEARTS_MODELS as M, clearBenefitBlocked as N, rateLimitFrame as O, creditRatioLabel as P, isBenefitModel as R, isTpmLimit as S, modelUnavailableReasonText as T, MANUAL_ACCOUNT_ID as U, CodeArtsAccountStore as V, codeartsAccountsPath as W, isIamTokenError as _, SNAP_HOST as a, isParamInvalidFrame as b, claimDailyWelfare as c, fetchCallerIdentity as d, fetchModels as f, isConcurrencyCap as g, firstFrameError as h, refreshCatalog as i, CodeArtsCatalog as j, signedGet as k, clearQueueStatus as l, fetchWelfareCampaigns as m, codeartsUsagePath as n, canonicalModel as o, fetchQueueStatus as p, startLogin as q, discoverModels as r, chatStream as s, CodeArtsUsageTracker as t, degradeTokenCeiling as u, isModelNotAccessible as v, maxTokensCeilingFor as w, isQueueableRate as x, isNotMultimodal as y, markModelUnavailable as z };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-codearts",
3
3
  "displayName": "DSH CodeArts Connect",
4
4
  "description": "把华为云 CodeArts 接入 DeepSeek Harness —— 内置 OAuth2 登录(PKCE + DPoP),登录后即可在 DSH 对话窗口使用 CodeArts 的模型。",
5
- "version": "1.2.9",
5
+ "version": "1.2.10",
6
6
  "packageManager": "pnpm@11.24.0",
7
7
  "author": "elegant01",
8
8
  "keywords": [