dsh-codearts 1.2.9 → 1.2.11

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.
@@ -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}}.xoziZG_modelSpec{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.xoziZG_doctorList{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_doctorRow{align-items:center;gap:8px;padding:4px 0;display:flex}.xoziZG_doctorName{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px;line-height:18px}.xoziZG_doctorRow .xoziZG_meta{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}";
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,96 @@ 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",
82
- "creditBlock": "xoziZG_creditBlock",
83
- "accountCard": "xoziZG_accountCard",
75
+ "usageFill": "xoziZG_usageFill",
76
+ "modelName": "xoziZG_modelName",
77
+ "tabPanel": "xoziZG_tabPanel",
78
+ "sectionHead": "xoziZG_sectionHead",
84
79
  "card": "xoziZG_card",
85
- "sectionLabel": "xoziZG_sectionLabel",
86
- "error": "xoziZG_error",
87
- "desc": "xoziZG_desc",
88
- "accountRowActions": "xoziZG_accountRowActions",
89
- "modelRow": "xoziZG_modelRow",
90
- "balanceUnit": "xoziZG_balanceUnit",
91
- "balance": "xoziZG_balance",
92
- "usageTipRow": "xoziZG_usageTipRow",
93
- "bar": "xoziZG_bar",
94
- "accountRow": "xoziZG_accountRow",
95
- "heatHourCell": "xoziZG_heatHourCell",
96
- "header": "xoziZG_header",
97
- "meta": "xoziZG_meta",
80
+ "usageTip": "xoziZG_usageTip",
81
+ "expiryRow": "xoziZG_expiryRow",
82
+ "statusLine": "xoziZG_statusLine",
98
83
  "tabs": "xoziZG_tabs",
99
- "modelChart": "xoziZG_modelChart",
100
- "usageTipName": "xoziZG_usageTipName",
101
- "accountName": "xoziZG_accountName",
84
+ "creditBlock": "xoziZG_creditBlock",
85
+ "link": "xoziZG_link",
86
+ "statGrid": "xoziZG_statGrid",
87
+ "creditRows": "xoziZG_creditRows",
88
+ "heatHours": "xoziZG_heatHours",
89
+ "manual": "xoziZG_manual",
90
+ "fieldLabel": "xoziZG_fieldLabel",
91
+ "area": "xoziZG_area",
92
+ "doctorRow": "xoziZG_doctorRow",
102
93
  "heatCell": "xoziZG_heatCell",
94
+ "creditHint": "xoziZG_creditHint",
95
+ "heatWeekday": "xoziZG_heatWeekday",
103
96
  "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",
97
+ "balanceUnit": "xoziZG_balanceUnit",
110
98
  "updated": "xoziZG_updated",
111
- "statGrid": "xoziZG_statGrid",
99
+ "heatAxisSlot": "xoziZG_heatAxisSlot",
112
100
  "field": "xoziZG_field",
113
- "creditRows": "xoziZG_creditRows",
101
+ "skeleton": "xoziZG_skeleton",
102
+ "trendTip": "xoziZG_trendTip",
103
+ "manualSummary": "xoziZG_manualSummary",
104
+ "hint": "xoziZG_hint",
114
105
  "modelRequests": "xoziZG_modelRequests",
115
- "manual": "xoziZG_manual",
116
- "skeletonRow": "xoziZG_skeletonRow",
117
- "expiryRow": "xoziZG_expiryRow",
118
- "manualForm": "xoziZG_manualForm",
119
106
  "name": "xoziZG_name",
120
- "usageTip": "xoziZG_usageTip",
121
- "avatar": "xoziZG_avatar",
122
- "heatAxisSlot": "xoziZG_heatAxisSlot",
123
- "modelTokens": "xoziZG_modelTokens",
124
- "expiryLabel": "xoziZG_expiryLabel",
125
- "heatHours": "xoziZG_heatHours",
126
- "heatLegendChip": "xoziZG_heatLegendChip",
127
- "heatGrid": "xoziZG_heatGrid",
128
- "accountEntry": "xoziZG_accountEntry",
129
- "modelName": "xoziZG_modelName",
107
+ "accountInfo": "xoziZG_accountInfo",
130
108
  "heatAxis": "xoziZG_heatAxis",
131
- "fieldLabel": "xoziZG_fieldLabel",
132
- "hint": "xoziZG_hint",
109
+ "usageBar": "xoziZG_usageBar",
110
+ "barFill": "xoziZG_barFill",
111
+ "danger": "xoziZG_danger",
112
+ "accountHint": "xoziZG_accountHint",
113
+ "modelShare": "xoziZG_modelShare",
114
+ "accountToolbar": "xoziZG_accountToolbar",
115
+ "section": "xoziZG_section",
116
+ "modelTokens": "xoziZG_modelTokens",
117
+ "skeletonRow": "xoziZG_skeletonRow",
118
+ "sectionLabel": "xoziZG_sectionLabel",
133
119
  "creditRow": "xoziZG_creditRow",
134
- "creditFooter": "xoziZG_creditFooter",
135
- "creditHint": "xoziZG_creditHint",
136
- "manualSummary": "xoziZG_manualSummary",
137
- "skeleton": "xoziZG_skeleton",
138
- "headText": "xoziZG_headText",
139
120
  "usageTipSep": "xoziZG_usageTipSep",
140
- "accountInfo": "xoziZG_accountInfo",
141
- "link": "xoziZG_link",
142
- "balanceMeta": "xoziZG_balanceMeta",
143
- "danger": "xoziZG_danger",
144
- "trendTip": "xoziZG_trendTip",
145
121
  "skeletonBreath": "xoziZG_skeletonBreath",
146
- "count": "xoziZG_count",
147
- "modelShare": "xoziZG_modelShare",
148
- "statusLine": "xoziZG_statusLine",
149
- "usageFill": "xoziZG_usageFill",
150
- "usageBar": "xoziZG_usageBar",
122
+ "body": "xoziZG_body",
123
+ "modelSpec": "xoziZG_modelSpec",
124
+ "heatLegendChip": "xoziZG_heatLegendChip",
125
+ "heatHourCell": "xoziZG_heatHourCell",
126
+ "modelRow": "xoziZG_modelRow",
127
+ "balance": "xoziZG_balance",
128
+ "meta": "xoziZG_meta",
129
+ "avatar": "xoziZG_avatar",
130
+ "heatGrid": "xoziZG_heatGrid",
131
+ "check": "xoziZG_check",
132
+ "statLabel": "xoziZG_statLabel",
133
+ "statSub": "xoziZG_statSub",
134
+ "statCard": "xoziZG_statCard",
135
+ "modelChart": "xoziZG_modelChart",
136
+ "actions": "xoziZG_actions",
151
137
  "choices": "xoziZG_choices",
138
+ "usageTipName": "xoziZG_usageTipName",
139
+ "balanceMeta": "xoziZG_balanceMeta",
140
+ "expiryLabel": "xoziZG_expiryLabel",
141
+ "accountName": "xoziZG_accountName",
142
+ "creditLink": "xoziZG_creditLink",
143
+ "doctorList": "xoziZG_doctorList",
144
+ "accountNameRow": "xoziZG_accountNameRow",
145
+ "accountCard": "xoziZG_accountCard",
152
146
  "balanceRow": "xoziZG_balanceRow",
153
- "actions": "xoziZG_actions",
147
+ "error": "xoziZG_error",
148
+ "modelFill": "xoziZG_modelFill",
149
+ "bar": "xoziZG_bar",
150
+ "creditFooter": "xoziZG_creditFooter",
154
151
  "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"
152
+ "choiceRow": "xoziZG_choiceRow",
153
+ "accountEntry": "xoziZG_accountEntry",
154
+ "headText": "xoziZG_headText",
155
+ "header": "xoziZG_header",
156
+ "count": "xoziZG_count",
157
+ "usageTipRow": "xoziZG_usageTipRow",
158
+ "accountRow": "xoziZG_accountRow",
159
+ "manualForm": "xoziZG_manualForm",
160
+ "doctorName": "xoziZG_doctorName",
161
+ "statValue": "xoziZG_statValue",
162
+ "claimAllRow": "xoziZG_claimAllRow",
163
+ "accountRowActions": "xoziZG_accountRowActions",
164
+ "desc": "xoziZG_desc"
161
165
  };
162
166
  //#endregion
163
167
  //#region src/client/CodeArtsPluginCard.tsx
@@ -222,6 +226,49 @@ const DOCK_DEFAULT = {
222
226
  * 后台再刷新 —— 比每次都先闪骨架舒服,也不会把「还没读到」误判成未登录。
223
227
  */
224
228
  let lastStatusSnapshot = null;
229
+ const lastTestResults = {};
230
+ /**
231
+ * 上下文窗口这类数字不适合印全值(1048576 比 1M 难读),按 K/M 取整。
232
+ *
233
+ * undefined 表示上游没给 —— 此时后端下发的 32768 是兜底值,不能当成真的印出来。
234
+ */
235
+ function formatWindow(tokens) {
236
+ if (tokens === void 0 || !Number.isFinite(tokens) || tokens <= 0) return "—";
237
+ if (tokens >= 1048576) return `${Math.round(tokens / 1048576)}M`;
238
+ if (tokens >= 1024) return `${Math.round(tokens / 1024)}K`;
239
+ return String(tokens);
240
+ }
241
+ /** 体检里一条检查的标题。账号级检查按 id 找回备注名,别让用户对着哈希猜。 */
242
+ function doctorCheckLabel(id, accounts, t) {
243
+ if (id.startsWith("account:")) {
244
+ const accountId = id.slice(8);
245
+ const account = accounts.find((entry) => entry.id === accountId);
246
+ const name = account?.label?.trim() || account?.userName?.trim() || accountId;
247
+ return `${t("doctorCheckAccount")} ${name}`;
248
+ }
249
+ switch (id) {
250
+ case "runtime": return t("doctorCheckRuntime");
251
+ case "accounts": return t("doctorCheckAccounts");
252
+ case "models": return t("doctorCheckModels");
253
+ case "usage": return t("doctorCheckUsage");
254
+ case "pi-ai": return t("doctorCheckPiAi");
255
+ default: return id;
256
+ }
257
+ }
258
+ /** 体检的 hints 是稳定 id(见 web-status.ts 的 doctorReport),这里翻成人话。 */
259
+ function doctorHintText(id, t) {
260
+ switch (id) {
261
+ case "no-account": return t("doctorHintNoAccount");
262
+ case "account-stale": return t("doctorHintAccountStale");
263
+ case "account-no-key": return t("doctorHintAccountNoKey");
264
+ case "account-expired": return t("doctorHintAccountExpired");
265
+ case "empty-catalog": return t("doctorHintEmptyCatalog");
266
+ case "usage-missing": return t("doctorHintUsageMissing");
267
+ case "dsh-home-missing": return t("doctorHintDshHome");
268
+ case "pi-ai": return t("doctorHintPiAi");
269
+ default: return t("doctorHintOther", { id });
270
+ }
271
+ }
225
272
  /** 一个 Tab 面板;未选中的用 hidden 留在 DOM 里,草稿和滚动位置都别丢。 */
226
273
  function TabPanel({ id, labelledBy, active, children }) {
227
274
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -753,8 +800,18 @@ function UsageSection({ usage, accounts, t }) {
753
800
  totals: entry.totals
754
801
  }));
755
802
  const today = usage.today;
756
- const hasUsage = usage.allTime.requests > 0 || today.requests > 0;
803
+ const failures = usage.failuresToday ?? {
804
+ total: 0,
805
+ byKind: {}
806
+ };
807
+ const hasUsage = usage.allTime.requests > 0 || today.requests > 0 || failures.total > 0;
757
808
  const hit = hitPercentOf(today);
809
+ const attempts = today.requests + failures.total;
810
+ const failRate = attempts > 0 ? Math.round(failures.total / attempts * 100) : void 0;
811
+ const latency = usage.latencyToday ?? {
812
+ samples: 0,
813
+ overflow: false
814
+ };
758
815
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
759
816
  className: CodeArtsPluginCard_module_css_default.section,
760
817
  children: [
@@ -814,6 +871,43 @@ function UsageSection({ usage, accounts, t }) {
814
871
  className: CodeArtsPluginCard_module_css_default.statValue,
815
872
  children: formatCount(today.requests)
816
873
  })]
874
+ }),
875
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
876
+ className: CodeArtsPluginCard_module_css_default.statCard,
877
+ children: [
878
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
879
+ className: CodeArtsPluginCard_module_css_default.statLabel,
880
+ children: t("usageStatFailures")
881
+ }),
882
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
883
+ className: CodeArtsPluginCard_module_css_default.statValue,
884
+ children: failRate === void 0 ? "—" : `${failRate}%`
885
+ }),
886
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
887
+ className: CodeArtsPluginCard_module_css_default.statSub,
888
+ children: t("usageStatFailureCount", { n: formatCount(failures.total) })
889
+ })
890
+ ]
891
+ }),
892
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
893
+ className: CodeArtsPluginCard_module_css_default.statCard,
894
+ children: [
895
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
896
+ className: CodeArtsPluginCard_module_css_default.statLabel,
897
+ children: t("usageStatLatency")
898
+ }),
899
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
900
+ className: CodeArtsPluginCard_module_css_default.statValue,
901
+ children: latency.p95 === void 0 ? "—" : latency.overflow ? ">30 s" : `${formatCount(latency.p95)} ms`
902
+ }),
903
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
904
+ className: CodeArtsPluginCard_module_css_default.statSub,
905
+ children: latency.p50 === void 0 ? t("usageStatLatencyEmpty") : t("usageStatLatencyDetail", {
906
+ p50: formatCount(latency.p50),
907
+ n: formatCount(latency.samples)
908
+ })
909
+ })
910
+ ]
817
911
  })
818
912
  ]
819
913
  }),
@@ -887,6 +981,8 @@ function CodeArtsPluginCard({ t }) {
887
981
  const [msg, setMsg] = (0, react.useState)(null);
888
982
  const [loginUrl, setLoginUrl] = (0, react.useState)(null);
889
983
  const [loginPending, setLoginPending] = (0, react.useState)(false);
984
+ /** 正在进行的是哪个账号的「重新登录」(无则 null)。用来只让那一行的按钮变「登录中」。 */
985
+ const [reloginId, setReloginId] = (0, react.useState)(null);
890
986
  const [selection, setSelection] = (0, react.useState)(null);
891
987
  const [draft, setDraft] = (0, react.useState)([]);
892
988
  const [savingModels, setSavingModels] = (0, react.useState)(false);
@@ -897,7 +993,12 @@ function CodeArtsPluginCard({ t }) {
897
993
  /** 正在实测的模型 id;同一时间只测一个,避免把上游并发槽位占满。 */
898
994
  const [testingId, setTestingId] = (0, react.useState)(null);
899
995
  /** 逐模型的测试结果(通过/失败 + 原因)。 */
900
- const [testResults, setTestResults] = (0, react.useState)({});
996
+ const [testResults, setTestResults] = (0, react.useState)(() => ({ ...lastTestResults }));
997
+ /** 正在提交 paused/pinned 的账号 id。 */
998
+ const [flagBusy, setFlagBusy] = (0, react.useState)(null);
999
+ const [doctor, setDoctor] = (0, react.useState)(null);
1000
+ const [doctorBusy, setDoctorBusy] = (0, react.useState)(false);
1001
+ const [doctorError, setDoctorError] = (0, react.useState)(null);
901
1002
  /** 正在领取的账号 id;批量领取时是 CLAIM_ALL。null 表示没有在飞。 */
902
1003
  const [claimingId, setClaimingId] = (0, react.useState)(null);
903
1004
  /** 逐账号的领取结果文案。 */
@@ -1101,6 +1202,52 @@ function CodeArtsPluginCard({ t }) {
1101
1202
  setBusy(false);
1102
1203
  }
1103
1204
  }
1205
+ /**
1206
+ * 改一个账号的 paused/pinned 标记。
1207
+ *
1208
+ * 暂停 ≠ 删除:凭证还在,只是不参与轮转(比如这个号今天额度用完了,但明天还要用)。
1209
+ * 置顶改变的是 pick() 的优先级,不是顺序本身 —— 取消置顶就回到「最久未用优先」。
1210
+ */
1211
+ async function setAccountFlag(id, patch) {
1212
+ setFlagBusy(id);
1213
+ setMsg(null);
1214
+ try {
1215
+ const res = await fetch("/api/codearts/accounts", {
1216
+ method: "POST",
1217
+ headers: {
1218
+ "Content-Type": "application/json",
1219
+ Accept: "application/json"
1220
+ },
1221
+ body: JSON.stringify({
1222
+ id,
1223
+ ...patch
1224
+ })
1225
+ });
1226
+ if (!res.ok) {
1227
+ const data = await res.json().catch(() => ({}));
1228
+ throw new Error(typeof data.error === "string" ? data.error : `HTTP ${res.status}`);
1229
+ }
1230
+ await refresh();
1231
+ } catch (err) {
1232
+ setMsg(err instanceof Error ? err.message : String(err));
1233
+ } finally {
1234
+ setFlagBusy(null);
1235
+ }
1236
+ }
1237
+ /** 点「体检」拉一次本机报告;只读,不改任何状态。 */
1238
+ async function runDoctor() {
1239
+ setDoctorBusy(true);
1240
+ setDoctorError(null);
1241
+ try {
1242
+ const res = await fetch("/api/codearts/doctor", { headers: { Accept: "application/json" } });
1243
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1244
+ setDoctor(await res.json());
1245
+ } catch (err) {
1246
+ setDoctorError(err instanceof Error ? err.message : String(err));
1247
+ } finally {
1248
+ setDoctorBusy(false);
1249
+ }
1250
+ }
1104
1251
  const all = selection?.choices.length ?? 0;
1105
1252
  const blockedCount = selection?.choices.filter((c) => c.blocked === true).length ?? 0;
1106
1253
  const wire = draft.length === all ? [] : draft;
@@ -1143,8 +1290,16 @@ function CodeArtsPluginCard({ t }) {
1143
1290
  * 上游的清单会列出调不动的模型(81003.401),刷新救不了;只有真发一次最小请求
1144
1291
  * 才知道。测试成功会清掉后端记的「异常」标记,所以结束后重拉一次 selection。
1145
1292
  */
1293
+ function recordTest(id, result) {
1294
+ lastTestResults[id] = result;
1295
+ setTestResults((current) => ({
1296
+ ...current,
1297
+ [id]: result
1298
+ }));
1299
+ }
1146
1300
  async function testModel(id) {
1147
1301
  setTestingId(id);
1302
+ delete lastTestResults[id];
1148
1303
  setTestResults((current) => {
1149
1304
  const next = { ...current };
1150
1305
  delete next[id];
@@ -1161,23 +1316,17 @@ function CodeArtsPluginCard({ t }) {
1161
1316
  });
1162
1317
  const data = await res.json().catch(() => null);
1163
1318
  if (!res.ok) throw new Error(data?.message ?? `HTTP ${res.status}`);
1164
- setTestResults((current) => ({
1165
- ...current,
1166
- [id]: {
1167
- ok: data?.ok === true,
1168
- message: data?.message ?? "",
1169
- ms: data?.ms
1170
- }
1171
- }));
1319
+ recordTest(id, {
1320
+ ok: data?.ok === true,
1321
+ message: data?.message ?? "",
1322
+ ms: data?.ms
1323
+ });
1172
1324
  await refreshSelection();
1173
1325
  } catch (err) {
1174
- setTestResults((current) => ({
1175
- ...current,
1176
- [id]: {
1177
- ok: false,
1178
- message: err instanceof Error ? err.message : String(err)
1179
- }
1180
- }));
1326
+ recordTest(id, {
1327
+ ok: false,
1328
+ message: err instanceof Error ? err.message : String(err)
1329
+ });
1181
1330
  } finally {
1182
1331
  setTestingId(null);
1183
1332
  }
@@ -1211,16 +1360,29 @@ function CodeArtsPluginCard({ t }) {
1211
1360
  setRefreshing(false);
1212
1361
  }
1213
1362
  }
1214
- async function startOAuthLogin() {
1363
+ /**
1364
+ * 开始一次浏览器登录。
1365
+ *
1366
+ * 不带 `targetId` 是「添加账号」;带 `targetId` 是「重新登录这个账号」——
1367
+ * 服务端会把新凭证写回原条目(保留顺序与备注),而不是又长出一条。
1368
+ */
1369
+ async function startOAuthLogin(targetId) {
1215
1370
  setBusy(true);
1216
1371
  setMsg(null);
1217
1372
  setLoginPending(true);
1373
+ if (targetId !== void 0) setReloginId(targetId);
1374
+ const finish = () => {
1375
+ setLoginUrl(null);
1376
+ setLoginPending(false);
1377
+ setReloginId(null);
1378
+ };
1218
1379
  try {
1219
- const res = await fetch("/api/codearts/login", { method: "POST" });
1380
+ const query = targetId === void 0 ? "" : `?account=${encodeURIComponent(targetId)}`;
1381
+ const res = await fetch(`/api/codearts/login${query}`, { method: "POST" });
1220
1382
  const data = await res.json().catch(() => ({}));
1221
1383
  if (!res.ok || typeof data.url !== "string") {
1222
1384
  setMsg(data.error ?? `HTTP ${res.status}`);
1223
- setLoginPending(false);
1385
+ finish();
1224
1386
  return;
1225
1387
  }
1226
1388
  setLoginUrl(data.url);
@@ -1228,20 +1390,18 @@ function CodeArtsPluginCard({ t }) {
1228
1390
  const poll = async () => {
1229
1391
  const st = await (await fetch(`/api/codearts/login/status?url=${encodeURIComponent(data.url)}`, { headers: { Accept: "application/json" } })).json().catch(() => ({ status: "pending" }));
1230
1392
  if (st.status === "done") {
1231
- setLoginUrl(null);
1232
- setLoginPending(false);
1393
+ finish();
1394
+ if (st.conflict === true) setMsg(t("reloginOtherAccount"));
1233
1395
  await refresh();
1234
1396
  return;
1235
1397
  }
1236
1398
  if (st.status === "error") {
1237
- setLoginUrl(null);
1238
- setLoginPending(false);
1399
+ finish();
1239
1400
  setMsg(t("loginFailed"));
1240
1401
  return;
1241
1402
  }
1242
1403
  if (st.status === "idle") {
1243
- setLoginUrl(null);
1244
- setLoginPending(false);
1404
+ finish();
1245
1405
  await refresh();
1246
1406
  return;
1247
1407
  }
@@ -1250,7 +1410,7 @@ function CodeArtsPluginCard({ t }) {
1250
1410
  poll();
1251
1411
  } catch (err) {
1252
1412
  setMsg(err instanceof Error ? err.message : String(err));
1253
- setLoginPending(false);
1413
+ finish();
1254
1414
  } finally {
1255
1415
  setBusy(false);
1256
1416
  }
@@ -1485,31 +1645,69 @@ function CodeArtsPluginCard({ t }) {
1485
1645
  }),
1486
1646
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1487
1647
  className: CodeArtsPluginCard_module_css_default.accountInfo,
1488
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1489
- className: CodeArtsPluginCard_module_css_default.accountNameRow,
1490
- children: [
1491
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1492
- className: CodeArtsPluginCard_module_css_default.accountName,
1493
- children: accountName(account)
1494
- }),
1495
- account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
1496
- !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
1497
- ]
1498
- }), accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1499
- className: CodeArtsPluginCard_module_css_default.meta,
1500
- children: accountLine
1501
- })]
1648
+ children: [
1649
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1650
+ className: CodeArtsPluginCard_module_css_default.accountNameRow,
1651
+ children: [
1652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1653
+ className: CodeArtsPluginCard_module_css_default.accountName,
1654
+ children: accountName(account)
1655
+ }),
1656
+ account.paused && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountPaused") }),
1657
+ account.pinned && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1658
+ tone: "success",
1659
+ children: t("accountPinned")
1660
+ }),
1661
+ account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
1662
+ !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
1663
+ ]
1664
+ }),
1665
+ accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1666
+ className: CodeArtsPluginCard_module_css_default.meta,
1667
+ children: accountLine
1668
+ }),
1669
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1670
+ className: CodeArtsPluginCard_module_css_default.meta,
1671
+ children: t("accountToday", {
1672
+ n: formatCount(status?.usage?.byAccountToday[account.id]?.requests ?? 0),
1673
+ failed: formatCount(status?.usage?.failuresByAccountToday?.[account.id] ?? 0)
1674
+ })
1675
+ })
1676
+ ]
1502
1677
  }),
1503
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1678
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1504
1679
  className: CodeArtsPluginCard_module_css_default.accountRowActions,
1505
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1506
- variant: "outline",
1507
- size: "sm",
1508
- className: CodeArtsPluginCard_module_css_default.danger,
1509
- disabled: busy,
1510
- onClick: () => void removeAccount(account.id),
1511
- children: t("accountRemove")
1512
- })
1680
+ children: [
1681
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1682
+ variant: "outline",
1683
+ size: "sm",
1684
+ disabled: busy || loginPending || flagBusy === account.id,
1685
+ onClick: () => void setAccountFlag(account.id, { paused: !account.paused }),
1686
+ children: account.paused ? t("accountResume") : t("accountPause")
1687
+ }),
1688
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1689
+ variant: "outline",
1690
+ size: "sm",
1691
+ disabled: busy || loginPending || flagBusy === account.id,
1692
+ onClick: () => void setAccountFlag(account.id, { pinned: !account.pinned }),
1693
+ children: account.pinned ? t("accountUnpin") : t("accountPin")
1694
+ }),
1695
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1696
+ variant: account.stale ? "primary" : "outline",
1697
+ size: "sm",
1698
+ disabled: busy || loginPending,
1699
+ onClick: () => void startOAuthLogin(account.id),
1700
+ children: reloginId === account.id && loginPending ? t("reloginPending") : t("accountRelogin")
1701
+ }),
1702
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1703
+ variant: "outline",
1704
+ size: "sm",
1705
+ className: CodeArtsPluginCard_module_css_default.danger,
1706
+ disabled: busy || loginPending,
1707
+ onClick: () => void removeAccount(account.id),
1708
+ children: t("accountRemove")
1709
+ })
1710
+ ]
1513
1711
  })
1514
1712
  ]
1515
1713
  }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
@@ -1593,7 +1791,7 @@ function CodeArtsPluginCard({ t }) {
1593
1791
  }),
1594
1792
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1595
1793
  className: CodeArtsPluginCard_module_css_default.choices,
1596
- children: selection.choices.map((choice) => {
1794
+ children: (selection.choices ?? []).map((choice) => {
1597
1795
  const result = testResults[choice.id];
1598
1796
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1599
1797
  className: CodeArtsPluginCard_module_css_default.choiceRow,
@@ -1605,6 +1803,17 @@ function CodeArtsPluginCard({ t }) {
1605
1803
  onChange: (on) => setModel(choice.id, on),
1606
1804
  label: modelName(choice)
1607
1805
  }),
1806
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1807
+ className: CodeArtsPluginCard_module_css_default.modelSpec,
1808
+ title: t("modelSpecTitle", {
1809
+ context: choice.contextWindow === void 0 ? "?" : formatCount(choice.contextWindow),
1810
+ output: choice.maxTokens === void 0 ? "?" : formatCount(choice.maxTokens)
1811
+ }),
1812
+ children: t("modelSpec", {
1813
+ context: formatWindow(choice.contextWindow),
1814
+ output: formatWindow(choice.maxTokens)
1815
+ })
1816
+ }),
1608
1817
  choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1609
1818
  tone: choice.blocked === true ? "warning" : "success",
1610
1819
  children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
@@ -1687,80 +1896,129 @@ function CodeArtsPluginCard({ t }) {
1687
1896
  id: panelId("display"),
1688
1897
  labelledBy: tabId("display"),
1689
1898
  active: activeTab === "display",
1690
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1691
- className: CodeArtsPluginCard_module_css_default.section,
1692
- children: [
1693
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1694
- className: CodeArtsPluginCard_module_css_default.sectionHead,
1695
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1696
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
1697
- children: t("displayTitle")
1698
- })
1699
- }),
1700
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1701
- className: CodeArtsPluginCard_module_css_default.hint,
1702
- children: t("displayHint")
1703
- }),
1704
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1705
- className: CodeArtsPluginCard_module_css_default.choices,
1706
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1707
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1708
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1709
- className: CodeArtsPluginCard_module_css_default.check,
1710
- checked: dock.credits,
1711
- disabled: !dockWritable || dockSaving,
1712
- onChange: (on) => void toggleDock("credits", on),
1713
- label: t("displayCreditsToggle")
1714
- })
1715
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1716
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1717
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1718
- className: CodeArtsPluginCard_module_css_default.check,
1719
- checked: dock.queue,
1720
- disabled: !dockWritable || dockSaving,
1721
- onChange: (on) => void toggleDock("queue", on),
1722
- label: t("displayQueueToggle")
1899
+ children: [
1900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1901
+ className: CodeArtsPluginCard_module_css_default.section,
1902
+ children: [
1903
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1904
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1905
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1906
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1907
+ children: t("displayTitle")
1723
1908
  })
1724
- })]
1725
- }),
1726
- !dockWritable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1727
- className: CodeArtsPluginCard_module_css_default.hint,
1728
- children: t("displayNotWritable")
1729
- }),
1730
- dockError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1731
- className: CodeArtsPluginCard_module_css_default.error,
1732
- children: t("displayFailed", { message: dockError })
1733
- })
1734
- ]
1735
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1736
- className: CodeArtsPluginCard_module_css_default.section,
1737
- children: [
1738
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1739
- className: CodeArtsPluginCard_module_css_default.sectionHead,
1740
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1741
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
1742
- children: t("displaySidebarTitle")
1909
+ }),
1910
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1911
+ className: CodeArtsPluginCard_module_css_default.hint,
1912
+ children: t("displayHint")
1913
+ }),
1914
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1915
+ className: CodeArtsPluginCard_module_css_default.choices,
1916
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1917
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1918
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1919
+ className: CodeArtsPluginCard_module_css_default.check,
1920
+ checked: dock.credits,
1921
+ disabled: !dockWritable || dockSaving,
1922
+ onChange: (on) => void toggleDock("credits", on),
1923
+ label: t("displayCreditsToggle")
1924
+ })
1925
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1926
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1927
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1928
+ className: CodeArtsPluginCard_module_css_default.check,
1929
+ checked: dock.queue,
1930
+ disabled: !dockWritable || dockSaving,
1931
+ onChange: (on) => void toggleDock("queue", on),
1932
+ label: t("displayQueueToggle")
1933
+ })
1934
+ })]
1935
+ }),
1936
+ !dockWritable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1937
+ className: CodeArtsPluginCard_module_css_default.hint,
1938
+ children: t("displayNotWritable")
1939
+ }),
1940
+ dockError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1941
+ className: CodeArtsPluginCard_module_css_default.error,
1942
+ children: t("displayFailed", { message: dockError })
1743
1943
  })
1744
- }),
1745
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1746
- className: CodeArtsPluginCard_module_css_default.hint,
1747
- children: t("displaySidebarHint")
1748
- }),
1749
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1750
- className: CodeArtsPluginCard_module_css_default.choices,
1751
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1752
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1753
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1754
- className: CodeArtsPluginCard_module_css_default.check,
1755
- checked: dock.sidebar,
1756
- disabled: !dockWritable || dockSaving,
1757
- onChange: (on) => void toggleDock("sidebar", on),
1758
- label: t("displaySidebarToggle")
1944
+ ]
1945
+ }),
1946
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1947
+ className: CodeArtsPluginCard_module_css_default.section,
1948
+ children: [
1949
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1950
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1951
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1952
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1953
+ children: t("displaySidebarTitle")
1954
+ })
1955
+ }),
1956
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1957
+ className: CodeArtsPluginCard_module_css_default.hint,
1958
+ children: t("displaySidebarHint")
1959
+ }),
1960
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1961
+ className: CodeArtsPluginCard_module_css_default.choices,
1962
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1963
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1964
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1965
+ className: CodeArtsPluginCard_module_css_default.check,
1966
+ checked: dock.sidebar,
1967
+ disabled: !dockWritable || dockSaving,
1968
+ onChange: (on) => void toggleDock("sidebar", on),
1969
+ label: t("displaySidebarToggle")
1970
+ })
1759
1971
  })
1760
1972
  })
1761
- })
1762
- ]
1763
- })]
1973
+ ]
1974
+ }),
1975
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1976
+ className: CodeArtsPluginCard_module_css_default.section,
1977
+ children: [
1978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1979
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1980
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1981
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1982
+ children: t("doctorTitle")
1983
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1984
+ variant: "outline",
1985
+ size: "sm",
1986
+ disabled: doctorBusy,
1987
+ onClick: () => void runDoctor(),
1988
+ children: doctorBusy ? t("doctorRunning") : t("doctorRun")
1989
+ })]
1990
+ }),
1991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1992
+ className: CodeArtsPluginCard_module_css_default.hint,
1993
+ children: t("doctorHint")
1994
+ }),
1995
+ doctorError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1996
+ className: CodeArtsPluginCard_module_css_default.error,
1997
+ children: t("doctorFailed", { message: doctorError })
1998
+ }),
1999
+ doctor !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2000
+ className: CodeArtsPluginCard_module_css_default.doctorList,
2001
+ children: doctor.checks.map((check) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2002
+ className: CodeArtsPluginCard_module_css_default.doctorRow,
2003
+ children: [
2004
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: check.ok ? "done" : "warning" }),
2005
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2006
+ className: CodeArtsPluginCard_module_css_default.doctorName,
2007
+ children: doctorCheckLabel(check.id, accounts, t)
2008
+ }),
2009
+ check.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2010
+ className: CodeArtsPluginCard_module_css_default.meta,
2011
+ children: check.detail
2012
+ })
2013
+ ]
2014
+ }, check.id))
2015
+ }), doctor.hints.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2016
+ className: CodeArtsPluginCard_module_css_default.hint,
2017
+ children: doctor.hints.map((id) => doctorHintText(id, t)).join(";")
2018
+ })] })
2019
+ ]
2020
+ })
2021
+ ]
1764
2022
  })
1765
2023
  ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1766
2024
  className: CodeArtsPluginCard_module_css_default.section,
@@ -2411,14 +2669,14 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
2411
2669
  document.head.appendChild(tag);
2412
2670
  }
2413
2671
  var CodeArtsPanel_module_css_default = {
2672
+ "body": "Z66cgG_body",
2673
+ "title": "Z66cgG_title",
2674
+ "page": "Z66cgG_page",
2675
+ "back": "Z66cgG_back",
2414
2676
  "head": "Z66cgG_head",
2415
2677
  "desc": "Z66cgG_desc",
2416
- "icon": "Z66cgG_icon",
2417
- "page": "Z66cgG_page",
2418
2678
  "backCaret": "Z66cgG_backCaret",
2419
- "body": "Z66cgG_body",
2420
- "back": "Z66cgG_back",
2421
- "title": "Z66cgG_title"
2679
+ "icon": "Z66cgG_icon"
2422
2680
  };
2423
2681
  //#endregion
2424
2682
  //#region src/client/CodeArtsPanel.tsx
@@ -2519,6 +2777,9 @@ const zh = {
2519
2777
  expiredHint: "凭证已过期,请重新登录以继续使用;已勾选的模型设置会保留。",
2520
2778
  accountsTitle: "账号",
2521
2779
  accountRemove: "删除",
2780
+ accountRelogin: "重新登录",
2781
+ reloginPending: "登录中…",
2782
+ reloginOtherAccount: "你登录的是另一个账号,已作为新账号添加;原账号保持不变。",
2522
2783
  addAccount: "添加账号",
2523
2784
  pasteTokenAdd: "粘贴 Token 添加",
2524
2785
  accountsRotateHint: "已存多个账号:请求会自动轮转,某个账号忙时改用下一个,不用干等。",
@@ -2570,6 +2831,40 @@ const zh = {
2570
2831
  usageTipHit: "命中率",
2571
2832
  usageStatHit: "缓存命中",
2572
2833
  usageStatRequests: "今日请求",
2834
+ usageStatFailures: "今日失败率",
2835
+ usageStatFailureCount: "失败 {n} 次",
2836
+ usageStatLatency: "首字 P95",
2837
+ usageStatLatencyDetail: "P50 {p50} ms · {n} 次",
2838
+ usageStatLatencyEmpty: "还没有成功请求",
2839
+ modelSpec: "{context} 上下文 · {output} 输出",
2840
+ modelSpecTitle: "上游返回的上下文窗口 {context} token,最大输出 {output} token",
2841
+ accountPaused: "已暂停",
2842
+ accountPinned: "已置顶",
2843
+ accountPause: "暂停",
2844
+ accountResume: "恢复",
2845
+ accountPin: "置顶",
2846
+ accountUnpin: "取消置顶",
2847
+ accountToday: "今日 {n} 次 · 失败 {failed}",
2848
+ doctorTitle: "体检",
2849
+ doctorHint: "只查本机状态(版本、凭证、目录、账本、pi-ai 兼容),不联网、不改任何东西。",
2850
+ doctorRun: "开始体检",
2851
+ doctorRunning: "检查中…",
2852
+ doctorFailed: "体检失败:{message}",
2853
+ doctorCheckAccount: "账号",
2854
+ doctorCheckRuntime: "运行环境",
2855
+ doctorCheckAccounts: "账号数量",
2856
+ doctorCheckModels: "模型目录",
2857
+ doctorCheckUsage: "用量账本",
2858
+ doctorCheckPiAi: "pi-ai 兼容",
2859
+ doctorHintNoAccount: "还没有账号:先添加一个,或用 token 手动接入。",
2860
+ doctorHintAccountStale: "有账号需要重新登录。",
2861
+ doctorHintAccountNoKey: "有账号缺少签名私钥,无法自动续期。",
2862
+ doctorHintAccountExpired: "有账号凭证已过期:重新登录即可续上。",
2863
+ doctorHintEmptyCatalog: "模型目录为空:点「重拉目录」或检查上游连通性。",
2864
+ doctorHintUsageMissing: "用量账本没有接上:重启宿主后再看。",
2865
+ doctorHintDshHome: "没有设置 DSH_HOME:凭证和账本会写到默认位置。",
2866
+ doctorHintPiAi: "宿主口的 pi-ai 版本与插件预期不一致,可能影响流式解析。",
2867
+ doctorHintOther: "未知提示:{id}",
2573
2868
  usageRequests: "{n} 次请求",
2574
2869
  usageTrendWeek: "本月 · 每日 token",
2575
2870
  usageTrendHour: "今天 · 逐小时 token",
@@ -2669,6 +2964,9 @@ const en = {
2669
2964
  expiredHint: "Your credential has expired. Sign in again to continue; your model selection is kept.",
2670
2965
  accountsTitle: "Accounts",
2671
2966
  accountRemove: "Remove",
2967
+ accountRelogin: "Sign in again",
2968
+ reloginPending: "Signing in…",
2969
+ reloginOtherAccount: "That was a different account, so it was added as a new one; the original stayed unchanged.",
2672
2970
  addAccount: "Add account",
2673
2971
  pasteTokenAdd: "Paste a token",
2674
2972
  accountsRotateHint: "Multiple accounts stored: requests rotate automatically, so a busy account hands over to the next one instead of making you wait.",
@@ -2720,6 +3018,40 @@ const en = {
2720
3018
  usageTipHit: "Hit rate",
2721
3019
  usageStatHit: "Cache hit",
2722
3020
  usageStatRequests: "Today requests",
3021
+ usageStatFailures: "Failure rate today",
3022
+ usageStatFailureCount: "{n} failed",
3023
+ usageStatLatency: "First token P95",
3024
+ usageStatLatencyDetail: "P50 {p50} ms · {n} samples",
3025
+ usageStatLatencyEmpty: "No successful request yet",
3026
+ modelSpec: "{context} ctx · {output} out",
3027
+ modelSpecTitle: "Context window {context} tokens, max output {output} tokens reported upstream",
3028
+ accountPaused: "Paused",
3029
+ accountPinned: "Pinned",
3030
+ accountPause: "Pause",
3031
+ accountResume: "Resume",
3032
+ accountPin: "Pin",
3033
+ accountUnpin: "Unpin",
3034
+ accountToday: "Today {n} · {failed} failed",
3035
+ doctorTitle: "Health check",
3036
+ doctorHint: "Local checks only (version, credentials, catalog, ledger, pi-ai compat). No network, changes nothing.",
3037
+ doctorRun: "Run check",
3038
+ doctorRunning: "Checking…",
3039
+ doctorFailed: "Health check failed: {message}",
3040
+ doctorCheckAccount: "Account",
3041
+ doctorCheckRuntime: "Runtime",
3042
+ doctorCheckAccounts: "Account count",
3043
+ doctorCheckModels: "Model catalog",
3044
+ doctorCheckUsage: "Usage ledger",
3045
+ doctorCheckPiAi: "pi-ai compat",
3046
+ doctorHintNoAccount: "No account yet: sign in or paste a token first.",
3047
+ doctorHintAccountStale: "An account needs to sign in again.",
3048
+ doctorHintAccountNoKey: "An account has no signing key and cannot refresh automatically.",
3049
+ doctorHintAccountExpired: "An account credential has expired: sign in again to renew it.",
3050
+ doctorHintEmptyCatalog: "Model catalog is empty: refresh it or check upstream connectivity.",
3051
+ doctorHintUsageMissing: "Usage ledger is not wired: restart the host and retry.",
3052
+ doctorHintDshHome: "DSH_HOME is not set: credentials and ledger fall back to the default location.",
3053
+ doctorHintPiAi: "Host pi-ai version differs from what the plugin expects; streaming parsing may be affected.",
3054
+ doctorHintOther: "Unknown hint: {id}",
2723
3055
  usageRequests: "{n} request(s)",
2724
3056
  usageTrendWeek: "This month · tokens per day",
2725
3057
  usageTrendHour: "Today · tokens by hour",